RU ▾
Получить API-ключ

Используйте ChatOpenAI в LangChain с API без цензуры

Класс ChatOpenAI в LangChain работает с любым эндпоинтом, совместимым с OpenAI, поэтому вам нужно изменить только базовый URL, ключ и имя модели. На этой странице показана настройка в Python и Node, затем мы переходим к потоковой передаче, инструментам и небольшому агенту.

Обновлено

Изометрическая цепочка связанных колец, передающих сообщения чата в серверный куб, представляющая подключение LangChain к API

Ключевые моменты

  1. ChatOpenAI требует трёх настроек: base_url, api_key и model со значением uncensored.
  2. Потоковая передача, вызов инструментов и JSON-режим проходят через стандартные интерфейсы LangChain.
  3. Ограничьте параллельные запросы до 8 и обрабатывайте HTTP 429 с повторными попытками, чтобы оставаться в пределах лимитов.
  4. Запуск агента из 10 шагов стоит менее цента при цене $0,15 и $0,50 за 1 млн токенов.

Краткий ответ: три настройки в ChatOpenAI

Если вы искали chat open ai langchain, вероятно, у вас уже есть проект LangChain, использующий ChatOpenAI, и вы хотите подключить его к другому бэкенду. Это изменение конфигурации, а не переписывание кода. API на этом сайте использует протокол chat completions от OpenAI, поэтому LangChain воспринимает его как любой другой сервер в стиле OpenAI.

Вам нужны базовый URL, ваш API-ключ и идентификатор модели uncensored. Сначала установите пакеты:

pip install -U langchain-openai langgraph

Затем создайте объект модели:

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)

Это вся интеграция. Каждая функция LangChain, построенная на ChatOpenAI, теперь работает с моделью uncensored: цепочки, ретриверы, вызывающие чат-модель, парсеры вывода и агенты. Если у вас ещё нет ключа, на странице API-ключа описаны регистрация и получение пробного баланса в один клик.

Не храните ключ в коде

Сохраните ключ в переменной окружения и прочитайте его при запуске. В Linux или на macOS:

export NOFILTER_API_KEY="paste-your-key-here"

Создайте один общий модуль клиента для проекта, например llm.py, который создаёт модель один раз и экспортирует её. Каждая цепочка импортирует один и тот же объект, и последующее изменение ключа, тайм-аута или температуры происходит в одном месте. Это также упрощает поддержание второго, более «холодного» экземпляра для шагов с инструментами и более «горячего» для творческого письма, оба указывающие на один и тот же эндпоинт с разными настройками.

Одна ловушка подстерегает многих: ChatOpenAI также читает OPENAI_API_KEY и OPENAI_API_BASE из окружения. Если эти переменные установлены для другого проекта, частично настроенный объект может отправить ваш запрос на неверный сервер. Явное указание base_url и api_key, как показано выше, устраняет неоднозначность.

Вы можете проверить соединение без LangChain вообще. Эндпоинт моделей должен вернуть одну запись:

curl https://api.nofilteraichat.com/v1/models \
  -H "Authorization: Bearer $NOFILTER_API_KEY"

Если это работает, но LangChain не работает, проблема в вашей Python-среде, а не в ключе. Если оба запроса возвращают ошибку 401, проверьте наличие лишнего пробела или символа новой строки в ключе. Быстрый старт содержит точный формат запроса для сравнения.

Потоковая передача и использование токенов

Чат-интерфейсы лучше воспринимаются, когда токены появляются по мере генерации. LangChain предоставляет доступ к этому через .stream(), а сервер отправляет стандартные фрагменты SSE, когда под капотом выставлен stream: true.

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)

С параметром stream_usage=True последний фрагмент содержит количество входных и выходных токенов, которые API отправляет в конце потока. Запоминайте эти числа. Это самый дешёвый способ узнать реальную стоимость работы агента, и мы используем их в разделе стоимости ниже.

Одна вещь, о которой следует помнить: потоковый запрос удерживает слот параллельных запросов до завершения потока. Если вы оставите поток без закрытия, этот слот будет занят дольше, чем вы ожидаете.

Node и TypeScript

Пакет JavaScript использует немного другое имя параметра. Базовый URL находится внутри configuration:

npm install @langchain/openai @langchain/core
import { 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);

Типы TypeScript для ответа — это обычные классы сообщений LangChain, поэтому существующий код, читающий res.content или res.usage_metadata, продолжает работать. При запуске этого кода внутри маршрута сервера создавайте модель один раз в области видимости модуля, а не для каждого запроса. Это позволяет избежать создания нового HTTP-клиента для каждого вызова и упрощает понимание параллелизма.

Всё остальное, включая .stream(), .bindTools() и .withStructuredOutput(), ведёт себя так же, как в Python. Температура, top_p, стоп-последовательности, seed и параметры штрафов передаются модели, поэтому вы можете установить их в конструкторе, как и для любого другого бэкенда в стиле OpenAI.

Вызов инструментов и небольшой агент

API поддерживает вызов инструментов: поля tools и tool_choice, потоковые tool_calls и результаты инструментов, возвращаемые как сообщения с role: "tool". Предварительно созданный агент LangGraph использует именно этот цикл. Вот агент с одним инструментом:

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)

Использование инструментов с моделями с открытыми весами менее предсказуемо, чем с флагманской хостинговой моделью, поэтому относитесь к этому как к чему-то, что нужно протестировать. Пишите описания инструментов простыми словами, держите JSON-схемы аргументов небольшими и устанавливайте temperature низким (0,2–0,4) для шагов агента, которые должны генерировать корректные аргументы. Если вызов возвращается в неверном формате, LangChain отображает его как неверный вызов инструмента, и повторная попытка с более чётким описанием обычно исправляет ситуацию.

Ограничьте цикл агента. LangGraph имеет лимит рекурсии, и вы должны установить его на число, которое можете себе позволить. Если агент может бесконечно вызывать инструменты, плохой промпт может быстро исчерпать баланс, пока вы отключились от клавиатуры. Лимит в 10–15 шагов — разумное значение по умолчанию для большинства задач, и вы можете передать его в конфигурации при вызове агента.

Структурированный вывод

JSON-режим доступен через response_format. В LangChain запросите его с помощью метода для JSON-режима и укажите имена ключей в вашем промпте:

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."
))

Лимиты запросов, повторные попытки и стоимость

Полный ключ позволяет 8 параллельных запросов и 300 запросов в минуту. Пробный ключ позволяет 2 и 60. При превышении любого из них API отвечает кодом HTTP 429 и кодом ошибки: rate_limited для запросов в минуту, concurrency для одновременных запросов. Временная перегрузка также возвращает 429 с заголовком Retry-After: 5.

LangChain предоставляет два параметра для этого. max_retries на модели повторяет неудачные вызовы с экспоненциальной задержкой (backoff), а max_concurrency в конфигурации выполнения ограничивает параллельную пакетную работу:

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},
)

Установка max_concurrency на 6 для полного ключа оставляет запас мощности для второго процесса. Помните, что каждый шаг агента — это отдельный запрос, а потоковый шаг занимает свой слот до завершения потока.

Сколько стоит запуск агента

Цены составляют $0,15 за 1M входных токенов и $0,50 за 1M выходных токенов. Предположим, шаг агента отправляет 3000 токенов истории, инструментов и инструкций, а модель генерирует 500 токенов. Входные данные стоят 3000 × $0,15 / 1 000 000 = $0,00045. Выходные данные стоят 500 × $0,50 / 1 000 000 = $0,00025. Один шаг стоит $0,0007. Запуск из десяти шагов стоит $0,007, а 1000 таких запусков стоят $7,00.

Агенты отправляют свою растущую историю на каждом шаге, поэтому входные токены доминируют. Удаление старых результатов инструментов — самая дешёвая оптимизация, которую вы можете сделать. Неудачные или отклонённые запросы не оплачиваются. Подробности о пополнении и бонусах на странице тарифов.

Распространённые проблемы

  • 404 при каждом вызове. Базовый URL должен заканчиваться на /v1 и не должен включать /chat/completions. LangChain добавляет путь самостоятельно.
  • Модель не найдена. Единственный идентификатор модели — uncensored. Имена вроде gpt-4o не сработают.
  • Ошибки контекста. Окно составляет 100 000 токенов для промпта и ответа. Длинные цепочки извлечения могут его превысить. Кратко изложите или сократите данные перед отправкой.
  • Запрос слишком большой. Лимит тела составляет 8 МБ, что важно, если вы вставляете целые документы в промпт.
  • Сбой эмбеддингов. Этот API предназначен только для текстового чата. Оставьте модель эмбеддингов у другого провайдера и используйте этот эндпоинт для генерации.

Та же схема работает для других фреймворков и интерфейсов чата; раздел руководство по интеграции охватывает больше клиентов. Для любых нестандартных случаев начните со страницы поддержки.

Вопросы и ответы

Можно ли использовать ChatOpenAI с пользовательским базовым URL?

Да. Укажите base_url (в Node — baseURL внутри конфигурации), ваш ключ и модель uncensored. LangChain безразлично, какой сервер отвечает, если он следует протоколу чата OpenAI.

Работает ли потоковая передача LangChain с этим API?

Да. API использует потоковую передачу через SSE и отправляет данные об использовании в конце, поэтому .stream() и astream() работают, а stream_usage=True предоставляет подсчёт токенов.

Можно ли использовать эмбеддинги или векторные хранилища LangChain с этим API?

Не подходит для эмбеддингов, так как API не имеет эндпоинта для эмбеддингов. Используйте другой источник эмбеддингов для поиска и отправьте найденный текст на этот эндпоинт для генерации.

Что происходит, когда я превышаю лимит запросов?

Вы получаете HTTP 429 с кодом rate_limited или concurrency. Установите max_retries в ChatOpenAI и ограничьте max_concurrency значением 8 или меньше для полного ключа.

Ваш ключ всего в одном шаге

Создайте аккаунт, скопируйте ключ, измените базовый URL. Это вся настройка.

Получить API-ключ