OpenAI SDK или LangChain: когда фреймворк нужен, а когда мешает

Один и тот же сценарий на чистом SDK и на LangChain: сколько кода, где проще отлаживать и как не потерять контроль над расходом токенов.

5 мин · · разработка · сравнение

Вопрос «openai sdk vs langchain» обычно задают в момент, когда пора выбирать основу для проекта: взять тонкую библиотеку и писать логику самому или подключить фреймворк с готовыми цепочками. Ответ зависит не от моды, а от того, что вы строите. Ниже один и тот же сценарий на OpenAI SDK и LangChain с Python: сравним объём кода, отладку и контроль токенов, а в конце сформулируем правило выбора.

Оба варианта работают с ключом fetch_... и адресом https://api.zukko.pro/v1: Zukko отдаёт OpenAI-совместимый API, поэтому менять придётся только base_url и имя модели.

Что такое OpenAI SDK и чем он отличается от LangChain

OpenAI SDK (пакет openai) — тонкая обёртка над HTTP-запросами: вы формируете список сообщений, вызываете метод, получаете ответ и поле usage с числом токенов. Всё, что происходит между вызовами, — ваш код.

LangChain — фреймворк поверх таких SDK. Он добавляет шаблоны промптов, парсеры ответов, цепочки, память, работу с векторными хранилищами и агентов. Модель в нём — один из взаимозаменяемых компонентов.

Короткая формула: SDK даёт один вызов, LangChain даёт каркас для нескольких вызовов и интеграций. Если вам нужен один вызов, каркас не нужен. Подробнее про сам SDK — в статье Python SDK: полный пример.

Один сценарий, два способа

Сценарий: получить на вход текст обращения клиента и вернуть JSON с категорией и приоритетом.

Чистый SDK

bash
import json
from openai import OpenAI

client = OpenAI(base_url="https://api.zukko.pro/v1", api_key="fetch_...")

def classify(text: str) -> dict:
    resp = client.chat.completions.create(
        model="gpt-6.1-sol",
        messages=[
            {"role": "system", "content": "Верни JSON: {\"category\": str, \"priority\": \"low|mid|high\"}"},
            {"role": "user", "content": text},
        ],
        response_format={"type": "json_object"},
    )
    print("токены:", resp.usage.prompt_tokens, resp.usage.completion_tokens)
    return json.loads(resp.choices[0].message.content)

print(classify("Не приходит письмо с подтверждением, а оплата уже прошла"))

Здесь видно всё: какие сообщения ушли, сколько токенов потрачено, что вернулось. Параметры запроса описаны в справочнике chat completions.

LangChain

bash
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import JsonOutputParser

llm = ChatOpenAI(
    model="gpt-6.1-sol",
    base_url="https://api.zukko.pro/v1",
    api_key="fetch_...",
)
prompt = ChatPromptTemplate.from_messages([
    ("system", "Верни JSON: {{\"category\": str, \"priority\": \"low|mid|high\"}}"),
    ("human", "{text}"),
])
chain = prompt | llm | JsonOutputParser()

print(chain.invoke({"text": "Не приходит письмо с подтверждением, а оплата уже прошла"}))

Строк примерно столько же. Выигрыша в объёме нет, а плюс появляется позже: цепочку prompt | llm | parser легко достроить следующим звеном. Минус — часть происходящего скрыта: итоговый текст промпта и usage придётся доставать отдельно (например, из AIMessage.usage_metadata, если вызвать модель без парсера). Названия классов и пакетов LangChain меняются от версии к версии, поэтому сверяйтесь с их документацией. Другой разбор подключения — в статье LangChain через шлюз.

Где фреймворк помогает

  • Несколько провайдеров в одном коде. Если вы хотите переключаться между моделями из разных семейств без переписывания вызовов. С Zukko это и так решается сменой строки model, но у LangChain есть готовые абстракции.
  • RAG и работа с документами. Загрузчики файлов, разбиение на куски, векторные хранилища — писать всё это с нуля долго.
  • Агенты с инструментами и состоянием. Если нужен граф шагов с ветвлением, готовые примитивы экономят время.
  • Команда уже знает фреймворк. Это законный довод: единый стиль дороже теоретической чистоты.

Где фреймворк мешает

  • Один-два вызова модели. Фреймворк тянет за собой дополнительные пакеты ради того, что делается пятнадцатью строками.
  • Отладка. Когда ответ странный, вам нужно увидеть точные сообщения, ушедшие в API. В чистом SDK это словарь в вашем коде, во фреймворке — результат работы нескольких слоёв.
  • Токены и деньги. Цепочка и агент делают столько вызовов, сколько им нужно, и каждый тащит накопленный контекст. Это видно, только если вы считаете.
  • Обновления. Интерфейсы фреймворка меняются, и код, написанный год назад, может потребовать правок. У тонкого SDK поверхность меньше.

Контроль токенов: считаем на примере

Пусть агент на LangChain делает пять шагов, и каждый шаг добавляет к контексту примерно 1000 токенов. Входы по шагам: 2000, 3000, 4000, 5000, 6000 токенов, итого 20 000. Выход — по 300 токенов на шаг, итого 1500.

Для gpt-6.1-sol (цены на 18 октября 2026: $0.27 за 1M входных, $1.32 за 1M выходных):

вход: 20 000 × 0.27 / 1 000 000 = $0.0054 выход: 1 500 × 1.32 / 1 000 000 = $0.00198 итого: ≈ $0.0074 за одну задачу

Сумма невелика, но если задачу вы считали как «один вызов по 2000 токенов» ($0.00054 на вход), реальный расход на вход выше в десять раз. Поэтому в любом варианте полезно:

  1. Логировать usage каждого вызова (в SDK это resp.usage, в LangChain — usage_metadata у сообщения).
  2. Смотреть расход в кабинете в разделе «Использование» и сравнивать с ожиданием.
  3. Заранее прикидывать размер запроса через эндпоинт подсчёта токенов.

Актуальные цены и список моделей — GET https://api.zukko.pro/v1/models или страница «Модели» в кабинете.

Простое правило выбора

СитуацияЧто взять
Один-три вызова модели, понятная логикачистый OpenAI SDK
Нужен жёсткий контроль токенов и отладкачистый SDK, фреймворк добавьте позже
RAG с несколькими источниками, готовые загрузчикиLangChain или аналог
Агент с ветвлением и состояниемфреймворк, но с логированием usage
Прототип на вечерчто быстрее для вас

Начинайте с SDK, а фреймворк подключайте, когда поймёте, какие именно его части вам нужны. Обратный путь (вырезать фреймворк из готового проекта) обычно дороже. Проверьте выбор на своей задаче: для небольшого сценария написать оба варианта несложно.

Чтобы попробовать, создайте ключ в кабинете и подставьте его вместе с адресом https://api.zukko.pro/v1 в любой из примеров выше. Документация по Python — здесь.

Частые вопросы

OpenAI SDK и LangChain можно использовать вместе?

Да. Частая схема: LangChain для загрузки документов и поиска, а сам вызов модели — через SDK или через ChatOpenAI с тем же base_url. Они не конфликтуют, оба ходят по одному ключу.

LangChain медленнее чистого SDK?

Сам по себе слой фреймворка добавляет небольшие накладные расходы на обработку, но основное время — ответ модели. Цифр мы не приводим: измерьте на своих данных. Заметнее разница в количестве вызовов, которые делает цепочка.

Нужно ли менять код, если сменить модель?

Для обоих вариантов достаточно заменить строку model, например на claude-sonnet-5-5 или deepseek-v4.1-flash. Если вы используете специфику одной модели (формат инструментов, кэш), проверьте поведение отдельно.

А если мне нужен формат Anthropic?

Тогда берите официальный Anthropic SDK с адресом https://api.zukko.pro без /v1. Это отдельный клиент, LangChain для него тоже имеет свой пакет, но проверяйте его документацию.

zukko

Платите в 25×
меньше

за Claude Code & ChatGPT

Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.