LangChain se ha consolidado como un entorno de trabajo esencial para orquestar modelos de lenguaje de gran tamaño (LLM). Su arquitectura permite a los desarrolladores conectar modelos generativos con fuentes de datos extenras, APIs y herramientas de cálculo, facilitando la creación de flujos de trabajo complejos y contextualizados.
Configuración del Entorno
Para comenzar, es necesario preparar el entorno de Python e instalar los paquetes principales. Dado que el ecosistema ha modularizado sus componentes, instalaremos el núcleo y las integraciones específicas requeridas:
pip install langchain langchain-openai langchain-community faiss-cpu langchain-text-splitters
Interacción Básica con Modelos (Cadenas Simples)
En las versiones modernas de la biblioteca, la composición de componentes se realiza preferentemente mediante el Lenguaje de Expresiones de LangChain (LCEL). A continuación, se muestra cómo estructurar una llamada básica al modelo utilizando plantillas de prompts y el operador de tubería (pipe):
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
# Inicialización del modelo de chat
modelo_chat = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.7)
# Definición de la plantilla de entrada
plantilla = ChatPromptTemplate.from_messages([
("system", "Eres un asistente técnico experto en {area}."),
("user", "Explica el concepto de {concepto} de manera concisa.")
])
# Construcción de la cadena mediante LCEL
cadena_basica = plantilla | modelo_chat | StrOutputParser()
# Ejecución de la cadena
resultado = cadena_basica.invoke({
"area": "inteligencia artificial",
"concepto": "mecanismos de atención"
})
print(resultado)
Integración con Fuentes de Datos (Cadenas de Recuperación)
Para dotar al modelo de conocimiento específico, se emplea la técnica de Generación Aumentada por Recuperación (RAG). Este proceso implica segmentar documentos, vectorizarlos y recuperar el contexto relevante antes de generar la respuesta final.
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain_core.runnables import RunnablePassthrough
from langchain_core.prompts import PromptTemplate
# 1. Carga y fragmentación de documentos
cargador = TextLoader("documento_tecnico.txt")
documentos = cargador.load()
divisor = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
fragmentos = divisor.split_documents(documentos)
# 2. Creación del almacén vectorial
embedder = OpenAIEmbeddings()
base_vectorial = FAISS.from_documents(fragmentos, embedder)
recuperador = base_vectorial.as_retriever(search_kwargs={"k": 3})
# 3. Definición del prompt para RAG
prompt_rag = PromptTemplate.from_template(
"Basado en el siguiente contexto:\n{contexto}\n\nResponde a la pregunta: {pregunta}"
)
# 4. Ensamblaje de la cadena de recuperación
def formatear_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
cadena_rag = (
{"contexto": recuperador | formatear_docs, "pregunta": RunnablePassthrough()}
| prompt_rag
| modelo_chat
| StrOutputParser()
)
respuesta_rag = cadena_rag.invoke("¿Cuáles son los requisitos de instalación?")
print(respuesta_rag)
Orquestación Avanzada y Lógica Personalizada
LCEL permite encadenar no solo modelos y prompts, sino también funciones personalizadas. Esto es útil para preprocesar datos, validar entradas o aplicar reglas de negocio dentro del flujo de ejecución.
Uso de Funciones Personalizadas en el Flujo
En lugar de heredar de clases base complejas, la metodología actual recomienda utilizar el decorador @chain para inyectar lógica a medida de forma limpia y funcionla:
from langchain_core.runnables import chain
@chain
def preprocesar_consulta(entrada: dict) -> dict:
"""Función personalizada para limpiar y enriquecer la entrada."""
texto_original = entrada.get("pregunta", "")
# Lógica de negocio: añadir un sufijo para forzar respuestas estructuradas
entrada["pregunta"] = f"{texto_original} (Responde estrictamente en formato JSON)"
return entrada
# Integración de la lógica personalizada en la cadena
cadena_avanzada = (
preprocesar_consulta
| prompt_rag
| modelo_chat
| StrOutputParser()
)
salida_final = cadena_avanzada.invoke({
"pregunta": "Lista los módulos principales",
"contexto": "..." # El contexto sería inyectado por el recuperador en un flujo real
})
print(salida_final)