Lancer une étape individuellement
Le pipeline complet se lance d’un seul argo submit (voir l’accueil). Mais pour déboguer, relancer une étape échouée ou itérer sur une seule brique, on peut exécuter chaque étape isolément — soit via Argo, soit en local. Cette page rassemble les commandes vérifiées pour les deux modes.
run_id et run_date
Par défaut, run_id vaut le nom du workflow Argo et run_date sa date de création. Une étape relancée isolément crée donc un nouveau dossier S3 vide si on ne lui passe pas explicitement le run_id/run_date du run d’origine — et elle ne trouvera pas ses entrées. Récupérez-les depuis le nom du workflow d’origine (argo list) ou depuis le chemin S3 …/workflow_runs/{run_date}/{run_id}/.
Prérequis : secrets et variables d’environnement
Via Argo, les secrets sont injectés depuis secret-codif-coicop-bdf (cf. README.md). En local, il faut exporter soi-même les variables requises par l’étape :
| Étape | Variables d’environnement requises |
|---|---|
preprocessing, codif-regex, codif-lcs, final-output |
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, AWS_S3_ENDPOINT, AWS_ENDPOINT_URL |
prune |
AWS_* + DDC_ENCRYPTION_KEY |
create-vector-db, create-vector-db-annotations |
AWS_* + DDC_ENCRYPTION_KEY + LLMLAB_URL, LLMLAB_API_KEY + QDRANT_URL, QDRANT_API_KEY, QDRANT_API_PORT |
run-rag, run-rag-annotations |
AWS_* + DDC_ENCRYPTION_KEY + LLMLAB_* + QDRANT_* + MLFLOW_TRACKING_URI, MLFLOW_TRACKING_USERNAME, MLFLOW_TRACKING_PASSWORD + LANGFUSE_BASE_URL, LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY |
run-ttc |
AWS_* + MLFLOW_TRACKING_* (chargement du modèle depuis MLflow) |
decide-coicop |
AWS_* + LLMLAB_API_KEY (+ LLMLAB_URL pour un endpoint non-OpenAI) |
report |
AWS_* + MLFLOW_TRACKING_* (facultatif : sans MLFLOW_TRACKING_URI, le log MLflow est sauté) |
Mode 1 — via Argo (--entrypoint)
Chaque étape est un template nommé dans argo/codif-pipeline.yaml. L’option --entrypoint lance ce template seul ; ses paramètres d’entrée sont résolus par nom depuis les -p passés en ligne de commande.
# Étapes simples : seuls run_id / run_date sont requis
argo submit argo/codif-pipeline.yaml --entrypoint codif-regex \
-p run_id=codif-abc12 -p run_date=2026-03-20
argo submit argo/codif-pipeline.yaml --entrypoint codif-lcs \
-p run_id=codif-abc12 -p run_date=2026-03-20
argo submit argo/codif-pipeline.yaml --entrypoint prune \
-p run_id=codif-abc12 -p run_date=2026-03-20
# preprocessing : il faut aussi le fichier d'entrée et le mappage de colonnes
argo submit argo/codif-pipeline.yaml --entrypoint preprocessing \
-p run_id=codif-abc12 -p run_date=2026-03-20 \
-p input_file=s3://projet-budget-famille/data/workflow_inputs/mon_fichier.csv \
-p text_column=NAT_DEP -p shop_column=MAG_DEP -p budget_column=MONT_DEP \
-p annee_column= -p source_column=
# run-rag / run-rag-annotations : model-name est un argument du workflow
# (pas de sampling ici : il est centralisé à codif-regex)
argo submit argo/codif-pipeline.yaml --entrypoint run-rag \
-p run_id=codif-abc12 -p run_date=2026-03-20 -p model-name=gemma4-26b-moe
argo submit argo/codif-pipeline.yaml --entrypoint run-rag-annotations \
-p run_id=codif-abc12 -p run_date=2026-03-20 \
-p model-name=gemma4-26b-moe -p sample-annotations=
# run-ttc : ttc-model-uri a une valeur par défaut, surchargeable
argo submit argo/codif-pipeline.yaml --entrypoint run-ttc \
-p run_id=codif-abc12 -p run_date=2026-03-20
# final-output : reprend le mappage de colonnes pour restaurer les noms d'origine
argo submit argo/codif-pipeline.yaml --entrypoint final-output \
-p run_id=codif-abc12 -p run_date=2026-03-20 \
-p text_column=NAT_DEP -p shop_column=MAG_DEP -p budget_column=MONT_DEP -p annee_column=Deux templates déclarent des inputs dont le nom diffère des paramètres globaux du workflow. En --entrypoint, c’est le nom de l’input du template qu’il faut passer :
# decide-coicop : inputs "model" et "concurrency"
# (et non decide-model / decide-concurrency)
argo submit argo/codif-pipeline.yaml --entrypoint decide-coicop \
-p run_id=codif-abc12 -p run_date=2026-03-20 \
-p model=gemma4-26b-moe -p concurrency=5
# report : inputs "experiment-name" (et non report-experiment) et "step-timings"
argo submit argo/codif-pipeline.yaml --entrypoint report \
-p run_id=codif-abc12 -p run_date=2026-03-20 \
-p input_file= -p experiment-name=codif-coicop-eval \
-p model-name= -p decide-model=gemma4-26b-moe \
-p decide-concurrency=5 -p ttc-model-uri= -p skip-vector-db=true \
-p skip-report=false -p step-timings='{}'En cas de doute, valider avec argo submit --dry-run … avant de soumettre.
Plutôt que de relancer étape par étape, argo retry <nom-du-workflow> reprend le DAG d’origine là où il a échoué, avec les mêmes paramètres (donc le même run_id).
Mode 2 — en local
Chaque sous-dossier est autonome (pyproject.toml + uv.lock). Les commandes ci-dessous sont celles exécutées par les conteneurs Argo, à lancer depuis la racine du dépôt après avoir exporté les variables d’environnement du tableau ci-dessus.
RUN_ID=codif-abc12
RUN_DATE=2026-03-20
RUN_ROOT="s3://projet-budget-famille/data/workflow_runs/$RUN_DATE/$RUN_ID"1. preprocessing
cd preprocessing && uv sync
uv run main.py --run-id $RUN_ID --run-date $RUN_DATE \
--input-file s3://projet-budget-famille/data/workflow_inputs/mon_fichier.csv \
--text-column NAT_DEP --shop-column MAG_DEP --budget-column MONT_DEP2. codif-regex
cd regex-codif && uv sync
uv run src/main.py --run-id $RUN_ID --run-date $RUN_DATE3. codif-lcs (R)
cd stats-annotations
Rscript R/main.R --run-id=$RUN_ID --run-date=$RUN_DATELe parsing des options de R/main.R impose la syntaxe --option=valeur (signe =, pas d’espace).
4. prune (depuis prune/)
cd prune && uv sync
uv run scripts/main.py --config config/config.yaml \
--run-id $RUN_ID --run-date $RUN_DATEProduit les 5 artefacts prunés sous $RUN_ROOT/prune/ (voir 3. Prune). À lancer avant les étapes RAG.
5. Branche RAG notices (depuis coicop-rag/)
cd coicop-rag && uv sync
# Partagé entre runs — à ne refaire que si la nomenclature prunée a changé :
uv run scripts/0_create_vector_db.py --config config/config.yaml \
--run-id $RUN_ID --run-date $RUN_DATE
# Propre au run :
uv run scripts/2_run_rag.py --config config/config.yaml \
--run-id $RUN_ID --run-date $RUN_DATE \
--model_name gemma4-26b-moe # facultatifAttention au mélange de styles : les scripts attendent --run-id/--run-date (tirets) mais --model_name/--sample_size (tirets bas).
6. Branche RAG annotations (depuis coicop-rag-annotations/)
cd coicop-rag-annotations && uv sync
# Partagé entre runs — indexe la KB prunée + le suggester dans Qdrant :
uv run scripts/0_build_annotation_vector_db.py --config config/config.yaml \
--run-id $RUN_ID --run-date $RUN_DATE
# Propre au run — --skip-eval false = mode évaluation (métriques),
# --skip-eval true = mode production (prédictions seules) :
uv run scripts/1_run_rag.py --config config/config.yaml \
--run-id $RUN_ID --run-date $RUN_DATE --skip-eval falseSortie : $RUN_ROOT/rag-annotation/predictions.parquet (le dossier s’appelle rag-annotation, pas run-rag-annotations).
7. run-ttc (depuis codif-ttc/)
cd codif-ttc && uv sync
uv run main.py predict-basic \
--model "mlflow-artifacts:/10/cacf2603514b4887bbfb77e2654c9bc1/artifacts/model" \
--file "$RUN_ROOT/codif-regex/raw_test_without_regex.parquet" \
--output "$RUN_ROOT/run-ttc/predictions.parquet" \
--text-column l_pr_product --top-k 10L’URI du modèle est le paramètre de workflow ttc-model-uri (cf. argo/codif-pipeline.yaml).
8. decide-coicop
cd decide-coicop && uv sync
uv run main.py decide-coicop \
--lcs-file "$RUN_ROOT/codif-lcs/raw_test_LCS.parquet" \
--rag-file "$RUN_ROOT/run-rag/predictions.parquet" \
--rag-annotations-file "$RUN_ROOT/rag-annotation/predictions.parquet" \
--ttc-file "$RUN_ROOT/run-ttc/predictions.parquet" \
--mapping-file "$RUN_ROOT/prune/mapping_lvl4.parquet" \
--output-file "$RUN_ROOT/decide-coicop/predictions.parquet" \
--extra-columns-file "$RUN_ROOT/preprocessing/raw_test.parquet" \
--model gemma4-26b-moe --concurrency 5En mode production, remplacer --extra-columns-file par "$RUN_ROOT/preprocessing/observations.parquet". Sans --mapping-file, les codes ne sont pas normalisés (troncature + élagage) — le pipeline Argo le passe toujours.
Si --output-file existe déjà, l’étape reprend automatiquement les observations non traitées (checkpoint toutes les 50 observations) — relancer la même commande suffit après une interruption.
Pour déboguer une seule observation (affiche le prompt et la décision, n’écrit rien) :
uv run main.py decide-coicop --id <uuid-de-la-ligne> --output json \
--model gemma4-26b-moe \
--lcs-file "$RUN_ROOT/codif-lcs/raw_test_LCS.parquet" \
--rag-file "$RUN_ROOT/run-rag/predictions.parquet" \
--rag-annotations-file "$RUN_ROOT/rag-annotation/predictions.parquet" \
--ttc-file "$RUN_ROOT/run-ttc/predictions.parquet" \
--mapping-file "$RUN_ROOT/prune/mapping_lvl4.parquet"9. final-output
cd final-output && uv sync
uv run main.py --run-id $RUN_ID --run-date $RUN_DATE \
--input-file s3://projet-budget-famille/data/workflow_inputs/mon_fichier.csv \
--text-column NAT_DEP --shop-column MAG_DEP --budget-column MONT_DEP(--input-file en mode production seulement : il sélectionne observations.parquet comme base et restaure le nom du fichier livré.)
10. report
cd report && uv sync
uv run main.py --run-id $RUN_ID --run-date $RUN_DATE \
--experiment-name codif-coicop-evalLe mode (évaluation ou prédiction) est détecté automatiquement (voir 8. Report). Sans MLFLOW_TRACKING_URI, le log MLflow est simplement sauté.
Déboguer un run
Logs des étapes. Chaque étape tourne dans son pod :
argo list # retrouver le workflow
argo get <nom-du-workflow> # statut du DAG, étape par étape
argo logs <nom-du-workflow> # logs agrégés (ou --container main, -f pour suivre)Inspecter les fichiers intermédiaires sur S3. Toutes les sorties d’étapes sont des parquet sous $RUN_ROOT/<étape>/. DuckDB permet de les interroger directement :
import duckdb, os
con = duckdb.connect()
con.execute(f"""
CREATE SECRET (TYPE S3,
KEY_ID '{os.environ["AWS_ACCESS_KEY_ID"]}',
SECRET '{os.environ["AWS_SECRET_ACCESS_KEY"]}',
SESSION_TOKEN '{os.environ["AWS_SESSION_TOKEN"]}',
ENDPOINT '{os.environ["AWS_S3_ENDPOINT"]}',
URL_STYLE 'path');
""")
con.sql(f"SELECT * FROM read_parquet('{RUN_ROOT}/decide-coicop/predictions.parquet') LIMIT 10")Comprendre un code manquant. Dans le fichier livré, predicted_code vide signifie « ni regex, ni LLM ». La raison de l’échec LLM est dans la colonne llm_error de $RUN_ROOT/decide-coicop/predictions.parquet (cf. 8. Decide).
Tracer les appels LLM. Les appels de run-rag et run-rag-annotations sont tracés dans Langfuse (prompt, réponse, latence par produit). Les métriques de chaque branche RAG vont dans MLflow (expériences test et rag-annotation), et les paramètres/métriques du run complet dans l’expérience codif-coicop-eval via l’étape report, avec le report.html en artefact.
Retour à l’accueil