Published

- 6 min read

Buscador de noticias inteligente con LangChain y Pydantic

img of Buscador de noticias inteligente con LangChain y Pydantic

En el post anterior exploramos cómo crear un buscador de noticias simple usando librerías estándar de Python. Hoy implementaremos una versión avanzada que utiliza LangChain para crear agentes inteligentes y Pydantic para validación de datos robusta.

Esta implementación está diseñada para entornos de producción donde necesitamos procesamiento inteligente, validación automática de datos y capacidad de razonamiento.

¿Qué diferencia este enfoque del anterior?

Versión anterior (75 líneas - Librería estándar)

  • Ultra simple: Solo urllib y json
  • Inmediata: Sin instalaciones complejas
  • Rápida: Resultados directos
  • Limitada: Sin inteligencia artificial
  • Básica: Sin validación de datos

Esta versión (LangChain + Pydantic - Avanzada)

  • Inteligente: Agentes que razonan antes de actuar
  • Robusta: Validación automática de datos con Pydantic
  • Escalable: Base para sistemas más complejos
  • Mantenible: Arquitectura modular y extensible
  • Más compleja: Requiere dependencias adicionales

Arquitectura del agente inteligente

Nuestro buscador utiliza el patrón ReAct (Reasoning + Acting) de LangChain:

  1. Thought: El agente analiza qué necesita hacer
  2. Action: Selecciona la herramienta adecuada
  3. Observation: Procesa el resultado obtenido
  4. Final Answer: Estructura la respuesta usando Pydantic

Esta arquitectura permite que el sistema tome decisiones inteligentes sobre qué herramientas usar y cómo procesar la información.

Componentes principales

1. Modelos Pydantic para validación

   class Noticia(BaseModel):
    titulo: str = Field(description="Título de la noticia")
    contenido: str = Field(description="Contenido de la noticia")
    url: str = Field(description="URL de la fuente")

class ResultadoBusqueda(BaseModel):
    tema: str = Field(description="Tema buscado")
    fecha: str = Field(description="Fecha de búsqueda")
    noticias: List[Noticia] = Field(description="Lista de noticias")
    analisis: str = Field(description="Análisis del agente")
    total: int = Field(description="Total de noticias")

Ventajas de Pydantic:

  • Validación automática: Datos siempre correctos
  • Serialización JSON: Conversión automática
  • Documentación integrada: Descriptions como documentación
  • Type hints: Mejor desarrollo con IDEs

2. Configuración de dependencias

   try:
    from pydantic import BaseModel, Field
    from langchain_openai import OpenAI
    from langchain.agents import Tool, initialize_agent, AgentType
    from langchain_community.utilities import GoogleSerperAPIWrapper
except ImportError as e:
    print(f"❌ Dependencias requeridas: {e}")
    exit(1)

Esta implementación requiere todas las dependencias instaladas para funcionar correctamente.

3. Agente LangChain con herramientas

   def _inicializar_agente_real(self):
    """Inicializar agente LangChain real"""
    self.llm = OpenAI(temperature=0, openai_api_key="tu-clave-aqui")

    tools = [
        Tool(
            name="BuscarNoticias",
            func=self._buscar_noticias_real,
            description="Busca noticias actuales sobre cualquier tema"
        ),
        Tool(
            name="FechaActual",
            func=lambda _: f"Hoy es {datetime.now().strftime('%d/%m/%Y')}",
            description="Obtiene la fecha actual"
        )
    ]

    self.agent = initialize_agent(
        tools=tools,
        llm=self.llm,
        agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
        verbose=True  # Para ver el razonamiento
    )

El poder del agente inteligente

Proceso de razonamiento visible

Cuando el agente funciona con LangChain real, puedes ver su proceso mental:

   Thought: Necesito buscar noticias actuales sobre inteligencia artificial
Action: BuscarNoticias
Action Input: inteligencia artificial
Observation: Encontré 5 noticias relevantes sobre IA...
Thought: He encontrado información relevante, procederé a estructurarla
Final Answer: [Resultado estructurado con Pydantic]

Configuración del LLM

   def configurar_entorno():
    """Configurar variables de entorno necesarias"""
    os.environ.setdefault("OPENAI_API_KEY", "tu-clave-openai")
    os.environ.setdefault("SERPER_API_KEY", "tu-clave-serper")

class BuscadorInteligente:
    def __init__(self):
        configurar_entorno()
        self.llm = OpenAI(temperature=0)
        self.agent = self._crear_agente()

Implementación de herramientas para el agente

Herramienta de búsqueda de noticias

   def buscar_noticias(query: str) -> str:
    """Función que busca noticias usando Serper API"""
    try:
        search = GoogleSerperAPIWrapper()
        results = search.results(query)

        if not results.get("organic"):
            return "No se encontraron noticias."

        output = f"Resultados para '{query}':\n\n"
        for i, item in enumerate(results["organic"][:3], 1):
            output += f"{i}. {item.get('title', 'Sin título')}\n"
            output += f"   Resumen: {item.get('snippet', 'Sin resumen')}\n"
            output += f"   URL: {item.get('link', 'Sin URL')}\n\n"

        return output
    except Exception as e:
        return f"Error buscando noticias: {str(e)}"

Configuración del agente

   def _crear_agente(self):
    tools = [
        Tool(
            name="BuscarNoticias",
            func=buscar_noticias,
            description="Busca noticias actuales sobre un tema específico"
        ),
        Tool(
            name="FechaActual",
            func=lambda _: f"Fecha actual: {datetime.now().strftime('%d de %B de %Y')}",
            description="Obtiene la fecha actual"
        )
    ]

    return initialize_agent(
        tools=tools,
        llm=self.llm,
        agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
        verbose=True
    )

Funciones principales del buscador

1. Método de búsqueda principal

   def buscar(self, tema: str) -> ResultadoNoticias:
    """Buscar noticias usando el agente y estructurar con Pydantic"""
    print(f"🔍 Buscando noticias sobre: {tema}")

    # El agente decide qué herramientas usar
    respuesta = self.agent.run(
        f"Busca noticias recientes sobre {tema}. "
        f"Primero obtén la fecha actual, luego busca las noticias."
    )

    # Obtener datos estructurados
    search = GoogleSerperAPIWrapper()
    results = search.results(tema)

    noticias = []
    for item in results.get("organic", [])[:3]:
        noticia = Noticia(
            titulo=item.get('title', 'Sin título'),
            resumen=item.get('snippet', 'Sin resumen'),
            url=item.get('link', 'Sin URL')
        )
        noticias.append(noticia)

    return ResultadoNoticias(
        tema=tema,
        fecha=datetime.now().strftime("%d de %B de %Y"),
        noticias=noticias,
        total=len(noticias)
    )

2. Presentación y exportación

   def mostrar_resultado(self, resultado: ResultadoNoticias):
    """Mostrar resultados de forma clara"""
    print(f"\n📰 NOTICIAS: {resultado.tema}")
    print(f"📅 {resultado.fecha}")
    print(f"📊 Total: {resultado.total}")

    for i, noticia in enumerate(resultado.noticias, 1):
        print(f"\n{i}. {noticia.titulo}")
        print(f"   📝 {noticia.resumen}")
        print(f"   🔗 {noticia.url}")

def exportar_json(self, resultado: ResultadoNoticias) -> str:
    """Exportar resultado a JSON"""
    archivo = f"noticias_{resultado.tema.replace(' ', '_')}.json"

    with open(archivo, 'w', encoding='utf-8') as f:
        json.dump(resultado.model_dump(), f, indent=2, ensure_ascii=False)

    print(f"💾 Exportado: {archivo}")
    return archivo

Comparación práctica: Antes vs Ahora

Búsqueda simple (versión anterior)

   noticias = buscador.buscar("inteligencia artificial")
# Resultado: Lista de objetos simples

Búsqueda inteligente (esta versión)

   resultado = agente.buscar_con_agente("inteligencia artificial")
# Resultado: Objeto Pydantic validado con análisis del agente

Diferencias en el resultado

Versión simple:

   {
  "tema": "inteligencia artificial",
  "total": 5,
  "noticias": [...]
}

Versión inteligente:

   {
  "tema": "inteligencia artificial",
  "fecha": "06 de September de 2025",
  "noticias": [...],
  "analisis": "Análisis del agente: He encontrado información relevante sobre inteligencia artificial. Los datos muestran tendencias importantes...",
  "total": 3
}

Instalación y uso

Instalación de dependencias

   pip install langchain langchain-community langchain-openai pydantic

Configuración de variables de entorno

   export OPENAI_API_KEY="tu-clave-openai"
export SERPER_API_KEY="tu-clave-serper"

Ejecución

   python3 buscador_inteligente.py

Ventajas de LangChain + Pydantic

🤖 Procesamiento inteligente

  • Agentes que razonan antes de actuar
  • Selección automática de herramientas
  • Capacidad de encadenar operaciones complejas

🛡️ Validación robusta

  • Pydantic evita errores de datos
  • Serialización automática a JSON
  • Type hints integrados

🔧 Arquitectura escalable

  • Fácil agregar nuevas herramientas
  • Modular y extensible
  • Preparado para sistemas más complejos

📊 Observabilidad

  • Modo verbose muestra el razonamiento
  • Logs detallados de cada paso
  • Debugging simplificado

Casos de uso en producción

1. Monitoreo de marca

   buscador = BuscadorInteligente()
resultado = buscador.buscar("mi-empresa noticias")
# Análisis automático de menciones

2. Research automatizado

   # El agente puede realizar múltiples búsquedas relacionadas
resultado = buscador.buscar("tendencias tecnología 2025")
# Datos estructurados listos para análisis

3. Integración con sistemas

   # Exportar directamente a bases de datos
resultado = buscador.buscar(tema)
db.insert(resultado.model_dump())

Extensiones avanzadas

Este buscador inteligente puede expandirse hacia:

  • Sistemas multi-agente: Especializados por tipo de contenido
  • RAG (Retrieval-Augmented Generation): Combinar búsqueda con generación
  • Análisis de sentimiento: Procesamiento NLP del contenido
  • Pipelines de datos: Integración con sistemas de procesamiento

Conclusión

La evolución del simple buscador de 75 líneas a este sistema inteligente con LangChain y Pydantic demuestra el poder de las herramientas especializadas para casos de uso específicos.

¿Cuándo usar cada versión?

Usa la versión simple (75 líneas) cuando:

  • Necesites resultados inmediatos
  • Quieras mínima complejidad
  • La velocidad sea crítica
  • El proyecto sea pequeño o personal

Usa la versión inteligente (LangChain + Pydantic) cuando:

  • Desarrolles aplicaciones de producción
  • Necesites validación robusta de datos
  • Planees expandir funcionalidad
  • Requieras observabilidad y debugging
  • Integres con sistemas más grandes

La arquitectura basada en agentes ofrece flexibilidad y escalabilidad que justifica la complejidad adicional en proyectos profesionales. El patrón ReAct permite que el sistema tome decisiones inteligentes, mientras que Pydantic garantiza la integridad de los datos.

Esta implementación proporciona una base sólida para sistemas de información más complejos, manteniendo código limpio y mantenible.