Reasoning
Сквозной справочник по reasoning- и thinking-возможностям LLM-моделей у разных провайдеров.
Обзор
Reasoning (у некоторых провайдеров — «thinking») позволяет моделям продемонстрировать пошаговый ход рассуждений перед выдачей итогового ответа. Эта возможность доступна у нескольких провайдеров, но реализована по-разному.
Meridian приводит все провайдер-специфичные форматы reasoning к единой OpenAI-совместимой структуре: поле reasoning в запросе и reasoning_details в ответе.
Матрица поддержки провайдерами
| Провайдер | Поле запроса | Поле ответа | Минимальный бюджет | Уровни effort | Streaming |
|---|---|---|---|---|---|
| OpenAI | reasoning | reasoning_details | нет | minimal, low, medium, high | ✅ |
| Anthropic | thinking | content-блоки | 1024 токенов | только enabled | ✅ |
| Bedrock (Anthropic) | thinking | content-блоки | 1024 токенов | только enabled | ✅ |
| Gemini 2.5+ | thinking_config | thought-части | 1024 | только бюджет | ✅ |
| Gemini 3.0+ | thinking_config | thought-части | 1024 | minimal, low, medium, high + бюджет | ✅ |
Конфигурация запроса
Chat Completions API
{
"model": "provider/model-name",
"messages": [...],
"reasoning": {
"effort": "high",
"max_tokens": 4096
}
}Responses API
{
"model": "provider/model-name",
"input": [...],
"reasoning": {
"effort": "high",
"max_tokens": 4096,
"summary": "detailed"
}
}Responses API принимает те же effort и max_tokens, что и Chat Completions, и дополнительно поддерживает необязательный параметр summary для суммаризации reasoning-вывода.
Справочник параметров
Параметры Chat Completions API
| Параметр | Тип | Описание |
|---|---|---|
effort | string | Уровень интенсивности reasoning |
max_tokens | int | Максимум токенов под reasoning (бюджет) |
Параметры Responses API
| Параметр | Тип | Описание |
|---|---|---|
effort | string | Уровень интенсивности reasoning |
max_tokens | int | Максимум токенов под reasoning (бюджет) |
summary | string | Уровень суммаризации: brief, detailed или json |
Responses API принимает те же параметры effort и max_tokens, что и Chat Completions, плюс необязательный summary для суммаризации reasoning-вывода.
Преобразования под конкретных провайдеров
OpenAI
OpenAI использует только effort-режим. Meridian применяет следующий приоритет:
- Если задан
reasoning.effort→ используется напрямую. - Иначе если задан
reasoning.max_tokens→ effort оценивается из него. - Поле
max_tokensудаляется перед отправкой в OpenAI.
Примеры преобразований:
// Запрос Meridian (с effort)
{
"reasoning": {
"effort": "high"
}
}
// Запрос, отправленный в OpenAI
{
"reasoning": {
"effort": "high"
}
}// Запрос Meridian с effort (нативное поле)
chatReq := &schemas.BifrostChatRequest{
Provider: schemas.OpenAI,
Model: "gpt-4o",
Input: messages,
Params: &schemas.ChatParameters{
MaxCompletionTokens: schemas.Ptr(4096),
Reasoning: &schemas.ChatReasoning{
Effort: schemas.Ptr("high"),
},
},
}
// OpenAI получает effort напрямую, max_tokens очищается// Запрос Meridian (только max_tokens)
{
"max_completion_tokens": 4096,
"reasoning": {
"max_tokens": 3000
}
}
// Оценка: ratio = 3000/4096 ≈ 0.73 → "high"
// Запрос, отправленный в OpenAI
{
"reasoning": {
"effort": "high"
}
}// Запрос Meridian только с max_tokens
chatReq := &schemas.BifrostChatRequest{
Provider: schemas.OpenAI,
Model: "gpt-4o",
Input: messages,
Params: &schemas.ChatParameters{
MaxCompletionTokens: schemas.Ptr(4096),
Reasoning: &schemas.ChatReasoning{
MaxTokens: schemas.Ptr(3000),
},
},
}
// Meridian оценивает effort из max_tokens
// ratio = 3000/4096 ≈ 0.73 → effort = "high"
// OpenAI получает effort, max_tokens очищаетсяПоддерживаемые уровни effort: minimal, low, medium, high.
Значение minimal при маршрутизации к не-OpenAI провайдерам конвертируется в low. Сам OpenAI принимает только low, medium, high.
Anthropic
Anthropic использует параметр thinking с другой структурой.
// Запрос Meridian
{
"reasoning": {
"effort": "high",
"max_tokens": 4096
}
}
// Запрос Anthropic
{
"thinking": {
"type": "enabled",
"budget_tokens": 4096
}
}// Ответ Anthropic (content-блоки)
{
"content": [
{
"type": "thinking",
"thinking": "Разберу шаг за шагом...",
"signature": "EqoBCkgIAR..."
},
{
"type": "text",
"text": "Ответ — 42."
}
]
}
// Ответ Meridian
{
"choices": [{
"message": {
"content": "Ответ — 42.",
"reasoning": "Разберу шаг за шагом...",
"reasoning_details": [{
"index": 0,
"type": "text",
"text": "Разберу шаг за шагом...",
"signature": "EqoBCkgIAR..."
}]
}
}]
}Правила преобразования:
| Meridian | Anthropic | Примечание |
|---|---|---|
reasoning.effort | thinking.type | всегда мапится в "enabled" |
reasoning.max_tokens | thinking.budget_tokens | бюджет токенов под reasoning |
Критичное ограничение: Anthropic требует reasoning.max_tokens >= 1024. Запросы с меньшим значением завершатся ошибкой.
Обработка динамического бюджета:
| Входное значение | Преобразуется в |
|---|---|
-1 (динамический) | 1024 (минимум по умолчанию) |
< 1024 | Ошибка |
>= 1024 | передаётся без изменений |
Ссылка на код: core/providers/anthropic/chat.go:104-134
Bedrock (модели Anthropic)
Bedrock для Claude-моделей использует ту же структуру, что и Anthropic.
// Запрос Meridian
{
"reasoning": {
"effort": "high",
"max_tokens": 4096
}
}
// Запрос Bedrock (для моделей Anthropic/Claude)
{
"additionalModelRequestFields": {
"reasoning_config": {
"type": "enabled",
"budget_tokens": 4096
}
}
}К моделям Anthropic в Bedrock применяется то же ограничение в 1024 токена. Попытка задать max_tokens ниже 1024 приведёт к ошибке.
Ссылка на код: core/providers/bedrock/utils.go:34-47
Bedrock (модели Nova)
Модели Bedrock Nova используют effort-подход, аналогичный OpenAI.
// Запрос Meridian
{
"reasoning": {
"effort": "high",
"max_tokens": 4096
}
}
// Запрос Bedrock (для моделей Nova)
{
"additionalModelRequestFields": {
"reasoningConfig": {
"type": "enabled",
"maxReasoningEffort": "high"
}
}
}| Effort в Meridian | Effort в Nova | Конфигурация |
|---|---|---|
minimal, low | "low" | обычные параметры разрешены |
medium | "medium" | обычные параметры разрешены |
high | "high" | очищаются maxTokens, temperature, topP |
Ключевые отличия от Anthropic:
- Нет минимального токен-бюджета.
- Используются уровни effort вместо токен-бюджета.
- Режим
highавтоматически очищает конфликтующие параметры.
Ссылка на код: core/providers/bedrock/utils.go:48-89
Gemini
Gemini использует thinking_config с двойной поддержкой токен-бюджетов и уровней effort — в зависимости от версии модели.
Поддержка по версиям моделей
| Версия Gemini | thinkingBudget | thinkingLevel | Примечание |
|---|---|---|---|
| 2.5+ | ✅ | ❌ | только бюджет |
| 3.0+ | ✅ | ✅ | бюджет и уровень |
Важно: Gemini принимает только ОДИН параметр за раз — либо thinkingBudget, либо thinkingLevel. Если в запросе Meridian заданы и reasoning.max_tokens, и reasoning.effort, приоритет у max_tokens, и он преобразуется в thinkingBudget.
Правила приоритета
Когда заданы и reasoning.max_tokens, и reasoning.effort:
1. Если задан max_tokens → ИСПОЛЬЗУЕТСЯ thinkingBudget (effort игнорируется)
2. Иначе если задан effort:
- Gemini 3.0+ → ИСПОЛЬЗУЕТСЯ thinkingLevel (нативный путь)
- Gemini 2.5 → effort КОНВЕРТИРУЕТСЯ в thinkingBudget
3. Иначе → reasoning отключён// Запрос Meridian — заданы оба поля
{
"model": "gemini-3.0-flash",
"reasoning": {
"effort": "high", // игнорируется
"max_tokens": 4096 // имеет приоритет
}
}
// Запрос в Gemini 3.0+ — отправляется только бюджет
{
"generation_config": {
"thinking_config": {
"include_thoughts": true,
"thinking_budget": 4096
}
}
}// Запрос Meridian — только effort
{
"model": "gemini-3.0-flash",
"reasoning": {
"effort": "high"
}
}
// Запрос в Gemini 3.0+ — конвертирован в level
{
"generation_config": {
"thinking_config": {
"include_thoughts": true,
"thinking_level": "high"
}
}
}// Запрос Meridian — только effort
{
"model": "gemini-2.5-flash",
"max_completion_tokens": 4096,
"reasoning": {
"effort": "high"
}
}
// Запрос в Gemini 2.5 — конвертирован в бюджет
// Расчёт: 1024 + (0.80 × (4096 - 1024)) = 3482
{
"generation_config": {
"thinking_config": {
"include_thoughts": true,
"thinking_budget": 3482
}
}
}Преобразования уровня под конкретные модели
У Pro-моделей Gemini действуют более жёсткие ограничения на thinking-уровни:
| Effort в Meridian | Не-Pro модели | Pro-модели | Примечание |
|---|---|---|---|
"none" | пустая строка | пустая строка | отключает thinking |
"minimal" | "minimal" | "low" | Pro не поддерживает minimal |
"low" | "low" | "low" | поддерживается везде |
"medium" | "medium" | "high" | Pro не поддерживает medium |
"high" | "high" | "high" | поддерживается везде |
Пример:
// Для "gemini-3.0-flash-thinking-exp" (не Pro)
effort: "medium" → thinkingLevel: "medium"
// Для "gemini-3.0-pro" (Pro-модель)
effort: "medium" → thinkingLevel: "high" // повышаетсяСпециальные значения
| Значение | Поле | Поведение | Сценарий |
|---|---|---|---|
0 | max_tokens | thinking_budget: 0, include_thoughts: false | явно отключить reasoning |
-1 | max_tokens | thinking_budget: -1 | динамический бюджет (Gemini сам решает) |
"none" | effort | thinking_budget: 0, include_thoughts: false | отключить reasoning |
// Запрос Meridian — динамический бюджет
{
"reasoning": {
"max_tokens": -1
}
}
// Запрос Gemini — передаётся как есть
{
"generation_config": {
"thinking_config": {
"include_thoughts": true,
"thinking_budget": -1
}
}
}// Запрос Meridian — способ 1
{
"reasoning": {
"max_tokens": 0
}
}
// Запрос Meridian — способ 2
{
"reasoning": {
"effort": "none"
}
}
// Запрос Gemini — оба становятся
{
"generation_config": {
"thinking_config": {
"include_thoughts": false,
"thinking_budget": 0
}
}
}Преобразование ответа
// Ответ Gemini
{
"candidates": [{
"content": {
"parts": [
{
"thought": true,
"text": "Анализирую задачу..."
},
{
"text": "Ответ — 42."
}
]
}
}]
}
// Ответ Meridian
{
"choices": [{
"message": {
"content": "Ответ — 42.",
"reasoning": "Анализирую задачу...",
"reasoning_details": [{
"index": 0,
"type": "text",
"text": "Анализирую задачу..."
}]
}
}]
}// После вызова Meridian Chat Completions с Gemini
resp, err := client.ChatCompletionRequest(schemas.NewBifrostContext(ctx, schemas.NoDeadline), chatReq)
if err != nil {
log.Fatal(err)
}
// Извлечь reasoning из ответа
choice := resp.Choices[0]
message := choice.Message
// Объединённый текст рассуждений
fmt.Printf("Reasoning: %s\n", message.Reasoning)
// Детальные блоки reasoning
for i, details := range message.ReasoningDetails {
if details.Type == "text" {
fmt.Printf("Блок thinking %d:\n%s\n", i, details.Text)
}
}
// Итоговый ответ
fmt.Printf("Ответ:\n%s\n", message.Content)Сводка преобразований
Meridian → Gemini (запрос):
| Вход | Gemini 2.5 | Gemini 3.0+ | Примечание |
|---|---|---|---|
max_tokens: 4096 | thinking_budget: 4096 | thinking_budget: 4096 | прямой проброс |
max_tokens: -1 | thinking_budget: -1 | thinking_budget: -1 | динамический бюджет |
max_tokens: 0 | thinking_budget: 0 | thinking_budget: 0 | выключено |
только effort: "high" | thinking_budget: 3482* | thinking_level: "high" | оценка или нативный путь |
только effort: "medium" | thinking_budget: 2330* | thinking_level: "medium" или "high"** | оценка или нативный путь |
effort + max_tokens | используется max_tokens | используется max_tokens | правило приоритета |
* при max_completion_tokens: 8192 (по умолчанию), используется формула оценки.
** Pro-модели конвертируют "medium" в "high".
Gemini → Meridian (ответ):
| Поле Gemini | Поле Meridian | Преобразование |
|---|---|---|
thinking_budget | reasoning.max_tokens | прямое мапирование |
thinking_level | reasoning.effort | мапирование уровень → effort |
thought: true-части | reasoning_details[] | массив блоков reasoning |
Ссылки на код:
core/providers/gemini/utils.go(Chat Completions)core/providers/gemini/responses.go(Responses API)core/providers/gemini/types.go(константы)
Два подхода к reasoning: effort и max_tokens
Meridian поддерживает две разных модели reasoning у разных провайдеров:
Типы reasoning-моделей
| Модель | Провайдеры | Поле запроса | Нативный формат |
|---|---|---|---|
| На основе effort | OpenAI, AWS Bedrock Nova | reasoning.effort | reasoning_effort (Chat) / effort (Responses) |
| На основе max_tokens | Anthropic, Cohere, Gemini | reasoning.max_tokens | thinking.budget_tokens |
Важно: в одном запросе можно задать и effort, и max_tokens. Meridian использует иерархию приоритетов, чтобы решить, какое из полей применить.
Логика приоритета: нативное vs. оценочное
Когда заданы и effort, и max_tokens, Meridian отдаёт приоритет тому полю, которое нативно для целевого провайдера:
Для провайдеров на основе max_tokens (Anthropic, Cohere, Gemini)
1. Если задан reasoning.max_tokens → ИСПОЛЬЗУЕТСЯ ОНО (нативное поле)
2. Иначе если задан reasoning.effort → max_tokens ОЦЕНИВАЕТСЯ из effort
3. Иначе → reasoning отключёнПример (Cohere):
// Запрос с обоими полями
{
"reasoning": {
"effort": "high",
"max_tokens": 2000
}
}Результат: используется max_tokens: 2000 напрямую, effort игнорируется.
Для провайдеров на основе effort (OpenAI, AWS Bedrock Nova)
1. Если задан reasoning.effort → ИСПОЛЬЗУЕТСЯ ОНО (нативное поле)
2. Иначе если задан reasoning.max_tokens → effort ОЦЕНИВАЕТСЯ из max_tokens
3. Иначе → reasoning отключёнПример (OpenAI Chat Completions):
// Запрос с обоими полями
{
"reasoning": {
"effort": "high",
"max_tokens": 2000
}
}Результат: используется effort: "high" напрямую, max_tokens удаляется из JSON.
Функции-оценщики
Meridian предоставляет две функции для конвертации между подходами reasoning. Они вызываются, когда нативное поле недоступно.
Функция 1: effort → max_tokens
Функция: GetBudgetTokensFromReasoningEffort()
Файл: core/providers/utils/utils.go:1350-1387
Сигнатура:
func GetBudgetTokensFromReasoningEffort(
effort string, // "minimal", "low", "medium", "high"
minBudgetTokens int, // минимум провайдера (например, 1024 у Anthropic)
maxTokens int, // общий лимит токенов под completion
) (int, error)Алгоритм:
1. Соотношение для уровня effort:
- "minimal" → 2.5% (0.025)
- "low" → 15% (0.15)
- "medium" → 42.5% (0.425)
- "high" → 80% (0.80)
2. Расчёт бюджета:
budget = minBudgetTokens + (ratio × (maxTokens - minBudgetTokens))
3. Ограничение допустимым диапазоном:
если budget < minBudgetTokens → budget = minBudgetTokens
если budget > maxTokens → budget = maxTokensПримеры преобразования (minBudgetTokens=1024, maxTokens=4096):
| Effort | Соотношение | Расчёт | Результат |
|---|---|---|---|
minimal | 2.5% | 1024 + 0.025 × 3072 | 1101 → 1024* |
low | 15% | 1024 + 0.15 × 3072 | 1485 |
medium | 42.5% | 1024 + 0.425 × 3072 | 2330 |
high | 80% | 1024 + 0.80 × 3072 | 3482 |
*Если результат ниже минимума, он подтягивается к minBudgetTokens (для Anthropic — 1024).
Обработка ошибок:
if minBudgetTokens > maxTokens {
return 0, fmt.Errorf("max_tokens must be > minBudgetTokens")
}Пример вызова:
// Cohere: конвертация effort в токен-бюджет
budgetTokens, err := providerUtils.GetBudgetTokensFromReasoningEffort(
"high", // effort
1, // минимум Cohere
4096, // лимит токенов под completion
)
// Возвращает: 3277 токеновФункция 2: max_tokens → effort
Функция: GetReasoningEffortFromBudgetTokens()
Файл: core/providers/utils/utils.go:1308-1345
Сигнатура:
func GetReasoningEffortFromBudgetTokens(
budgetTokens int, // токен-бюджет под reasoning
minBudgetTokens int, // минимум провайдера
maxTokens int, // общий лимит токенов под completion
) string // возвращает: "low", "medium", "high"Алгоритм:
1. Привести бюджет к допустимому диапазону:
если budget < min → budget = min
если budget > max → budget = max
2. Рассчитать соотношение:
ratio = (budgetTokens - minBudgetTokens) / (maxTokens - minBudgetTokens)
3. Сопоставить соотношение с уровнем effort:
если ratio ≤ 0.25 → "low"
если ratio ≤ 0.60 → "medium"
если ratio > 0.60 → "high"Примеры преобразования (minBudgetTokens=1024, maxTokens=4096):
| Бюджет токенов | Соотношение | Effort |
|---|---|---|
| 1024 | 0% | low |
| 1101 | 2.5% | low |
| 1500 | 15.6% | low |
| 1900 | 28.6% | medium |
| 2500 | 48.1% | medium |
| 3000 | 64.5% | high |
| 3400 | 77.6% | high |
Защитные значения по умолчанию:
if budgetTokens <= 0 {
return "none"
}
if maxTokens <= 0 {
return "medium" // безопасный дефолт
}
if maxTokens <= minBudgetTokens {
return "high" // соотношение посчитать невозможно
}Пример вызова:
// Конвертировать бюджет Anthropic обратно в effort для отображения
effort := providerUtils.GetReasoningEffortFromBudgetTokens(
3000, // токен-бюджет из ответа Anthropic
1024, // минимум Anthropic
4096, // лимит токенов
)
// Возвращает: "high"Константы по провайдерам
У разных провайдеров — разные ограничения на reasoning-бюджет.
Минимальные значения бюджета
| Провайдер | Файл | MinBudgetTokens | Причина |
|---|---|---|---|
| Anthropic | core/providers/anthropic/types.go | 1024 | требование Anthropic API |
| Bedrock Anthropic | core/providers/bedrock/types.go | 1024 | то же, что у Anthropic |
| Bedrock Nova | core/providers/bedrock/types.go | 1 | гибче |
| Cohere | core/providers/cohere/types.go | 1 | гибко |
| Gemini | core/providers/gemini/types.go | 1024 | дефолтный минимум для конвертаций |
Лимит completion-токенов по умолчанию (для расчёта соотношения)
Если max_completion_tokens не задан, используются эти значения:
| Провайдер | По умолчанию | Файл |
|---|---|---|
| OpenAI, Anthropic, Cohere, Bedrock | 4096 | core/providers/*/types.go |
| Gemini | 8192 | core/providers/gemini/types.go |
Примеры конвертации effort ↔ токены
Пример 1: оценка токенов из effort (Anthropic)
Вход:
{
"model": "anthropic/claude-3-5-sonnet",
"max_completion_tokens": 2000,
"reasoning": {
"effort": "high"
}
}Процесс конвертации:
effort = "high"→ratio = 0.80minBudgetTokens = 1024(Anthropic)maxCompletionTokens = 2000budget = 1024 + (0.80 × (2000 - 1024))budget = 1024 + (0.80 × 976)budget = 1024 + 780- Результат: 1804 токена
Сгенерированный запрос Anthropic:
{
"thinking": {
"type": "enabled",
"budget_tokens": 1804
}
}Пример 2: оценка effort из токенов (Bedrock Nova)
Вход:
{
"model": "bedrock/us.amazon.nova-pro-v1:0",
"max_completion_tokens": 4096,
"reasoning": {
"max_tokens": 2000
}
}Процесс конвертации:
budgetTokens = 2000minBudgetTokens = 1(Nova)maxCompletionTokens = 4096ratio = (2000 - 1) / (4096 - 1)ratio = 1999 / 4095ratio = 0.488(48.8%)- Поскольку
0.25 < 0.488 ≤ 0.60→ Результат: "medium"
Сгенерированный запрос Bedrock Nova:
{
"reasoningConfig": {
"type": "enabled",
"maxReasoningEffort": "medium"
}
}Пример 3: оба поля заданы (применён приоритет)
Вход:
{
"model": "anthropic/claude-3-5-sonnet",
"max_completion_tokens": 4096,
"reasoning": {
"effort": "medium",
"max_tokens": 2500
}
}Логика для провайдера на основе max_tokens:
- Проверка: задан ли
max_tokens? → ДА - Использовать
max_tokensнапрямую (игнорироватьeffort). - Валидация:
2500 >= 1024? → ДА
Сгенерированный запрос Anthropic:
{
"thinking": {
"type": "enabled",
"budget_tokens": 2500
}
}Примечание: effort: "medium" полностью игнорируется, потому что приоритет у max_tokens.
Формат ответа
Стандартный ответ Meridian
Все провайдеры возвращают reasoning в нормализованном массиве reasoning_details:
{
"choices": [{
"message": {
"role": "assistant",
"content": "Итоговый текст ответа",
"reasoning_details": [
{
"index": 0,
"type": "text",
"text": "Пошаговый ход рассуждений...",
"signature": "необязательная_подпись_для_верификации"
}
]
}
}]
}Поля reasoning_details
| Поле | Тип | Описание | Где встречается |
|---|---|---|---|
index | int | позиция в последовательности reasoning | везде |
type | string | тип содержимого (text, encrypted, summary) | везде |
text | string | содержимое reasoning | Chat Completions |
summary | string | суммаризация reasoning | Responses API |
signature | string | криптографическая подпись для верификации | Anthropic, Bedrock |
Сопоставление типов
| Тип reasoning | Когда применяется | Источник |
|---|---|---|
reasoning.text | прямой текст thinking/reasoning | Anthropic, Gemini, Bedrock |
reasoning.encrypted | reasoning с подписью | Anthropic, Bedrock Nova |
reasoning.summary | суммаризованный reasoning (Responses API) | все провайдеры |
Реализация OpenAI: OpenAI (и Chat Completions, и Responses API) работает на основе effort и следует стандартной логике приоритета: если задан effort, он используется напрямую; если задан только max_tokens, effort оценивается из него. Поле max_tokens затем удаляется перед сериализацией в JSON через MarshalJSON (core/providers/openai/types.go:383-453), поскольку API OpenAI его не принимают.
Streaming
Типы событий стрима
| Провайдер | Событие reasoning | Событие подписи |
|---|---|---|
| OpenAI | reasoning (на верхнем уровне) | — |
| Anthropic | thinking_delta | signature_delta |
| Bedrock | thinking_delta | signature_delta |
| Gemini | thought (внутри content) | thought_signature |
Пример streaming у Anthropic
// События стрима
event: content_block_start
data: {"type": "content_block_start", "content_block": {"type": "thinking"}}
event: content_block_delta
data: {"type": "content_block_delta", "delta": {"type": "thinking_delta", "thinking": "Сейчас"}}
event: content_block_delta
data: {"type": "content_block_delta", "delta": {"type": "thinking_delta", "thinking": " разберу..."}}
event: content_block_delta
data: {"type": "content_block_delta", "delta": {"type": "signature_delta", "signature": "EqoB..."}}
event: content_block_stop
data: {"type": "content_block_stop"}Ответ Meridian в стриме
// Дельта thinking
{
"choices": [{
"delta": {
"reasoning_details": [{
"index": 0,
"type": "text",
"text": "Сейчас разберу..."
}]
}
}]
}
// Дельта подписи
{
"choices": [{
"delta": {
"reasoning_details": [{
"index": 0,
"signature": "EqoB..."
}]
}
}]
}Сводка ограничений
Полное сравнение провайдеров
Модель reasoning
| Провайдер | Тип модели | Тип бюджета | Минимальный бюджет | Поддержка подписи |
|---|---|---|---|---|
| OpenAI | на основе effort | на основе effort | нет | ❌ |
| Anthropic | thinking-блоки | токен-бюджет | 1024 | ✅ |
| Bedrock (Anthropic) | reasoning_config | токен-бюджет | 1024 | ✅ |
| Bedrock (Nova) | reasoning_config | на основе effort | нет | ❌ |
| Gemini 2.5+ | thinking_config | токен-бюджет | 1024 | ✅ |
| Gemini 3.0+ | thinking_config | двойной (бюджет + уровень) | 1024 | ✅ |
Поддержка параметров
| Провайдер | effort | max_tokens | summary | Streaming |
|---|---|---|---|---|
| OpenAI | ✅ (4 уровня) | ✅ | ❌ | ✅ |
| Anthropic | ❌ (бинарный) | ✅ | ✅ | ✅ |
| Bedrock (Anthropic) | ❌ (бинарный) | ✅ | ✅ | ✅ |
| Bedrock (Nova) | ✅ (3 уровня) | ⚠️ (игнорируется) | ❌ | ✅ |
| Gemini 2.5+ | ⚠️ (конвертируется в бюджет) | ✅ | ❌ | ✅ |
| Gemini 3.0+ | ✅ (4 уровня) | ✅ | ❌ | ✅ |
Устранение неполадок
Anthropic: reasoning.max_tokens must be >= 1024
Причина: попытка использовать reasoning с max_tokens < 1024.
Решение: для моделей Anthropic и Bedrock Anthropic задавайте reasoning.max_tokens >= 1024.
// ❌ Неверно
{"reasoning": {"effort": "high", "max_tokens": 500}}
// ✅ Верно
{"reasoning": {"effort": "high", "max_tokens": 1024}}OpenAI: модель не поддерживает reasoning
Причина: используется устаревшая модель без поддержки reasoning (например, gpt-4-turbo).
Решение: используйте модели с поддержкой reasoning: gpt-4o, gpt-4o-mini (серия o1 с нативным reasoning).
Bedrock Nova: параметр max_tokens игнорируется
Ожидаемое поведение: Bedrock Nova работает только в режиме на основе effort.
Решение: для моделей Nova передавайте effort, а не max_tokens.
// ✅ Корректно для Nova
{"reasoning": {"effort": "high"}}