LangChain se ha convertido en el estándar de facto para construir aplicaciones con modelos de lenguaje. En 2026, si estás construyendo algo serio con LLMs, necesitas entender LangChain profundamente.
En este tutorial extenso, te guiaré desde conceptos básicos hasta aplicaciones complejas: chains, agents inteligentes, memory persistente, RAG (Retrieval-Augmented Generation), y LCEL (LangChain Expression Language). Al final, habrás construido un sistema Q&A completo.
¿Qué es LangChain y por qué importa?
LangChain es un framework que abstrae la complejidad de trabajar con LLMs. Sin LangChain, integrar modelos, manejar memoria, construir workflows, y conectar herramientas es tedioso. LangChain lo simplifica dramáticamente.
Problemas que LangChain resuelve
Prompt Management: Los prompts crecen. "Hola, eres un experto" se convierte en 200 líneas de instrucciones complejas. LangChain proporciona PromptTemplate para manejar esto de forma elegante.
Secuencias Complejas: Ejecutar un LLM, procesar su salida, ejecutar otro LLM, parsear JSON, filtrar resultados... esto es tedioso manualmente. LangChain's Chains lo hace declarativo.
Memoria de Conversación: Mantener historial de chats, resumir conversaciones largas, inyectar contexto previo... LangChain's Memory maneja esto automáticamente.
Integración con Herramientas: Conectar LLMs a APIs, bases de datos, buscadores... LangChain proporciona abstracciones.
RAG (Búsqueda + Generación): El LLM necesita información externa. LangChain integra retrieval, embeddings, y generación en un pipeline cohesivo.
Instalación y Setup
1pip install langchain2pip install langchain-openai # Para ChatGPT3pip install langchain-community # Integraciones4pip install python-dotenv # Variables de entorno
Crea un archivo .env con tu clave API:
1OPENAI_API_KEY=sk-...
Carga en tu código:
1from dotenv import load_dotenv2import os3 4load_dotenv()5api_key = os.getenv("OPENAI_API_KEY")
Conceptos fundamentales: Chains
Una Chain es una secuencia de operaciones encadenadas. El output de una se convierte en input de la siguiente.
Prompt Templates
Los templates parametrizan prompts:
1from langchain.prompts import PromptTemplate2 3# Template simple4template = """Traduce el siguiente texto al español:5{texto_original}6 7Traducción:"""8 9prompt = PromptTemplate(10 input_variables=["texto_original"],11 template=template12)13 14# Uso15texto = "Hello, how are you?"16prompt_formateado = prompt.format(texto_original=texto)17print(prompt_formateado)
LLMChain: El primer paso
1from langchain_openai import ChatOpenAI2from langchain.chains import LLMChain3from langchain.prompts import PromptTemplate4 5# Configura el LLM6llm = ChatOpenAI(model="gpt-4o", temperature=0.7)7 8# Prompt template9template = """Eres un experto en {tema}.10La pregunta es: {pregunta}11 12Respuesta detallada:"""13 14prompt = PromptTemplate(15 input_variables=["tema", "pregunta"],16 template=template17)18 19# Crea la chain20chain = LLMChain(llm=llm, prompt=prompt)21 22# Ejecuta23resultado = chain.invoke({24 "tema": "Machine Learning",25 "pregunta": "¿Qué es overfitting?"26})27 28print(resultado["text"])
Chains Secuenciales: SequentialChain
Ejecuta múltiples chains en secuencia:
1from langchain.chains import SequentialChain2 3# Chain 1: Genera título de artículo4tema_template = """Genera un título creativo para un artículo sobre {tema}.5Título:"""6 7tema_prompt = PromptTemplate(8 input_variables=["tema"],9 template=tema_template10)11titulo_chain = LLMChain(llm=llm, prompt=tema_prompt, output_key="titulo")12 13# Chain 2: Genera introducción basada en el título14intro_template = """Basado en el título "{titulo}", escribe una introducción atractiva.15Introducción:"""16 17intro_prompt = PromptTemplate(18 input_variables=["titulo"],19 template=intro_template20)21intro_chain = LLMChain(llm=llm, prompt=intro_prompt, output_key="introduccion")22 23# Ejecuta secuencialmente24overall_chain = SequentialChain(25 chains=[titulo_chain, intro_chain],26 input_variables=["tema"],27 output_variables=["titulo", "introduccion"]28)29 30resultado = overall_chain({"tema": "Inteligencia Artificial"})31print(resultado)
Agents: IA Autónoma
Una Agent es un LLM que puede decidir qué herramienta usar para resolver un problema.
El paradigma de Agents
Sin agents:
1Pregunta → LLM → Respuesta (limitada a conocimiento de entrenamiento)
Con agents:
1Pregunta → LLM → "Necesito buscar esto" → Ejecuta herramienta → LLM con resultados → Respuesta mejorada
Definiendo Tools
1from langchain.tools import tool2import requests3 4@tool5def obtener_precio_bitcoin() -> str:6 """Obtiene el precio actual de Bitcoin en USD."""7 try:8 response = requests.get("https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd")9 data = response.json()10 precio = data["bitcoin"]["usd"]11 return f"El precio actual de Bitcoin es: ${precio:,.2f}"12 except Exception as e:13 return f"Error obteniendo precio: {e}"14 15@tool16def buscar_informacion(query: str) -> str:17 """Busca información sobre un tema."""18 # Implementación simulada19 return f"Información relevante sobre: {query}"20 21# Define las herramientas disponibles22tools = [obtener_precio_bitcoin, buscar_informacion]
Creando una Agent
1from langchain.agents import create_react_agent, AgentExecutor2from langchain import hub3 4# Usa el prompt del ReAct (Reasoning + Acting)5react_prompt = hub.pull("hwchase17/react")6 7# Crea el agent8agent = create_react_agent(llm, tools, react_prompt)9 10# Executor ejecuta el agent11agent_executor = AgentExecutor(12 agent=agent,13 tools=tools,14 verbose=True, # Muestra el pensamiento del agent15 max_iterations=516)17 18# Prueba19resultado = agent_executor.invoke({20 "input": "¿Cuál es el precio actual de Bitcoin? ¿Ha subido mucho este año?"21})22 23print(resultado["output"])
Output:
1Thought: Necesito obtener el precio actual de Bitcoin primero.2Action: obtener_precio_bitcoin3Observation: El precio actual de Bitcoin es: $94,230.504Thought: Ahora tengo el precio. Puedo comparar con precios históricos...
Memory: Mantener Contexto
ConversationBufferMemory
Mantiene todo el historial:
1from langchain.memory import ConversationBufferMemory2from langchain.chains import ConversationChain3 4memory = ConversationBufferMemory()5 6# Chain con memoria7conversation = ConversationChain(8 llm=llm,9 memory=memory,10 verbose=True11)12 13# Primera pregunta14print(conversation.run(input="Hola, me llamo Javier"))15# Segunda pregunta16print(conversation.run(input="¿Cuál es mi nombre?"))17# El LLM recuerda que te llamas Javier
ConversationSummaryMemory
Resume conversaciones largas:
1from langchain.memory import ConversationSummaryMemory2 3memory = ConversationSummaryMemory(4 llm=llm,5 max_token_limit=300 # Limita resumen a 300 tokens6)7 8conversation = ConversationChain(llm=llm, memory=memory)9 10# Charla larga...11for i in range(10):12 conversation.run(input=f"Pregunta número {i}")13 14# Memory automáticamente resume lo anterior
ConversationBufferWindowMemory
Mantiene solo los últimos N turnos:
1from langchain.memory import ConversationBufferWindowMemory2 3memory = ConversationBufferWindowMemory(k=5) # Últimos 5 mensajes4 5conversation = ConversationChain(llm=llm, memory=memory)
RAG: Retrieval-Augmented Generation
RAG permite que un LLM responda basándose en documentos específicos que le proporciones.
Setup básico
1pip install langchain-community2pip install faiss-cpu # O faiss-gpu si tienes NVIDIA3pip install pypdf
Ejemplo: Q&A sobre PDFs
1from langchain_community.document_loaders import PyPDFLoader2from langchain.text_splitter import RecursiveCharacterTextSplitter3from langchain_community.vectorstores import FAISS4from langchain_openai import OpenAIEmbeddings5from langchain.chains import RetrievalQA6 7# 1. Carga documentos8loader = PyPDFLoader("documento.pdf")9documents = loader.load()10 11# 2. Divide en chunks12splitter = RecursiveCharacterTextSplitter(13 chunk_size=1000,14 chunk_overlap=20015)16chunks = splitter.split_documents(documents)17 18# 3. Crea embeddings y vector store19embeddings = OpenAIEmbeddings()20vector_store = FAISS.from_documents(chunks, embeddings)21 22# 4. Crea Q&A chain23qa_chain = RetrievalQA.from_chain_type(24 llm=llm,25 chain_type="stuff",26 retriever=vector_store.as_retriever()27)28 29# 5. Consulta30respuesta = qa_chain.invoke("¿Cuál es el tema principal del documento?")31print(respuesta["result"])
RAG Avanzado: Multi-Document Search
1from langchain.schema import Document2 3# Carga múltiples documentos4all_chunks = []5for archivo in ["doc1.pdf", "doc2.pdf", "doc3.pdf"]:6 loader = PyPDFLoader(archivo)7 docs = loader.load()8 chunks = splitter.split_documents(docs)9 all_chunks.extend(chunks)10 11# Vector store con todos12vector_store = FAISS.from_documents(all_chunks, embeddings)13 14# Búsqueda similar (antes de Q&A)15docs_similares = vector_store.similarity_search(16 "¿Cómo se implementa autenticación?",17 k=3 # Top 3 documentos18)19 20for doc in docs_similares:21 print(doc.page_content[:200])22 print("---")
LCEL: LangChain Expression Language
LCEL es la forma moderna de construir chains en LangChain (2024+).
Sintaxis LCEL
1from langchain.prompts import ChatPromptTemplate2from langchain_openai import ChatOpenAI3 4# Componentes5prompt = ChatPromptTemplate.from_template(6 "Traduce al español: {texto}"7)8llm = ChatOpenAI()9 10# Pipe (|) encadena componentes11chain = prompt | llm12 13# Ejecuta14resultado = chain.invoke({"texto": "Hello world"})15print(resultado.content) # "Hola mundo"
Chains Complejas en LCEL
1from langchain.schema.output_parser import StrOutputParser2import json3 4# Componentes5prompt = ChatPromptTemplate.from_template(6 """Responde en JSON con estructura:7 {{"respuesta": "...", "confianza": 0-100}}8 9 Pregunta: {pregunta}"""10)11llm = ChatOpenAI()12parser = StrOutputParser()13 14# Chain con parseo manual15chain = prompt | llm | parser16 17resultado = chain.invoke({"pregunta": "¿Cuál es la capital de Francia?"})18print(resultado)19 20# Parseá JSON21respuesta_json = json.loads(resultado)22print(f"Respuesta: {respuesta_json['respuesta']}")23print(f"Confianza: {respuesta_json['confianza']}%")
Branching en LCEL
1from langchain.schema.runnable import RunnableBranch2 3# Crea ramas basadas en condiciones4clasificador_prompt = ChatPromptTemplate.from_template(5 "Clasifica como: TECNICO, GENERAL o CREATIVO\nTexto: {texto}\nClasificación:"6)7 8tecnico_chain = ChatPromptTemplate.from_template(9 "Como experto técnico, responde: {pregunta}"10) | llm11 12general_chain = ChatPromptTemplate.from_template(13 "Responde claramente: {pregunta}"14) | llm15 16creativo_chain = ChatPromptTemplate.from_template(17 "Responde de forma creativa: {pregunta}"18) | llm19 20# Branch21branch = RunnableBranch(22 (lambda x: "TECNICO" in x["clasificacion"], tecnico_chain),23 (lambda x: "CREATIVO" in x["clasificacion"], creativo_chain),24 general_chain25)
Proyecto Completo: Sistema Q&A Inteligente
1from langchain_openai import ChatOpenAI, OpenAIEmbeddings2from langchain.prompts import ChatPromptTemplate3from langchain_community.vectorstores import FAISS4from langchain.memory import ConversationBufferMemory5from langchain.chains import ConversationRetrievalChain6import os7 8class SistemaQA:9 def __init__(self, pdf_path: str):10 self.llm = ChatOpenAI(model="gpt-4o", temperature=0.3)11 self.embeddings = OpenAIEmbeddings()12 self.memory = ConversationBufferMemory(13 memory_key="chat_history",14 return_messages=True15 )16 17 # Carga PDF18 from langchain_community.document_loaders import PyPDFLoader19 from langchain.text_splitter import RecursiveCharacterTextSplitter20 21 loader = PyPDFLoader(pdf_path)22 docs = loader.load()23 splitter = RecursiveCharacterTextSplitter(chunk_size=1000)24 chunks = splitter.split_documents(docs)25 26 # Vector store27 self.vector_store = FAISS.from_documents(chunks, self.embeddings)28 self.retriever = self.vector_store.as_retriever()29 30 # Chain con conversación + RAG31 self.chain = ConversationRetrievalChain.from_llm(32 llm=self.llm,33 retriever=self.retriever,34 memory=self.memory,35 verbose=True36 )37 38 def consulta(self, pregunta: str) -> str:39 """Realiza una consulta con contexto de conversación."""40 resultado = self.chain.invoke({"question": pregunta})41 return resultado["answer"]42 43 def historial(self) -> str:44 """Retorna el historial de conversación."""45 return self.memory.buffer46 47# Uso48qa = SistemaQA("documento.pdf")49 50print(qa.consulta("¿Cuál es el tema principal?"))51print(qa.consulta("¿Puedes dar más detalles?")) # Recuerda pregunta anterior52print(qa.historial())
Debugging y Optimización
Habilitar Verbose
1llm = ChatOpenAI(model="gpt-4o")2chain = LLMChain(llm=llm, prompt=prompt, verbose=True)3 4# Imprime prompts y respuestas5resultado = chain.invoke({"variable": "valor"})
LangSmith Debugging
LangSmith permite tracear ejecuciones:
1os.environ["LANGCHAIN_TRACING_V2"] = "true"2os.environ["LANGSMITH_API_KEY"] = "tu_api_key"3 4# Ahora todas las llamadas se registran en LangSmith
Caching de Embeddings
1from langchain.cache import RedisCache2import redis3 4redis_client = redis.Redis.from_url("redis://localhost:6379")5cache = RedisCache(redis_client=redis_client)6 7# LangChain cachea llamadas al LLM
Mejores prácticas
Usa LCEL: Es más limpio y el futuro de LangChain. Evita chains legacy.
Temperatura según caso: 0.1 para respuestas determinísticas (Q&A), 0.7-0.9 para creatividad.
Chunking inteligente: Chunks muy pequeños (100 tokens) crean ruido; muy grandes pierden contexto. 1000 es típicamente bueno.
Memory según escala: BufferMemory para apps pequeñas; SummaryMemory para conversaciones largas.
Monitorea costos: gpt-4o es 10x más caro que gpt-3.5-turbo. Para prototipado, usa gpt-3.5-turbo.
1# Usa gpt-3.5 para desarrollo2llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.7)3 4# Cambia a gpt-4o solo en producción si es crítico5if os.getenv("ENVIRONMENT") == "production":6 llm = ChatOpenAI(model="gpt-4o", temperature=0.7)
Preguntas frecuentes
¿Cuál es la diferencia entre Chains y Agents?
Chains son secuencias predefinidas. Sabes exactamente qué pasos ocurren. Agents son más autónomas: el LLM decide qué herramientas usar basándose en la pregunta. Agents son más flexibles pero menos predecibles.
¿Necesito usar OpenAI o puedo usar Ollama?
Puedes usar Ollama:
1from langchain_community.llms import Ollama2 3llm = Ollama(model="mistral", base_url="http://localhost:11434")
¿Cómo manejo conversaciones muy largas?
Usa ConversationSummaryMemory para resumir automáticamente. También puedes implementar un resumen manual cada N turnos:
1if len(memory.buffer) > 5000: # Si el buffer es muy largo2 summary = llm.predict(f"Resume brevemente: {memory.buffer}")3 memory.clear()4 memory.save_context({"input": "Resumen anterior"}, {"output": summary})
¿Cómo aseguro que el agent no gaste demasiados tokens?
Limita iteraciones:
1agent_executor = AgentExecutor(2 agent=agent,3 tools=tools,4 max_iterations=3 # Solo 3 pasos máximo5)
¿LangChain vs Langflow vs LlamaIndex?
- LangChain: Framework completo, máxima flexibilidad
- Langflow: UI visual para chains, menos código
- LlamaIndex: Especializado en RAG, mejor indexación
Para aplicaciones complejas, LangChain. Para prototipos visuales, Langflow. Para RAG puro, LlamaIndex.
LangChain ha evolucionado a la herramienta estándar de la industria. Con esta guía, estás preparado para construir aplicaciones IA serias. ¡Comienza a experimentar!