Начиная приложение на LangChain, сначала обычно настраивают ключ, а не пишут цепочку. Один и тот же код у кого-то работает локально, но после развёртывания даёт 401; кто-то вставляет ключ в Notebook и забывает удалить. Проблема чаще не во фреймворке, а в источнике ключа, порядке загрузки и границах прав.

Разберём порядок «источник — настройка — изоляция — ротация — диагностика» и объясним, как управлять API Key в проекте LangChain. Конкретные модели, квоты и цены — на странице цены на модели и в документации используемого провайдера.

Примечание: LangChain — товарный знак LangChain, Inc. Материал носит технический характер и не означает подчинения или партнёрства с LangChain, Inc.; поведение пакетов интеграции может меняться от версии к версии — сверяйтесь с документацией соответствующей версии.

1. Важно сразу разделить: LangChain не выдаёт ключи моделей

LangChain — открытый фреймворк разработки приложений, который связывает модели, инструменты, поиск и оркестрацию процессов. Обычно он не включает квоту на вызовы моделей, поэтому «ключа модели LangChain» не существует. Учётные данные, которые вы передаёте в LangChain, на самом деле принадлежат провайдеру модели, облачной платформе или AI-шлюзу.

В проекте обычно есть как минимум три типа учётных данных с разным назначением:

Учётные данные Назначение Где получить
API Key модели Вызов чата, рассуждений, Embedding и других моделей Консоль провайдера модели или AI-шлюза
LANGCHAIN_API_KEY Трассировка и оценка в LangSmith LangSmith, только если включена наблюдаемость
Учётные данные облака Доступ к размещённым моделям или ресурсам Консоль управления соответствующего облака

Если смешать три типа в один ключ, права окажутся слишком широкими, а ротация — сложной. Сначала разделите их по назначению, затем настраивайте.

2. Переменные окружения: соглашения по умолчанию и явная передача

ChatOpenAI из langchain-openai по умолчанию читает OPENAI_API_KEY, а OpenAI-совместимая точка входа задаётся параметром base_url. Минимальная рабочая конфигурация:

import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI

# Читаем .env рядом с проектом; в продакшене лучше системные переменные или менеджер секретов
load_dotenv()

llm = ChatOpenAI(
    model=os.environ["ZSQH_MODEL"],       # ID модели — по странице тарифов
    api_key=os.environ["ZSQH_API_KEY"],   # можно использовать и OPENAI_API_KEY по умолчанию
    base_url="https://ai.zhongshangqihang.com/v1",
    temperature=0,
)

print(llm.invoke("Объясни в одном предложении, что такое API-шлюз").content)

Несколько деталей, которые легко упустить:

  • Переменные окружения читаются при создании клиента, а не при импорте модуля. Если в Notebook присвоить os.environ по ходу работы, экземпляр ChatOpenAI нужно создать заново.
  • Явно переданная пустая строка перекрывает переменную окружения. При диагностике 401 сначала поищите в коде остатки вроде api_key="".
  • Разные пакеты интеграции читают разные имена переменных; у Anthropic и Google свои соглашения — сверяйтесь с их документацией.
  • init_chat_model умеет единообразно создавать модели разных провайдеров, но дополнительные параметры и переменные по умолчанию всё равно определяются нижней интеграцией; после обновления проверяйте поведение повторно.

3. .env и SecretStr: две линии защиты локальной разработки

Для локальной разработки удобен .env, но нужны два правила.

Первое: .env никогда не попадает в систему контроля версий. Добавьте его в .gitignore при инициализации проекта и закоммитьте .env.example без реальных значений, чтобы новые участники знали набор переменных. Если файл уже был ошибочно закоммичен, удаление не очищает историю: немедленно отзовите ключ, затем разбирайтесь с историей репозитория.

Второе: понимайте SecretStr в LangChain. Поле ключа в ChatOpenAI обычно хранится как SecretStr и при печати объекта или записи в лог отображается маской, а не открытым текстом. Это защищает от части случайных утечек, но не от явного get_secret_value(), ручной сборки заголовков или печати всего запроса в исключении. Не считайте, что «фреймворк маскирует данные» означает «можно логировать всё подряд».

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

4. Несколько провайдеров и моделей: один ключ или несколько?

Ответ зависит от того, един ли вход. При использовании AI-шлюза обычно один ключ шлюза даёт доступ к нескольким моделям, а модель выбирается параметром model; при прямом подключении нескольких провайдеров чаще нужен отдельный ключ для каждого.

Давайте переменным читаемые имена и фиксируйте их в команде:

  • Шлюз: ZSQH_API_KEY, ZSQH_BASE_URL.
  • Провайдеры: имена, принятые пакетом интеграции, например ANTHROPIC_API_KEY, GOOGLE_API_KEY.
  • Суффикс среды: _DEV, _STAGING, _PROD, чтобы тестовый ключ не попал в продакшен.

К нескольким моделям относятся и fallback с маршрутизацией. В LangChain можно использовать .with_fallbacks(), чтобы переключиться на резервную модель при сбое основной, но резервные модели тоже нужно отдельно авторизовать. Не предполагайте, что «один ключ вызывает все модели»: у шлюза может быть белый список, а ключ провайдера — доступ только к части моделей. Доступные ID — на странице цены на модели.

5. Минимальные права: ключи по средам и назначению

Цель управления ключами — не «чем меньше, тем лучше», а «чем яснее границы, тем лучше». Практические шаги:

  • Для разработки, предпродакшена и продакшена — отдельные ключи; продакшен-ключ не хранится на машине разработчика.
  • Для каждого приложения и участника — отдельный ключ, общие ключи запрещены.
  • Тестовым ключам задайте меньший бюджет и ограничьте список моделей.
  • Если консоль поддерживает белый список IP, напоминания о квоте или список моделей — включите всё.
  • В логах, тикетах и скриншотах оставляйте только последние символы ключа.

Если шлюз умеет считать расход по ключам, один ключ служит и для учёта затрат, и для локализации сбоев; общий «универсальный ключ» делает аномальный счёт неатрибутируемым.

6. Ротация и отзыв: сначала новый, потом переключение, затем отзыв

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

  1. Создайте в консоли новый ключ с датой или версией в имени, например prod-app-202610.
  2. Запишите новый ключ в менеджер секретов или переменные окружения платформы развёртывания.
  3. Перезапустите или переразверните приложение и убедитесь, что новый процесс загрузил новое значение.
  4. Отправьте реальный запрос и проверьте, что модель отвечает, а расход учитывается на новом ключе.
  5. Понаблюдайте некоторое время: не осталось ли старых экземпляров, которые ещё вызывают API.
  6. Только после проверки отзовите старый ключ и обновите внутренний реестр.

Если ключ читается из переменных окружения, менять код обычно не нужно, но требуется перезапуск или постепенное развёртывание. Долгоживущие соединения и постоянные процессы могут удерживать старый ключ, поэтому перед отзывом убедитесь, что все экземпляры заменены.

7. CI и командная работа: не пускайте ключи в логи

CI одновременно выполняет код автоматически и хранит логи, поэтому это зона повышенного риска утечки. Несколько базовых правил:

  • Ключ хранится в зашифрованном Secret CI-платформы, а не открытым текстом в файле пайплайна.
  • Отключите отладочные опции, печатающие команды, чтобы set -x не вывел заголовки запроса.
  • Для CI создайте отдельный ключ с низкой квотой и ограниченным списком моделей.
  • Используйте сканер секретов перед коммитом и блокируйте при обнаружении похожего на ключ значения.
  • На код-ревью считайте .env, конфигурационные файлы и снимки тестов чувствительными.

В документе передачи команде укажите ответственного за ключ, назначение, дату создания, дату следующей ротации и порядок отзыва при увольнении или потере устройства.

8. Диагностика: сначала переменные, потом протокол

При ошибке авторизации идите по порядку — обычно это быстрее, чем заново создавать ключ:

  1. Убедитесь, что переменная попала в процесс: печатайте только факт наличия, не значение. В Notebook перезапустите ядро, в контейнере проверьте, что переменная внедрена в нужный сервис.
  2. Проверьте явное перекрытие: нет ли в коде или конфигурации пустого api_key или неверного base_url.
  3. Сверьте путь протокола: OpenAI-совместимая точка входа обычно заканчивается на /v1; лишний или недостающий сегмент даёт 404.
  4. Сверьте ID модели: отображаемое имя не равно API-идентификатору; сравнивайте посимвольно со страницей тарифов.
  5. Разделяйте по статусу: 401 — сам ключ, 403 — права и список моделей, 429 — параллелизм и квота, 5xx — сначала повтор и сохранение времени запроса.
  6. Проверьте сеть и прокси: переменные прокси и корпоративные сертификаты могут ломать запрос, а сообщение будет похоже на ошибку авторизации.

Меняйте по одной переменной за раз. Сначала ключ, потом модель — так быстро видно, «этот ключ не работает» или «эта модель недоступна».

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

Нужен ли LangChain собственный API Key?

Самому фреймворку — нет. Учётные данные нужны только для вызова удалённых моделей, сервиса Embedding или наблюдаемости LangSmith.

Переменная задана, но всё равно возвращается 401. Почему?

Четыре частые причины: переменная действует только в текущем терминале, ядро Notebook не перезапущено, код явно передаёт пустой ключ, в ключе есть пробелы или переводы строк. Сначала убедитесь, что переменная видна процессу, затем проверьте, не перекрыта ли она кодом.

Может ли один ключ вызывать несколько моделей?

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

Попадает ли ключ в трассировки LangSmith?

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

Нужно ли менять код после ротации ключа?

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

Что дальше

Управление ключами в LangChain сводится к четырём тезисам: ключ принадлежит провайдеру модели, а не фреймворку; локально — .env, в продакшене — менеджер секретов; ключи разделяются по средам и назначению; при ротации сначала создаётся новый, затем отзывается старый. Если нужен единый вход к моделям и управление расходом по ключам, зарегистрируйтесь в ZSQH AI Gateway; модели и цены — на странице цены на модели.

Читайте также: