Saltar al contenido
jvela.dev
← Todos los artículos

Por Jose Vela Backend Development · 5 min de lectura

Buscador de noticias inteligente con LangChain y Pydantic

Tutorial de un buscador de noticias con LangChain y Pydantic: agentes con herramientas, validación de datos y una arquitectura lista para producción.

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

python
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

python
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

python
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:

código
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

python
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

python
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

python
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

python
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

python
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)

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

Búsqueda inteligente (esta versión)

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

Diferencias en el resultado

Versión simple:

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

Versión inteligente:

json
{
  "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

bash
pip install langchain langchain-community langchain-openai pydantic

Configuración de variables de entorno

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

Ejecución

bash
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

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

2. Research automatizado

python
# 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

python
# 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.