Comprobación de datos y prevención de alucinaciones
Verificación fundamentada: cada afirmación debe poder rastrearse hasta una fuente recuperada.
Comprobación de datos y prevención de alucinaciones es una lección gratuita de AI Agents en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Agents, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Agents incluye 4 lecciones en total.
El problema de las alucinaciones en los agentes de investigación
Los LLM pueden generar afirmaciones plausibles que no tienen fundamento en las fuentes recuperadas. En un agente de investigación, esto es especialmente peligroso porque el resultado parece autorizado y se presenta con citas que quizá no respalden realmente la afirmación.
La prevención de alucinaciones debe ser una preocupación prioritaria.
Fundamentación: toda afirmación se remonta a una fuente
El principio fundamental de la fundamentación es que toda afirmación factual de la salida final debe poder rastrearse hasta al menos un documento recuperado. Las afirmaciones que no pueden rastrearse son alucinaciones o no están respaldadas; ambas situaciones son inaceptables en un informe de investigación.
def check_grounding(claim: str, retrieved_docs: list[dict]) -> dict:
doc_texts = '\n\n'.join(
f'[DOC {i+1}] ({d["url"]})\n{d["text"][:800]}'
for i, d in enumerate(retrieved_docs[:5])
)
return {
'claim': claim,
'docs': doc_texts,
'grounded': None # to be filled by LLM verifier
}
if __name__ == '__main__':
docs = [{'url': 'https://example.com/geo', 'text': 'Paris is the capital of France.'}]
result = check_grounding('Paris is the capital of France.', docs)
print('Claim:', result['claim'])
print('Supporting docs used:')
print(result['docs'])
Patrón LLM como verificador
Utilice una llamada independiente al LLM —el «verificador»— para determinar si una afirmación está respaldada por las fuentes proporcionadas. Esto crea un mecanismo de control y equilibrio en el que el generador y el verificador son llamadas independientes.
import openai, json
client = openai.OpenAI(api_key='YOUR_OPENAI_KEY')
def verify_claim(claim: str, source_texts: list[str]) -> dict:
sources_block = '\n---\n'.join(source_texts[:3])
prompt = (
f'Is the following claim directly supported by the provided sources?\n'
f'Claim: "{claim}"\n\n'
f'Sources:\n{sources_block}\n\n'
f'Return JSON: {{\n'
f' "supported": true/false,\n'
f' "confidence": 0.0-1.0,\n'
f' "reason": "one sentence explanation"\n'
f'}}'
)
resp = client.chat.completions.create(
model='gpt-4o',
messages=[{'role': 'user', 'content': prompt}],
response_format={'type': 'json_object'}
)
return json.loads(resp.choices[0].message.content)Salida condicionada por la confianza
Establezca umbrales para la puntuación de confianza del verificador. Las afirmaciones superiores a 0.85 se publican. Las que se encuentran entre 0.5 y 0.85 se publican con un aviso de advertencia. Las inferiores a 0.5 se excluyen.
INCLUDE_THRESHOLD = 0.85
DISCLAIMER_THRESHOLD = 0.50
def gate_claim(claim: str, source_texts: list[str]) -> dict:
result = verify_claim(claim, source_texts)
conf = result.get('confidence', 0.0)
supported = result.get('supported', False)
if not supported or conf < DISCLAIMER_THRESHOLD:
return {'action': 'exclude', 'claim': claim, 'reason': result.get('reason')}
elif conf < INCLUDE_THRESHOLD:
return {
'action': 'include_with_disclaimer',
'claim': f'[LOW CONFIDENCE] {claim}',
'reason': result.get('reason')
}
else:
return {'action': 'include', 'claim': claim}Detección de patrones específicos de alucinación
Ciertos patrones de afirmaciones presentan un alto riesgo de alucinación: estadísticas exactas (porcentajes, cantidades monetarias), fechas específicas, personas identificadas por su nombre y relaciones causales. Aplíqueles un escrutinio adicional.
import re
def is_high_risk_claim(claim: str) -> bool:
patterns = [
r'\d+\.?\d*\s*%', # percentages: 9.1%
r'\$\s*\d+', # dollar amounts
r'\b(January|February|March|April|May|June|July|August|September|October|November|December)\s+\d{4}', # dates
r'\b[A-Z][a-z]+\s+[A-Z][a-z]+\s+(said|stated|argued|claimed)', # named quotes
r'(caused?|led to|resulted in)', # causal claims
]
return any(re.search(p, claim) for p in patterns)
print(is_high_risk_claim('Inflation hit 9.1% in June 2022')) # True
print(is_high_risk_claim('Inflation was elevated')) # FalseBucle de verificación descompuesto
En el caso de secciones extensas, descomponga el texto en afirmaciones individuales, verifique cada afirmación de forma independiente y, después, reconstruya la sección utilizando únicamente las afirmaciones verificadas.
def decompose_into_claims(section_text: str) -> list[str]:
prompt = (
f'Break this text into individual verifiable factual claims.\n'
f'Each claim should be a single sentence containing exactly one fact.\n'
f'Return JSON: {{"claims": ["..."]}}\n\n'
f'TEXT:\n{section_text}'
)
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('claims', [])Reconstrucción de texto verificado
Después de filtrar cada afirmación, reconstruya una sección clara y coherente utilizando únicamente las afirmaciones verificadas. Excluya las que tengan baja confianza y reescriba el texto para mejorar su legibilidad.
def reconstruct_section(verified_claims: list[str],
section_name: str) -> str:
claims_text = '\n'.join(f'- {c}' for c in verified_claims)
prompt = (
f'Rewrite these verified facts as a coherent {section_name} section.\n'
f'Do NOT add any new information not present in the claims.\n'
f'Only use the facts provided.\n\n'
f'VERIFIED CLAIMS:\n{claims_text}'
)
resp = client.chat.completions.create(
model='gpt-4o',
messages=[{'role': 'user', 'content': prompt}]
)
return resp.choices[0].message.contentDetección de desviaciones numéricas
En ocasiones, los LLM alteran sutilmente los números de la fuente (por ejemplo, 9.1% se convierte en 9.2%). Extraiga los números tanto de la afirmación como del texto fuente y compárelos explícitamente.
import re
def extract_numbers(text: str) -> list[float]:
matches = re.findall(r'[-+]?\d*\.?\d+', text)
return [float(m) for m in matches]
def check_numeric_drift(claim: str, source_text: str,
tolerance: float = 0.01) -> bool:
claim_nums = extract_numbers(claim)
source_nums = extract_numbers(source_text)
for cn in claim_nums:
found_match = any(abs(cn - sn) <= tolerance for sn in source_nums)
if not found_match:
return True # numeric drift detected
return False
print(check_numeric_drift(
'Inflation reached 9.2% in June 2022',
'The CPI rose 9.1 percent in June 2022'
)) # True — 9.2 vs 9.1Auditoría de atribución
Después de generar un informe completo, realice una auditoría de atribución: para cada oración del informe, confirme que puede atribuirse a una de las fuentes. Marque toda oración que no tenga ningún fragmento de fuente coincidente.
def attribution_audit(report_text: str, sources: list[dict]) -> list[str]:
sentences = [s.strip() for s in report_text.split('.') if len(s.strip()) > 20]
unattributed = []
for sentence in sentences:
found = False
for src in sources:
if any(word in src.get('text', '') for word in sentence.split()[:5]):
found = True
break
if not found:
unattributed.append(sentence)
return unattributed
# Flag unattributed sentences for manual review or re-verification
if __name__ == '__main__':
report = ("Water boils at 100 degrees Celsius at sea level. "
"The moon is made primarily of green cheese according to this document.")
sources = [{'text': 'Water boils at 100C (212F) at standard atmospheric pressure.'}]
unattributed = attribution_audit(report, sources)
print('Unattributed sentences (need manual review):')
for s in unattributed:
print(' -', s)
Uso de lenguaje cauteloso para afirmaciones inciertas
No todo puede verificarse con un alto nivel de confianza. En lugar de excluir por completo las afirmaciones dudosas, utilice un lenguaje cauteloso: «Algunos analistas sugieren...», «Según X...» o «Se ha informado que...». Esto conserva la información y, al mismo tiempo, comunica la incertidumbre.
def hedge_claim(claim: str, confidence: float) -> str:
if confidence >= 0.85:
return claim # state as fact
elif confidence >= 0.65:
hedges = ['Some sources suggest', 'According to available evidence',
'Analysts have noted']
return f'{hedges[hash(claim) % len(hedges)]}, {claim.lower()}'
else:
return f'It has been reported (with low confidence) that {claim.lower()}'
print(hedge_claim('Inflation peaked at 9.1%', 0.90))
print(hedge_claim('Supply chain disruptions contributed to inflation', 0.72))
print(hedge_claim('Specific policy caused inflation', 0.45))Supervisión de la tasa de alucinaciones
Realice un seguimiento de la tasa de alucinaciones a lo largo del tiempo: ¿qué porcentaje de las afirmaciones generadas no supera la verificación? Establezca un umbral de alerta. Si la tasa aumenta bruscamente, la ingeniería de prompts o la calidad de la recuperación se han deteriorado.
verification_log = [] # In production: a database
def log_verification(claim: str, supported: bool, confidence: float):
verification_log.append({
'claim': claim[:100],
'supported': supported,
'confidence': confidence
})
def hallucination_rate() -> float:
if not verification_log:
return 0.0
failed = sum(1 for v in verification_log if not v['supported'])
return failed / len(verification_log)
def check_hallucination_alert(threshold: float = 0.15):
rate = hallucination_rate()
if rate > threshold:
print(f'ALERT: Hallucination rate {rate:.1%} exceeds threshold {threshold:.1%}')
return rate
if __name__ == '__main__':
log_verification('The sky is blue', True, 0.95)
log_verification('The moon is made of cheese', False, 0.2)
log_verification('Water boils at 100C at sea level', True, 0.99)
rate = check_hallucination_alert(threshold=0.15)
print(f'Hallucination rate so far: {rate:.1%}')
¿Cuál es el propósito principal del patrón «LLM como verificador»?
El LLM como verificador es un patrón arquitectónico clave para prevenir alucinaciones. Es fundamental comprender qué comprueba y por qué se realiza mediante una llamada independiente.
Resumen de la prevención de alucinaciones
Prevenga las alucinaciones mediante: comprobaciones de fundamentación (cada afirmación se remonta a una fuente), LLM como verificador (una llamada independiente determina si existe respaldo), filtrado por confianza (excluir las afirmaciones por debajo del umbral), detección de desviaciones numéricas, lenguaje cauteloso para los casos dudosos y supervisión de la tasa de alucinaciones para detectar regresiones.
Aprende AI Agents con un tutor de IA — gratis
Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.
- Cursos
- 60
- Lecciones
- 239
Preguntas frecuentes
¿La lección «Comprobación de datos y prevención de alucinaciones» es gratis?
Sí — el texto completo de «Comprobación de datos y prevención de alucinaciones» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Agents, actualiza a CoddyKit PRO. El curso de AI Agents incluye 4 lecciones en total.
¿Qué aprenderé en «Comprobación de datos y prevención de alucinaciones»?
Verificación fundamentada: cada afirmación debe poder rastrearse hasta una fuente recuperada. Practicas AI Agents con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar AI Agents?
No se requiere experiencia previa. AI Agents en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.
¿Cuánto tiempo toma la lección «Comprobación de datos y prevención de alucinaciones»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de AI Agents?
Sí. Cada lección de AI Agents incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Diseño de bucles de investigación en varios pasos
- Verificación de fuentes y citas
- Generación de informes estructurados
- Comprobación de datos y prevención de alucinaciones