# Reasoning আর thinking model

> Tokens দিয়ে reasoning model চালানো: Chat Completions-এ reasoning_effort, Messages-এ thinking ও effort, reasoning text কীভাবে ফেরত আসে ও stream হয়, reasoning token কীভাবে গোনা ও বিল হয়, আর gateway কী বদলায় বা বাদ দেয়।

Reasoning model (OpenAI এদের বলে reasoning model, Anthropic ফিচারটার নাম দিয়েছে thinking) উত্তর লেখার আগে সমস্যাটা নিয়ে ভাবে। এই বাড়তি ভাবনায় কঠিন coding, অঙ্ক আর planning-এর কাজে ফল ভালো হয়। তবে দামও আছে: token আর সময় দুটোই বেশি লাগে। model যে thinking token বানায়, সেগুলো হয়তো আপনি কখনো দেখেনই না, কিন্তু তার বিল আপনাকেই দিতে হয়।

এই পেজে আছে: কী পাঠাতে পারেন, কী ফেরত আসে, Tokens thinking token কীভাবে গোনে ও বিল করে, আর কোথায় gateway আপনার request বদলে দেয়। parameter-এর নাম আর প্রতিটা value-র মানে ঠিক করে সেই provider, যে model-টা চালায়। Tokens এগুলো শুধু forward করে, ব্যাখ্যা করে না। তাই provider-এর আচরণ নিয়ে লেখা অংশগুলোকে model-এর maker-দের documentation-এর সারাংশ ধরুন (October 2026-এ checked), Tokens-এর কোনো প্রতিশ্রুতি নয়।

## সংক্ষেপে

| আপনি যা call করেন      | reasoning নিয়ন্ত্রণ করবেন যা দিয়ে                                                   | reasoning text ফিরে আসে যেভাবে                                                              |
| ---------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `/v1/chat/completions` | `reasoning_effort`                                                                    | message বা stream delta-তে `reasoning_content`, model যদি সেটা দেখায়                        |
| `/v1/messages`         | `thinking` আর `output_config.effort` (পুরোনো Claude model-এ: `thinking.budget_tokens`) | `thinking` content block, আর stream-এ `thinking_delta` event                                |
| `/v1/responses`        | `reasoning.effort` আর `reasoning.summary`                                             | `reasoning` output item, যার ভেতরে `summary` list থাকে                                       |

এর কোনটা একটা model মানবে, তা model-ভেদে আলাদা। কোনো model সব সময়ই reasoning করে, বন্ধ করার switch নেই। কোনোটা effort level নেয়, কোনোটা token budget নেয়, আর কোনোটা এই সব field-ই উপেক্ষা করে।

## কোনো model reasoning করে কি না, কীভাবে জানবেন

[/models](/models)-এর catalog-এ প্রতিটা model-এর context window, দাম আর বিবরণ আছে। কিন্তু "reasoning" বা "thinking" বোঝানোর কোনো flag নেই। জানার উপায়:

- model-এর পেজ আর maker-এর documentation পড়ুন। [Choosing a model](/docs/choosing-a-model) পেজে কয়েকটা model-এর কথা আছে যেগুলো সব সময় thinking করে, যেমন Kimi K3 আর GLM-5.3। সেখানে এটাও লেখা আছে, always-on thinking মানে প্রতিটা call-এ বাড়তি output token।
- একটা test request পাঠিয়ে উত্তরটা দেখুন। reasoning model সাধারণত `reasoning_content` field, `thinking` block বা `usage`-এর ভেতরে reasoning token-এর details ফেরত দেয়। যে উত্তরটা আপনি দেখছেন তার তুলনায় `completion_tokens` অনেক বেশি হলেও বোঝা যায়।

```python
import os
from openai import OpenAI

client = OpenAI(base_url="https://tokens.bd/v1", api_key=os.environ["TOKENS_API_KEY"])

resp = client.chat.completions.create(
    model="deepseek/deepseek-v4.1-flash",
    max_tokens=2000,
    messages=[{"role": "user", "content": "A train leaves at 09:10 and arrives at 11:45. How long is the trip?"}],
)

message = resp.choices[0].message
print("visible answer:", message.content)
print("reasoning text:", getattr(message, "reasoning_content", None))
print("usage:", resp.usage)
```

`reasoning_content` OpenAI-র নিজের API-র অংশ নয়। কিছু OpenAI-compatible provider model-এর reasoning text পাঠাতে এই নামটা ব্যবহার করে, আর provider পাঠালে gateway সেটা যেমন আছে তেমনই পৌঁছে দেয়।

## Chat Completions: reasoning_effort

`reasoning_effort` হলো OpenAI-র parameter, যা ঠিক করে reasoning model কতটা ভাববে। OpenAI-র reasoning guide অনুযায়ী কোন value চলবে তা model-ভেদে আলাদা, আর তালিকায় আছে `none`, `minimal`, `low`, `medium`, `high`, `xhigh` ও `max`। field না দিলে বেশির ভাগ বর্তমান OpenAI model default হিসেবে `medium` ধরে। কিছু model কিছু value নেয় না: OpenAI-র documentation অনুযায়ী GPT-6 Astra `none` দিলে 400 ফেরত দেয়, আর GPT-6.1 Sol `none` ও `minimal` দুটোই ফিরিয়ে দেয়। effort কম হলে উত্তর দ্রুত আর সস্তা হয়। কঠিন সমস্যায় effort বেশি দিন।

:::code-tabs

```bash title="cURL"
curl https://tokens.bd/v1/chat/completions \
  -H "Authorization: Bearer $TOKENS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek/deepseek-v4.1-flash",
    "max_completion_tokens": 4000,
    "reasoning_effort": "low",
    "messages": [
      {"role": "user", "content": "Find the bug: for i in range(len(xs)+1): total += xs[i]"}
    ]
  }'
```

```python title="Python"
import os
from openai import OpenAI

client = OpenAI(base_url="https://tokens.bd/v1", api_key=os.environ["TOKENS_API_KEY"])

resp = client.chat.completions.create(
    model="deepseek/deepseek-v4.1-flash",
    max_completion_tokens=4000,
    reasoning_effort="low",
    messages=[
        {"role": "user", "content": "Find the bug: for i in range(len(xs)+1): total += xs[i]"}
    ],
)
print(resp.choices[0].message.content)
print(resp.usage)
```

```typescript title="Node.js"
import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://tokens.bd/v1", apiKey: process.env.TOKENS_API_KEY });

const resp = await client.chat.completions.create({
  model: "deepseek/deepseek-v4.1-flash",
  max_completion_tokens: 4000,
  reasoning_effort: "low",
  messages: [{ role: "user", content: "Find the bug: for i in range(len(xs)+1): total += xs[i]" }],
});
console.log(resp.choices[0].message.content, resp.usage);
```

:::

field-টার কী হবে, তা নির্ভর করে model আর তার পেছনের provider-এর ওপর। model `reasoning_effort` না নিলে provider হয় সেটা উপেক্ষা করে, নয়তো 400 ফেরত দেয়, যা আপনার কাছে আসে `invalid_request` হয়ে ([errors](/docs/errors))। একই ধারণার জন্য কিছু maker নিজেদের field-এর নাম ব্যবহার করে। gateway Chat Completions-এর field validate করে না, তাই body-তে provider-specific কোনো field থাকলে সেটা যেমন আছে তেমনই forward হয়। OpenAI SDK-তে এমন field দিতে `extra_body` ব্যবহার করতে পারেন। provider সেটা মানবে কি না, তা maker-এর সিদ্ধান্ত, তাই তাদের documentation দেখে নিন।

OpenAI-র documentation থেকে দুটো কথা বাস্তবে কাজে লাগে। এক, reasoning model-এর thinking-ও output limit থেকে গোনা হয়। দুই, GPT-5.4 থেকে শুরু করে Chat Completions-এ `reasoning_effort` `none` ছাড়া অন্য কিছু হলে tool calling চলে না। ওই model-এ tool ব্যবহার করতে চাইলে `reasoning_effort: "none"` দিন, অথবা Responses API ব্যবহার করুন।

### OpenAI reasoning model-এর জন্য gateway কী বদলায়

OpenAI-র o-series আর GPT-5 ও তার পরের model `max_tokens` নেয় না, আর `temperature` বা `top_p` 1 ছাড়া অন্য কিছু হলেও ফিরিয়ে দেয়। তবু অনেক client এগুলো পাঠিয়ে দেয়। তাই এই ধরনের model-এ (model-এর নাম দেখে চেনা হয়) Chat Completions request গেলে gateway forward করার আগে body বদলে নেয়:

- `max_tokens`-এর নাম বদলে `max_completion_tokens` হয় (দুটোই পাঠালে আপনারটা থাকে)।
- `temperature` আর `top_p` বাদ যায়, যদি value ঠিক 1 না হয়।

এটা শুধু `/v1/chat/completions`-এ হয়, Messages বা Responses-এ নয়, আর অন্য maker-দের model-এও নয়। অন্য maker-দের model আপনার parameter যেমন পাঠিয়েছেন তেমনই পায়, আর তাদের কয়েকটা reasoning চলাকালে `temperature` ফিরিয়ে দেয় বা উপেক্ষা করে।

আপনার চাওয়া `max_tokens` বা `max_completion_tokens`-এর খরচ ব্যালান্স দিয়ে না মিটলে gateway সেটা কমিয়ে দিতে পারে (16-র নিচে নামায় না), যেমনটা [Chat Completions](/docs/chat-completions) পেজে বলা আছে। reasoning model-এ এই কমানোর ফলে পুরো allowance thinking-এই শেষ হয়ে যেতে পারে, আর উত্তর ফাঁকা বা ছোট আসে, সঙ্গে `finish_reason: "length"`। এমন limit দিন যা আপনার ব্যালান্স মেটাতে পারে, নয়তো [Billing](/dashboard/billing)-এ গিয়ে টাকা যোগ করুন।

## Messages: thinking and effort

`/v1/messages`-এ Anthropic-এর model একটা `thinking` object নেয়, আর বর্তমান model-এ একটা `output_config.effort` level-ও। যে provider Messages API বোঝে, তার কাছে gateway দুটোই না বদলে forward করে। Anthropic-এর documentation অনুযায়ী (October 2026-এ checked, [thinking](https://platform.claude.com/docs/en/build-with-claude/thinking), [extended thinking](https://platform.claude.com/docs/en/build-with-claude/extended-thinking), [effort](https://platform.claude.com/docs/en/build-with-claude/effort)):

- **বর্তমান Claude model (4.7 ও তার পরের, 5.x line-সহ):** `thinking: {"type": "adaptive"}` দিন, আর গভীরতা ঠিক করুন `output_config: {"effort": "low" | "medium" | "high" | "xhigh" | "max"}` দিয়ে। কোন level আছে, তা model-ভেদে আলাদা। কয়েকটা 5.x model-এ `thinking` field ছাড়াই thinking আগে থেকে চালু থাকে। পুরোনো form `thinking: {"type": "enabled", "budget_tokens": N}` এই model-গুলোতে 400 ফেরত দেয়।
- **Claude 4.6:** `enabled` form এখনো চলে, কিন্তু deprecated।
- **Claude 4.5 ও তার আগের:** শুধু `enabled` form আছে। `budget_tokens` একটা লক্ষ্যমাত্রা, যা অন্তত 1,024 হতে হবে আর `max_tokens`-এর চেয়ে কম।
- **Thinking text দেখা:** অনেক বর্তমান model-এ প্রতিটা block-এর `thinking` field default-এ ফাঁকা আসে (`display` তখন `omitted`)। reasoning-এর সারাংশ পেতে `thinking` object-এর ভেতরে `"display": "summarized"` দিন। Anthropic কোনো setting-এই raw chain of thought ফেরত দেয় না।

:::code-tabs

```python title="Python: current Claude models"
import os
import anthropic

client = anthropic.Anthropic(base_url="https://tokens.bd", api_key=os.environ["TOKENS_API_KEY"])

message = client.messages.create(
    model="deepseek/deepseek-v4.1-flash",
    max_tokens=8000,
    thinking={"type": "adaptive", "display": "summarized"},
    output_config={"effort": "medium"},
    messages=[{"role": "user", "content": "Plan a safe rollout for a database column rename."}],
)

for block in message.content:
    if block.type == "thinking":
        print("thinking summary:", block.thinking)
    elif block.type == "text":
        print("answer:", block.text)
print(message.usage)
```

```python title="Python: Claude 4.5 and earlier"
import os
import anthropic

client = anthropic.Anthropic(base_url="https://tokens.bd", api_key=os.environ["TOKENS_API_KEY"])

message = client.messages.create(
    model="deepseek/deepseek-v4.1-flash",
    max_tokens=8000,
    thinking={"type": "enabled", "budget_tokens": 4000},  # at least 1024, below max_tokens
    messages=[{"role": "user", "content": "Plan a safe rollout for a database column rename."}],
)

for block in message.content:
    if block.type == "thinking":
        print("thinking:", block.thinking)
    elif block.type == "text":
        print("answer:", block.text)
```

```bash title="cURL"
curl https://tokens.bd/v1/messages \
  -H "x-api-key: $TOKENS_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "deepseek/deepseek-v4.1-flash",
    "max_tokens": 8000,
    "thinking": {"type": "adaptive", "display": "summarized"},
    "output_config": {"effort": "medium"},
    "messages": [
      {"role": "user", "content": "Plan a safe rollout for a database column rename."}
    ]
  }'
```

:::

`output_config`-এর জন্য নতুন Anthropic SDK লাগে। এই উদাহরণগুলো Claude model-এর request-এর গড়ন দেখায়; আপনার model-এর maker যে form documented করেছে, সেটাই ব্যবহার করুন। কোন model কোন form নেয়, তা Tokens-এর catalog-এ লেখা নেই।

thinking থাকলে response-এ `text` block-এর আগে `thinking` block আসে:

```json
{
  "content": [
    { "type": "thinking", "thinking": "The rename needs a two-step deploy...", "signature": "EosnCkYICxIM..." },
    { "type": "text", "text": "Roll it out in three steps: add the new column..." }
  ],
  "stop_reason": "end_turn",
  "usage": { "input_tokens": 24, "output_tokens": 912 }
}
```

`signature` হলো encrypted data, যার সাহায্যে model নিজের reasoning চালিয়ে যেতে পারে। tool-use loop-এ tool result ফেরত পাঠানোর সময় Anthropic চায় thinking block অপরিবর্তিত অবস্থায় আবার পাঠানো হোক। `redacted_thinking` block-ও একই নিয়ম: তাতে encrypted content থাকে, পড়ার মতো কোনো text থাকে না। শুধু text নয়, assistant-এর পুরো `content` array রেখে দিন। [Tool calling](/docs/tool-calling) পেজের loop-এ `{"role": "assistant", "content": resp.content}` দেখানো আছে। Anthropic আরও জানিয়েছে, manual extended thinking-এ `tool_choice` শুধু `auto` বা `none` হতে পারে।

## Translate হলে কী টিকে থাকে

প্রতিটা model এক বা একাধিক provider চালায়, আর gateway সেই provider-কেই পছন্দ করে যে আপনার request-এর format-ই বোঝে। কোনো model শুধু অন্য format-এ পাওয়া গেলে gateway translate করে ([Messages](/docs/messages) দেখুন), আর তখন reasoning এভাবে সামলানো হয়:

| কোন দিকে                                                | request-এ reasoning নিয়ন্ত্রণ                   | উত্তরে reasoning                                                                                                                                                  |
| ------------------------------------------------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Messages request, provider OpenAI format-এ চলে          | `thinking` আর `output_config` **যায় না**        | provider যে `reasoning_content` পাঠায়, সেটা `thinking` block হয়ে ফেরত আসে **না**, বাদ পড়ে                                                                      |
| Chat Completions request, provider Anthropic format-এ চলে | `reasoning_effort` **যায় না**                 | `thinking` block হয়ে যায় `message.reasoning_content` (stream করলে `delta.reasoning_content`)। `redacted_thinking` block আর `signature` value বাদ পড়ে             |

এর ফল:

- translate হওয়া পথে ওই field দিয়ে reasoning চালু করা বা তার level বদলানো যায় না। তখন model reasoning করবে কি না, তা model-এর default-এর ওপর নির্ভর করে।
- model thinking-এ যে token খরচ করেছে, usage-এর সংখ্যায় সেগুলো ধরা থাকে। অর্থাৎ যে reasoning আপনি দেখতে পাচ্ছেন না, তার বিলও আপনার।
- Chat Completions request-এ Anthropic-এর thinking signature যায় না। তাই যে tool-use loop-এ thinking block ফেরত পাঠাতে হয়, সেটা `/v1/messages`-এ চালান।

নির্দিষ্ট কোনো reasoning setting খাটাতেই হলে model-এর নিজস্ব format-এর endpoint-এ call করুন, আর একটা test request পাঠিয়ে মিলিয়ে নিন: উত্তরে reasoning আছে কি না (একটা `thinking` block বা `reasoning_content`), অথবা setting বদলালে `usage` বদলায় কি না।

## Responses API

`POST https://tokens.bd/v1/responses`-এ OpenAI-র parameter হলো `reasoning`, যার ভেতরে `effort` আর, পড়ার মতো সারাংশ চাইলে, `summary`। gateway body যেমন আছে তেমনই forward করে, আর support নির্ভর করে model-এর পেছনের provider-এর ওপর ([Responses API](/docs/responses) দেখুন)।

```python
import os
from openai import OpenAI

client = OpenAI(base_url="https://tokens.bd/v1", api_key=os.environ["TOKENS_API_KEY"])

resp = client.responses.create(
    model="deepseek/deepseek-v4.1-flash",
    input="Find the bug: for i in range(len(xs)+1): total += xs[i]",
    reasoning={"effort": "low", "summary": "auto"},
    max_output_tokens=4000,
)
print(resp.output_text)
print(resp.usage)
```

OpenAI-র documentation অনুযায়ী raw reasoning token কখনো ফেরত দেওয়া হয় না। `summary` দিলে response-এ একটা `reasoning` output item আসে, যার `summary` list-এ পড়ার মতো একটা সারাংশ থাকে। tool loop চালিয়ে গেলে function-call-এর output-এর সঙ্গে reasoning item-ও model-কে আবার পাঠাতে বলেছে OpenAI।

## Reasoning stream করা

`"stream": true` দিলে উত্তরের আগে reasoning আসে, আর model আগে ভাবলে stream কিছুক্ষণ চুপচাপ থাকে।

**Chat Completions।** যে provider reasoning text দেখায়, সে সেটা পাঠায় `delta.reasoning_content` হিসেবে, তারপর উত্তরের জন্য `delta.content`। translate হওয়া Anthropic thinking-ও একই ভাবে পৌঁছায়। যে client অচেনা field উপেক্ষা করে, সে শুধু উত্তরটাই দেখাবে।

:::code-tabs

```python title="Python"
import os
from openai import OpenAI

client = OpenAI(base_url="https://tokens.bd/v1", api_key=os.environ["TOKENS_API_KEY"])

stream = client.chat.completions.create(
    model="deepseek/deepseek-v4.1-flash",
    max_tokens=4000,
    stream=True,
    stream_options={"include_usage": True},
    messages=[{"role": "user", "content": "Why does 0.1 + 0.2 != 0.3 in floating point?"}],
)

for chunk in stream:
    if chunk.usage:
        print("\nusage:", chunk.usage)
    if not chunk.choices:
        continue
    delta = chunk.choices[0].delta
    reasoning = getattr(delta, "reasoning_content", None)
    if reasoning:
        print(reasoning, end="", flush=True)  # reasoning text, if the model sends it
    if delta.content:
        print(delta.content, end="", flush=True)
```

```typescript title="Node.js"
import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://tokens.bd/v1", apiKey: process.env.TOKENS_API_KEY });

const stream = await client.chat.completions.create({
  model: "deepseek/deepseek-v4.1-flash",
  max_tokens: 4000,
  stream: true,
  stream_options: { include_usage: true },
  messages: [{ role: "user", content: "Why does 0.1 + 0.2 != 0.3 in floating point?" }],
});

for await (const chunk of stream) {
  if (chunk.usage) console.log("\nusage:", chunk.usage);
  const delta = chunk.choices[0]?.delta as
    | { content?: string | null; reasoning_content?: string | null }
    | undefined;
  if (delta?.reasoning_content) process.stdout.write(delta.reasoning_content);
  if (delta?.content) process.stdout.write(delta.content);
}
```

:::

**Messages।** thinking আসে `content_block_delta` event-এ `thinking_delta` হিসেবে। block বন্ধ হওয়ার ঠিক আগে আসে একটা `signature_delta`, তারপর text block-গুলো। `display` `omitted` হলে `thinking_delta` event-এ ফাঁকা string থাকে, শুধু signature আসে।

```python
import os
import anthropic

client = anthropic.Anthropic(base_url="https://tokens.bd", api_key=os.environ["TOKENS_API_KEY"])

stream = client.messages.create(
    model="deepseek/deepseek-v4.1-flash",
    max_tokens=8000,
    stream=True,
    thinking={"type": "adaptive", "display": "summarized"},
    messages=[{"role": "user", "content": "Why does 0.1 + 0.2 != 0.3 in floating point?"}],
)

for event in stream:
    if event.type == "content_block_delta":
        if event.delta.type == "thinking_delta":
            print(event.delta.thinking, end="", flush=True)
        elif event.delta.type == "text_delta":
            print(event.delta.text, end="", flush=True)
```

stream-এর format, disconnect আর timeout নিয়ে আরও আছে [streaming](/docs/streaming) পেজে।

## Token গোনা আর বিল

Reasoning token আসলে output token। OpenAI আর Anthropic দুজনেই জানিয়েছে, model thinking-এ যে token খরচ করে সেগুলো output token হিসেবে বিল হয়, আর output limit (`max_completion_tokens` বা `max_tokens`)-এর মধ্যে গোনা হয়, reasoning text আপনাকে ফেরত না দিলেও।

- provider `usage`-এ যা রিপোর্ট করে, Tokens সেটাই বিল করে: input, output, আর cache read ও write। প্রতিটা ধরনের token-এর দাম model-এর catalog price অনুযায়ী ([prices](/models))। reasoning token output count-এরই অংশ, তাই model-এর output rate-এ দাম ধরা হয়। reasoning-এর আলাদা কোনো দাম নেই।
- যে উত্তরটা আপনি দেখছেন, সেটা বিলের ছোট একটা অংশ হতে পারে। 300 token-এর উত্তর আর 1,200 thinking token মিলে বিল হয় 1,500 output token। Usage analytics ([usage](/docs/usage-and-alerts)) output token ঠিক যেভাবে বিল হয়েছে সেভাবেই দেখায়।
- summary বা omitted thinking-এ বিল কমে না। Anthropic জানিয়েছে, summary-র নয়, পুরো thinking token-এর চার্জ লাগে, আর `display: "omitted"` শুধু latency কমায়।
- কিছু provider `usage`-এর ভেতরেই ভাগটা দেখায়, যেমন Chat Completions-এ `completion_tokens_details.reasoning_tokens`, Responses-এ `output_tokens_details.reasoning_tokens` আর Messages-এ `output_tokens_details.thinking_tokens`। field-গুলো provider-এর, যেমন আছে তেমনই পাঠানো হয়। এগুলো শুধু তথ্যের জন্য, বিল হয় output-এর মোট সংখ্যা ধরে।
- provider কোনো usage না পাঠালে gateway response-এর আকার দেখে আন্দাজ করে, উত্তরের সঙ্গে `reasoning_content` text-ও গুনে।
- Anthropic জানিয়েছে, তাদের নতুন model আগের turn-এর thinking block context-এ রেখে দেয় আর পরের turn-এ সেগুলো input হিসেবে বিল করে। thinking-সহ লম্বা tool loop প্রতি round-এ এগুলো আবার পাঠায়, তাই round যত বাড়ে, খরচও তত বাড়ে।

forward করার আগে gateway আপনার output limit ধরে (কিছু না দিলে 8,192 token) worst case-এর টাকা ব্যালান্স থেকে আলাদা করে রাখে, যেমন [Chat Completions](/docs/chat-completions)-এ বলা আছে। reasoning model-এ 32,000 বা তার বেশির মতো বড় limit দিলে model আগে শেষ করলেও অনেক টাকা আটকে থাকে। তবে চার্জ হয় আসল usage অনুযায়ী।

## কতটা সীমা রাখবেন

- output limit এত বড় রাখুন, যাতে thinking আর উত্তর দুটোই ধরে। model পুরোটা thinking-এই খরচ করে ফেললে উত্তর কাটা বা ফাঁকা আসে, সঙ্গে `finish_reason: "length"` (Chat Completions) বা `stop_reason: "max_tokens"` (Messages)। OpenAI-র reasoning model নিয়ে শুরু করার সময় reasoning আর output মিলিয়ে অন্তত 25,000 token রাখতে বলেছে, পরে ধীরে ধীরে কমিয়ে আনতে বলেছে।
- low বা medium effort দিয়ে শুরু করুন, উত্তর যথেষ্ট ভালো না হলে তবেই বাড়ান। effort বেশি মানে thinking token বেশি, latency-ও বেশি।
- নিত্যকার কাজে (rename, formatting, ছোটখাটো edit) non-reasoning model, বা model যেখানে মানে সেখানে `reasoning_effort: "none"`, সস্তা আর দ্রুত।

## Latency আর timeout

যে model উত্তরের আগে ভাবে, সে প্রথম token দেওয়ার আগে অনেকক্ষণ চুপ থাকতে পারে। response stream করুন, তাতে আপনার client অগ্রগতি দেখাতে পারবে আর connection সচল থাকবে।

gateway-ও চুপ থাকাটা নজরে রাখে। একটা model-এর পেছনে একাধিক provider থাকলে, streaming provider-এর প্রথম event-এর জন্য gateway default-এ 30 সেকেন্ড অপেক্ষা করে (operator এটা বদলাতে পারেন), তারপর আরেকটা provider configure করা থাকলে সেটা চেষ্টা করে। non-streaming request পায় অন্তত 120 সেকেন্ড। chain-এর শেষ provider-এর জন্য আগেভাগে কেটে দেওয়ার কোনো সময় নেই। যে provider 600 সেকেন্ড কিছুই পাঠায় না, তার শেষ হয় `504 upstream_timeout` দিয়ে ([errors](/docs/errors))। ধীর reasoning model non-streaming call-এ timeout হলে streaming-এ যান, আর নিজের client-এর timeout এমন রাখুন যা আপনার আশা করা সবচেয়ে লম্বা উত্তরের চেয়েও বেশি।

## সমস্যা হলে

| লক্ষণ                                                          | সম্ভাব্য কারণ                                                              | সমাধান                                                                                                              |
| -------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `reasoning_effort` দেওয়ার পর 400 `invalid_request`            | model বা provider ওই field বা value নেয় না                                | field-টা সরিয়ে দিন, অথবা ওই model-এর জন্য maker যে value documented করেছে সেটা দিন।                                 |
| `budget_tokens`-সহ `thinking`-এ 400                            | Claude model শুধু adaptive thinking মানে                                   | `thinking: {"type": "adaptive"}` আর `output_config.effort` ব্যবহার করুন।                                            |
| `max_tokens` বা `temperature`-এ 400                            | OpenAI reasoning model এমন পথে, যেখানে gateway এগুলো বদলায় না             | Chat Completions-এ gateway বদলে দেয়; Messages বা Responses-এ model-এর নিজের parameter-এর নাম ব্যবহার করুন।         |
| উত্তর ফাঁকা, `finish_reason: "length"`                         | thinking পুরো output limit খেয়ে ফেলেছে                                    | `max_tokens` বা `max_completion_tokens` বাড়ান, অথবা effort কমান।                                                   |
| response-এ reasoning text নেই                                  | model সেটা দেখায় না, `display` `omitted`, অথবা পথের মাঝে সেটা বাদ পড়েছে   | Claude model-এ `display: "summarized"` দিন, অথবা উপরের translate-এর টেবিলটা দেখুন।                                  |
| Claude ছাড়া অন্য model-এ Messages-এ `thinking` block আসে না   | model OpenAI format-এ চলে আর `reasoning_content` বাদ পড়ছে                 | reasoning পড়তে Chat Completions ব্যবহার করুন।                                                                      |
| উত্তরের চেয়ে বিল অনেক বেশি                                    | thinking token আসলে output token                                          | effort বা budget কমান, অথবা ছোট model নিন।                                                                          |
| লম্বা non-streaming call-এ `504 upstream_timeout`              | model upstream-এর অপেক্ষার সময়ের চেয়ে বেশি ভেবেছে                       | response stream করুন।                                                                                               |
| Claude-এ tool loop thinking-block error দিয়ে ভাঙছে            | thinking block অপরিবর্তিত অবস্থায় ফেরত পাঠানো হয়নি                       | `/v1/messages`-এ assistant-এর পুরো `content` আবার পাঠান, `thinking` ও `redacted_thinking` block সহ।                 |

---
Page: https://tokens.bd/bn/docs/reasoning
