В процессе работы с фреймворком LangChain была обнаружена существенная проблема в чат-классах, таких как ChatOpenAI и ChatDeepSeek, при интеграции с различными провайдерами и агрегаторами LLM. Ни один из них не сохраняет содержимое блока рассуждений (reasoning content) в финальном ответе. Это увеличивает время ожидания ответа и ухудшает пользовательский опыт в ИИ-приложениях, использующих модели с цепочками рассуждений (CoT).
В статье описывается способ решения этой проблемы на примере модели stepfun/step-3.5-flash и провайдера polza.ai.
Почему все так? Путаница в стандартах
При разработке ИИ-ассистента для инвестирования автор столкнулся с тем, что блок reasoning content теряется в процессе обработки. Первоначальная попытка использовать официальную библиотеку OpenAI не позволила в полной мере задействовать возможности LangChain и LangGraph в MVP-решении. Анализ проблемы выявил следующее.
ChatOpenAI не будет добавляться поддержка полей ответа reasoning_content, reasoning, reasoning_details или других полей, специфичных для конкретного поставщика услуг. ChatOpenAI будет ориентирован на официальную спецификацию API завершения чата OpenAI. reasoning_content не является частью этой спецификации — это нестандартное расширение, разработанное DeepSeek и принятое другими поставщиками (OpenRouter, vLLM, xAI и т. д.), которые используют формат завершения чата. Каждый поставщик также реализует его немного по-разному (reasoning_content vs reasoning vs reasoning_details), и эти поля продолжают развиваться (например, vLLM перешёл с reasoning_content на reasoning). Добавление поддержки этих полей в ChatOpenAI означало бы: Поддержание постоянно растущего набора сопоставлений полей, специфичных для каждого поставщика услуг. Мы неявно обязуемся отслеживать изменения у поставщиков услуг, которые мы не контролируем. Создание ChatOpenAI по сути универсального адаптера, что не является его предназначением.
Разработчики LangChain предлагают использовать специализированные чат-классы, например ChatDeepSeek или ChatOpenRouter. Однако большинство провайдеров придерживаются стандарта OpenAI Chat Completion API. Возникает противоречие: с одной стороны — отсутствие поля в официальной спецификации, с другой — его активное использование в экосистеме.
Как всё исправить?
Решение требует внесения изменений в исходный код модуля langchain_openai/chat_models/base.py. Необходимо модифицировать две функции: convert_dict_to_message и convert_delta_to_message_chunk.
После внесения правок блок рассуждений будет сохраняться в поле additional_kwargs как при обычном, так и при потоковом вызове модели.
Проблема потери reasoning content в CoT-моделях при использовании LangChain остаётся актуальной. Официальное исправление может появиться не скоро, но разработчики могут применить локальный патч уже сейчас.
Изменение минимальное и не нарушает архитектуру фреймворка. Оно позволяет извлекать важные данные из ответов CoT-моделей и улучшает функциональность ИИ-приложений.
Если у вас есть альтернативные способы решения или вы столкнулись с трудностями при реализации — делитесь в обсуждении.