Verifica delle fonti e citazioni
Confronto incrociato delle affermazioni tra le fonti e associazione degli URL delle fonti ai fatti.
Verifica delle fonti e citazioni è una lezione AI Agents gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Agents, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Agents include 4 lezioni in totale.
Perché la verifica delle fonti è importante
Un agente può recuperare un'affermazione falsa da una fonte di bassa qualità e presentarla come un fatto. Senza verifica, l'agente di ricerca è soltanto un motore di ricerca sofisticato privo di un filtro di qualità.
La verifica aggiunge un livello che controlla se le affermazioni sono confermate da più fonti indipendenti.
La regola delle due fonti
Un'affermazione è considerata verificata quando compare in almeno due fonti indipendenti. Per «indipendenti» si intendono domini diversi: trovare la stessa affermazione su due siti che citano entrambi l'articolo originale non è sufficiente.
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)) # TrueCorrispondenza semantica basata su LLM
Il confronto tra stringhe non rileva le affermazioni parafrasate. Utilizzi un LLM per valutare se due fatti sono semanticamente equivalenti prima di considerarli come conferme provenienti da fonti diverse.
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'
)) # TrueValutazione della qualità delle fonti
Non tutte le fonti hanno lo stesso valore. Valuti ogni fonte in base al tipo di dominio, alla data di pubblicazione e all'affidabilità nota. Le fonti di livello 1, come le statistiche governative e le riviste sottoposte a revisione paritaria, dovrebbero avere un peso maggiore rispetto ai blog o ai social media.
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))Verifica incrociata delle affermazioni con le fonti
Per ogni affermazione che l'agente intende includere nel report finale, esegua una verifica incrociata con tutti i documenti recuperati per trovare le fonti di conferma migliori.
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)Verifica delle qualifiche dell'autore
Per le affermazioni scientifiche o mediche, le qualifiche dell'autore sono importanti. Uno studio con autori identificati affiliati a istituzioni accreditate ha più valore di un post anonimo su un blog. Estragga le informazioni sugli autori e segnali le affermazioni provenienti da fonti anonime.
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)Segnalazione delle affermazioni non verificate
Le affermazioni che non possono essere verificate tramite due fonti indipendenti devono essere contrassegnate come non verificate nell'output. A seconda del livello di rischio del report, le affermazioni non verificate possono essere escluse oppure presentate con una clausola di esclusione di 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 classifiedFormato delle citazioni: nel testo ed elenco delle fonti
I report dovrebbero includere citazioni nel testo, sotto forma di apici numerati, e un elenco delle fonti alla fine. Generi entrambi a partire dai metadati delle fonti verificate.
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)
Rilevamento delle contraddizioni tra le fonti
A volte due fonti affidabili si contraddicono. Rilevi le contraddizioni e presenti entrambi i punti di vista invece di sceglierne uno in modo arbitrario e senza segnalarlo. Questo è particolarmente importante per le affermazioni empiriche controverse.
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 contradictionsScheda riepilogativa della verifica
Prima di generare il report finale, produca un riepilogo della verifica: il numero di affermazioni verificate e non verificate, le principali fonti in base al punteggio di autorevolezza e le eventuali contraddizioni rilevate.
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}')
Output soggetto a una soglia di affidabilità
Imposti una soglia minima di verifica prima della pubblicazione. Se meno del 70% delle affermazioni è verificato, chieda al ciclo di ricerca di eseguire un'altra iterazione mirata specificamente alle affermazioni non verificate.
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)
Che cosa definisce due fonti «indipendenti» secondo la regola di verifica delle due fonti?
Il criterio di indipendenza impedisce una verifica basata su un'eco mediatica, in cui la stessa affermazione viene ricondotta a un'unica fonte originale citata da numerose testate.
Riepilogo della verifica delle fonti
Una ricerca verificata richiede: conferme da due fonti appartenenti a domini diversi, corrispondenza semantica basata su LLM per rilevare equivalenze parafrasate, valutazione della qualità delle fonti (autorevolezza del dominio e aggiornamento), rilevamento delle contraddizioni e un output soggetto a una soglia di affidabilità che avvii ulteriori ricerche se il tasso di verifica è troppo basso.
Domande Frequenti
La lezione «Verifica delle fonti e citazioni» è gratuita?
Sì — il testo completo di «Verifica delle fonti e citazioni» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Agents, passa a CoddyKit PRO. Il corso AI Agents include 4 lezioni in totale.
Cosa imparerò in «Verifica delle fonti e citazioni»?
Confronto incrociato delle affermazioni tra le fonti e associazione degli URL delle fonti ai fatti. Eserciti AI Agents con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare AI Agents?
Non è richiesta alcuna esperienza precedente. AI Agents su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.
Quanto tempo richiede la lezione «Verifica delle fonti e citazioni»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione AI Agents?
Sì. Ogni lezione AI Agents include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Progettazione di cicli di ricerca multi-passaggio
- Verifica delle fonti e citazioni
- Generazione di report strutturati
- Verifica dei fatti e prevenzione delle allucinazioni