DEV Community

Jesus Oviedo Riquelme
Jesus Oviedo Riquelme

Posted on

LLMZ25-6 Review : Propuesta de Integración con LangChain para lus-laboris-py

lus-laboris-py es un sistema de investigación legal impulsado por IA que actualmente utiliza una arquitectura basada en FastAPI con integración de OpenAI, Qdrant para búsqueda vectorial, y Arize Phoenix para monitoreo. Este post propone una modernización arquitectónica integrando LangChain para mejorar la modularidad, escalabilidad y mantenibilidad del sistema.


Arquitectura Actual vs Propuesta

Arquitectura Actual de lus-laboris-py

Según el README del proyecto github.com/jesusoviedo/lus-laboris-py, el sistema actual implementa:

Usuario → FastAPI → OpenAI LLM → Qdrant Vector Search → Respuesta Legal
Enter fullscreen mode Exit fullscreen mode

Stack Tecnológico Actual:

  • FastAPI para la API
  • OpenAI para procesamiento de LLM
  • Qdrant para búsqueda vectorial
  • Arize Phoenix para monitoreo
  • Docker para containerización
  • UV como gestor de paquetes

Características Actuales:

  • Sistema de investigación legal automatizado
  • Integración con Qdrant para búsqueda de documentos legales
  • Monitoreo con Phoenix
  • Documentación con Guías en docs/README.md
  • Deploy a GCP

Limitaciones detectadas:

  • Arquitectura sin framework especializado (sin LangChain)
  • Flujo de trabajo custom sin estándares LCEL
  • Prompts probablemente embebidos en código
  • No aprovecha retriever patterns de LangChain
  • Limitada modularidad y reutilización

Arquitectura Propuesta (Con LangChain)

Usuario → Query Analysis → Multi-Search → Re-ranking → Legal Analysis → Response
Enter fullscreen mode Exit fullscreen mode

Ventajas de la Propuesta:

  • Modular con RunnableLambda para orquestación flexible
  • Prompts separados con PromptTemplate para mejor mantenibilidad
  • Recuperación avanzada con ParentDocumentRetriever para jerarquía de documentos
  • Re-ranking con ContextualCompressionRetriever y Flashrank
  • Observabilidad mejorada con Phoenix integrado a LangChain
  • Escalable con LCEL (LangChain Expression Language)
  • Patterns estándar de la industria
  • Fácil integración con nuevos LLMs (Claude, Gemini, etc.)

Implementación Propuesta

1. Estructura de Prompts

from langchain.prompts import PromptTemplate

QUERY_ANALYSIS_PROMPT = PromptTemplate(
    input_variables=["user_query", "country", "legal_area"],
    template="""
Eres un experto en análisis de consultas legales.

Consulta del usuario: {user_query}
País: {country}
Área legal: {legal_area}

Instrucciones:
1. Identifica el tipo de consulta legal
2. Extrae conceptos clave y términos legales relevantes
3. Genera entre 3-5 consultas de búsqueda optimizadas

Devuelve JSON con: query_type, key_concepts, search_queries, related_areas
"""
)

LEGAL_ANALYSIS_PROMPT = PromptTemplate(
    input_variables=["query", "legal_documents", "jurisdiction"],
    template="""
Eres un abogado experto analizando documentos legales.

Consulta: {query}
Jurisdicción: {jurisdiction}

Documentos legales:
{legal_documents}

Analiza y proporciona: resumen ejecutivo, análisis legal, leyes relevantes, recomendaciones
"""
)
Enter fullscreen mode Exit fullscreen mode

2. Pipeline con RunnableLambda

from langchain_core.runnables import RunnableLambda
from langchain_openai import ChatOpenAI
from langchain_qdrant import QdrantVectorStore

llm = ChatOpenAI(model="gpt-4o", temperature=0.3)

def _analyze_query(inputs):
    """Etapa 1: Analizar consulta"""
    chain = QUERY_ANALYSIS_PROMPT | llm
    result = chain.invoke({
        "user_query": inputs["query"],
        "country": inputs["country"],
        "legal_area": inputs["legal_area"]
    })
    return {**inputs, "query_analysis": parse_json(result.content)}

def _retrieve_docs(inputs):
    """Etapa 2: Recuperar documentos"""
    all_docs = []
    for query in inputs["search_queries"]:
        docs = compressed_retriever.invoke(query)
        all_docs.extend(docs)
    return {**inputs, "documents": deduplicate(all_docs)}

def _analyze_legal(inputs):
    """Etapa 3: Análisis legal con LLM"""
    chain = LEGAL_ANALYSIS_PROMPT | llm
    result = chain.invoke({
        "query": inputs["query"],
        "legal_documents": format_docs(inputs["documents"]),
        "jurisdiction": inputs["country"]
    })
    return {**inputs, "legal_analysis": result.content}

# Pipeline completo
legal_workflow = (
    RunnableLambda(_analyze_query)
    | RunnableLambda(_retrieve_docs)
    | RunnableLambda(_analyze_legal)
)

def process_legal_query(query: str, country: str = "Spain"):
    """Procesar consulta legal"""
    return legal_workflow.invoke({"query": query, "country": country})
Enter fullscreen mode Exit fullscreen mode

Comparación Antes vs Después

Aspecto Sin LangChain Con LangChain
Prompts Embebidos en código PromptTemplate separado
Workflow Hardcodeado Pipeline modular
Retrieval Manual ParentDocumentRetriever + re-ranking
Observabilidad Limitada Phoenix integrado
Debugging Difícil Traces completos

Ventajas de la Nueva Arquitectura

  1. Modularidad: Componentes intercambiables
  2. Observabilidad: Traces con Phoenix
  3. Escalabilidad: Fácil agregar features
  4. Mantenibilidad: Código más limpio
  5. Optimización: A/B testing de prompts
  6. Performance: Retrieval avanzado + re-ranking

Plan de Migración (10 semanas)

Fase 1-2: Preparación (Semanas 1-2)

  • Instalar dependencias de LangChain: uv add langchain langchain-openai langchain-qdrant
  • Configurar integración de Phoenix con LangChain
  • Revisar estructura actual del proyecto
  • Estudiar README y documentación existente

Fase 3-4: Migración de Prompts (Semanas 3-4)

  • Extraer prompts del código actual
  • Convertir a PromptTemplate de LangChain
  • Crear archivo legal_prompts.py con templates especializados
  • Testing A/B de prompts

Fase 5-6: Implementación de Retrievers (Semanas 5-6)

  • Configurar ParentDocumentRetriever con Qdrant existente
  • Implementar ContextualCompressionRetriever con Flashrank
  • Optimizar chunking para documentos legales (500-800 chars)
  • Implementar deduplicación de resultados

Fase 7-8: Pipeline con RunnableLambda (Semanas 7-8)

  • Convertir funciones existentes a RunnableLambda
  • Implementar workflow_chain con LCEL
  • Migrar lógica de búsqueda a retriever chain
  • Testing end-to-end

Fase 9-10: Optimización y Deployment (Semanas 9-10)

  • Configurar observabilidad mejorada con Phoenix
  • Monitorear métricas (latency, cost, quality)
  • Optimizar prompts y parámetros
  • Actualizar documentación y guías
  • Deploy a GCP con nueva arquitectura

Conclusión

La integración de LangChain en lus-laboris-py transformará el sistema en una arquitectura moderna, observable y escalable, siguiendo las mejores prácticas demostradas en el proyecto ziweidoushu.

Beneficios Esperados

  1. Modularidad Mejorada

    • Componentes intercambiables (Qdrant, Pinecone, etc.)
    • Fácil cambiar de GPT-4 a Claude u otros LLMs
    • Prompts reutilizables y versionados
  2. Observabilidad Profesional

    • Traces automáticos con Phoenix
    • Métricas detalladas de latency, tokens, costos
    • Debug simplificado con spans y context
  3. Escalabilidad Futura

    • Agregar nuevas fuentes legales es trivial
    • Soporte multi-idioma con translate chains
    • Agentes para búsqueda dinámica
  4. Mantenibilidad

    • Código más limpio y organizado
    • Separación clara de concerns
    • Testing más fácil de unit e integration

Repositorios:

Referencias:

Top comments (0)