Patrones de razonamiento entre modalidades
Fundamentación de afirmaciones textuales en imágenes y síntesis de contexto multimodal procedente de varias fuentes.
Patrones de razonamiento entre modalidades 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.
Razonamiento entre modalidades
El razonamiento entre modalidades ocurre cuando un agente debe reconciliar información de dos o más modalidades, como texto, imágenes, gráficos o tablas, que pueden coincidir, contradecirse o complementarse. Por ejemplo, el texto de un informe afirma que los ingresos crecieron un 20 %, pero el gráfico adjunto muestra una línea plana.
El agente debe decidir qué fuente es correcta o señalar la discrepancia para que la revise una persona.
Correspondencia entre texto e imagen
La correspondencia entre texto e imagen consiste en verificar que las afirmaciones del texto puedan confirmarse visualmente en una imagen complementaria. Por ejemplo: ¿la descripción del producto coincide con la foto del producto? ¿El documento menciona una tabla que realmente aparece en la imagen?
import anthropic
import base64
def ground_text_in_image(
text_claim: str,
image_path: str
) -> dict:
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
with open(image_path, 'rb') as f:
b64 = base64.standard_b64encode(f.read()).decode('utf-8')
prompt = (
f'Text claim: "{text_claim}"\n\n'
'Does the image above support, contradict, or partially support this claim?\n'
'Return JSON: {"verdict": "support|contradict|partial|insufficient_evidence", '
'"confidence": 0.0, "evidence": "..."}'
)
response = client.messages.create(
model='claude-opus-4-5', max_tokens=256,
messages=[{'role': 'user', 'content': [
{'type': 'image', 'source': {'type': 'base64',
'media_type': 'image/jpeg', 'data': b64}},
{'type': 'text', 'text': prompt}
]}]
)
import json
return json.loads(response.content[0].text)Detección de contradicciones entre gráficos y texto
Un caso frecuente en el mundo real es que la prosa de un informe financiero afirme una cosa, mientras que el gráfico incluido en el documento cuenta una historia diferente. El agente puede extraer visualmente los datos del gráfico y compararlos con las afirmaciones numéricas del texto.
def compare_chart_to_text(
chart_image_path: str,
text_with_claims: str
) -> dict:
import anthropic, base64, json
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
with open(chart_image_path, 'rb') as f:
b64 = base64.standard_b64encode(f.read()).decode('utf-8')
prompt = (
'The following text makes claims about data.\n'
f'TEXT: {text_with_claims}\n\n'
'Compare the chart image to the text claims. '
'List any contradictions and agreements. '
'Return JSON: {"agreements": [str], "contradictions": [str], '
'"verdict": "consistent|inconsistent|partial"}'
)
response = client.messages.create(
model='claude-opus-4-5', max_tokens=512,
messages=[{'role': 'user', 'content': [
{'type': 'image', 'source': {'type': 'base64',
'media_type': 'image/jpeg', 'data': b64}},
{'type': 'text', 'text': prompt}
]}]
)
return json.loads(response.content[0].text)Estrategias de combinación de señales
Cuando las señales de varias modalidades coinciden, aumente la confianza. Cuando discrepen, aplique una estrategia de resolución de conflictos: confíe en la fuente más estructurada (para los números, los gráficos tienen prioridad sobre la prosa), señale el caso para que lo revise una persona o pida al LLM que razone sobre cuál fuente es más fiable.
SIGNAL_SOURCES = {
'chart': 0.9, # high trust for quantitative data
'table': 0.85,
'photo': 0.8,
'prose': 0.6, # lower trust — may be imprecise or outdated
'caption': 0.7
}
def combine_signals(signals: list) -> dict:
"""
signals: list of {'source': str, 'claim': str, 'supports': bool}
Returns weighted verdict.
"""
support_weight = 0.0
total_weight = 0.0
for sig in signals:
w = SIGNAL_SOURCES.get(sig['source'], 0.5)
total_weight += w
if sig['supports']:
support_weight += w
confidence = support_weight / total_weight if total_weight > 0 else 0.0
return {
'confidence': round(confidence, 3),
'verdict': 'supported' if confidence >= 0.6 else 'contested',
'needs_review': 0.4 <= confidence < 0.6
}
if __name__ == '__main__':
signals = [
{'source': 'chart', 'claim': 'Revenue grew 20%', 'supports': True},
{'source': 'prose', 'claim': 'Revenue grew 20%', 'supports': False},
]
print(combine_signals(signals))
Pipeline de verificación de texto e imagen
Un pipeline de verificación de productos recibe la descripción de un producto y su foto, y comprueba que todos los atributos clave mencionados en el texto sean visibles en la imagen. Devuelve un informe estructurado de coincidencias y discrepancias.
def verify_product_description(
description: str,
product_image_path: str
) -> dict:
import anthropic, base64, json
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
with open(product_image_path, 'rb') as f:
b64 = base64.standard_b64encode(f.read()).decode('utf-8')
prompt = (
f'Product description:\n{description}\n\n'
'For each attribute mentioned in the description (color, shape, material, '
'size, features), check whether it is visible in the product photo.\n'
'Return JSON: {"verified": [{"attribute": str, "status": str}], '
'"unverified": [str], "overall_match": float}\n'
'status: confirmed / contradicted / not_visible\n'
'overall_match: 0.0-1.0'
)
response = client.messages.create(
model='claude-opus-4-5', max_tokens=512,
messages=[{'role': 'user', 'content': [
{'type': 'image', 'source': {'type': 'base64',
'media_type': 'image/jpeg', 'data': b64}},
{'type': 'text', 'text': prompt}
]}]
)
return json.loads(response.content[0].text)Contraste entre documento e imagen
Al analizar documentos escaneados, existen tanto el texto obtenido mediante OCR como la imagen subyacente. Contrástelos: ¿el texto extraído coincide con lo que aparece visualmente? Las discrepancias pueden indicar errores de OCR que deben corregirse.
def crossref_ocr_with_image(
ocr_text: str,
document_image_path: str
) -> dict:
import anthropic, base64, json
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
with open(document_image_path, 'rb') as f:
b64 = base64.standard_b64encode(f.read()).decode('utf-8')
prompt = (
f'The OCR system produced this text from the document image:\n\n'
f'{ocr_text}\n\n'
'Compare the OCR text to what you actually see in the image. '
'Identify any OCR errors, missed text, or hallucinated characters.\n'
'Return JSON: {"ocr_errors": [{"incorrect": str, "correct": str}], '
'"missed_sections": [str], "accuracy_estimate": float}'
)
response = client.messages.create(
model='claude-opus-4-5', max_tokens=512,
messages=[{'role': 'user', 'content': [
{'type': 'image', 'source': {'type': 'base64',
'media_type': 'image/jpeg', 'data': b64}},
{'type': 'text', 'text': prompt}
]}]
)
return json.loads(response.content[0].text)Agente de razonamiento con múltiples fuentes
Un agente de razonamiento con múltiples fuentes recopila sistemáticamente pruebas de cada modalidad, combina las señales y produce una conclusión final con una puntuación de confianza. Indica qué fuentes respaldan su conclusión y cuáles la contradicen.
def multi_source_reasoning(
claim: str,
evidence_sources: list # list of {'type': 'text'|'image', 'content': str|path}
) -> dict:
import anthropic, base64, json
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
content_blocks = [
{'type': 'text',
'text': f'Evaluate this claim using ALL sources below:\nClaim: "{claim}"\n'}
]
for i, src in enumerate(evidence_sources):
if src['type'] == 'text':
content_blocks.append(
{'type': 'text', 'text': f'Source {i+1} (text): {src["content"]}'}
)
elif src['type'] == 'image':
with open(src['content'], 'rb') as f:
b64 = base64.standard_b64encode(f.read()).decode('utf-8')
content_blocks.append(
{'type': 'text', 'text': f'Source {i+1} (image):'}
)
content_blocks.append(
{'type': 'image', 'source': {'type': 'base64',
'media_type': 'image/jpeg', 'data': b64}}
)
content_blocks.append({'type': 'text', 'text':
'Return JSON: {"verdict": str, "confidence": float, '
'"supporting_sources": [int], "contradicting_sources": [int]}'
})
response = client.messages.create(
model='claude-opus-4-5', max_tokens=512,
messages=[{'role': 'user', 'content': content_blocks}]
)
return json.loads(response.content[0].text)Generación de hechos a partir de imágenes
A veces se dispone de una imagen y es necesario generar hechos estructurados a partir de ella para utilizarlos posteriormente en razonamiento basado en texto. Extraiga como JSON los datos cuantitativos de gráficos y tablas para poder verificarlos matemáticamente frente a las afirmaciones del texto.
def extract_facts_from_chart(chart_path: str) -> dict:
import anthropic, base64, json
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
with open(chart_path, 'rb') as f:
b64 = base64.standard_b64encode(f.read()).decode('utf-8')
prompt = (
'Extract all quantitative data from this chart. '
'Return JSON with: chart_type, x_axis_label, y_axis_label, '
'and data_points as [{label: str, value: float}].\n'
'Also extract any trend: increasing/decreasing/stable/volatile.'
)
response = client.messages.create(
model='claude-opus-4-5', max_tokens=512,
messages=[{'role': 'user', 'content': [
{'type': 'image', 'source': {'type': 'base64',
'media_type': 'image/jpeg', 'data': b64}},
{'type': 'text', 'text': prompt}
]}]
)
return json.loads(response.content[0].text)Enrutamiento según umbrales de confianza
Después del razonamiento entre modalidades, dirija el resultado según su confianza: confianza alta → aprobación automática; confianza media → señalización para una revisión opcional; confianza baja → escalamiento a una persona. Nunca apruebe automáticamente señales contradictorias, independientemente de la puntuación de confianza.
def route_cross_modal_result(result: dict) -> str:
confidence = result.get('confidence', 0.0)
has_contradiction = bool(result.get('contradicting_sources'))
if has_contradiction:
return 'ESCALATE'
if confidence >= 0.85:
return 'AUTO_APPROVE'
if confidence >= 0.6:
return 'OPTIONAL_REVIEW'
return 'ESCALATE'
# Example routing table:
# confidence >= 0.85, no contradiction -> AUTO_APPROVE
# confidence 0.6-0.85, no contradiction -> OPTIONAL_REVIEW
# any contradiction, or confidence < 0.6 -> ESCALATE
def handle_routing(claim: str, evidence_sources: list):
result = multi_source_reasoning(claim, evidence_sources)
action = route_cross_modal_result(result)
print(f'Claim: "{claim}"')
print(f'Verdict: {result["verdict"]} (confidence={result["confidence"]:.2f})')
print(f'Action: {action}')
return action, resultGestión de evidencia visual insuficiente
A veces, una imagen tiene una resolución demasiado baja, está borrosa o está parcialmente obstruida para proporcionar pruebas útiles. El agente debe detectarlo y abstenerse de formular una conclusión entre modalidades en lugar de inventarla.
def assess_image_evidence_quality(
image_path: str,
claim: str
) -> dict:
import anthropic, base64, json
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
with open(image_path, 'rb') as f:
b64 = base64.standard_b64encode(f.read()).decode('utf-8')
prompt = (
f'Claim to verify: "{claim}"\n\n'
'Assess whether this image provides sufficient evidence to evaluate the claim.\n'
'Consider: image quality, relevance, completeness, and readability.\n'
'Return JSON: {"sufficient": bool, "quality_issues": [str], '
'"usable_evidence": str}'
)
response = client.messages.create(
model='claude-opus-4-5', max_tokens=256,
messages=[{'role': 'user', 'content': [
{'type': 'image', 'source': {'type': 'base64',
'media_type': 'image/jpeg', 'data': b64}},
{'type': 'text', 'text': prompt}
]}]
)
return json.loads(response.content[0].text)Creación de un verificador de hechos entre modalidades
Para integrar todos estos conceptos, cree un verificador de hechos de documentos que reciba un informe (texto e imágenes integradas) y compruebe cada afirmación cuantitativa del texto frente a los gráficos y las tablas que la respaldan. Devuelve un informe de verificación estructurado.
def fact_check_report(
report_text: str,
image_paths: list
) -> dict:
import re
# Extract numeric claims from text (simple regex pattern)
claim_pattern = r'[A-Z][^.!?]*[0-9][%$][^.!?]*[.!?]'
claims = re.findall(claim_pattern, report_text)
results = []
for claim in claims:
sources = [
{'type': 'text', 'content': report_text},
] + [{'type': 'image', 'content': p} for p in image_paths]
reasoning = multi_source_reasoning(claim, sources)
action = route_cross_modal_result(reasoning)
results.append({
'claim': claim,
'verdict': reasoning['verdict'],
'confidence': reasoning['confidence'],
'action': action
})
total = len(results)
auto_approved = sum(1 for r in results if r['action'] == 'AUTO_APPROVE')
return {
'total_claims': total,
'auto_approved': auto_approved,
'escalated': total - auto_approved,
'details': results
}Comprobación de conocimientos
Cuando las señales del texto y del gráfico se contradicen, ¿qué debe hacer el agente entre modalidades según las buenas prácticas?
Repaso: patrones de razonamiento entre modalidades
Ha completado esta lección. Estos son los puntos clave:
- Correspondencia entre texto e imagen: verifique las afirmaciones del texto frente a la evidencia visual
- Combinación de señales: confianza ponderada (para los números, los gráficos tienen prioridad sobre la prosa); las fuentes estructuradas prevalecen sobre las no estructuradas
- Detección de contradicciones: escale siempre el caso a una persona; nunca resuelva automáticamente las contradicciones
- Enrutamiento según la confianza: aprobación automática (alta) → revisión opcional (media) → escalamiento (baja o contradicción)
- Evidencia insuficiente: absténgase en lugar de inventar una conclusión entre modalidades
Siguiente curso: agentes basados en IoT y sensores: procesamiento de flujos de datos del mundo real con MQTT.
Preguntas frecuentes
¿La lección «Patrones de razonamiento entre modalidades» es gratis?
Sí — el texto completo de «Patrones de razonamiento entre modalidades» 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 «Patrones de razonamiento entre modalidades»?
Fundamentación de afirmaciones textuales en imágenes y síntesis de contexto multimodal procedente de varias fuentes. 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 «Patrones de razonamiento entre modalidades»?
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
- Agentes de imagen + texto con Claude Vision y GPT-4V
- Flujos de trabajo de agentes de audio + texto
- Comprensión de vídeo en agentes
- Patrones de razonamiento entre modalidades