กลับไปที่บล็อก

API และ SDKคู่มือ

การสตรีมคำตอบใน Python

พิมพ์คำตอบของโมเดลขณะที่มันถูกสร้างด้วยแพ็กเกจ openai อย่างเป็นทางการ — ตัวอย่างแบบ sync และ async เอาต์พุตการให้เหตุผล การใช้โทเคน และการจัดการข้อผิดพลาด

โดย CheapTokens Teamเผยแพร่เมื่อ ใช้เวลาอ่าน 3 นาที

โค้ด Python ที่มี for loop วนอ่านชังก์จากสตรีมและข้อความที่ปรากฏทีละโทเคน
ในหน้านี้
  1. การตั้งค่า
  2. ตัวอย่างแบบมินิมอล
  3. โมเดลที่ใช้การให้เหตุผล
  4. การใช้โทเคน
  5. asyncio
  6. การหยุดก่อนเวลาและ timeout
  7. ข้อผิดพลาด
  8. สิ่งที่ส่งบนไวร์

เมื่อใช้สตรีมมิ่ง คำตอบจะมาทีละส่วนในขณะที่โมเดลยังสร้างอยู่ ผู้ใช้จึงเห็นข้อความทันทีแทนที่จะรอทั้งคำตอบ API ใช้รูปแบบสตรีมมิ่งมาตรฐานของ OpenAI (server-sent events) และแพ็กเกจ 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 อาจว่างเปล่าได้ ชังก์แรกมักมีแค่ role และชังก์สุดท้ายมีแค่ finish_reason พิมพ์ข้อความเฉพาะเมื่อมีอยู่

โมเดลที่ใช้การให้เหตุผล#

zai-org/GLM-5.3-Flash ให้เหตุผลก่อนตอบ เหตุผลมาในฟิลด์แยกของ delta คือ 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}")

คูณตัวเลขเหล่านี้ด้วยอัตราของโมเดลเพื่อคำนวณค่าใช้จ่ายของคำขอ — ดู How to estimate the cost of an AI agent

asyncio#

ในโค้ดแบบ async ใช้ 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())

การหยุดก่อนเวลาและ timeout#

ออกจากลูปเพื่อหยุดการสร้าง การเปิดสตรีมด้วย with จะปิดการเชื่อมต่อเมื่อบล็อกจบ timeout ของไคลเอนต์ตั้งไว้อย่างชัดเจน; 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)

ข้อผิดพลาด#

ข้อผิดพลาดที่เกิดก่อนชังก์แรก — คีย์ผิด ยอดเงินว่าง โมเดลไม่รู้จัก — จะถูกโยนเป็น exception เมื่อคุณสร้างสตรีม:

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)

รายการรหัสสถานะและวิธีแก้แบบเต็มอยู่ใน Common connection errors and how to fix them

สิ่งที่ส่งบนไวร์#

สำหรับดีบัก ให้ดูสตรีมดิบด้วย 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] บรรทัดที่ขึ้นต้นด้วยเครื่องหมายทวิภาคคือคอมเมนต์ keep-alive ที่ส่งระหว่างการหยุดนาน — ไคลเอนต์จะไม่สนใจ