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:

  1. Solicita con curl base_url más /chat/completions para confirmar que la dirección y la clave funcionan.
  2. Crea ChatOpenAI en Python y llama a invoke una sola vez.
  3. Imprime resp.content y resp.response_metadata para comprobar el nombre del modelo y los campos de uso.
  4. 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.ChatOpenAI pasa a langchain_openai.ChatOpenAI.
  • Nombres de parámetros: model_name pasa a model y openai_api_base pasa a base_url.
  • La clase OpenAI de completado de texto deja paso a los modelos de chat; en proyectos nuevos usa directamente ChatOpenAI.
  • 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: