
上一课的请求要等模型把整段回答写完才返回,长一点的回答要等十几秒。聊天应用里大家习惯看到字一个个蹦出来,这就是流式输出。另外,模型本身不记得上一轮说过什么,「记住上下文」是你的程序做的,这就是多轮对话。
流式输出:边生成边显示

请求里加上 stream: true,接口会改成 SSE(Server-Sent Events)格式,一小段一小段地推送:
python
import os
from openai import OpenAI
client = OpenAI(base_url="https://hivegpt.cn/v1", api_key=os.environ["HIVEGPT_API_KEY"])
stream = client.chat.completions.create(
model="gpt-5.5",
messages=[{"role": "user", "content": "写一首关于秋天的四行小诗"}],
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()js
import OpenAI from 'openai'
const client = new OpenAI({ baseURL: 'https://hivegpt.cn/v1', apiKey: process.env.HIVEGPT_API_KEY })
const stream = await client.chat.completions.create({
model: 'gpt-5.5',
messages: [{ role: 'user', content: '写一首关于秋天的四行小诗' }],
stream: true,
})
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content || '')
}
process.stdout.write('\n')bash
curl -N https://hivegpt.cn/v1/chat/completions \
-H "Authorization: Bearer $HIVEGPT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-5.5","stream":true,
"messages":[{"role":"user","content":"写一首关于秋天的四行小诗"}]}'
# 会看到一行行 data: {...},最后一行是 data: [DONE]几个要点:
- 流式时每个片段在
choices[0].delta.content里,不是message.content;把所有片段拼起来就是完整回答。 - 有的片段没有文字(比如第一个只带角色、最后一个只带
finish_reason),代码里要判断一下再用。 - 总耗时不会变短,变短的是用户看到第一个字的时间。
网页里怎么用
浏览器不能直接拿着 Key 调接口(会泄露 Key)。常见做法是:你的后端调 HiveGPT 的流式接口,再把内容通过 SSE 或 WebSocket 转发给网页。A 路线的结业项目会完整做一遍。
多轮对话:自己维护 messages
模型每次请求都是「失忆」的。要让它记住前面的内容,就把之前的对话全部带上:
python
messages = [
{"role": "system", "content": "你是一个耐心的编程老师,每次回答不超过 100 字。"},
]
def ask(question):
messages.append({"role": "user", "content": question})
resp = client.chat.completions.create(model="gpt-5.5", messages=messages)
answer = resp.choices[0].message.content
messages.append({"role": "assistant", "content": answer}) # 记下模型的回答
return answer
print(ask("Python 里的列表和元组有什么区别?"))
print(ask("那它们哪个更快?")) # 「它们」指什么,模型从上一轮知道三种角色:
| 角色 | 作用 |
|---|---|
system | 设定身份、语气和规则,放在最前面,整段对话都生效 |
user | 用户说的话 |
assistant | 模型之前的回答,由你的程序存下来再发回去 |
在下面试试多轮对话:先问一个问题,再接着追问(页面里是一次性返回,流式效果请在本地运行上面的代码)。
对话越长越贵

每一轮都要把之前的全部内容重新发一遍,所以第 10 轮的请求包含前 9 轮的所有文字,输入 token 一路上涨。常用的控制办法:
- 只保留最近几轮:比如只带最近 10 条消息,最早的丢掉。
- 摘要:对话太长时,让模型把前面的内容总结成一段,替换掉原始记录。
- system 写短:system 每轮都会发送,写得越长,每轮都多花一份钱。
另外,每个模型都有上下文长度上限,超过会直接报错(提示对话内容太长)。上面两个办法同时也是在防止超限。
小结
stream: true+ 读delta.content,就能边生成边显示。- 模型不记事,多轮对话靠你把历史
messages一起发过去。 - 历史越长越贵,也可能超出上下文上限,要裁剪或摘要。
下一课解决另一个工程问题:让模型稳定地返回 JSON,程序可以直接解析,不用再写一堆正则。