引言:
- 用过 ChatGPT 的人都知道,当你与 chatgpt 对话的时候,它是“逐字输出”的,就像真的有个人在跟你打字一样。
- 其实,这种技术并没有那么神奇,这种技术叫做
“实时文本生成”或“逐字输出”技术,官方成“自回归(autoregressive)”技术
揭秘:
实际上,ChatGPT 官网也是在获取到完整响应后进行逐字输出的。逐字输出功能仅用于向用户展示响应时的视觉效果。在请求 OpenAI API 时,你会收到一个包含完整响应的结果。使用逐字输出只是为了在显示过程中更有趣且类似于实时对话的交互效果。
- 原理如下:
1、网站会话逐字展示效果的原理
在我们通过官网与chatgpt对话时,我们可以看到逐字输出(实时文本生成)的文字效果。但其实这种效果也是通过网站的前端代码处理的,其实后台返回的响应也是整体传回来的,这样做只是为了提高用户体验,让对话看起来更加自然和动态。
2、调用API会返回的是完整响应
我们实际上在调用API时返回的响应也是完整的。API会在后台把响应处理好,并在生成完整的响应后将其返回,所以不会逐字输出。
3、实现逐字展示的原理
如果要通过 python 对接 openai 实现这种效果,openai后台把响应整合好,你直接用python遍历这个响应让其逐字输出展示即可。(后面实践章节有代码示例)
4、模型的底层原理
无论通过官网对话还是调用API获得响应,后台给我们返回的结果都是完整的。但是,openai的后台,在生成这个响应结果时,确实逐字逐词构造出来的,官方称之为自回归(autoregressive)
的方式。
简单解释下“自回归”方式的意思,大致就是模型首先接收一个输入(如问题或提示),然后逐步生成单词或字符序列。在生成每个新单词或字符时,模型会考虑到目前为止生成的所有单词或字符。通过这样的方式,模型就能够生成上下文相关且连贯的文本。
总结一下,无论通过网站还是调用API,ChatGPT生成的响应是完整返回的。展现出来的逐字响应效果,都是前端代码处理完成的。但ChatGPT生成这个响应之前,其底层逻辑确实是逐字生成的。
5、不同见解
有圈友提出了不同见解,认为 ChatGPT 的逐字输出是通过 stream 流式技术实现的。
即:通过用 websocket + async await + 接口参数中 设置stream=True 可以实现逐字输出效果,他的解答是,oepnai 会将整个结果分段流式响应,达到预期效果。
那么,你的见解是什么呢? 可以把你的想法打在评论区,大家讨论一下~
实践:
而要实现这种效果,最简单的办法就是可以根据调整 time.sleep() 参数来改变逐个字符输出之间的延迟时间来间断的显示响应结果。也可以结合 websocket 以及 Python async 异步等技术实现。
也可以看看这位小哥实现的 websocket 效果,很棒
chatgpt流式服务
看看 ChatGPT4 如何解答?
python 实现 chatgpt 逐字输出,大家可以运行看一下效果,为了方便起见,这里用 gpt3 模型,其他模型原理相同
1、确保将 OPENAI_API_KEY 替换为你自己的 OpenAI API 密钥,然后运行此代码。它将使用 GPT-3.5-turbo 引擎生成一则关于狗的笑话,并逐个字符显示响应。可以根据需要调整 time.sleep() 参数来改变字符输出之间的延迟时间。
2、需要注意的是,逐字输出仅作为模拟用途,实际上在调用API时返回的响应是完整的。在这个示例中,我们只是逐个字符地显示响应。
import openai
import time
# Set up the OpenAI API key
openai.api_key = "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"
# Set up the prompt
prompt = "Hello, how are you?"
# Set up the parameters for the completion request
parameters = {
"model": "text-davinci-003",
"prompt": prompt,
"temperature": 0.5,
"max_tokens": 1,
"n": 1,
"stop": None,
}
# Send the completion request to the OpenAI API
response = openai.Completion.create(**parameters)
# # Loop to continue the conversation
while True:
time.sleep(0.02)
prompt += response.choices[0].text
parameters["prompt"] = prompt
response = openai.Completion.create(**parameters)
print(response.choices[0].text)
# 另外一种实现
# response = openai.Completion.create(parameters)
# response_text = response.choices[0].text.strip()
# for char in response_text:
# print(char, end="", flush=True)
# time.sleep(0.1)
stream=True 的效果