Add Légifrance API integration for live legal text injection
Implements a two-layer approach to ensure legal texts are accurate and current: Option A — runtime injection (legifrance_client.py): - LegifranceClient: OAuth2 via PISTE (oauth.piste.gouv.fr), fetches consolidated article text via api.piste.gouv.fr/dila/legifrance/lf-engine-app - Redis cache with 24h TTL (in-memory fallback if no Redis) - build_filter_prompt() injects live texts into the prompt with explicit priority over static descriptions — model uses official Légifrance text, not training memory - Graceful fallback to static prompt if API is unavailable — filtering never blocks Option B — weekly sync script (scripts/check_legal_refs.py): - Reads legal_refs.yaml (11 tracked articles, priority critical/high/medium) - Fetches current text from Légifrance, diffs against stored baseline - --init: resolves LEGIARTI IDs on first run - --check: report only; --update: saves new texts to YAML - Exit code 2 when changes detected (CI/n8n-compatible) Supporting changes: - legal_refs.yaml: tracked articles with code LEGITEXT IDs, priorities, rationale - requirements.txt: add pyyaml>=6.0.2 and requests>=2.32.0 - .env.example: document PISTE_CLIENT_ID, PISTE_CLIENT_SECRET, LEGIFRANCE_CACHE_TTL - transparence.tsx: document the Légifrance injection for public transparency - Fixed portal URL: piste.gouv.fr (not piste.api.gouv.fr — verified June 2026) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,7 +19,57 @@ Sources françaises :
|
||||
- Code pénal français (partie législative et réglementaire)
|
||||
- Loi sur la liberté de la presse du 29 juillet 1881
|
||||
- Code civil français
|
||||
|
||||
Injection dynamique :
|
||||
- Les textes consolidés des articles critiques sont récupérés en temps réel
|
||||
depuis l'API Légifrance (PISTE) et injectés dans le prompt via build_filter_prompt().
|
||||
- Le suivi des changements est assuré par scripts/check_legal_refs.py.
|
||||
- Fichier de configuration : legal_refs.yaml (articles surveillés, LEGIARTI IDs).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from datetime import date
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_CRITERIA_ANCHOR = (
|
||||
"═══════════════════════════════════════════════════════════════════════════════\n"
|
||||
"CRITÈRES D'ACCEPTATION"
|
||||
)
|
||||
|
||||
|
||||
def build_filter_prompt(live_texts: dict[str, str] | None = None) -> str:
|
||||
"""
|
||||
Construit le prompt de filtrage en injectant les textes légaux consolidés
|
||||
récupérés depuis Légifrance.
|
||||
|
||||
live_texts : {ref_article: texte_en_vigueur} issu de LegifranceClient.
|
||||
Si vide ou None, retourne LEGAL_FILTER_PROMPT statique.
|
||||
|
||||
Les textes injectés ont PRIORITÉ ABSOLUE sur les descriptions statiques
|
||||
du cadre légal. Ils sont placés juste avant les critères d'acceptation.
|
||||
"""
|
||||
if not live_texts:
|
||||
return LEGAL_FILTER_PROMPT
|
||||
|
||||
today = date.today().isoformat()
|
||||
block = (
|
||||
"═══════════════════════════════════════════════════════════════════════════════\n"
|
||||
f"TEXTES LÉGAUX EN VIGUEUR — SOURCE LÉGIFRANCE ({today})\n"
|
||||
"═══════════════════════════════════════════════════════════════════════════════\n\n"
|
||||
"Ces extraits sont récupérés depuis l'API officielle Légifrance (PISTE).\n"
|
||||
"Ils ont PRIORITÉ ABSOLUE sur les descriptions du cadre ci-dessus.\n\n"
|
||||
)
|
||||
for ref, text in live_texts.items():
|
||||
block += f"[{ref}] — texte consolidé en vigueur :\n{text}\n\n"
|
||||
|
||||
if _CRITERIA_ANCHOR in LEGAL_FILTER_PROMPT:
|
||||
parts = LEGAL_FILTER_PROMPT.split(_CRITERIA_ANCHOR, 1)
|
||||
return parts[0] + block + _CRITERIA_ANCHOR + parts[1]
|
||||
|
||||
logger.warning("build_filter_prompt: ancre CRITÈRES D'ACCEPTATION introuvable — fallback statique")
|
||||
return LEGAL_FILTER_PROMPT
|
||||
|
||||
LEGAL_FILTER_PROMPT = """
|
||||
Tu es un agent de filtrage éthique pour une plateforme démocratique citoyenne.
|
||||
|
||||
Reference in New Issue
Block a user