Токены мыслей
Для моделей, которые это поддерживают, API AITUNNEL может возвращать токены мыслей (reasoning tokens), также известные как thinking tokens. AITUNNEL нормализует различные способы настройки количества токенов рассуждений, которые будет использовать модель, предоставляя единый интерфейс для разных провайдеров.
Токены мыслей дают прозрачный взгляд на шаги рассуждений, которые делает модель. Токены мыслей считаются выходными токенами и оплачиваются соответственно.
Токены мыслей включены в ответ по умолчанию, если модель решает их вывести. Токены мыслей будут появляться в поле reasoning каждого сообщения, если вы не решите их исключить.
Некоторые reasoning-модели не возвращают токены мыслей
Хотя большинство моделей и провайдеров делают токены мыслей доступными в ответе, некоторые (например, OpenAI o-series) этого не делают.
Управление токенами мыслей
Вы можете управлять токенами мыслей в ваших запросах, используя параметр reasoning:
{
"model": "your-model",
"messages": [],
"reasoning": {
// Один из следующих (не оба):
"effort": "high", // Может быть "xhigh", "high", "medium", "low", "minimal" или "none" (стиль OpenAI)
"max_tokens": 2000, // Конкретный лимит токенов (стиль Anthropic)
// Опционально: по умолчанию false. Поддерживается всеми моделями.
"exclude": false, // Установите true, чтобы исключить токены мыслей из ответа
// Или включите рассуждения с параметрами по умолчанию:
"enabled": true // По умолчанию: выводится из `effort` или `max_tokens`
}
}Объект конфигурации reasoning объединяет настройки для управления силой рассуждений в разных моделях. Смотрите примечание для каждого варианта ниже, чтобы узнать, какие модели поддерживаются и как будут вести себя другие модели.
Максимальное количество токенов для рассуждений
Поддерживаемые модели
В настоящее время поддерживается:
- Gemini thinking-моделями
- Anthropic reasoning-моделями (через параметр
reasoning.max_tokens) - Некоторыми Alibaba Qwen thinking-моделями (маппится в
thinking_budget)
Для Alibaba поддержка зависит от модели — проверьте описание конкретной модели, доступен ли reasoning.max_tokens (через thinking_budget).
Для моделей, которые поддерживают выделение токенов для рассуждений, вы можете управлять этим следующим образом:
"max_tokens": 2000— напрямую указывает максимальное количество токенов для использования в рассуждениях
Для моделей, которые поддерживают только reasoning.effort (см. ниже), значение max_tokens будет использоваться для определения уровня усилий.
Уровень усилий рассуждений
Поддерживаемые модели
В настоящее время поддерживается моделями OpenAI reasoning (o1 series, o3 series, GPT-5 series) и Grok
"effort": "xhigh"— выделяет наибольшую часть токенов для рассуждений (примерно 95% от max_tokens)"effort": "high"— выделяет большую часть токенов для рассуждений (примерно 80% от max_tokens)"effort": "medium"— выделяет умеренную часть токенов (примерно 50% от max_tokens)"effort": "low"— выделяет меньшую часть токенов (примерно 20% от max_tokens)"effort": "minimal"— выделяет ещё меньшую часть токенов (примерно 10% от max_tokens)"effort": "none"— полностью отключает рассуждения
Для моделей, которые поддерживают только reasoning.max_tokens, уровень усилий будет установлен на основе процентов выше.
Исключение токенов мыслей
Если вы хотите, чтобы модель использовала рассуждения внутренне, но не включала их в ответ:
"exclude": true— модель всё равно будет использовать рассуждения, но они не будут возвращены в ответе
Токены мыслей будут появляться в поле reasoning каждого сообщения.
Включение рассуждений с конфигурацией по умолчанию
Чтобы включить рассуждения с параметрами по умолчанию:
"enabled": true— включает рассуждения на уровне усилий «medium» без исключений.
Примеры
Базовое использование с токенами мыслей
from openai import OpenAI
client = OpenAI(
base_url="https://api.aitunnel.ru/v1",
api_key="<AITUNNEL_API_KEY>",
)
response = client.chat.completions.create(
model="o3-mini",
messages=[
{"role": "user", "content": "Как бы вы построили самый высокий небоскреб в мире?"}
],
extra_body={
"reasoning": {
"effort": "high"
}
},
)
msg = response.choices[0].message
print(getattr(msg, "reasoning", None))
print(getattr(msg, "content", None))import OpenAI from "openai";
const openai = new OpenAI({
baseURL: "https://api.aitunnel.ru/v1",
apiKey: "<AITUNNEL_API_KEY>",
});
async function getResponseWithReasoning() {
const response = await openai.chat.completions.create({
model: "o3-mini",
messages: [
{
role: "user",
content: "Как бы вы построили самый высокий небоскреб в мире?",
},
],
reasoning: {
effort: "high",
},
});
type ReasoningMessage = (typeof response)["choices"][number]["message"] & {
reasoning?: string;
reasoning_details?: unknown;
};
const msg = response.choices[0].message as ReasoningMessage;
console.log("REASONING:", msg.reasoning);
console.log("CONTENT:", msg.content);
}
getResponseWithReasoning();Использование максимального количества токенов для рассуждений
Для моделей, которые поддерживают прямое выделение токенов (например, модели Anthropic), вы можете указать точное количество токенов для использования в рассуждениях:
from openai import OpenAI
client = OpenAI(
base_url="https://api.aitunnel.ru/v1",
api_key="<AITUNNEL_API_KEY>",
)
response = client.chat.completions.create(
model="claude-sonnet-4.5",
messages=[
{"role": "user", "content": "Какой самый эффективный алгоритм для сортировки большого набора данных?"}
],
extra_body={
"reasoning": {
"max_tokens": 2000
}
},
)
msg = response.choices[0].message
print(getattr(msg, "reasoning", None))
print(getattr(msg, "content", None))import OpenAI from "openai";
const openai = new OpenAI({
baseURL: "https://api.aitunnel.ru/v1",
apiKey: "<AITUNNEL_API_KEY>",
});
async function getResponseWithReasoning() {
const response = await openai.chat.completions.create({
model: "claude-sonnet-4.5",
messages: [
{
role: "user",
content: "Какой самый эффективный алгоритм для сортировки большого набора данных?",
},
],
reasoning: {
max_tokens: 2000,
},
});
type ReasoningMessage = (typeof response)["choices"][number]["message"] & {
reasoning?: string;
};
const msg = response.choices[0].message as ReasoningMessage;
console.log("REASONING:", msg.reasoning);
console.log("CONTENT:", msg.content);
}
getResponseWithReasoning();Исключение токенов мыслей из ответа
Если вы хотите, чтобы модель использовала рассуждения внутренне, но не включала их в ответ:
from openai import OpenAI
client = OpenAI(
base_url="https://api.aitunnel.ru/v1",
api_key="<AITUNNEL_API_KEY>",
)
response = client.chat.completions.create(
model="deepseek-r1",
messages=[
{"role": "user", "content": "Объясните квантовые вычисления простыми словами."}
],
extra_body={
"reasoning": {
"effort": "high",
"exclude": True
}
},
)
msg = response.choices[0].message
print(getattr(msg, "content", None))import OpenAI from "openai";
const openai = new OpenAI({
baseURL: "https://api.aitunnel.ru/v1",
apiKey: "<AITUNNEL_API_KEY>",
});
async function getResponseWithReasoning() {
const response = await openai.chat.completions.create({
model: "deepseek-r1",
messages: [
{
role: "user",
content: "Объясните квантовые вычисления простыми словами.",
},
],
reasoning: {
effort: "high",
exclude: true,
},
});
const msg = response.choices[0].message as {
content?: string | null;
};
console.log("CONTENT:", msg.content);
}
getResponseWithReasoning();Продвинутое использование: цепочка рассуждений
Этот пример показывает, как использовать токены мыслей в более сложном рабочем процессе. Он внедряет рассуждения одной модели в другую для улучшения качества ответа:
from openai import OpenAI
client = OpenAI(
base_url="https://api.aitunnel.ru/v1",
api_key="<AITUNNEL_API_KEY>",
)
question = "Что больше: 9.11 или 9.9?"
def do_req(model: str, content: str, reasoning_config: dict | None = None):
payload = {
"model": model,
"messages": [{"role": "user", "content": content}],
"stop": "</think>",
}
if reasoning_config:
payload.update(reasoning_config)
return client.chat.completions.create(**payload)
# Получить рассуждения от способной модели
content = f"{question} Пожалуйста, подумайте об этом, но не выводите ответ"
reasoning_response = do_req("deepseek-r1", content)
reasoning = getattr(reasoning_response.choices[0].message, "reasoning", "")
# Давайте проверим! Вот наивный ответ:
simple_response = do_req("gpt-4o-mini", question)
print(getattr(simple_response.choices[0].message, "content", None))
# Вот ответ с внедрённым токеном рассуждений:
content = f"{question}. Вот контекст, который поможет вам: {reasoning}"
smart_response = do_req("gpt-4o-mini", content)
print(getattr(smart_response.choices[0].message, "content", None))import OpenAI from "openai";
const openai = new OpenAI({
baseURL: "https://api.aitunnel.ru/v1",
apiKey: "<AITUNNEL_API_KEY>",
});
async function doReq(model, content, reasoningConfig) {
const payload = {
model,
messages: [{ role: "user", content }],
stop: "</think>",
...reasoningConfig,
};
return openai.chat.completions.create(payload);
}
async function getResponseWithReasoning() {
const question = "Что больше: 9.11 или 9.9?";
const reasoningResponse = await doReq(
"deepseek-r1",
`${question} Пожалуйста, подумайте об этом, но не выводите ответ`
);
const reasoning = reasoningResponse.choices[0].message.reasoning;
// Давайте проверим! Вот наивный ответ:
const simpleResponse = await doReq("gpt-4o-mini", question);
console.log(simpleResponse.choices[0].message.content);
// Вот ответ с внедрённым токеном рассуждений:
const content = `${question}. Вот контекст, который поможет вам: ${reasoning}`;
const smartResponse = await doReq("gpt-4o-mini", content);
console.log(smartResponse.choices[0].message.content);
}
getResponseWithReasoning();Сохранение рассуждений
Чтобы сохранить контекст рассуждений между несколькими ходами, вы можете передать его обратно в API одним из двух способов:
message.reasoning(string): передайте текст рассуждений как строковое поле в сообщении ассистентаmessage.reasoning_details(array): передайте полный блокreasoning_details
Используйте reasoning_details, когда работаете с моделями, которые возвращают специальные типы рассуждений (например, зашифрованные или суммаризированные) — это сохраняет полную структуру, необходимую для таких моделей.
Для моделей, которые возвращают только сырые строки рассуждений, можно использовать более простое поле reasoning. Также можно использовать reasoning_content как алиас — он работает идентично reasoning.
Поддержка моделей
Сохранение рассуждений в настоящее время поддерживается следующими проприетарными моделями:
- Все OpenAI reasoning-модели (o1 series, o3 series, GPT-5 series и новее)
- Все Anthropic reasoning-модели (Claude 3.7 series и новее)
- Все Gemini Reasoning-модели
- Все xAI reasoning-модели
И следующими open source моделями:
- Alibaba: Qwen3.5 и новее
- Arcee AI: Trinity Large Thinking и новее
- MiniMax: MiniMax M2 и новее
- MoonShot: Kimi K2 Thinking и новее
- NVIDIA: Nemotron 3 Nano и новее
- Prime Intellect: INTELLECT-3
- Xiaomi: MiMo-V2-Flash и новее
- Z.ai: GLM 4.5 и новее
Примечание: поддерживается только стандартное interleaved thinking. Функция preserved thinking для моделей Z.ai пока не поддерживается.
Функциональность reasoning_details работает одинаково для всех поддерживаемых reasoning-моделей. Вы можете легко переключаться между OpenAI reasoning-моделями (например, gpt-5) и Anthropic reasoning-моделями (например, claude-sonnet-4.5) без изменения структуры кода.
Сохранение блоков рассуждений особенно полезно для tool calling. Когда модели вроде Claude вызывают инструменты, они приостанавливают построение ответа, ожидая внешнюю информацию. Когда возвращаются результаты инструментов, модель продолжает строить существующий ответ. Это требует сохранения блоков рассуждений при использовании инструментов по двум причинам:
Непрерывность рассуждений: блоки рассуждений фиксируют пошаговое мышление модели, которое привело к запросам инструментов. При отправке результатов инструментов включение исходных рассуждений позволяет модели продолжить с того места, где она остановилась.
Поддержание контекста: хотя результаты инструментов появляются как сообщения пользователя в структуре API, они являются частью непрерывного потока рассуждений. Сохранение блоков рассуждений поддерживает этот концептуальный поток между несколькими вызовами API.
Важно для reasoning-моделей
При передаче блоков reasoning_details вся последовательность последовательных блоков рассуждений должна совпадать с выводом, сгенерированным моделью при исходном запросе; вы не можете переставлять или изменять последовательность этих блоков.
Пример: сохранение блоков рассуждений с Claude
from openai import OpenAI
client = OpenAI(
base_url="https://api.aitunnel.ru/v1",
api_key="<AITUNNEL_API_KEY>",
)
# Определите инструменты один раз и переиспользуйте
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Получить текущую погоду",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"}
},
"required": ["location"]
}
}
}]
# Первый вызов API с инструментами
response = client.chat.completions.create(
model="claude-sonnet-4.5",
messages=[
{"role": "user", "content": "Какая погода в Бостоне? Затем порекомендуй, что надеть."}
],
tools=tools,
extra_body={"reasoning": {"max_tokens": 2000}}
)
# Извлеките сообщение ассистента с reasoning_details
message = response.choices[0].message
# Сохраните полный reasoning_details при передаче обратно
messages = [
{"role": "user", "content": "Какая погода в Бостоне? Затем порекомендуй, что надеть."},
{
"role": "assistant",
"content": message.content,
"tool_calls": message.tool_calls,
"reasoning_details": message.reasoning_details # Передайте без изменений
},
{
"role": "tool",
"tool_call_id": message.tool_calls[0].id,
"content": '{"temperature": 45, "condition": "rainy", "humidity": 85}'
}
]
# Второй вызов API — Claude продолжает рассуждения с того места, где остановился
response2 = client.chat.completions.create(
model="claude-sonnet-4.5",
messages=messages,
tools=tools
)import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.aitunnel.ru/v1",
apiKey: "<AITUNNEL_API_KEY>",
});
// Определите инструменты один раз и переиспользуйте
const tools = [
{
type: "function",
function: {
name: "get_weather",
description: "Получить текущую погоду",
parameters: {
type: "object",
properties: {
location: { type: "string" },
},
required: ["location"],
},
},
},
] as const;
// Первый вызов API с инструментами
const response = await client.chat.completions.create({
model: "claude-sonnet-4.5",
messages: [
{
role: "user",
content: "Какая погода в Бостоне? Затем порекомендуй, что надеть.",
},
],
tools,
reasoning: { max_tokens: 2000 },
});
// Извлеките сообщение ассистента с reasoning_details
type ReasoningMessage = (typeof response)["choices"][number]["message"] & {
reasoning_details?: unknown;
};
const message = response.choices[0].message as ReasoningMessage;
// Сохраните полный reasoning_details при передаче обратно
const messages = [
{
role: "user" as const,
content: "Какая погода в Бостоне? Затем порекомендуй, что надеть.",
},
{
role: "assistant" as const,
content: message.content,
tool_calls: message.tool_calls,
reasoning_details: message.reasoning_details, // Передайте без изменений
},
{
role: "tool" as const,
tool_call_id: message.tool_calls?.[0]?.id,
content: JSON.stringify({
temperature: 45,
condition: "rainy",
humidity: 85,
}),
},
];
// Второй вызов API — Claude продолжает рассуждения с того места, где остановился
const response2 = await client.chat.completions.create({
model: "claude-sonnet-4.5",
messages,
tools,
});Подробнее о шифровании мышления, редактированных блоках и продвинутых сценариях см. документацию Anthropic по extended thinking.
Подробнее о reasoning-моделях OpenAI см. документацию OpenAI по reasoning.
Структура API reasoning_details
Когда reasoning-модели генерируют ответы, информация о рассуждениях структурируется в стандартизированном формате через массив reasoning_details. Этот раздел описывает структуру ответа API для reasoning details в streaming и non-streaming режимах.
Структура массива reasoning_details
Поле reasoning_details содержит массив объектов reasoning detail. Каждый объект представляет конкретный фрагмент информации о рассуждениях и следует одному из трёх возможных типов. Расположение массива различается между streaming и non-streaming ответами:
- Non-streaming ответы:
reasoning_detailsнаходится вchoices[].message.reasoning_details - Streaming ответы:
reasoning_detailsнаходится вchoices[].delta.reasoning_detailsдля каждого чанка
Общие поля
Все объекты reasoning detail имеют следующие общие поля:
id(string | null): уникальный идентификатор reasoning detailformat(string): формат reasoning detail, возможные значения:"unknown"— формат не указан"openai-responses-v1"— формат OpenAI responses version 1"azure-openai-responses-v1"— формат Azure OpenAI responses version 1"xai-responses-v1"— формат xAI responses version 1"anthropic-claude-v1"— формат Anthropic Claude version 1 (по умолчанию)"google-gemini-v1"— формат Google Gemini version 1
index(number, optional): последовательный индекс reasoning detail
Типы reasoning detail
1. Summary Type (reasoning.summary)
Содержит высокоуровневое резюме процесса рассуждения:
{
"type": "reasoning.summary",
"summary": "Модель проанализировала задачу, сначала определив ключевые ограничения, затем оценив возможные решения...",
"id": "reasoning-summary-1",
"format": "anthropic-claude-v1",
"index": 0
}2. Encrypted Type (reasoning.encrypted)
Содержит зашифрованные данные рассуждений, которые могут быть редактированы или защищены:
{
"type": "reasoning.encrypted",
"data": "eyJlbmNyeXB0ZWQiOiJ0cnVlIiwiY29udGVudCI6IltSRURBQ1RFRF0ifQ==",
"id": "reasoning-encrypted-1",
"format": "anthropic-claude-v1",
"index": 1
}3. Text Type (reasoning.text)
Содержит сырой текст рассуждений с опциональной проверкой подписи:
{
"type": "reasoning.text",
"text": "Давайте разберём это пошагово:\n1. Сначала мне нужно понять вопрос пользователя...",
"signature": "sha256:abc123def456...",
"id": "reasoning-text-1",
"format": "anthropic-claude-v1",
"index": 2
}Примеры ответов
Non-streaming ответ
В non-streaming ответах reasoning_details находится в сообщении:
{
"choices": [
{
"message": {
"role": "assistant",
"content": "На основе моего анализа я рекомендую следующий подход...",
"reasoning_details": [
{
"type": "reasoning.summary",
"summary": "Проанализировал задачу, разбив её на компоненты",
"id": "reasoning-summary-1",
"format": "anthropic-claude-v1",
"index": 0
},
{
"type": "reasoning.text",
"text": "Давайте разберём это систематически:\n1. Первое соображение...\n2. Второе соображение...",
"signature": null,
"id": "reasoning-text-1",
"format": "anthropic-claude-v1",
"index": 1
}
]
}
}
]
}Streaming ответ
В streaming ответах reasoning_details появляется в delta-чанках по мере генерации рассуждений:
{
"choices": [
{
"delta": {
"reasoning_details": [
{
"type": "reasoning.text",
"text": "Давайте подумаем об этом пошагово...",
"signature": null,
"id": "reasoning-text-1",
"format": "anthropic-claude-v1",
"index": 0
}
]
}
}
]
}Примечания по streaming-поведению:
- Каждый чанк reasoning detail отправляется, как только становится доступен
- Массив
reasoning_detailsв каждом чанке может содержать один или несколько объектов рассуждений - Для зашифрованных рассуждений содержимое может появляться как
[REDACTED]в streaming ответах - Полная последовательность рассуждений собирается конкатенацией всех чанков по порядку
Устаревшие параметры
Для обратной совместимости AITUNNEL всё ещё поддерживает следующие устаревшие параметры:
include_reasoning: true— эквивалентноreasoning: {}include_reasoning: false— эквивалентноreasoning: { exclude: true }
Однако мы рекомендуем использовать новый унифицированный параметр reasoning для лучшего контроля и совместимости в будущем.
Реализация рассуждений для конкретных провайдеров
Модели Anthropic с токенами мыслей
Последние модели Claude, такие как claude-sonnet-4.5, поддерживают работу с токенами мыслей и их возврат.
Вы можете включить рассуждения в моделях Anthropic только через унифицированный параметр reasoning с effort или max_tokens.
Примечание: вариант :thinking больше не поддерживается для моделей Anthropic. Используйте параметр reasoning вместо него.
Максимальное количество токенов для рассуждений в моделях Anthropic
При использовании моделей Anthropic с рассуждениями:
- При использовании параметра
reasoning.max_tokensэто значение используется напрямую с минимумом 1024 токенов. - При использовании параметра
reasoning.effortбюджет токенов рассчитывается на основе значенияmax_tokens.
Выделение токенов для рассуждений ограничено максимумом 128 000 токенов и минимумом 1024 токена. Формула для расчёта budget_tokens: budget_tokens = max(min(max_tokens * {effort_ratio}, 128000), 1024)
effort_ratio составляет 0.95 для xhigh, 0.8 для high, 0.5 для medium, 0.2 для low и 0.1 для minimal.
Важно
max_tokens должен быть строго больше бюджета рассуждений, чтобы гарантировать наличие токенов для финального ответа после размышлений.
Использование токенов и биллинг
Обратите внимание, что токены мыслей считаются выходными токенами для целей биллинга. Использование токенов мыслей увеличит ваше использование токенов, но может значительно улучшить качество ответов модели.
Пример: streaming с токенами мыслей Anthropic
from openai import OpenAI
client = OpenAI(
base_url="https://api.aitunnel.ru/v1",
api_key="<AITUNNEL_API_KEY>",
)
def chat_completion_with_reasoning(messages):
response = client.chat.completions.create(
model="claude-sonnet-4.5",
messages=messages,
max_tokens=10000,
extra_body={
"reasoning": {
"max_tokens": 8000
}
},
stream=True
)
return response
for chunk in chat_completion_with_reasoning([
{"role": "user", "content": "Что больше, 9.9 или 9.11?"}
]):
if hasattr(chunk.choices[0].delta, 'reasoning_details') and chunk.choices[0].delta.reasoning_details:
print(f"REASONING_DETAILS: {chunk.choices[0].delta.reasoning_details}")
elif getattr(chunk.choices[0].delta, 'content', None):
print(f"CONTENT: {chunk.choices[0].delta.content}")import OpenAI from "openai";
const openai = new OpenAI({
baseURL: "https://api.aitunnel.ru/v1",
apiKey: "<AITUNNEL_API_KEY>",
});
async function chatCompletionWithReasoning(messages) {
const response = await openai.chat.completions.create({
model: "claude-sonnet-4.5",
messages,
max_tokens: 10000,
reasoning: {
max_tokens: 8000,
},
stream: true,
});
return response;
}
(async () => {
for await (const chunk of chatCompletionWithReasoning([
{ role: "user", content: "Что больше, 9.9 или 9.11?" },
])) {
if (chunk.choices[0].delta?.reasoning_details) {
console.log("REASONING_DETAILS:", chunk.choices[0].delta.reasoning_details);
} else if (chunk.choices[0].delta?.content) {
console.log(`CONTENT: ${chunk.choices[0].delta.content}`);
}
}
})();Модели Google Gemini 3 с уровнями thinking
Модели Gemini 3 (такие как gemini-3.1-pro-preview и gemini-3-flash-preview) используют API Google thinkingLevel вместо старого API thinkingBudget, который использовался моделями Gemini 2.5.
AITUNNEL маппит параметр reasoning.effort напрямую в значения Google thinkingLevel:
AITUNNEL reasoning.effort | Google thinkingLevel |
|---|---|
"minimal" | "minimal" |
"low" | "low" |
"medium" | "medium" |
"high" | "high" |
"xhigh" | "high" (маппится вниз) |
Потребление токенов определяется Google
При использовании thinkingLevel фактическое количество потреблённых токенов рассуждений определяется внутренне Google. Публично задокументированных точек перелома лимитов токенов для каждого уровня нет. Например, установка effort: "low" может привести к нескольким сотням токенов рассуждений в зависимости от сложности задачи. Это ожидаемое поведение и отражает внутреннюю реализацию thinking levels в Google.
Если модель не поддерживает конкретный уровень усилий (например, если модель поддерживает только low и high), AITUNNEL смаппит запрошенный effort к ближайшему поддерживаемому уровню.
Использование max_tokens с Gemini 3
Если вы явно указываете reasoning.max_tokens, AITUNNEL передаст его как thinkingBudget в API Google. Однако для моделей Gemini 3 Google внутренне маппит это значение бюджета в thinkingLevel, поэтому вы не получите точного контроля над количеством токенов. Фактическое потребление токенов по-прежнему определяется реализацией thinkingLevel в Google, а не конкретным значением бюджета, которое вы указали.
Пример: использование thinking levels с Gemini 3
from openai import OpenAI
client = OpenAI(
base_url="https://api.aitunnel.ru/v1",
api_key="<AITUNNEL_API_KEY>",
)
response = client.chat.completions.create(
model="gemini-3.1-pro-preview",
messages=[
{"role": "user", "content": "Объясните последствия квантовой запутанности."}
],
extra_body={
"reasoning": {
"effort": "low" # Маппится в thinkingLevel: "low"
}
},
)
msg = response.choices[0].message
print(getattr(msg, "reasoning", None))
print(getattr(msg, "content", None))import OpenAI from "openai";
const openai = new OpenAI({
baseURL: "https://api.aitunnel.ru/v1",
apiKey: "<AITUNNEL_API_KEY>",
});
async function getResponseWithThinkingLevel() {
const response = await openai.chat.completions.create({
model: "gemini-3.1-pro-preview",
messages: [
{
role: "user",
content: "Объясните последствия квантовой запутанности.",
},
],
reasoning: {
effort: "low", // Маппится в thinkingLevel: "low"
},
});
type ReasoningMessage = (typeof response)["choices"][number]["message"] & {
reasoning?: string;
};
const msg = response.choices[0].message as ReasoningMessage;
console.log("REASONING:", msg.reasoning);
console.log("CONTENT:", msg.content);
}
getResponseWithThinkingLevel();