LangChain и китайские модели: собираем пайплайн
Пайплайн из отдельных блоков: замена провайдера не ломает остальную цепочку

Проект на LangChain уже работает с OpenAI, а теперь нужно добавить DeepSeek, Qwen или GLM. Первая мысль — переписывать цепочки целиком. На практике чаще всего хватает замены провайдера: LangChain китайские модели подключает через OpenAI-совместимый интерфейс. Ниже — как собрать такой пайплайн и что проверить до продакшена.

Почему при смене модели всё рвётся

Код, который вызывал OpenAI, написан под конкретные ответы. Он ждёт определённое поле в ответе, своё поведение при вызове инструментов, знакомый формат стриминга. Как только модель меняется, часть этих ожиданий перестаёт выполняться, и падает не запрос, а разбор результата.

Обычно проблема прячется в трёх местах.

  • Адрес и ключ. Клиент смотрит на api.openai.com, а модель живёт за другим адресом.
  • Схема ответа. Формат вызова функции или структурированного вывода у разных моделей отличается.
  • Настройки по умолчанию. Лимиты, таймауты, размер контекста у новой модели свои.

Ни один пункт не требует переписывать логику. Требуется изолировать слой, который знает про конкретную модель.

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

Провайдер и модель: что это в терминах LangChain

В LangChain есть абстракция чат-модели. Вы работаете с ней одинаково: собираете список сообщений, вызываете invoke или stream, получаете ответ. Провайдер — это адаптер, который переводит ваш вызов в HTTP-запрос к конкретному API и разбирает ответ обратно.

Держите эту границу в голове, и смена модели перестаёт быть переписыванием кода. Меняется адаптер, остальные шаги цепочки остаются на месте. Это тот же подход, что работает и при переходе с одного SDK на другой: меняется точка подключения, а не вся логика вокруг неё.

OpenAI-совместимый путь: меняем base_url

Если модель отдаётся по OpenAI-совместимому протоколу, отдельный класс не нужен. Достаточно указать базовый адрес и ключ. На примере пакета langchain-openai это выглядит так.

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
model="deepseek-chat",
base_url="https://адрес-шлюза/v1",
api_key="КЛЮЧ_ИЗ_ПЕРЕМЕННЫХ_ОКРУЖЕНИЯ",
)

answer = llm.invoke("Собери короткое описание товара по трём характеристикам")
print(answer.content)

Ключ лучше брать из переменных окружения, а не писать прямо в коде. Один и тот же объект дальше работает в цепочках и агентах, а также в вызовах инструментов, без изменений.

Когда base_url хватит, а когда нужна обёртка

Начните с простого варианта и не усложняйте, пока он работает.

  • OpenAI-совместимый адрес. Хватит смены base_url и имени модели.
  • Свой формат запроса. Если провайдер не повторяет протокол, напишите небольшой класс поверх базового и переведите вызов внутри него.
  • Инструменты и структурированный вывод. Проверьте отдельно: не все модели одинаково надёжно возвращают вызов функции. Это частая причина тихих ошибок.

Разница проявляется на реальных задачах, а не на демо из документации. Если цепочка использует агент с инструментами, прогоните отдельный сценарий именно для него.

Что проверить до продакшена

Смена модели меняет поведение системы, даже если код не тронут. Пройдитесь по короткому списку.

  1. Ключи вынесены в переменные окружения и не лежат в репозитории.
  2. Заданы лимиты на расход и таймауты на запрос.
  3. Есть обработка ошибок и повторные попытки для сетевых сбоев.
  4. Логируются запросы и ответы там, где это не нарушает правила по данным.
  5. Тестовый и рабочий контуры разнесены разными ключами.

Откат к прежней модели на этом этапе — правка одной строки в конфиге. Это и есть главная выгода аккуратного слоя.

Частые ошибки на старте

Большинство сбоев при первом подключении связаны не с моделью, а с настройкой вокруг неё.

  • Перепутаны ключи. Тестовый уходит в продакшен, рабочий — в скрипт проверки. Разведите их по разным переменным окружения.
  • Забыт префикс версии в адресе. Часть шлюзов ждёт путь с /v1, часть — без него. Сверьте адрес с документацией провайдера.
  • Проверка на одном запросе. Один удачный ответ ничего не говорит о поведении на потоке. Нужен набор запросов.
  • Молчаливый таймаут. Без явного лимита запрос ждёт слишком долго и роняет сценарий. Задайте таймаут и повтор.

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

Что можно применить прямо сейчас

Проверка не требует договора и предоплаты.

  1. Соберите набор из пятнадцати-двадцати реальных запросов, включая неудобные формулировки.
  2. Пропустите набор через новую модель и сравните ответы: где приходится править результат и сколько ждёт пользователь.
  3. Оставьте переключатель провайдера в конфиге, чтобы менять модель без выпуска новой версии.

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

Как это устроено в Китай-API

Мы делаем Китай-API — российский шлюз к китайским моделям DeepSeek, Qwen, GLM, Kimi. Для LangChain это привычный приём: один OpenAI-совместимый base_url, один ключ, тот же пакет. Вокруг — оплата в рублях и документы для бухгалтерии. Меняете адрес и модель, цепочка остаётся рабочей.

Платформа готовится, запуск — скоро. Заявку на ранний доступ можно оставить в Telegram-боте: напишем, когда откроем доступ первым. Как устроен шлюз, коротко на главной странице.

Про подключение и документы читайте в статье «API китайских моделей в России», про переход кода — в разборе «OpenAI SDK и китайские модели», про выбор между моделями — в статье «Qwen или GLM».