Vérification des sources et citations
Comparer les affirmations entre plusieurs sources et associer les URL des sources aux faits.
Vérification des sources et citations est une leçon AI Agents gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage AI Agents, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours AI Agents comprend 4 leçons au total.
Pourquoi la vérification des sources est importante
Un agent peut récupérer une affirmation fausse depuis une source de mauvaise qualité et la présenter comme un fait. Sans vérification, l’agent de recherche n’est qu’un moteur de recherche sophistiqué dépourvu de filtre de qualité.
La vérification ajoute une couche qui contrôle si les affirmations sont corroborées par plusieurs sources indépendantes.
La règle des deux sources
Une affirmation est considérée comme vérifiée lorsqu’elle apparaît dans au moins deux sources indépendantes. « Indépendantes » signifie issues de domaines différents : trouver la même affirmation sur deux sites qui citent tous deux l’article original ne compte pas.
from urllib.parse import urlparse
def extract_domain(url: str) -> str:
return urlparse(url).netloc.replace('www.', '')
def is_verified(fact: str, all_facts: list[dict]) -> bool:
matching_domains = set()
for f in all_facts:
if fact.lower() in f['fact'].lower() or f['fact'].lower() in fact.lower():
matching_domains.add(extract_domain(f['source']))
return len(matching_domains) >= 2
# Example
facts = [
{'fact': 'Inflation peaked at 9.1% in June 2022', 'source': 'https://bls.gov/cpi'},
{'fact': 'US inflation hit 9.1% peak in mid-2022', 'source': 'https://reuters.com/article/a'}
]
print(is_verified('inflation peaked at 9.1%', facts)) # TrueAppariement sémantique fondé sur un LLM
La comparaison de chaînes de caractères ne détecte pas les affirmations paraphrasées. Utilisez un LLM pour déterminer si deux faits sont sémantiquement équivalents avant de les compter comme provenant de sources corroborantes.
import openai, json
client = openai.OpenAI(api_key='YOUR_OPENAI_KEY')
def claims_are_equivalent(claim_a: str, claim_b: str) -> bool:
prompt = (
f'Are these two statements making the same factual claim?\n'
f'A: "{claim_a}"\n'
f'B: "{claim_b}"\n'
f'Answer JSON: {{"equivalent": true/false}}'
)
resp = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': prompt}],
response_format={'type': 'json_object'}
)
return json.loads(resp.choices[0].message.content).get('equivalent', False)
print(claims_are_equivalent(
'CPI hit 9.1% in June 2022',
'US consumer prices rose 9.1 percent year-over-year in June 2022'
)) # TrueÉvaluation de la qualité des sources
Toutes les sources ne se valent pas. Évaluez chaque source selon le type de domaine, la date de publication et sa fiabilité connue. Les sources de niveau 1, comme les statistiques gouvernementales et les revues évaluées par des pairs, doivent avoir plus de poids que les blogs ou les réseaux sociaux.
from datetime import datetime, timezone
HIGH_AUTHORITY_DOMAINS = [
'gov', 'edu', 'nature.com', 'science.org', 'pubmed.ncbi.nlm.nih.gov',
'reuters.com', 'bbc.com', 'apnews.com', 'who.int'
]
def score_source(url: str, publication_date: str | None) -> float:
score = 0.5 # baseline
domain = extract_domain(url)
tld = domain.split('.')[-1]
# Domain authority
if any(ha in domain for ha in HIGH_AUTHORITY_DOMAINS):
score += 0.3
elif tld in ('gov', 'edu', 'org'):
score += 0.1
# Recency
if publication_date:
try:
pub = datetime.fromisoformat(publication_date)
days_old = (datetime.now(timezone.utc) - pub.replace(tzinfo=timezone.utc)).days
if days_old < 365:
score += 0.1
elif days_old > 1825: # 5 years
score -= 0.1
except ValueError:
pass
return min(1.0, max(0.0, score))Recoupement des affirmations avec les sources
Pour chaque affirmation que l’agent prévoit d’inclure dans le rapport final, recoupez-la avec tous les documents récupérés afin de trouver les meilleures sources corroborantes.
def cross_reference(claim: str, all_facts: list[dict]) -> list[dict]:
supporting = []
seen_domains = set()
for fact in all_facts:
if claims_are_equivalent(claim, fact['fact']):
domain = extract_domain(fact['source'])
if domain not in seen_domains: # only one per domain
seen_domains.add(domain)
supporting.append({
'source': fact['source'],
'domain': domain,
'fact': fact['fact'],
'score': score_source(fact['source'], fact.get('publication_date'))
})
return sorted(supporting, key=lambda x: x['score'], reverse=True)Vérification des qualifications des auteurs
Pour les affirmations scientifiques ou médicales, les qualifications des auteurs sont importantes. Une étude dont les auteurs sont nommés et rattachés à des établissements accrédités a plus de poids qu’un article de blog anonyme. Extrayez les informations sur les auteurs et signalez les affirmations provenant de sources anonymes.
def assess_authorship(url: str, page_text: str) -> dict:
prompt = (
f'From this webpage text, extract:\n'
f'1. Author name(s) (or null)\n'
f'2. Author affiliation/credentials (or null)\n'
f'3. Publication name (or null)\n'
f'Return JSON: {{"authors": [], "affiliation": null, "publication": null}}\n\n'
f'TEXT:\n{page_text[:2000]}'
)
resp = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': prompt}],
response_format={'type': 'json_object'}
)
return json.loads(resp.choices[0].message.content)Signalement des affirmations non vérifiées
Les affirmations qui ne peuvent pas être recoupées à partir de deux sources indépendantes doivent être signalées comme non vérifiées dans le résultat. Selon le niveau de risque du rapport, les affirmations non vérifiées peuvent être exclues ou présentées avec une clause de non-responsabilité.
def classify_claims(claims: list[str], all_facts: list[dict]) -> list[dict]:
classified = []
for claim in claims:
support = cross_reference(claim, all_facts)
classified.append({
'claim': claim,
'verified': len(support) >= 2,
'sources': support[:3], # top 3 supporting sources
'confidence': 'high' if len(support) >= 3 else
'medium' if len(support) == 2 else
'low'
})
return classifiedFormat des citations : intégrées et bibliographiques
Les rapports doivent inclure des citations intégrées, sous forme d’exposants numérotés, ainsi qu’une liste de références à la fin. Générez les deux à partir des métadonnées des sources vérifiées.
def format_citations(classified_claims: list[dict]) -> tuple[list[str], list[str]]:
ref_list = []
ref_map = {} # url -> citation number
inline_claims = []
for item in classified_claims:
nums = []
for src in item['sources']:
url = src['source']
if url not in ref_map:
ref_map[url] = len(ref_list) + 1
ref_list.append(f'[{ref_map[url]}] {url}')
nums.append(f'[{ref_map[url]}]')
citation_str = ''.join(nums)
prefix = '' if item['verified'] else '[UNVERIFIED] '
inline_claims.append(f'{prefix}{item["claim"]} {citation_str}')
return inline_claims, ref_list
if __name__ == '__main__':
demo_claims = [
{'claim': 'Revenue grew 12% year over year', 'verified': True, 'sources': [{'source': 'https://example.com/report'}]},
{'claim': 'The CEO plans to step down', 'verified': False, 'sources': [{'source': 'https://example.com/rumor'}]},
]
inline, refs = format_citations(demo_claims)
for line in inline:
print(line)
print('References:')
for r in refs:
print(' ', r)
Détection des contradictions entre les sources
Il arrive que deux sources fiables se contredisent. Détectez les contradictions et présentez les deux points de vue au lieu d’en choisir un en silence. Cela est particulièrement important pour les affirmations empiriques contestées.
def find_contradictions(claim: str, all_facts: list[dict]) -> list[dict]:
contradictions = []
for fact in all_facts:
if extract_domain(fact['source']) == extract_domain(claim):
continue
prompt = (
f'Does fact B contradict fact A?\n'
f'A: "{claim}"\nB: "{fact["fact"]}"\n'
f'JSON: {{"contradicts": true/false}}'
)
resp = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': prompt}],
response_format={'type': 'json_object'}
)
result = json.loads(resp.choices[0].message.content)
if result.get('contradicts'):
contradictions.append(fact)
return contradictionsFiche de vérification
Avant de générer le rapport final, produisez un résumé de la vérification : nombre d’affirmations vérifiées, nombre d’affirmations non vérifiées, principales sources selon leur score d’autorité et éventuelles contradictions détectées.
def verification_report_card(classified: list[dict]) -> dict:
total = len(classified)
verified = sum(1 for c in classified if c['verified'])
all_sources = [
src for c in classified for src in c['sources']
]
top_domains = sorted(
set(s['domain'] for s in all_sources),
key=lambda d: max(s['score'] for s in all_sources if s['domain'] == d),
reverse=True
)[:5]
return {
'total_claims': total,
'verified': verified,
'unverified': total - verified,
'verification_rate': f'{verified/max(total,1)*100:.0f}%',
'top_sources': top_domains
}
if __name__ == '__main__':
demo_classified = [
{'verified': True, 'sources': [{'domain': 'docs.python.org', 'score': 1.3}]},
{'verified': False, 'sources': [{'domain': 'quora.com', 'score': 0.5}]},
]
card = verification_report_card(demo_classified)
for k, v in card.items():
print(f'{k}: {v}')
Sortie conditionnée par le niveau de confiance
Définissez un seuil minimal de vérification avant la publication. Si moins de 70 % des affirmations sont vérifiées, demandez à la boucle de recherche d’effectuer une itération supplémentaire ciblant précisément les affirmations non vérifiées.
MIN_VERIFICATION_RATE = 0.70
def should_run_more_research(classified: list[dict]) -> list[str]:
unverified = [c for c in classified if not c['verified']]
total = len(classified)
if total == 0:
return []
rate = (total - len(unverified)) / total
if rate >= MIN_VERIFICATION_RATE:
return [] # Sufficient confidence — stop
# Return search queries to verify remaining claims
return [f'verify: {c["claim"]}' for c in unverified[:3]]
if __name__ == '__main__':
demo_classified = [
{'claim': 'A', 'verified': True},
{'claim': 'B', 'verified': False},
{'claim': 'C', 'verified': False},
]
followups = should_run_more_research(demo_classified)
print('Follow-up queries needed:', followups)
Qu’est-ce qui définit deux sources « indépendantes » selon la règle de vérification des deux sources ?
Le critère d’indépendance empêche une vérification en vase clos, dans laquelle la même affirmation remonte à une seule source originale citée par de nombreux médias.
Récapitulatif de la vérification des sources
Une recherche vérifiée exige : une corroboration par deux sources issues de domaines différents, un appariement sémantique par LLM pour détecter les équivalents paraphrasés, une évaluation de la qualité des sources (autorité du domaine et actualité), la détection des contradictions et une sortie conditionnée par le niveau de confiance qui déclenche des recherches supplémentaires si le taux de vérification est trop faible.
Questions Fréquemment Posées
La leçon « Vérification des sources et citations » est-elle gratuite ?
Oui — le texte complet de « Vérification des sources et citations » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours AI Agents, passe à CoddyKit PRO. Le cours AI Agents comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Vérification des sources et citations » ?
Comparer les affirmations entre plusieurs sources et associer les URL des sources aux faits. Tu pratiques AI Agents avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer AI Agents ?
Aucune expérience préalable n'est requise. AI Agents sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.
Combien de temps prend la leçon « Vérification des sources et citations » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon AI Agents ?
Oui. Chaque leçon AI Agents inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Conception d’une boucle de recherche en plusieurs étapes
- Vérification des sources et citations
- Génération de rapports structurés
- Vérification des faits et prévention des hallucinations