RU ▾

Настройка прокси API в популярных фреймворках: от SDK до Dify

Для подключения прокси API нужны всего три значения: адрес API, ключ и имя модели. Сложность в том, что в разных фреймворках эти параметры называются по-разному: где-то base_url, где-то api_base, а в Dify — это целая форма. В этой статье мы сопоставили все параметры, привели рабочий код и добавили чек-лист для последовательного поиска ошибок.

Обновлено

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

  1. Храните адрес и ключ в переменных окружения API_BASE и API_KEY, чтобы они не отображались в коде открытым текстом.
  2. Адрес API должен заканчиваться на /v1, имя модели всегда указывается как uncensored.
  3. В LangChain используется base_url, а в LlamaIndex (OpenAILike) — api_base. Названия разные, но смысл одинаковый.
  4. В Dify выберите провайдера «OpenAI-API-compatible», вручную укажите имя модели, адрес и длину контекста.

Подготовьте три обязательных значения

Независимо от выбранного фреймворка, сначала убедитесь, что у вас есть эти три значения. Дальнейшая настройка — это просто заполнение полей.

  • Адрес API: https://api.llmzhongzhuan.com/v1. Оставьте /v1, но не добавляйте /chat/completions — SDK сам соберёт путь.
  • Ключ: отображается сразу после регистрации по email и паролю на странице получения ключа. У каждого аккаунта свой ключ, его можно сбросить; старый ключ перестаёт действовать сразу после сброса.
  • Имя модели: только одно — uncensored. Вы можете проверить это самостоятельно через GET /v1/models.

Кроме того, запомните несколько ограничений: общая длина контекста — 100 000 токенов, значение max_tokens по умолчанию равно 2048, максимум — 32 000, лимит запросов — 300 запросов в минуту на один ключ. Эти цифры будут неоднократно встречаться в настройках параметров ниже.

Синтаксис переменных окружения

Самая частая причина сбоев — жёсткая привязка ключа в коде. Рекомендуемый подход: читать только переменные окружения, а при развёртывании вставлять их через контейнер или систему управления секретами. В примерах для всех фреймворков используются переменные API_KEY и API_BASE.

# Linux / macOS:写进 ~/.zshrc 或 .env 加载脚本
export API_KEY="替换为你的密钥"
export API_BASE="https://api.llmzhongzhuan.com/v1"

# Windows PowerShell(仅当前会话)
$env:API_KEY = "替换为你的密钥"
$env:API_BASE = "https://api.llmzhongzhuan.com/v1"

Если вы используете файл .env, не забудьте добавить его в .gitignore. Официальный SDK для Python по умолчанию считывает переменные OPENAI_API_KEY и OPENAI_BASE_URL. Вы можете использовать эти переменные или явно передать параметры в конструктор, как показано ниже. Явная передача параметров защищает от влияния оставшихся в системе старых переменных и упрощает отладку.

OpenAI Python SDK и Node SDK

Для Python требуется версия v1 или выше пакета openai, для Node.js — v4 или выше. Разница только в синтаксисе: при создании клиента достаточно передать адрес и ключ. Сначала рассмотрим нестриминговый вызов на Python с выводом usage для контроля списаний:

import os
from openai import OpenAI

client = OpenAI(
    base_url=os.environ.get("API_BASE", "https://api.llmzhongzhuan.com/v1"),
    api_key=os.environ["API_KEY"],
)

resp = client.chat.completions.create(
    model="uncensored",
    messages=[{"role": "user", "content": "写一条 20 字以内的发布公告标题。"}],
    max_tokens=100,
)
print(resp.choices[0].message.content)
print(resp.usage)

Пример на Node.js использует потоковую передачу (streaming), что является стандартным способом реализации эффекта «печатающей машинки» во фронтенде. В конце потока сервер автоматически отправляет фрагмент с usage, дополнительные параметры не нужны:

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: process.env.API_BASE ?? "https://api.llmzhongzhuan.com/v1",
  apiKey: process.env.API_KEY,
});

const stream = await client.chat.completions.create({
  model: "uncensored",
  messages: [{ role: "user", content: "列出三个命名服务端日志字段的好习惯。" }],
  stream: true,
  max_tokens: 300,
});

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
process.stdout.write("\n");

Пример на Node.js использует top-level await. Для этого нужен файл с расширением .mjs или настройка "type": "module" в package.json. Если ваш рантайм не поддерживает это, оберните код в async-функцию.

LangChain: base_url для ChatOpenAI

В LangChain не нужны специальные адаптеры. Просто используйте класс ChatOpenAI из пакета langchain_openai и укажите ему параметр base_url.

import os
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="uncensored",
    base_url=os.environ.get("API_BASE", "https://api.llmzhongzhuan.com/v1"),
    api_key=os.environ["API_KEY"],
    temperature=0.7,
    max_tokens=500,
    timeout=60,
)

print(llm.invoke("把“服务已降级”改写成对用户友好的一句话。").content)

Два важных замечания. Во-первых, параметры max_tokens и timeout лучше задавать явно, так как значения по умолчанию могут не подходить для вашей задачи. Во-вторых, если вы используете вызов функций в цепочке, наш API поддерживает формат OpenAI tools, поэтому метод bind_tools в LangChain работает корректно. При потоковой передаче просто обрабатывайте данные по фрагментам в методе stream().

LlamaIndex: OpenAILike

Встроенный класс OpenAI в LlamaIndex проверяет, входит ли имя модели в официальный список, и выдаёт ошибку для кастомных моделей. В этом случае следует использовать класс OpenAILike из пакета llama-index-llms-openai-like. Он не проводит эту проверку, но использует другие имена параметров: адрес называется api_base.

import os
from llama_index.llms.openai_like import OpenAILike

llm = OpenAILike(
    model="uncensored",
    api_base=os.environ.get("API_BASE", "https://api.llmzhongzhuan.com/v1"),
    api_key=os.environ["API_KEY"],
    is_chat_model=True,
    context_window=100000,
    max_tokens=500,
)

print(llm.complete("用一句话解释什么是幂等请求。"))

Параметр is_chat_model=True здесь критически важен: он указывает LlamaIndex использовать интерфейс чата, а не устаревший интерфейс дополнения. Установите context_window равным 100000, чтобы LlamaIndex не обрезал ваш документ по умолчанию (обычно он ограничивается несколькими тысячами токенов).

Dify: провайдер OpenAI-API-compatible

Визуальные платформы вроде Dify не требуют кода, а настраиваются через формы. Интерфейс может немного отличаться в разных версиях, но шаги одинаковы:

  1. Перейдите в «Настройки», найдите раздел «Поставщики моделей», выберите в списке «OpenAI-API-compatible» и нажмите «Добавить модель».
  2. Тип модели выберите «LLM», а в поле имени модели введите uncensored.
  3. В поле API Key введите ваш ключ, а в поле API endpoint URL — https://api.llmzhongzhuan.com/v1.
  4. В поле длины контекста модели укажите 100000, а в поле максимального лимита токенов — 32000.
  5. Если вы планируете использовать вызов функций в рабочих процессах, включите поддержку function calling. Потоковую передачу (streaming) также следует оставить включённой.
  6. После сохранения создайте простое чат-приложение, выберите добавленную модель и отправьте сообщение, чтобы убедиться, что ответ приходит корректно.

Платформа может отправить тестовый запрос при сохранении. Если это не удалось, скорее всего, вы добавили лишний путь к адресу или в ключ попали лишние пробелы. Если Dify запущен в контейнере, убедитесь, что контейнер имеет доступ к внешним доменам.

Параметры и настройки развёртывания перед запуском

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

  • max_tokens: по умолчанию 2048. Для длинных ответов увеличьте это значение явно, максимум — 32,000. Учтите, что сумма входных и выходных токенов не должна превышать 100,000, иначе вы получите ошибку 400.
  • timeout: запросы с длинными ответами выполняются дольше. В сценариях потоковой передачи рекомендуется установить таймаут чтения не менее 60 секунд, для нестриминговых запросов ориентируйтесь на максимальное время генерации.
  • temperature / top_p / stop: эти стандартные параметры выборки передаются напрямую. Значения, заданные во фреймворке, применяются сразу, дополнительные переключатели не нужны.
  • Параллельные запросы: лимит составляет 300 запросов в минуту на один ключ. Если несколько экземпляров сервиса используют один ключ, лимит считается суммарно. Не рассчитывайте на 300 запросов для каждого экземпляра отдельно.
  • Повторные попытки: встроенные механизмы повторных попыток обычно обрабатывают только сетевые ошибки. Для кодов 429 и 503 необходимо реализовать собственную политику backoff. Пример реализации см. в разделе о стабильности.

При развёртывании в контейнере подход тот же: «ключ не должен быть в образе», он должен внедряться оркестратором при запуске. Вот минимальная конфигурация для docker-compose:

# docker-compose.yml 片段
services:
  app:
    image: your-app:latest
    environment:
      API_BASE: https://api.llmzhongzhuan.com/v1
      API_KEY: ${API_KEY}   # 从宿主机环境或 .env 读取,不写进镜像

В Kubernetes используйте ссылку на Secret, принцип остаётся прежним. Также рекомендуется использовать разные учётные записи или ключи для разных сред (например, для разработки, пре-продакшена и продакшена). Так утечка ключа или исчерпание баланса в одной среде не повлияют на работу основной. Поскольку у каждого аккаунта только один ключ, для нескольких сред лучше создать несколько аккаунтов и заранее пополнить их балансы.

Наконец, о логировании. Многие фреймворки в режиме отладки выводят полные заголовки запросов, включая Authorization. Обязательно отключите этот вывод в продакшене или настройте фильтрацию для маскировки ключа. Запись поля usage — хорошая практика: она поможет свериться со счётом и вовремя заметить, если промпт для какой-то функции внезапно стал слишком длинным.

Порядок устранения ошибок

90% проблем на этапе подключения сосредоточены в нескольких местах. Для быстрого поиска следуйте этому порядку:

  1. 401: API-ключ пустой, при копировании попали пробелы либо вы продолжаете использовать старый ключ после его сброса.
  2. 404: В адресе указана корневая директория без /v1 либо дважды указан путь /chat/completions.
  3. 402: Код ошибки no_credit означает, что баланс исчерпан или пробный период истёк; необходимо пополнить предоплаченный баланс.
  4. 400: Чаще всего это связано с тем, что значение параметра max_tokens превышает 100,000 либо тело запроса превышает 8 MB.
  5. 429 / 503: первый код означает лимит запросов в 300 запросов в минуту, второй — upstream_busy. Подождите несколько секунд и повторите запрос; подробности см. в разделе стабильность API.

Есть ещё один часто упускаемый из виду фактор — сетевая среда. Корпоративная сеть, прокси-серверы или правила групп безопасности могут приводить к тому, что DNS-имя разрешается успешно, но HTTPS-соединение не устанавливается. Это проявляется в виде длительных зависаний и таймаута, а не явного кода ошибки. В таких случаях сначала попробуйте выполнить запрос к /v1/models с помощью curl на том же компьютере: если соединение устанавливается, проблема на уровне приложения; если нет — проверьте прокси и брандмауэр. Зафиксируйте порядок действий в документации команды, чтобы новым сотрудникам было проще подключиться в будущем.

Если все три значения указаны верно, но запрос всё равно не выполняется, сначала выполните прямой запрос через curl, чтобы исключить проблемы самого фреймворка. Если хотите узнать, как именно работает прокси, ознакомьтесь со статьёй Принцип работы прокси.

Часто задаваемые вопросы

Нужно ли указывать /v1 в base_url?

Да. Укажите https://api.llmzhongzhuan.com/v1; SDK автоматически добавит к нему /chat/completions, поэтому не дублируйте путь.

Почему в LlamaIndex используется класс OpenAILike, а не OpenAI?

Класс OpenAI проверяет, входит ли имя модели в официальный список; для пользовательских моделей возникает ошибка. Класс OpenAILike не выполняет проверку, что лучше подходит для подключения к совместимым интерфейсам.

Можно ли произвольно указывать имя модели в Dify?

Нет, имя модели должно быть uncensored, так как запрос передаёт этот идентификатор без изменений. Отображаемое имя можно задать отдельно, но поле модели должно совпадать.

Почему изменения переменных окружения не вступают в силу?

Чаще всего причина в том, что терминал или процесс не были перезапущены. Рекомендуется явно передавать base_url и api_key в коде, а также выводить в лог фактический адрес для проверки.

Заполните форму, чтобы получить ключ

Создайте аккаунт, скопируйте ключ, измените Base URL. Настройка именно такая простая.

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