Veristral est une pipeline de fact-checking temps réel pour débats, interviews et prises de parole en direct.
Le système :
- capture l'audio depuis un micro,
- transcrit les phrases complètes,
- envoie chaque phrase dans Temporal,
- analyse la phrase avec un pipeline de fact-check,
- poste le résultat vers l'application Laravel,
- diffuse un bandeau overlay,
- archive la transcription complète avec les fact-checks associés.
Le dépôt contient donc trois briques principales :
texte/etingestion/: transcription temps réel,workflows/: orchestration Temporal + analyse,app/: API Laravel + overlay temps réel.
Arborescence racine et niveau 2 :
.
├── .docs/
│ └── obs-mediamtx-setup.md
├── .env
├── .env.example
├── .gitignore
├── .venv/
│ ├── bin/
│ ├── include/
│ ├── lib/
│ ├── .gitignore
│ └── pyvenv.cfg
├── README.md
├── Trash/
│ ├── Agents.ipynb
│ ├── README.md
│ ├── Untitled.ipynb
│ ├── activities.py
│ └── test_agents.ipynb
├── antigravity.env/
├── app/
│ ├── .dockerignore
│ ├── .editorconfig
│ ├── .env
│ ├── .env.example
│ ├── .gitattributes
│ ├── .github/
│ ├── .gitignore
│ ├── .npmrc
│ ├── .vscode/
│ ├── AGENTS.md
│ ├── Dockerfile
│ ├── README.md
│ ├── app/
│ ├── artisan
│ ├── boost.json
│ ├── bootstrap/
│ ├── composer.json
│ ├── composer.lock
│ ├── config/
│ ├── database/
│ ├── docker/
│ ├── eslint.config.js
│ ├── package.json
│ ├── phpunit.xml
│ ├── pint.json
│ ├── pnpm-lock.yaml
│ ├── public/
│ ├── resources/
│ ├── routes/
│ ├── storage/
│ ├── tests/
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── cle.env
├── cle.env.example
├── debug_micro.jsonl
├── docker-compose.yml
├── dynamicconfig/
│ ├── README.md
│ ├── development-cass.yaml
│ ├── development-sql.yaml
│ └── docker.yaml
├── ingestion/
│ ├── README.md
│ ├── realtime_transcript.py
│ └── requirements.txt
├── mediamtx.yml
├── reports/
│ ├── live_transcripts/
│ └── mistral_503_discord_report_2026-03-17.md
├── requirements.txt
├── scripts/
│ ├── create-namespace.sh
│ ├── mock_fact_check_receiver.py
│ ├── run_stack.sh
│ ├── setup-cassandra-es.sh
│ ├── setup-mysql-es.sh
│ ├── setup-mysql.sh
│ ├── setup-postgres-es-tls.sh
│ ├── setup-postgres-es.sh
│ ├── setup-postgres-opensearch.sh
│ ├── setup-postgres.sh
│ └── validate-temporal.sh
├── texte/
│ ├── README.md
│ ├── realtime_transcript_elevenlabs.py
│ ├── realtime_transcript_fusion.py
│ ├── requirements.txt
│ ├── run_elevenlabs_to_temporal.sh
│ └── run_fusion_to_temporal.sh
└── workflows/
├── .python-version
├── Dockerfile
├── README.md
├── activities_emma.py
├── debate_config.py
├── debate_jsonl_to_temporal.py
├── debate_worker.py
├── debate_workflow.py
├── main.py
├── pyproject.toml
├── requirements.worker.txt
├── transcript_archive.py
├── uv.lock
├── worker.py
└── workflows.py
Repères importants :
docker-compose.yml: stack complète locale.cle.env: configuration principale des workflows Python.texte/run_fusion_to_temporal.sh: commande la plus directe pour lancer micro -> Temporal.workflows/activities_emma.py: logique métier principale de fact-check.workflows/transcript_archive.py: archivage de la transcription enrichie.app/routes/api.php: endpoints API de fact-check.app/routes/web.php: pages overlay.reports/live_transcripts/: sorties archivées des sessions.
Prérequis recommandés :
- Docker Desktop avec
docker compose - Python 3.11+
- un micro fonctionnel
- accès réseau pour appeler Mistral
Selon la machine, PyAudio peut nécessiter des dépendances système supplémentaires.
Installer l'environnement local :
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
pip install -r ingestion/requirements.txt
pip install -r texte/requirements.txtLe backend Laravel, Reverb, Temporal et le worker Python tournent via Docker :
docker compose up -d --buildÀ configurer :
cle.env: configuration du pipeline Python / workerapp/.env: configuration Laravel / Reverb / OBS
Création initiale :
cp cle.env.example cle.env
cp app/.env.example app/.envDans cle.env :
MISTRAL_API_KEY: obligatoireFACT_CHECK_ACTIVITY_IMPL=emmaFACT_CHECK_POST_URL=http://app-web:8000/api/stream/fact-checkPIPELINE_LANGUAGE=frFACT_CHECK_ANALYSIS_TIMEOUT_SECONDS=90MISTRAL_AGENT_CALL_TIMEOUT_SECONDS=20VIDEO_STREAM_DELAY_SECONDS=30ou0pour les tests instantanés
Variables optionnelles utiles :
GEMINI_API_KEYMISTRAL_WEB_SEARCH_MODELSOURCE_SELECTION_MODEFACT_CHECK_ANALYZE_ACTIVITY_MAX_ATTEMPTS- variables de backoff Mistral
Dans app/.env :
BROADCAST_CONNECTION=reverbREVERB_*VITE_REVERB_*OBS_*si usage OBS
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
pip install -r ingestion/requirements.txt
pip install -r texte/requirements.txt
cp cle.env.example cle.env
cp app/.env.example app/.envRenseigner au minimum dans cle.env :
MISTRAL_API_KEY=...
FACT_CHECK_ACTIVITY_IMPL=emma
FACT_CHECK_POST_URL=http://app-web:8000/api/stream/fact-check
PIPELINE_LANGUAGE=fr
FACT_CHECK_ANALYSIS_TIMEOUT_SECONDS=90
MISTRAL_AGENT_CALL_TIMEOUT_SECONDS=20Option recommandée :
./scripts/run_stack.sh up --buildOption directe :
docker compose up -d --builddocker compose ps
docker compose logs --tail=40 workflows-workerServices attendus :
app-web:http://localhost:8000temporal-ui:http://localhost:8080app-reverb:http://localhost:8081temporal: port7233
- Overlay :
http://localhost:8000/overlays/fact-check-2 - Temporal UI :
http://localhost:8080/namespaces/default/workflows
Lister les périphériques :
source .venv/bin/activate
python texte/realtime_transcript_fusion.py --list-devicesLancer le pipeline complet micro -> Temporal :
export VIDEO_DELAY_SECONDS=0
export MAX_WAIT_NEXT_PHRASE_SECONDS=0.5
./texte/run_fusion_to_temporal.sh \
--input-device-index 0 \
--personne "Emma" \
--source-video "Test micro Mac" \
--question-posee ""Ce qui doit apparaître :
- workflows dans Temporal UI
- bandeaux dans l'overlay
- transcription archivée dans :
reports/live_transcripts/<session_id>/
Fichiers produits :
transcript.mdtranscript.jsonlentries/*.json
Vérifications :
- lancer
python texte/realtime_transcript_fusion.py --list-devices - vérifier l'index du micro
- vérifier les permissions micro macOS
Cause la plus fréquente :
- timeout d'analyse trop court pendant un appel Mistral
À vérifier :
FACT_CHECK_ANALYSIS_TIMEOUT_SECONDSMISTRAL_AGENT_CALL_TIMEOUT_SECONDS- ne pas relancer avec un
ANALYSIS_TIMEOUT_SECONDS=20hérité d'un ancien test
Cause probable :
- erreur côté
app-web
Commandes utiles :
docker compose logs --tail=100 app-web
docker compose logs --tail=100 app-reverbCause probable :
- verdict LLM incohérent
- résumé pas assez explicite
Le front applique maintenant une détection renforcée sur les faux chiffres, mais si besoin vérifier :
app/resources/js/lib/factCheck.tsoverall_verdictanalysis.summary
Cause probable :
- l'agent contexte ou l'éditeur final a répondu vide
Le pipeline contient désormais un fallback Context pour les événements identifiables :
- JO / Jeux olympiques
- grève
- guerre
- manifestation
- élection
- loi / décret / réforme
Vérifier :
app-webrépond bien sur8000app-reverbtourne- la page overlay est rechargée après un rebuild front
Commandes utiles :
docker compose ps
docker compose logs --tail=100 app-web app-reverb workflows-workerLe worker principal charge uniquement :
workflows/activities_emma.py
L'ancien module a été déplacé dans :
Trash/activities.py
Vérifier :
- que le workflow va jusqu'au bout
- que
archive_result.archivedvauttrue - que le dossier de session existe sous
reports/live_transcripts/
./scripts/run_stack.sh downou :
docker compose down