پاسخ جریانی (stream)
SSE، خواندن chunkها، پایان stream و اینکه قطع وسط راه چطور حساب میشود.
با stream=true پاسخ بهصورت SSE میآید و اولین توکنها خیلی زودتر به کاربر میرسند. برای هر رابط زندهٔ چت این حالت پیشفرضِ درست است.
resp = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": "یک داستان کوتاه بنویس"}],
stream=True,
)
for chunk in resp:
print(chunk.choices[0].delta.content or "", end="", flush=True)شکل خام
data: {"id":"chatcmpl-...","choices":[{"delta":{"content":"سلام"},"index":0}]}
data: {"id":"chatcmpl-...","choices":[{"delta":{"content":"!"},"index":0}]}
data: [DONE]- پایان stream با
data: [DONE]اعلام میشود. - فیلدهای
idوmodelدر طول یک stream ثابت میمانند. - هدرهای پاسخ (از جمله x-request-id) پیش از اولین chunk فرستاده میشوند، پس همیشه در دسترساند.
- آخرین chunk پیش از
[DONE]فیلدusageرا دارد: شمارش نهایی توکنها و cost_rial همین درخواست. choices آن خالی است.
اگر وسط راه قطع شود
پس از ارسال اولین بایت، دیگر امکان جابهجایی به مسیر دیگر نیست — تغییر مدل وسط یک پاسخ، پاسخی میسازد که هیچکس نمیخواهد. توکنهایی که تا آن لحظه واقعاً تولید شدهاند محاسبه و از شما کسر میشوند، چون ما هم بابتشان به بالادست پرداختهایم.
برای پاسخهای طولانی، متن دریافتی را در سمت خودتان نگه دارید تا اگر اتصال قطع شد، مجبور به شروع از صفر نباشید.
پشت nginx یا لودبالانسر
ما هدر X-Accel-Buffering: no را ست میکنیم تا واسطهها stream را بافر نکنند. اگر پاسخ بهجای جریانداشتن یکجا میرسد، ایراد از بافر واسطهٔ خودتان است.