jdmagent / src /jdm_agent /factcheck /pipeline.py
expAge
feat(phase-11): moteur d'inférence + consolidation + soumission
5c1d1c7
"""Pipeline complet : texte → claims → verdicts → Report."""
from __future__ import annotations
from typing import Any, Iterable, List, Optional
from jdm_agent.client import JDMClient
from jdm_agent.factcheck.extractor import extract_claims
from jdm_agent.factcheck.models import Claim, Report
from jdm_agent.factcheck.verifier import verify_claim
def factcheck(
text: str,
*,
client: Optional[JDMClient] = None,
llm: Optional[Any] = None,
claims: Optional[Iterable[Claim]] = None,
effort: int = 1,
) -> Report:
"""Vérifie les claims (extraites ou fournies) d'un texte contre JDM.
Phase 9b : aucun seuil de filtrage exposé — JDM décide.
Phase 11 : `effort=1` par défaut — le fact-checking d'un texte cherche
d'abord si l'info est dans JDM, et si elle n'y est pas, l'infère.
Args:
text: le texte source (pour traçabilité dans le rapport).
client: JDMClient. Créé par défaut.
llm: LangChain ChatModel pour l'extraction. Inutile si `claims` est fourni.
claims: claims pré-extraites (skip extraction). Si None, on appelle `llm`.
effort: 0 = contenance pure ; 1 = + inférence noyau ; 2 = inférence complète.
Returns:
`Report` avec un Verdict par claim.
"""
if client is None:
client = JDMClient()
if claims is None:
if llm is None:
raise ValueError("Fournis soit `claims` (claims pré-extraites), soit `llm` (extraction LLM).")
claims = extract_claims(text, llm)
verdicts = [verify_claim(client, c, effort=effort) for c in claims]
return Report(text=text, verdicts=verdicts)
def factcheck_claims(
claims: Iterable[Claim],
*,
client: Optional[JDMClient] = None,
effort: int = 1,
) -> Report:
"""Variante directe sans extraction : tu fournis déjà les claims."""
if client is None:
client = JDMClient()
verdicts = [verify_claim(client, c, effort=effort) for c in claims]
return Report(text="", verdicts=verdicts)