Architecture
Vue d'ensemble
Le labo reproduit, avec des briques open source, les quatre composants d'un environnement Snowflake :
| Composant | Implémentation au labo | Équivalent Snowflake |
|---|---|---|
| Socle | MinIO (brique du NUC), tables Apache Iceberg v2, catalogue REST Apache Polaris persisté sur PostgreSQL (brique du NUC), Trino, DuckDB | Stockage et stages, format de table, couche de métadonnées et RBAC, virtual warehouses |
| Collecte et retraitement | Paquet ingest/, projet dbt dbt/, Marquez pour le lineage |
Stages, COPY INTO, Snowpipe, tables, semantic views, lineage |
cortex_lab |
Paquet cortex_lab/ : fonctions AI_* aux noms et contrats Cortex, routées vers LiteLLM (brique du NUC) |
Snowflake Cortex AI Functions |
| Prévision | Paquet forecast/ et image forecast/Dockerfile (t0-gamma, CPU) |
Service conteneurisé dans Snowpark Container Services chez le client |
Principe d'implantation (décision déléguée, voir decisions.md) : les briques d'infrastructure partagées du NUC sont consommées, jamais embarquées. Le fichier docker-compose.yml (projet Compose snowlab) ne contient que Polaris, Trino, Marquez, leurs jobs d'initialisation et le service de prévision à la demande. PostgreSQL (pg-central), MinIO (minio-central) et LiteLLM sont joints sur le réseau Docker externe data.
Hors périmètre (CLAUDE.md, PLAN.md) : performance (micro-partitions, caches, dimensionnement des warehouses), Marketplace réel, Native Apps, Secure Data Sharing, clonage d'un catalogue entier, fonctions IA de Trino, API DataFrame de Snowpark, API Retrocast, SNOWFLAKE.ML.FORECAST, toute donnée du client.
Déploiement
flowchart LR
subgraph NUC["Briques du NUC (réseau Docker externe data)"]
PG[("pg-central:5432<br/>snowlab_polaris_db<br/>snowlab_marquez_db")]
S3[("minio-central:9000<br/>bucket snowlab<br/>landing/ et warehouse/")]
LLM["LiteLLM<br/>alias cortex-classify,<br/>cortex-sentiment, cortex-complete"]
TRAEFIK["Traefik<br/>entrypoint web, local-only@file"]
end
subgraph COMPOSE["docker-compose.yml (projet snowlab)"]
MINIT["minio-init<br/>amazon/aws-cli:2.38.5"]
PBOOT["polaris-bootstrap<br/>apache/polaris-admin-tool:1.8.0"]
POLARIS["polaris<br/>apache/polaris:1.8.0<br/>127.0.0.1:18181"]
PINIT["polaris-init<br/>python:3.12.15-slim-trixie"]
TRINO["trino<br/>trinodb/trino:484<br/>127.0.0.1:18080"]
MARQUEZ["marquez<br/>marquezproject/marquez:0.51.1<br/>127.0.0.1:15000"]
FC["forecast (profil forecast)<br/>image forecast/Dockerfile"]
end
subgraph HOST["Poste (uv run)"]
PY["ingest, dbt-duckdb,<br/>cortex_lab, data.generate, tests"]
end
MINIT --> S3
PBOOT --> PG
POLARIS --> PG
POLARIS --> S3
PINIT --> POLARIS
TRINO --> POLARIS
TRINO --> S3
MARQUEZ --> PG
FC --> POLARIS
FC --> S3
FC --> DUCK
PY --> POLARIS
PY --> S3
PY --> LLM
PY --> MARQUEZ
PY --> DUCK
TRAEFIK --> TRINO
TRAEFIK --> POLARIS
TRAEFIK --> MARQUEZ
Services du compose
| Service | Image | Rôle | Ports hôte | Réseaux | Redémarrage |
|---|---|---|---|---|---|
minio-init |
amazon/aws-cli:2.38.5 |
Vérifie que l'utilisateur scopé atteint le bucket et crée les préfixes landing/ et warehouse/ (infra/minio/init.sh) |
aucun | data |
no |
polaris-bootstrap |
apache/polaris-admin-tool:1.8.0 |
Crée le realm POLARIS et les identifiants root dans PostgreSQL (rejouable) |
aucun | data |
no |
polaris |
apache/polaris:1.8.0 |
Catalogue REST Iceberg, état persisté dans snowlab_polaris_db |
127.0.0.1:18181 vers 8181 |
lab, data, web |
unless-stopped |
polaris-init |
python:3.12.15-slim-trixie |
Exécute infra/polaris/init_catalog.py : catalogue, principaux, rôles, droits, namespaces |
aucun | lab |
no |
trino |
trinodb/trino:484 |
Moteur SQL, catalogue analytics |
127.0.0.1:18080 vers 8080 |
lab, data, web |
unless-stopped |
marquez |
marquezproject/marquez:0.51.1 |
API OpenLineage (sans interface web) | 127.0.0.1:15000 vers 5000 |
lab, data, web |
unless-stopped |
docs |
construite depuis website/Dockerfile (nginx-unprivileged 1.31.7-alpine3.24) |
Site de documentation docs.openflake.nuc : page d'accueil et docs/ |
aucun | web |
unless-stopped |
forecast |
construite depuis forecast/Dockerfile |
Prévision t0-gamma à la demande (profil forecast) |
aucun | lab, data |
no |
Chaîne de dépendances (depends_on) : polaris-bootstrap terminé avec succès, puis polaris sain (healthcheck sur http://localhost:8182/q/health), et minio-init terminé, puis polaris-init terminé, puis trino. marquez ne dépend d'aucun service du compose. forecast attend polaris sain.
Réseaux :
lab: réseau interne du projet (Polaris joint parhttp://polaris:8181).data: réseau externe des briques du NUC (pg-central,minio-central, LiteLLM).web: réseau externe de Traefik. Quatre routeurs, tous sur l'entrypointwebavec le seul middlewarelocal-only@file(avenant Traefik dePLAN.md) :openflake.nucvers Trino,polaris.openflake.nucvers Polaris,marquez.openflake.nucvers Marquez,docs.openflake.nucvers le site de documentation (avenant du 2026-10-26 (4)).
Tous les ports publiés sont liés à 127.0.0.1 ; PostgreSQL n'est pas publié (contrôlé par tests/test_repo_conventions.py).
Modules Python
| Paquet | Fichiers | Rôle |
|---|---|---|
lab/ |
config.py, naming.py, types.py, duckdb_connect.py, iceberg.py, maintenance.py |
Configuration lue dans l'environnement, nommage à trois niveaux, correspondance des types, connexion DuckDB (extension iceberg, catalogue Polaris, cortex_lab), accès PyIceberg, équivalents Time Travel, rétention et clone |
ingest/ |
landing.py, detect.py, classify.py, schema_registry.py, raw_loader.py, mapping.py, exceptions.py, lineage.py, shared_snapshots.py |
Collecte : dépôt immuable, détection de schéma, classification, registre, chargement raw (rôle de COPY INTO et Snowpipe), mapping, exceptions et file de revue, lineage, snapshots shared_* |
cortex_lab/ |
core/, duckdb/, snowpark.py, cortex.py, compat.py, dbt_plugin.py |
Fonctions AI_CLASSIFY, AI_SENTIMENT, AI_COMPLETE et macro GET |
forecast/ |
inputs.py, model.py, writer.py, backtest.py, run.py, Dockerfile |
Prévision t0-gamma, tables forecast.forecast et forecast.backtest_metrics |
data/ |
generate.py, README.md |
Générateurs synthétiques |
dbt/ |
dbt_project.yml, profiles.example.yml, models/, snapshots/, seeds/, macros/, tests/ |
Projet dbt unique (standardized, semantic MetricFlow, SCD2, tests de qualité) |
infra/ |
minio/, polaris/, trino/, marquez/ |
Configuration des services et jobs d'initialisation |
Dépendances Python (pyproject.toml, toutes épinglées exactement, verrouillées par uv.lock) : pydantic==2.14.1, duckdb==2.0.0, pyarrow==26.0.0, openai==3.37.0, pyiceberg[pyarrow]==0.12.0, dbt-core==1.12.6, dbt-duckdb==1.11.0, dbt-trino==1.10.6, dbt-metricflow==0.15.0, openlineage-python==1.54.0, openlineage-dbt==1.54.0, pyyaml==6.0.3, jsonschema==4.26.0, numpy==2.5.4. Groupes : dev (par défaut : pytest==9.1.1, pyiceberg[sql-sqlite], httpx2==2.16.0), forecast (tfc-t0[torch]==0.6.0, torch==2.14.1 en roues CPU depuis l'index pytorch-cpu), snowflake (dbt-snowflake==1.12.4, installé par défaut en développement depuis le 2026-10-23, pour les contrôles B1 et B2). Aucune dépendance litellm : le client est le SDK openai pointé sur LITELLM_BASE_URL.
Flux de données
flowchart TD
GEN["data.generate<br/>(fichiers synthétiques)"] --> PUT["LandingStore.put<br/>ingest/landing.py"]
PUT --> LAND[("MinIO s3://snowlab/landing/source/date/")]
LAND --> DET["detect.py<br/>sniff_csv, read_json_auto"]
DET --> CLS["classify.py<br/>règles, puis AI_CLASSIFY"]
CLS -->|non classé| EXC
CLS --> LOAD["raw_loader.py<br/>COPY INTO / Snowpipe"]
LOAD --> REG[("analytics.intake.schema_registry")]
LOAD --> HIST[("analytics.intake.load_history")]
LOAD --> EXC[("analytics.intake.exceptions<br/>analytics.intake.review_queue")]
LOAD --> RAW[("analytics.raw.pms_daily<br/>bookings_reservations<br/>rate_shop_rates")]
LOAD -.->|OpenLineage| MQZ["Marquez"]
RAW --> DBT["dbt-duckdb<br/>(Polaris attaché sous l'alias analytics)"]
DBT --> STD[("analytics.standardized : std_*, snap_*<br/>analytics.semantic : dim_*, fct_hotel_daily")]
DBT -.->|seed mapping_rules| INTSEED[("analytics.intake.mapping_rules")]
SNAP["shared_snapshots.py"] --> CAL[("analytics.shared_calendar.calendar_days")]
STD --> FC["conteneur forecast<br/>t0-gamma"]
CAL --> FC
FC --> FOR[("analytics.forecast.forecast<br/>analytics.forecast.backtest_metrics")]
MAP["mapping.py<br/>AI_COMPLETE"] --> SUG[("analytics.intake.mapping_suggestions")]
SUG --> EXC
CLS -.-> LLM["LiteLLM"]
MAP -.-> LLM
Étapes, avec le module qui les porte :
- Dépôt :
data.generateproduit les fichiers d'une date ;LandingStore.putles écrit souslanding/<source>/<date>/<fichier>dans le bucketsnowlab. Un fichier déposé n'est jamais remplacé. - Détection et classification :
ingest.detect.detectlit le schéma avec DuckDB ;ingest.classify.classifyapplique les règles sur le nom et les colonnes, et n'appelleAI_CLASSIFYque si les règles ne donnent pas un type unique. Un fichier non classé devient une exception et un élément de la file de revue. - Chargement raw :
ingest.raw_loader.RawLoader.loadajoute les colonnes de preuve et la clé de hash, enregistre l'empreinte de schéma, fait évoluer le schéma Iceberg, écrit la table raw par PyIceberg, rapproche les totaux et note le chargement dansintake.load_history(mémoire de 14 jours, comme Snowpipe). - Retraitement : dbt (adapter
dbt-duckdbpar défaut) lit les tables raw via Polaris et écrit les couches standardized et semantic, ainsi que les snapshots SCD2, dans Polaris, en tables Iceberganalytics.standardized.*etanalytics.semantic.*(Polaris est attaché à DuckDB sous le nomanalytics, base DuckDB locale en mémoire). - Données partagées :
ingest.shared_snapshots.write_calendar_snapshotécrit un snapshot daté dansshared_calendar.calendar_days. - Prévision : le conteneur
forecastlit la couche standardized, les snapshots SCD2 et le calendrier partagé dans Polaris (DuckDB, nomsanalytics.<schéma>.<table>), sans volume local, et écritforecast.forecastetforecast.backtest_metricsdans Iceberg. - Lineage :
ingest.lineage.LineageEmitterémet START, COMPLETE ou FAIL vers Marquez pour chaque chargement raw, y compris depuis la CLIpython -m ingest.raw_loaderquandMARQUEZ_URLest défini ; les exécutions dbt se tracent avec l'enveloppedbt-old'openlineage-dbt.
Où vivent les tables
| Schéma (namespace) | Tables | Stockage physique | Écrivain |
|---|---|---|---|
raw |
pms_daily, bookings_reservations, rate_shop_rates |
Iceberg (Polaris, s3://snowlab/warehouse/) |
PyIceberg (ingest/raw_loader.py) |
intake |
load_history, schema_registry, exceptions, review_queue, mapping_suggestions |
Iceberg | PyIceberg (ingest/) |
intake (seed) |
mapping_rules |
Iceberg | dbt seed (dbt-duckdb) |
standardized |
std_pms_daily, std_bookings, std_rate_shop, snap_bookings_otb, snap_rate_shop |
Iceberg | dbt (dbt-duckdb) |
semantic |
dim_hotel, dim_comp_set, fct_hotel_daily, metricflow_time_spine, seeds hotels et comp_sets |
Iceberg | dbt (dbt-duckdb) |
shared_calendar |
calendar_days |
Iceberg | PyIceberg (ingest/shared_snapshots.py) |
forecast |
forecast, backtest_metrics |
Iceberg | PyIceberg (forecast/writer.py) |
Les six namespaces Polaris (raw, standardized, semantic, intake, forecast, shared_calendar) sont créés par infra/polaris/init_catalog.py. Avec l'adapter par défaut dbt-duckdb, dbt écrit directement dans ces namespaces (voie A de l'avenant du 2026-10-23) : les tables sont lisibles en analytics.<schéma>.<table> par Trino et par DuckDB. Avec la cible trino de dbt/profiles.example.yml, les mêmes modèles s'écriraient aussi en Iceberg via Trino (cible compilée dans les tests, exécution complète non couverte : à vérifier).
Identités d'accès
| Client | Identité Polaris | Contrôle d'accès effectif |
|---|---|---|
| Trino | toujours le principal lab_tech (rôle lab_tech_role, fichier infra/trino/catalog/analytics.properties) |
Règles de fichier infra/trino/rules.json selon le nom d'utilisateur Trino déclaré (aucune authentification) |
PyIceberg (lab/iceberg.py) |
lab_tech ou lab_reader selon LabConfig.from_env("tech" ou "reader") |
Privilèges Polaris du rôle de catalogue |
DuckDB (lab/duckdb_connect.py, profil dbt-duckdb) |
lab_tech par défaut |
Privilèges Polaris |
Conteneur forecast |
lab_tech |
Privilèges Polaris |
polaris-init |
root (création), puis lab_tech pour les namespaces |
Administration |
Tous les moteurs lisent et écrivent les fichiers directement sur MinIO avec les clés statiques de l'utilisateur scopé snowlab : Polaris ne délivre pas d'identifiants temporaires (catalogue stsUnavailable).
Correspondance avec Snowflake
| Snowflake | Labo | Fichiers |
|---|---|---|
Base ANALYTICS, schémas, tables |
Catalogue Trino analytics, catalogue et namespaces Polaris, tables Iceberg v2 ; même nom à trois niveaux, en minuscules |
infra/trino/catalog/analytics.properties, lab/naming.py |
| Stockage interne, stages | Bucket snowlab, préfixe landing/<source>/<date>/ |
infra/minio/init.sh, ingest/landing.py |
COPY INTO, Snowpipe |
ingest.raw_loader, déclenché à la main ; fichier déjà chargé ignoré pendant 14 jours |
ingest/raw_loader.py |
METADATA$FILENAME, METADATA$FILE_ROW_NUMBER |
_source_file, _row_number |
ingest/__init__.py, ingest/raw_loader.py |
Time Travel (AT, BEFORE) |
FOR VERSION AS OF, FOR TIMESTAMP AS OF (Trino), lecture par snapshot (PyIceberg) |
lab/maintenance.py |
DATA_RETENTION_TIME_IN_DAYS |
expire_snapshots avec rétention par défaut d'un jour |
lab/maintenance.py |
| Zero-copy clone | Branche ou tag Iceberg par table | lab/maintenance.py |
| RBAC (rôles, privilèges) | Principal, rôle de principal, rôle de catalogue, privilèges Polaris ; règles de fichier Trino par-dessus | infra/polaris/init_catalog.py, infra/trino/rules.json |
| Virtual warehouse | Trino (nœud unique), DuckDB embarqué | infra/trino/config.properties |
VARIANT, OBJECT, ARRAY |
JSON en chaîne | lab/types.py |
TIMESTAMP_NTZ, TIMESTAMP_TZ |
timestamp, timestamptz (microsecondes) ; lu par Snowflake sur une table Iceberg, timestamptz devient TIMESTAMP_LTZ (voir socle.md) |
lab/types.py |
NUMBER(38, s) |
decimal(38, s) |
lab/types.py |
GET(x, 'champ'), x:champ |
Macro get (DuckDB) et macro dbt get avec dispatch ; la syntaxe x:champ n'est pas utilisée |
cortex_lab/duckdb/macros.sql, dbt/macros/get.sql |
| Semantic views | dbt avec MetricFlow | dbt/models/semantic/semantic_models.yml |
| Lineage Snowsight | OpenLineage vers Marquez (API seule) | ingest/lineage.py, infra/marquez/marquez.yml |
| Marketplace, Data Sharing | Schémas shared_* en lecture seule alimentés par snapshots datés |
ingest/shared_snapshots.py |
| Cortex AI Functions | cortex_lab (DuckDB et Python) : AI_CLASSIFY, AI_SENTIMENT, AI_COMPLETE (forme chaîne), AI_FILTER, AI_EXTRACT (texte), AI_TRANSLATE, AI_SUMMARIZE (texte), AI_AGG, AI_SUMMARIZE_AGG, AI_EMBED et AI_SIMILARITY (texte), AI_COUNT_TOKENS, AI_REDACT, PROMPT |
cortex_lab/ |
snowflake.cortex, snowflake.snowpark.functions.ai_* |
cortex_lab.cortex, cortex_lab.snowpark, bascule cortex_lab.compat |
cortex_lab/compat.py |
| Snowpark Container Services, Model Registry | Conteneur forecast exécuté par Docker Compose |
forecast/Dockerfile |
Écarts de fidélité connus
| Écart | Détail | Où |
|---|---|---|
| Casse des identifiants | Snowflake stocke les identifiants non quotés en majuscules (ANALYTICS.RAW.PMS_DAILY), le labo en minuscules ; la règle « minuscules, jamais quotés » rend le même SQL valide des deux côtés |
lab/naming.py |
| Précision des timestamps | Nanosecondes par défaut pour les tables natives de Snowflake, microsecondes en Iceberg v2 des deux côtés (relu le 2026-10-23) | lab/types.py, ingest/raw_loader.py |
VARIANT |
Pas de type variant en Iceberg v2 : valeurs imbriquées stockées en JSON compact (chaîne) | ingest/raw_loader.py |
GET |
Renvoie NULL pour une clé absente comme Snowflake, mais renvoie un VARCHAR (chaîne sans guillemets, ou texte JSON) au lieu d'un VARIANT |
cortex_lab/duckdb/macros.sql |
| Snowpipe | Déclenchement manuel par commande, pas d'auto-ingest par notification d'événements | ingest/raw_loader.py |
| Clone | Par table seulement (branche ou tag), pas de clone de schéma ni de base | lab/maintenance.py |
| RBAC Trino | Trino n'authentifie pas : le nom d'utilisateur déclaré choisit les règles ; Trino parle à Polaris sous l'identité lab_tech |
infra/trino/rules.json |
| Couche semantic | MetricFlow au lieu de CREATE SEMANTIC VIEW |
dbt/models/semantic/ |
| Emplacement de standardized et semantic (corrigé le 2026-10-23) | Avant : fichier DuckDB local, Polaris attaché sous l'alias lake. Maintenant : tables Iceberg dans Polaris, alias analytics, mêmes noms à trois niveaux dans dbt, Trino, DuckDB et Snowflake. Particularités de dbt-duckdb sur Polaris : transactions désactivées (Polaris refuse le commit multi-tables), suppression sans CASCADE, nom intermédiaire unique par exécution ; une matérialisation table recrée la table à chaque exécution, donc son historique de snapshots Iceberg repart de zéro (comme CREATE OR REPLACE TABLE) |
dbt/profiles.example.yml, dbt/macros/ |
| Lineage de la CLI du chargeur (corrigé le 2026-10-23) | Avant : python -m ingest.raw_loader n'émettait aucun événement et le dataset de sortie était toujours raw.<table>. Maintenant : la CLI émet vers Marquez quand MARQUEZ_URL est défini, avec le schéma réel (--raw-schema) |
ingest/raw_loader.py, ingest/lineage.py |
AI_COMPLETE |
Forme chaîne seulement ; la macro DuckDB renvoie toujours un VARCHAR ; guardrails à TRUE est une erreur |
cortex_lab/core/functions/ai_complete.py |
snowflake.cortex.sentiment |
Renvoie un float entre -1 et 1 (forme du module Python Snowflake), pas l'objet d'AI_SENTIMENT |
cortex_lab/cortex.py |
| Limites de jetons | Estimation à 4 caractères par jeton, pas de tokenizer du modèle géré (AI_COUNT_TOKENS comprise) |
cortex_lab/core/limits.py |
| Fenêtre de contexte | Celle du modèle local (32 768 jetons en chat, 2 048 en embedding, mesurées le 2026-10-23) : au-delà, erreur par ligne, jamais une troncature silencieuse | cortex_lab/core/limits.py, cortex_lab/core/client.py |
Cible dbt-trino |
Les deux dbt build passent (le second remplace les tables) grâce à la purge de suppression activée sur le catalogue Polaris analytics ; la macro trino__list_relations_without_caching contourne le refus du catalogue system |
infra/polaris/init_catalog.py, dbt/macros/trino_list_relations.sql, tests/ingest/test_dbt_trino_integration.py |
| Lineage dbt | Les datasets de dbt-ol portent l'espace de noms duckdb://:memory:, ceux du chargeur iceberg://analytics : pas de lien dans Marquez |
tests/ingest/test_dbt_lineage_integration.py |
Cible dbt-snowflake |
Profil déclaré ; dbt parse et dbt compile --no-introspect aboutissent hors connexion (2026-10-23, B1 et B2) ; SQL non validé sur Snowflake, exécution chez le client |
dbt/profiles.example.yml, tests/ingest/test_dbt_snowflake_offline.py |
| Marquez | API seule, pas d'interface web | infra/marquez/marquez.yml |
Références Snowflake
Les pages ci-dessous sont celles citées dans PLAN.md, avec leur statut de vérification à cette date.
| Élément | Page | Vérifié |
|---|---|---|
| Tables Iceberg | https://docs.snowflake.com/en/user-guide/tables-iceberg | 2026-10-22 |
| Types de données Iceberg | https://docs.snowflake.com/en/user-guide/tables-iceberg-data-types | 2026-10-23 |
| Stages internes | https://docs.snowflake.com/en/user-guide/data-load-local-file-system-create-stage | 2026-10-22 |
METADATA$FILENAME, METADATA$FILE_ROW_NUMBER |
https://docs.snowflake.com/en/user-guide/querying-metadata | 2026-10-22 |
| Snowpipe | https://docs.snowflake.com/en/user-guide/data-load-snowpipe-intro | 2026-10-22 |
| Time Travel | https://docs.snowflake.com/en/user-guide/data-time-travel | 2026-10-22 |
| Zero-copy clone | https://docs.snowflake.com/en/user-guide/tables-storage-considerations | 2026-10-22 |
CREATE ... CLONE |
https://docs.snowflake.com/en/sql-reference/sql/create-clone | 2026-10-23 |
| Contrôle d'accès | https://docs.snowflake.com/en/user-guide/security-access-control-overview | 2026-10-22 |
| Identifiants | https://docs.snowflake.com/en/sql-reference/identifiers-syntax | 2026-10-22 |
| Types date et heure | https://docs.snowflake.com/en/sql-reference/data-types-datetime | 2026-10-22 |
| Types semi-structurés | https://docs.snowflake.com/en/sql-reference/data-types-semistructured | 2026-10-22 |
GET |
https://docs.snowflake.com/en/sql-reference/functions/get | 2026-10-22 |
| Semantic views | https://docs.snowflake.com/en/user-guide/views-semantic/overview | 2026-10-22 |
CREATE SEMANTIC VIEW |
https://docs.snowflake.com/en/sql-reference/sql/create-semantic-view | 2026-10-22 |
| Lineage | https://docs.snowflake.com/en/user-guide/ui-snowsight-lineage | 2026-10-23 |
| Data Sharing | https://docs.snowflake.com/en/user-guide/data-sharing-intro | 2026-10-23 |
| Snowpark Container Services | https://docs.snowflake.com/en/developer-guide/snowpark-container-services/overview | 2026-10-22 |
| Modèle custom du Model Registry | https://docs.snowflake.com/en/developer-guide/snowflake-ml/model-registry/bring-your-own-model-types | 2026-10-22 |
Les références des fonctions Cortex sont dans cortex-lab.md.