LangChain no es un servicio de modelos: se encarga de encadenar prompts, modelos, herramientas y analizadores de salida dentro de una aplicación. Siempre que el servicio de destino ofrezca una interfaz compatible con OpenAI, puedes conectarlo con ChatOpenAI del paquete langchain-openai y dirigir las solicitudes a tu propia Base URL. En la práctica, lo que suele bloquear a la gente no es el framework, sino tres campos: en qué nivel se escribe la dirección, de dónde se lee la clave y si el nombre del modelo coincide con el que está habilitado en la pasarela.
Este artículo recorre el orden «instalación—ejemplo mínimo—variables de entorno—cadenas—streaming—agentes—diagnóstico—migración». Las versiones de LangChain avanzan con rapidez; los nombres de clase y los parámetros deben contrastarse con la documentación de la versión que hayas instalado.
Nota: LangChain es una marca de LangChain, Inc. y OpenAI es una marca de su titular. Este artículo no tiene afiliación con esos fabricantes. Los nombres de modelo y los precios se rigen por la página de precios de modelos, y los detalles de la interfaz, por la documentación oficial.
1. Instalación: el núcleo son dos paquetes
Después de crear un entorno virtual, instala:
python -m venv .venv
source .venv/bin/activate
pip install -U langchain langchain-openai
langchain-openai es el paquete de integración para OpenAI y las interfaces compatibles; langchain aporta las capacidades de nivel superior, como cadenas y agentes, y langchain-core se instala como dependencia. En producción conviene fijar versiones en requirements.txt para evitar que distintas máquinas instalen APIs incompatibles. La ruta clásica de los tutoriales antiguos, langchain.chat_models.ChatOpenAI, ya se migró; la importación actual es langchain_openai.
2. Ejemplo mínimo: ChatOpenAI apuntando a una dirección personalizada
El núcleo son tres parámetros: model, base_url y api_key. base_url suele escribirse hasta /v1, sin /chat/completions, porque el cliente añade la ruta por su cuenta.
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="nombre-de-tu-modelo",
base_url="https://direccion-de-tu-pasarela/v1",
api_key="sk-tu-clave",
temperature=0.3,
timeout=60,
)
resp = llm.invoke("Explica en una frase qué es una interfaz compatible con OpenAI.")
print(resp.content)
Primero haz funcionar este bloque y después añade prompts y herramientas. Orden recomendado de validación:
- Solicita con curl
base_urlmás/chat/completionspara confirmar que la dirección y la clave funcionan. - Crea
ChatOpenAIen Python y llama ainvokeuna sola vez. - Imprime
resp.contentyresp.response_metadatapara comprobar el nombre del modelo y los campos de uso. - Cuando funcione, agrega plantillas de prompt, analizadores de salida y herramientas.
Si aquí aparece un 404, revisa primero el nivel de la dirección; si aparece un 401, revisa la clave y la cabecera de autenticación; si el modelo no existe, consulta /v1/models para comparar nombres. El nombre del modelo debe coincidir exactamente con el que devuelve la pasarela: las mayúsculas, el sufijo de fecha y los alias también cuentan como diferencias.
3. Parámetros y variables de entorno
No codifiques la clave directamente en el código. El SDK de OpenAI lee OPENAI_API_KEY y también puede leer OPENAI_BASE_URL; parte del código y la documentación antiguos usan OPENAI_API_BASE. El comportamiento varía entre versiones, así que lo más seguro es pasar los parámetros de forma explícita y dejar las variables de entorno solo como valores predeterminados.
| Parámetro | Función | Forma habitual |
|---|---|---|
model |
Identificador del modelo | Igual a lo que devuelve /v1/models |
base_url |
Dirección raíz de la interfaz | https://host/v1 |
api_key |
Clave de autenticación | Explícita o desde OPENAI_API_KEY |
temperature |
Aleatoriedad del muestreo | Según el rango que admita el modelo |
timeout |
Tiempo máximo por solicitud | Ajustado a la duración de la tarea |
max_retries |
Reintentos del cliente | Alrededor de 2 por lo general |
En desarrollo local puedes usar un archivo .env con python-dotenv, pero .env debe estar en .gitignore. En equipos conviene separar claves por proyecto y entorno, con límites distintos para producción y pruebas, de modo que un problema permita desactivar una clave sin afectar al resto.
4. Cadenas: unir prompt y modelo con LCEL
El lenguaje de expresiones de LangChain (LCEL) compone componentes con el operador de tubería. La cadena más básica es «prompt → modelo → analizador de salida»:
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_messages([
("system", "Eres un asistente de soporte técnico. Responde de forma concreta y empieza por la conclusión."),
("user", "{question}"),
])
chain = prompt | llm | StrOutputParser()
print(chain.invoke({"question": "¿Hasta qué nivel debe escribirse la Base URL?"}))
invoke recibe una entrada y devuelve un resultado; batch recibe una lista y procesa en lote; stream devuelve la respuesta por fragmentos. El analizador de salida convierte el mensaje del modelo en texto o en un objeto estructurado. Si necesitas JSON, usa primero la salida estructurada que admita el modelo y luego añade análisis y validación; no dependas solo del prompt.
5. Streaming y llamadas por lotes
El streaming es útil para interfaces de chat y respuestas largas:
for chunk in chain.stream({"question": "Explica qué es la llamada a herramientas"}):
print(chunk, end="", flush=True)
Si invoke funciona pero stream no entrega fragmentos, normalmente hay un proxy con almacenamiento en búfer en la ruta o el proveedor no admite streaming. Comprueba si la pasarela devuelve text/event-stream y si el proxy inverso desactivó el buffering. En las llamadas por lotes hay que cuidar la concurrencia: batch puede enviar solicitudes en paralelo; ante un 429, reduce la concurrencia o procesa por lotes más pequeños y conserva los elementos fallidos para reintentarlos.
6. Agentes: modelo, herramientas y bucle
Un agente es esencialmente un bucle: el modelo decide si debe llamar a una herramienta, el entorno ejecuta la herramienta y devuelve el resultado, y el modelo decide el siguiente paso hasta dar una respuesta final. LangChain 1.x ofrece interfaces de alto nivel como create_agent; las versiones 0.3 y anteriores suelen usar AgentExecutor. La forma de escribirlos es distinta y copiar tutoriales antiguos puede provocar errores de importación.
Las herramientas se definen con un decorador; el nombre de la función, los tipos de los parámetros y la cadena de documentación influyen en la elección del modelo:
from langchain_core.tools import tool
@tool
def get_order_status(order_id: str) -> str:
"""Consulta el estado logístico según el número de pedido."""
return "Enviado; entrega estimada en tres días"
Al conectar una pasarela personalizada hay que tener en cuenta que la llamada a herramientas depende de que el proveedor admita por completo tools, tool_choice y el formato de devolución de resultados. Algunos servicios compatibles solo implementan el chat básico: ante una llamada a herramientas ignoran los parámetros o devuelven un error. Valida primero con una herramienta y una pregunta sencilla, y después aumenta el número de herramientas y las llamadas en paralelo.
7. Errores comunes y diagnóstico
| Síntoma | Causa posible | Tratamiento |
|---|---|---|
| 401 No autenticado | Clave inválida, ausente o con espacios | Pasa api_key explícita y revisa las variables de entorno |
| 404 model_not_found | Nombre de modelo distinto o ruta sobrante | Consulta /v1/models; base_url solo hasta /v1 |
| 429 Too Many Requests | Concurrencia alta o cuota agotada | Reduce la concurrencia, procesa por lotes y reintenta con retroceso |
| 400 context_length_exceeded | Entrada por encima del límite de contexto | Recorta el historial, divide documentos o resume primero |
| OutputParserException | Salida del modelo fuera del formato esperado | Restringe el formato, valida y reintenta una vez |
| APIConnectionError / timeout | Red, proxy, certificado o fallo del proveedor | Revisa las variables del proxy, el DNS y los tiempos de espera |
| La herramienta no responde | El proveedor no admite el protocolo tools |
Usa un modelo con soporte de herramientas o una cadena normal |
Para diagnosticar, primero evita LangChain y solicita la misma dirección con curl o con el SDK de OpenAI. Si la conexión directa funciona y LangChain falla, el problema suele estar en los nombres de los parámetros, las variables de entorno o la versión. Si fallan ambas, el problema está en la pasarela, la clave o la red.
8. Migración desde la sintaxis anterior
- Ruta de importación:
langchain.chat_models.ChatOpenAIpasa alangchain_openai.ChatOpenAI. - Nombres de parámetros:
model_namepasa amodelyopenai_api_basepasa abase_url. - La clase
OpenAIde completado de texto deja paso a los modelos de chat; en proyectos nuevos usa directamenteChatOpenAI. - Algunas cadenas y agentes antiguos se trasladaron a un paquete de compatibilidad en 1.x; revisa las notas de migración antes de mover código y no mezcles varias versiones mayores.
- Gestión de dependencias: fija versiones antes de actualizar y ejecuta la ruta principal en un entorno de pruebas, con especial atención al streaming, las herramientas y la salida estructurada.
Preguntas frecuentes
¿Hay que incluir /v1 en base_url?
La mayoría de los servicios compatibles con OpenAI pide llegar hasta /v1, y el cliente añade /chat/completions. También hay pasarelas que colocan el prefijo de versión en otra ruta; consulta la documentación del proveedor. El criterio es simple: si curl puede solicitar base_url + /chat/completions, la dirección es correcta.
¿Se puede usar la variable OPENAI_BASE_URL?
Sí, el SDK de OpenAI la lee; parte de la documentación antigua la escribe como OPENAI_API_BASE. El soporte no es idéntico en todas las versiones, así que en código de producción conviene pasar base_url de forma explícita para evitar que una diferencia de entorno envíe la solicitud a otra dirección.
¿Por qué invoke funciona pero stream no devuelve nada?
Las causas habituales son el almacenamiento en búfer del proxy, la falta de soporte de streaming en el proveedor o un tratamiento del resultado como cadena completa en lugar de flujo. Confirma primero que el tipo de respuesta sea un flujo de eventos y después revisa la configuración del proxy inverso y la forma de lectura.
¿LangChain puede conectarse a Claude, DeepSeek y otros modelos que no son de OpenAI?
Sí. Si el servicio ofrece una interfaz compatible con OpenAI, basta con usar ChatOpenAI y cambiar la dirección y el nombre del modelo; si usa el protocolo nativo del fabricante, emplea el paquete de integración correspondiente. Los parámetros y la capacidad de llamada a herramientas difieren entre ambos enfoques y deben validarse por separado.
¿Qué hacer si el agente da error de parámetros al llamar a una herramienta?
Revisa primero si la estructura de la llamada devuelta por el modelo cumple el protocolo y después comprueba los tipos de los parámetros y los campos obligatorios de la función. Algunas pasarelas compatibles admiten de forma incompleta las llamadas paralelas; desactiva el paralelismo, entrega una sola herramienta por vez y avanza paso a paso.
Siguiente paso
La clave para conectar LangChain a una API personalizada es fijar tres cosas —dirección, clave y nombre del modelo—, validarlas con una solicitud mínima y solo después añadir cadenas y herramientas. Si necesitas una entrada única compatible con OpenAI, claves virtuales y registro de uso, puedes registrarte en ZSQH AI Gateway; los modelos y precios se rigen por la página de precios de modelos.
Lecturas relacionadas:
