La respuesta corta: tres configuraciones en ChatOpenAI
Si buscaste chat open ai langchain, probablemente tengas un proyecto LangChain que ya usa ChatOpenAI y quieres que hable con un backend diferente. Eso es un cambio de configuración, no una reescritura. La API de este sitio habla el protocolo de completación de chat de OpenAI, por lo que LangChain lo trata como cualquier otro servidor de estilo OpenAI.
Necesitas la URL base, tu clave de API y el ID del modelo uncensored. Instala los paquetes primero:
pip install -U langchain-openai langgraphLuego crea el objeto del modelo:
import os
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.nofilteraichat.com/v1",
api_key=os.environ["NOFILTER_API_KEY"],
temperature=0.8,
)
reply = llm.invoke("Write a two-sentence villain monologue for a heist novel.")
print(reply.content)Esa es toda la integración. Cada función de LangChain basada en ChatOpenAI ahora se ejecuta contra el modelo sin censura: cadenas, recuperadores que llaman al modelo de chat, analizadores de salida y agentes. Si aún no tienes una clave, la página de clave de API explica el registro y el crédito de prueba con un clic.
Mantén la clave fuera de tu código
Coloca la clave en una variable de entorno y léela al inicio. En Linux o macOS:
export NOFILTER_API_KEY="paste-your-key-here"Crea un único módulo de cliente compartido para el proyecto, por ejemplo llm.py que construya el modelo una vez y lo exporte. Cada cadena luego importa el mismo objeto, y un cambio posterior de clave, tiempo de espera o temperatura ocurre en un solo lugar. Esto también facilita mantener una segunda instancia más fría para pasos de herramientas y una más cálida para escritura creativa, ambas apuntando al mismo endpoint con configuraciones diferentes.
Una trampa atrapa a mucha gente: ChatOpenAI también lee OPENAI_API_KEY y OPENAI_API_BASE del entorno. Si esas variables están configuradas para otro proyecto, un objeto parcialmente configurado puede enviar tu petición al servidor equivocado. Pasar base_url y api_key explícitamente, como arriba, elimina la ambigüedad.
Puedes confirmar la conexión sin LangChain en absoluto. El endpoint de modelos debería devolver una única entrada:
curl https://api.nofilteraichat.com/v1/models \
-H "Authorization: Bearer $NOFILTER_API_KEY"Si eso funciona pero LangChain falla, el problema está en tu entorno de Python, no en la clave. Si ambas fallan con 401, busca un espacio o salto de línea extraño en la clave. La guía de inicio rápido lista el formato exacto de la petición para comparación.
Streaming y uso de tokens
Las interfaces de chat se sienten mejor cuando los tokens aparecen a medida que se generan. LangChain expone eso a través de .stream(), y el servidor envía fragmentos SSE estándar cuando stream: true está configurado internamente.
from langchain_openai import ChatOpenAI
import os
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.nofilteraichat.com/v1",
api_key=os.environ["NOFILTER_API_KEY"],
stream_usage=True,
)
final = None
for chunk in llm.stream("Describe a rainy harbour town in four sentences."):
print(chunk.content, end="", flush=True)
final = chunk if final is None else final + chunk
print()
print(final.usage_metadata)Con stream_usage=True el último fragmento lleva los recuentos de tokens de entrada y salida, que la API envía al final del streaming. Guarda esos números. Es la forma más barata de ver cuánto cuesta realmente un agente, y los usamos en la sección de costes a continuación.
Una cosa a recordar: una petición en streaming mantiene su ranura de concurrencia hasta que termina el streaming. Si abandonas un streaming sin cerrarlo, esa ranura permanece ocupada más tiempo del esperado.
Node y TypeScript
El paquete de JavaScript usa un nombre de opción ligeramente diferente. La URL base va dentro de configuration:
npm install @langchain/openai @langchain/coreimport { ChatOpenAI } from "@langchain/openai";
const llm = new ChatOpenAI({
model: "uncensored",
apiKey: process.env.NOFILTER_API_KEY,
configuration: { baseURL: "https://api.nofilteraichat.com/v1" },
temperature: 0.8,
});
const res = await llm.invoke("Give me three names for a smuggler's ship.");
console.log(res.content);Los tipos de TypeScript para la respuesta son las clases de mensaje habituales de LangChain, por lo que el código existente que lee res.content o res.usage_metadata sigue funcionando. Cuando ejecutes esto dentro de una ruta de servidor, construye el modelo una vez en el ámbito del módulo en lugar de por petición. Eso evita crear un nuevo cliente HTTP para cada llamada y mantiene tu concurrencia fácil de razonar.
Todo lo demás, incluyendo .stream(), .bindTools() y .withStructuredOutput(), se comporta de la misma manera que en Python. Temperatura, top_p, secuencias de parada, semilla y las opciones de penalización se pasan al modelo, por lo que puedes establecerlas en el constructor como lo harías para cualquier otro backend de estilo OpenAI.
Llamadas a funciones y un agente pequeño
La API admite llamadas a funciones: los campos tools y tool_choice, el streaming de tool_calls y los resultados de las herramientas devueltos como mensajes role: "tool". El agente preconstruido de LangGraph usa exactamente ese bucle. Aquí tienes un agente con una herramienta:
import os
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
@tool
def roll_dice(sides: int) -> int:
"""Roll a die with the given number of sides."""
import random
return random.randint(1, sides)
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.nofilteraichat.com/v1",
api_key=os.environ["NOFILTER_API_KEY"],
)
agent = create_react_agent(llm, [roll_dice])
out = agent.invoke(
{"messages": [("user", "Roll a twenty-sided die twice and tell me the total.")]}
)
print(out["messages"][-1].content)El uso de herramientas con modelos de pesos abiertos es menos predecible que con un modelo destacado alojado, así que trátalo como algo que debes probar. Escribe las descripciones de las herramientas en palabras sencillas, mantén los esquemas de argumentos pequeños y establece temperature en un valor bajo (0.2 a 0.4) para los pasos del agente que deben producir argumentos válidos. Si una llamada devuelve un formato incorrecto, LangChain lo muestra como una llamada a herramienta inválida, y un reintento con una descripción más clara suele solucionarlo.
Mantén el bucle del agente acotado. LangGraph tiene un límite de recursión, y debes establecerlo en un número que puedas permitirte. Si un agente puede llamar a herramientas para siempre, un prompt malo puede consumir créditos mientras estás lejos del teclado. Un límite de 10 a 15 pasos es un valor predeterminado sensato para la mayoría de las tareas, y puedes pasarlo en la configuración cuando invoques al agente.
Salida estructurada
El modo JSON está disponible a través de response_format. En LangChain, pídelo con el método de modo JSON y nombra las claves en tu prompt:
from pydantic import BaseModel
from langchain_openai import ChatOpenAI
import os
class Character(BaseModel):
name: str
role: str
secret: str
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.nofilteraichat.com/v1",
api_key=os.environ["NOFILTER_API_KEY"],
)
structured = llm.with_structured_output(Character, method="json_mode")
print(structured.invoke(
"Return JSON with keys name, role and secret for a noir detective."
))Límites de peticiones, reintentos y coste
Una clave completa permite 8 peticiones simultáneas y 300 peticiones por minuto. Una clave de prueba permite 2 y 60. Cuando excedes cualquiera de estos límites, la API responde con HTTP 429 y un código de error: rate_limited para peticiones por minuto, concurrency para demasiadas a la vez. Una sobrecarga temporal también devuelve 429, con un encabezado Retry-After: 5.
LangChain te da dos perillas para esto. max_retries en el modelo reintenta las llamadas fallidas con retroceso, y max_concurrency en la configuración de ejecución limita el trabajo paralelo por lotes:
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.nofilteraichat.com/v1",
api_key=os.environ["NOFILTER_API_KEY"],
max_retries=4,
timeout=120,
)
answers = llm.batch(
["Prompt one", "Prompt two", "Prompt three", "Prompt four"],
config={"max_concurrency": 6},
)Establecer max_concurrency en 6 en una clave completa deja margen para un segundo proceso. Recuerda que cada paso de agente es una petición separada, y un paso en streaming ocupa su ranura hasta que termina el streaming.
Cuánto cuesta una ejecución de agente
Los precios son $0.15 por 1M de tokens de entrada y $0.50 por 1M de tokens de salida. Supongamos que un paso de agente envía 3,000 tokens de historial, herramientas e instrucciones, y el modelo genera 500 tokens. La entrada cuesta 3,000 × $0.15 / 1,000,000 = $0.00045. La salida cuesta 500 × $0.50 / 1,000,000 = $0.00025. Un paso cuesta $0.0007. Una ejecución de diez pasos cuesta $0.007, y 1,000 de esas ejecuciones cuestan $7.00.
Los agentes reenvían su historial creciente en cada paso, por lo que los tokens de entrada dominan. Recortar la salida de herramientas antigua es la optimización más barata que tienes. Las peticiones fallidas o rechazadas no se cobran. Los detalles de las recargas y bonificaciones están en la página de precios.
Problemas comunes
- 404 en cada llamada. La URL base debe terminar en
/v1y no debe incluir/chat/completions. LangChain añade la ruta por sí misma. - Modelo no encontrado. El único ID de modelo es
uncensored. Nombres como gpt-4o no funcionarán. - Errores de contexto. La ventana es de 100.000 tokens para prompt más finalización. Las cadenas de recuperación largas pueden excederla. Resume o recorta antes de enviar.
- Petición demasiado grande. El límite del cuerpo es 8 MB, lo cual importa si metes documentos enteros en un prompt.
- Fallo de embeddings. Esta API es solo chat de texto. Mantén tu modelo de embeddings en otro proveedor y usa este endpoint para la generación.
El mismo patrón funciona para otros marcos y interfaces de chat; la guía de integración cubre más clientes. Para cualquier cosa inusual, la página de soporte es el lugar para empezar.
