En este tutorial, creamos un agente de investigación tipo “navaja suiza” que va mucho más allá de simples interacciones de chat y resuelve activamente problemas de investigación de varios pasos de principio a fin. Combinamos una arquitectura de agentes que utiliza herramientas con búsqueda web en vivo, ingesta de PDF local, análisis de gráficos basado en visión y generación automatizada de informes para demostrar cómo los agentes modernos pueden razonar, verificar y producir resultados estructurados. Al conectar pequeños agentes, modelos OpenAI y utilidades prácticas de extracción de datos, mostramos cómo un solo agente puede explorar fuentes, verificar afirmaciones y sintetizar hallazgos en informes Markdown y DOCX de nivel profesional.
Configuramos el entorno de ejecución completo y cargamos de forma segura todas las credenciales requeridas sin secretos de codificación. Importamos todas las dependencias necesarias para la búsqueda web, el análisis de documentos, el análisis de visión y la orquestación de agentes. También inicializamos utilidades compartidas para estandarizar las marcas de tiempo y los nombres de archivos en todo el flujo de trabajo.
para el artículo en (data.get (“orgánico”) o [])[:k]: out.append({ “title”: item.get(“title”,””), “url”: item.get(“link”,””), “snippet”: item.get(“snippet”,””), }) return out = []
con DDGS() como ddgs: para r en ddgs.text(query, max_results=k): out.append({ “title”: r.get(“title”,””), “url”: r.get(“href”,””), “snippet”: r.get(“body”,””), }) devuelve def fetch_url_text(url: str) -> Dict[str, Any]: intente: descargado = trafilatura.fetch_url(url, timeout=30) si no está descargado: regrese {“url”: url, “ok”: False, “error”: “fetch_failed”, “text”: “”} texto = trafilatura.extract(descargado, include_comments=False, include_tables=True) si no texto: regrese {“url”: url, “ok”: False, “error”: “extract_failed”, “text”: “”} title_guess = next((ln.strip() para ln en text.splitlines() si ln.strip()), “”)[:120]
return {“url”: url, “ok”: Verdadero, “title_guess”: title_guess, “text”: texto} excepto Excepción como e: return {“url”: url, “ok”: Falso, “error”: str(e), “text”: “”}
Permitimos la ingesta local de PDF y establecemos un canal de búsqueda web flexible que funciona con o sin una API de búsqueda paga. Mostramos cómo manejamos con elegancia los insumos opcionales mientras mantenemos un flujo de investigación confiable. También implementamos una sólida recuperación de URL y extracción de texto para preparar material fuente limpio para el razonamiento posterior.
para i en el rango (páginas): intente: trozos.append(reader.pages[i].extract_text() o “”) excepto Excepción: chunks.append(“”) return {“pdf_path”: pdf_path, “pages_read”: páginas, “text”: “\n\n”.join(chunks).strip()} def extract_pdf_images(pdf_path: str, out_dir: str = “/content/extracted_images”, max_pages: int = 10) -> Lista[str]: os.makedirs(out_dir, exist_ok=True) doc = fitz.open(pdf_path) guardado = []
páginas = min(len(doc), max_pages) base = _safe_filename(os.path.basename(pdf_path).rsplit(“.”, 1)[0]) para p en rango (páginas): página = doc[p]
img_list = page.get_images(full=True) para img_i, img en enumerate(img_list): xref = img[0]
pix = fitz.Pixmap(doc, xref) if pix.n – pix.alpha >= 4: pix = fitz.Pixmap(fitz.csRGB, pix) img_path = os.path.join(out_dir, f”{base}_p{p+1}_img{img_i+1}.png”) pix.save(img_path) save.append(img_path) doc.close() devolver guardado def vision_analyze_image(image_path: str, pregunta: str, modelo: str = “gpt-4.1-mini”) -> Dict[str, Any]: con open(image_path, “rb”) como f: img_bytes = f.read() resp = client.responses.create( modelo=modelo, entrada=[{
“role”: “user”,
“content”: [
{“type”: “input_text”, “text”: f”Answer concisely and accurately.\n\nQuestion: {question}”},
{“type”: “input_image”, “image_data”: img_bytes},
]}], ) devuelve {“image_path”: image_path, “respuesta”: resp.output_text}
Nos centramos en la comprensión profunda de los documentos mediante la extracción de texto estructurado y artefactos visuales de archivos PDF. Integramos un modelo con capacidad de visión para interpretar gráficos y figuras en lugar de tratarlos como imágenes opacas. Nos aseguramos de que las tendencias numéricas y los conocimientos visuales se puedan convertir en evidencia explícita basada en texto.
devolver json.dumps(ordenado(rutas), asegurar_ascii=False) @tool def t_read_pdf_text(pdf_path: str, max_pages: int = 30) -> str: devolver json.dumps(read_pdf_text(pdf_path, max_pages=max_pages), asegurar_ascii=False) @tool def t_extract_pdf_images(pdf_path: str, max_pages: int = 10) -> str: imgs = extract_pdf_images(pdf_path, max_pages=max_pages) return json.dumps(imgs, asegurar_ascii=False) @tool def t_vision_analyze_image(image_path: str, question: str) -> str: return json.dumps(vision_analyze_image(image_path, question), asegurar_ascii=False) @tool def t_write_markdown(ruta: str, contenido: str) -> str: devolver write_markdown(ruta, contenido) @tool def t_write_docx_from_markdown(docx_path: str, md_path: str, título: str = “Informe de investigación”) -> str: con open(md_path, “r”, codificación=”utf-8″) as f: md = f.read() return write_docx_from_markdown(docx_path, md, título=título)
Implementamos la capa de salida completa generando informes Markdown y convirtiéndolos en documentos DOCX pulidos. Exponemos todas las capacidades centrales como herramientas explícitas sobre las que el agente puede razonar e invocar paso a paso. Nos aseguramos de que cada transformación desde los datos sin procesar hasta el informe final siga siendo determinista e inspeccionable.
t_web_search,
t_fetch_url_text,
t_list_pdfs,
t_read_pdf_text,
t_extract_pdf_images,
t_vision_analyze_image,
t_write_markdown,
t_write_docx_from_markdown,
]modelo=modelo, add_base_tools=Falso, importaciones_autorizadas_adicionales=[“json”,”re”,”os”,”math”,”datetime”,”time”,”textwrap”]) SYSTEM_INSTRUCTIONS = “”” Usted es un agente de investigación de la navaja suiza. “”” def run_research(topic: str): os.makedirs(“/content/report”, exist_ok=True) Prompt = f”””{SYSTEM_INSTRUCTIONS.strip()} Pregunta de investigación: {topic} Pasos: 1) Enumere los archivos PDF disponibles (si los hay) y decida cuáles son relevantes. 2) Realice una búsqueda en la web para el tema. 3) Busque y extraiga el texto de las mejores fuentes. 4) Si existen archivos PDF, extraiga texto e imágenes. 5) Analice visualmente las figuras. 6) Escriba un informe de Markdown y conviértalo a DOCX. salir = run_research(tema) imprimir(salir[:1500] si isinstance(out, str) else out) intente: desde google.colab importar archivos files.download(“/content/report/report.md”) files.download(“/content/report/report.docx”) excepto la excepción como e: print(“Descarga omitida:”, str(e))
Armamos el agente de investigación completo y definimos un plan de ejecución estructurado para un razonamiento de varios pasos. Guiamos al agente para que busque, analice, sintetice y escriba utilizando un único mensaje coherente. Demostramos cómo el agente produce un artefacto de investigación terminado que puede revisarse, compartirse y reutilizarse inmediatamente.
En conclusión, demostramos cómo un agente que utiliza herramientas bien diseñado puede funcionar como un asistente de investigación confiable en lugar de un juguete conversacional. Mostramos cómo las herramientas explícitas, las indicaciones disciplinadas y la ejecución paso a paso permiten al agente buscar en la web, analizar documentos e imágenes y generar informes rastreables y con reconocimiento de citas. Este enfoque ofrece un plan práctico para crear agentes de investigación confiables que enfaticen la evaluación, la evidencia y la conciencia de fallas, capacidades cada vez más esenciales para los sistemas de IA del mundo real.
Consulte los códigos completos aquí. Además, no dude en seguirnos en Twitter y no olvide unirse a nuestro SubReddit de más de 100.000 ML y suscribirse a nuestro boletín. ¡Esperar! estas en telegrama? Ahora también puedes unirte a nosotros en Telegram.