- 如何使用流式输出;
- 使用流式输出时的常见问题;
- 在不使用 Python SDK 的场合下如何处理流式输出;
如何使用流式输出
流式输出(Streaming),一言以蔽之,就是每当 Kimi 大模型生成了一定数量的 Tokens 时(通常情况下,这个数量是 1 Token),立刻将这些 Tokens 传输给客户端,而不再是等待所有 Tokens 生成完毕后再传输给客户端。当你与 Kimi 智能助手 进行对话时,Kimi 智能助手的回复是按字符逐个”跳”出来的,这即是流式输出的表现之一,流式输出能让用户第一时间看到 Kimi 大模型输出的第一个 Token,减少用户的等待时间。 你可以通过这样的方式(stream=True)来使用流式输出,并获得流式输出的响应:- python
- node.js
使用流式输出时的常见问题
当您成功运行上述代码,并了解了流式输出的基本原理后,现在让我们向你讲述一些流式输出的细节和常见问题,以便于你更好的实现自己的业务逻辑。接口细节
当启用流式输出模式(stream=True)时,Kimi 大模型不再返回一个 JSON 格式(Content-Type: application/json)的响应,而是使用 Content-Type: text/event-stream(简称 SSE),这种响应格式支持服务端源源不断地向客户端传输数据,在使用 Kimi 大模型的场景,可以理解为服务端源源不断地向客户端传输 Tokens。
当你查看 SSE 的 HTTP 响应体时,它看起来像这样:
data: 为前缀,紧跟一个合法的 JSON 对象,随后以两个换行符 \n\n 结束当前传输的数据块。最后,在所有数据块均传输完成时,会使用 data: [DONE] 来标识传输已完成,此时可断开网络连接。
Tokens 计算
当使用流式输出模式时,有两种计算 Tokens 的方式,最直接也是最准确的一种计算 Tokens 的方式,是等待所有数据块传输完毕后,通过访问最后一个数据块中的usage 字段来查看整个流式输出过程中产生的 prompt_tokens/completion_tokens/total_tokens。
- python
- node.js
如何终止输出
如果你想要终止流式输出,你可以直接关闭 HTTP 网络连接,或是直接丢弃后续的数据块。例如:在不使用 SDK 的场合下如何处理流式输出
如果你不想使用 Python SDK 来处理流式输出,而是想直接以对接 HTTP 接口的方式来使用 Kimi 大模型(例如某些没有 SDK 的语言,或是你有自己独特的业务逻辑而 SDK 无法满足的情况),我们给出一些示例来帮助你理解如何正确处理 HTTP 中 SSE 响应体(在这里我们仍然以 Python 代码为例,详细的说明将以注释的形式呈现)。- python
- node.js
- 发起 HTTP 请求,并在请求体中,将
stream参数设置为true; - 接收服务端返回的响应,注意到响应
Headers中的Content-Type为text/event-stream,则说明当前响应内容为流式输出; - 逐行读取响应内容并解析数据块(数据块以 JSON 格式呈现),注意通过
data:前缀及换行符\n来判断数据块的开始位置和结束位置; - 通过判断当前数据块内容是否为
[DONE]来判断是否已传输完成;
data: [DONE] 来判断数据是否已传输完成,而不是使用 finish_reason 或其他方式。如果未接收到 data: [DONE] 的消息块,即使已经获取了 finish_reason=stop 的信息,也不应视作数据块传输已完成。换句话说,在未接收到 data: [DONE] 的数据块前,都应视作消息是不完整的。
在流式输出过程中,只有 content 字段会被流式输出,即每个数据块包含 content 的部分 Tokens,而对于不需要流式输出的字段,例如 role 和 usage,我们通常会在第一个或最后一个数据块中一次呈现,而不会在每个数据块中都包含 role 和 usage 字段(具体的,role 字段仅会在第一个数据块中出现,在后续数据块中不会包含 role 字段;而 usage 字段仅会在最后一个数据块中出现,而在前面的数据块中不会包含 usage 字段)。
n>1 时如何处理
在某些场合,我们会希望输出多个结果以供选择,此时正确的做法是将请求参数中的n 设置为比 1 大的一个值。在流式输出中,我们同样支持 n>1 的使用方式,在这种场合下,我们需要添加一些额外的代码来判断当前数据块的 index 值,来确定传输的数据块具体归属于第几个回复,我们用示例代码来说明:
- python
- node.js
n>1 时,处理流式输出的要点在于,你需要先根据数据块的 index 值来判断当前数据块的内容归属于第几个回复消息,再进行后续的逻辑处理。