ব্লগে ফিরে যান

API ও SDKগাইড

Python-এ স্ট্রিমিং প্রতিক্রিয়া

অফিসিয়াল openai প্যাকেজ দিয়ে মডেলের উত্তর তৈরি হওয়ার সাথে সাথে প্রিন্ট করুন — সিঙ্ক এবং অ্যাসিঙ্ক উদাহরণ, রিজনিং আউটপুট, টোকেন ব্যবহার এবং ত্রুটি পরিচালনা।

CheapTokens Team দ্বারাপ্রকাশিত হয়েছে 5 মিনিট পড়ার সময়

স্ট্রিম চাঙ্কের উপর একটি for লুপ এবং টোকেন ধরে ধরে টেক্সট দেখা যাওয়া Python কোড
এই পৃষ্ঠায়
  1. সেটআপ
  2. ন্যূনতম উদাহরণ
  3. রিজনিং মডেল
  4. টোকেন ব্যবহার
  5. asyncio
  6. আগে থামানো এবং টাইমআউট
  7. ত্রুটি
  8. তারে কী আছে

স্ট্রিমিংয়ের সাথে, মডেলটি উত্তর তৈরি করার সময়ই তা টুকরো টুকরো করে আসে, তাই আপনার ব্যবহারকারীরা পুরো উত্তরের জন্য অপেক্ষা না করে সাথে সাথেই টেক্সট দেখতে পান। API স্ট্যান্ডার্ড OpenAI স্ট্রিমিং ফরম্যাট (সার্ভার-সেন্ট ইভেন্ট) ব্যবহার করে, এবং অফিসিয়াল openai Python প্যাকেজটি আপনার হয়ে এটি সামলায়।

নিচের প্রতিটি উদাহরণ সম্পূর্ণ: এটি একটি ফাইলে কপি করে চালান। উদাহরণগুলো Python 3.10.12 এবং openai 3.31.0 দিয়ে একটি লোকাল টেস্ট সার্ভারের বিপরীতে যাচাই করা হয়েছে যা API-এর স্ট্রিমিং ফরম্যাট পুনরুৎপাদন করে (সিনট্যাক্স এবং এক্সিকিউশন)।

সেটআপ#

bash
pip install openai
export CHEAPTOKENS_API_KEY="paste-your-key-here"

ন্যূনতম উদাহরণ#

python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.cheaptokens.dev/v1",
    api_key=os.environ["CHEAPTOKENS_API_KEY"],
)

stream = client.chat.completions.create(
    model="deepseek-ai/DeepSeek-V4-Flash-0731",
    messages=[{"role": "user", "content": "Write a haiku about latency"}],
    stream=True,
)
for chunk in stream:
    if not chunk.choices:  # service chunk without text, e.g. the final usage chunk
        continue
    text = chunk.choices[0].delta.content
    if text:
        print(text, end="", flush=True)
print()

দুটি বিষয় গুরুত্বপূর্ণ:

  • choices ছাড়া চাঙ্কগুলো এড়িয়ে যান। কিছু চাঙ্কে কোনো টেক্সট থাকে না — উদাহরণস্বরূপ টোকেন ব্যবহারসহ শেষ চাঙ্কটি।
  • delta.content খালি হতে পারে। প্রথম চাঙ্কটি প্রায়শই শুধু রোল বহন করে, এবং শেষটি শুধু finish_reason। টেক্সট শুধু তখনই প্রিন্ট করুন যখন তা থাকে।

রিজনিং মডেল#

zai-org/GLM-5.3-Flash উত্তর দেওয়ার আগে চিন্তা করে। রিজনিং ডেল্টার একটি আলাদা ফিল্ডে আসে, reasoning_content, এবং উত্তর নিজেই content-এ। SDK অজানা ফিল্ডগুলো রাখে, তাই আপনি এটি getattr দিয়ে পড়তে পারেন। এটি নিজস্ব ক্লায়েন্ট এবং নিজস্ব স্ট্রিমসহ একটি সম্পূর্ণ উদাহরণ:

python
import os
import sys
from openai import OpenAI

client = OpenAI(
    base_url="https://api.cheaptokens.dev/v1",
    api_key=os.environ["CHEAPTOKENS_API_KEY"],
)

stream = client.chat.completions.create(
    model="zai-org/GLM-5.3-Flash",
    messages=[{"role": "user", "content": "Is 1013 a prime number?"}],
    stream=True,
)
for chunk in stream:
    if not chunk.choices:
        continue
    delta = chunk.choices[0].delta
    thinking = getattr(delta, "reasoning_content", None)
    if thinking:
        print(thinking, end="", flush=True, file=sys.stderr)  # reasoning → stderr
    if delta.content:
        print(delta.content, end="", flush=True)              # answer → stdout
print()

উত্তরের প্রথম শব্দটি আসার আগে রিজনিং কিছু সময় নিতে পারে — স্ট্রিম করার আরেকটি কারণ।

টোকেন ব্যবহার#

stream_options দিয়ে ব্যবহার চান; এটি শেষ চাঙ্কে আসে, যেখানে choices থাকে না:

python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.cheaptokens.dev/v1",
    api_key=os.environ["CHEAPTOKENS_API_KEY"],
)

stream = client.chat.completions.create(
    model="deepseek-ai/DeepSeek-V4-Flash-0731",
    messages=[{"role": "user", "content": "Explain idempotency in one paragraph"}],
    stream=True,
    stream_options={"include_usage": True},
)
usage = None
for chunk in stream:
    if chunk.usage:
        usage = chunk.usage
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

if usage:
    print(f"\ninput: {usage.prompt_tokens}, output: {usage.completion_tokens}")

অনুরোধের খরচ পেতে এই সংখ্যাগুলোকে মডেলের রেট দিয়ে গুণ করুন — দেখুন কীভাবে একটি AI এজেন্টের খরচ অনুমান করবেন।

asyncio#

অ্যাসিঙ্ক কোডে AsyncOpenAI এবং async for ব্যবহার করুন। ক্লায়েন্টের নিজস্ব নাম আছে, async_client, যাতে এটি অন্য উদাহরণগুলোর সিঙ্ক্রোনাস client-এর সাথে সংঘর্ষ না করে:

python
import asyncio
import os
from openai import AsyncOpenAI

async_client = AsyncOpenAI(
    base_url="https://api.cheaptokens.dev/v1",
    api_key=os.environ["CHEAPTOKENS_API_KEY"],
)

async def main() -> None:
    stream = await async_client.chat.completions.create(
        model="deepseek-ai/DeepSeek-V4-Flash-0731",
        messages=[{"role": "user", "content": "Name three uses of a message queue"}],
        stream=True,
    )
    async for chunk in stream:
        if chunk.choices and chunk.choices[0].delta.content:
            print(chunk.choices[0].delta.content, end="", flush=True)
    print()

asyncio.run(main())

আগে থামানো এবং টাইমআউট#

জেনারেশন থামাতে লুপটি ছেড়ে দিন। with দিয়ে স্ট্রিম খুললে ব্লক শেষ হলে সংযোগটি বন্ধ হয়ে যায়। ক্লায়েন্ট টাইমআউট স্পষ্টভাবে সেট করা; SDK কিছু ব্যর্থ অনুরোধ নিজে থেকেও পুনরায় চেষ্টা করে (max_retries, ডিফল্টভাবে 2)।

python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.cheaptokens.dev/v1",
    api_key=os.environ["CHEAPTOKENS_API_KEY"],
    timeout=120,  # seconds; long answers take time
)

received = ""
with client.chat.completions.create(
    model="deepseek-ai/DeepSeek-V4-Flash-0731",
    messages=[{"role": "user", "content": "Write a long story about a lighthouse"}],
    stream=True,
) as stream:
    for chunk in stream:
        if chunk.choices and chunk.choices[0].delta.content:
            received += chunk.choices[0].delta.content
        if len(received) > 300:  # stop early: enough text received
            break
print(received)

ত্রুটি#

প্রথম চাঙ্কের আগে ঘটে যাওয়া ত্রুটি — ভুল কী, খালি ব্যালেন্স, অজানা মডেল — স্ট্রিম তৈরি করার সময় ব্যতিক্রম হিসেবে উত্থাপিত হয়:

python
import os
import openai
from openai import OpenAI

client = OpenAI(
    base_url="https://api.cheaptokens.dev/v1",
    api_key=os.environ["CHEAPTOKENS_API_KEY"],
)

try:
    stream = client.chat.completions.create(
        model="deepseek-ai/DeepSeek-V4-Flash-0731",
        messages=[{"role": "user", "content": "Hello"}],
        stream=True,
    )
    for chunk in stream:
        if chunk.choices and chunk.choices[0].delta.content:
            print(chunk.choices[0].delta.content, end="", flush=True)
    print()
except openai.AuthenticationError:          # 401: wrong or rotated key
    print("Check the API key")
except openai.BadRequestError as e:         # 400: e.g. unknown model ID
    print("Bad request:", e.message)
except openai.APIStatusError as e:          # other statuses, e.g. 402 when the balance is used up
    print(e.status_code, e.message)

স্ট্যাটাস কোড এবং সমাধানের সম্পূর্ণ তালিকা সাধারণ সংযোগ ত্রুটি এবং কীভাবে সেগুলো ঠিক করবেন-এ আছে।

তারে কী আছে#

ডিবাগ করতে, curl দিয়ে কাঁচা স্ট্রিম দেখুন (-N বাফারিং বন্ধ করে):

bash
curl -N https://api.cheaptokens.dev/v1/chat/completions \
  -H "Authorization: Bearer $CHEAPTOKENS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "deepseek-ai/DeepSeek-V4-Flash-0731", "stream": true,
       "messages": [{"role": "user", "content": "Hi"}]}'

প্রতিটি ইভেন্ট একটি data: {…} লাইন যাতে একটি JSON চাঙ্ক থাকে; স্ট্রিমটি data: [DONE] দিয়ে শেষ হয়। কোলন দিয়ে শুরু হওয়া লাইনগুলো দীর্ঘ বিরতির সময় পাঠানো কীপ-অ্যালাইভ মন্তব্য — ক্লায়েন্টরা সেগুলো উপেক্ষা করে।