ChatGPT 打字机效果原理

一、背景

在初次使用 ChatGPT 时,我就被打字机的视觉效果吸引。总是感觉似曾相识,因为经常在一些科幻电影中看到,高级文明回传的信息在通讯设备的屏幕上以打字机效果逐步出现,在紧张的氛围下,输出人类可读的内容,拉动着观众的神经,一步步将故事情节拉向高潮。

在很早之前我就了解过 Server-Sent Events 这门服务端推送技术,当时看过很多博客介绍其原理和使用场景,最后也没有留下深刻的印象。这一次 ChatGPT 的使用感受带给我一些触动,也激发了对技术的思考,究竟什么样的技术是一门好的技术 ”需要一个杀手级的应用,现实应用会促进技术发展“,技术不是冰冷无情的,贴近生活挖掘其实用价值,一样可以表现出感性的艺术效果。

二、SSE 工作原理

Server-Sent Events(SSE)是一种允许服务器单向推送信息到客户端的技术,与传统的请求/响应模式相比,这种模式更加适合处理实时数据。以下是一些常见的 Server-Sent Events 应用场景:

  • ChatGPT 大型语言模型处理自然语言需要大量的计算资源和时间,响应速度肯定比普通的 HTTP 请求要慢的多。对于这种单项对话场景,ChagtGPT 将先计算出的数据 “推送” 给用户,边计算边返回,提升用户体验。
  • 实时通知:SSE 非常适合于实时通知的场景,例如电子邮件或社交媒体通知。一旦有新消息,服务器可以立即将其推送给客户端,而无需客户端定时轮询检查新消息。
  • 实时数据流:在金融服务、股票市场、体育比赛等场景中,SSE 可以用于实时推送数据流,如股票价格等。

2.1 SSE 工作原理

SSE 的基本工作原理是客户端首先向服务器发送一个 HTTP 请求,然后服务器保持这个连接打开,并周期性地通过这个连接向客户端发送数据。每个数据块都是一个独立的消息,每个消息都以一个空行结束。

使用 SSE 的主要步骤如下:

  1. 客户端创建一个新的EventSource对象,参数是服务器的URL。
let source = new EventSource("http://xxx/chat/completions");
  1. 服务器返回一个 HTTP 响应,Content-Type 为 "text/event-stream",并保持连接打开。
HTTP/1.1 200 OK
Content-Type: text/event-stream
Connection: keep-alive
Cache-Control: no-cache
  1. 服务器通过打开的连接向客户端发送消息。每个消息都包含一些数据,数据可以是任何格式的文本,比如 JSON。消息以两个连续的换行符结束。
data: This is a message\n\n
  1. 客户端监听 "message" 事件,当收到新的消息时,这个事件会被触发。
source.onmessage = function(event) {console.log(event.data);
};

注意,由于 SSE 是基于 HTTP 的,因此它受到同源策略的限制。如果你需要进行跨域 SSE,你需要在服务器端设置适当的 CORS 头部信息。另外,SSE 只支持文本数据,不支持二进制数据。如果你需要发送二进制数据,你可能需要考虑使用 WebSockets。

2.2 Fetch API 模拟 SSE

Fetch API 是一种通用的 HTTP 请求和响应模型,它可以用于发送和接收任何类型的 HTTP 请求,支持文本和二进制数据。由于其对流(Stream)的支持,可以模拟 Server-Sent Events (SSE),需要手动处理重连和流式数据。

在某些情况下,你可能会选择使用 Fetch API 模拟 SSE,而不是直接使用 SSE:

  • 发送二进制数据:如果你需要发送或接收二进制数据,你必须使用 Fetch API 或其他技术,因为 SSE 只支持文本数据。
  • 双向通信:如果你需要进行双向通信,你必须使用 Fetch API 或其他技术,因为 SSE 只支持单向通信。
  • 更大的灵活性:Fetch API 提供了更大的灵活性,例如,你可以控制请求头、请求方法、响应处理等。
const url = 'https://your-server.com/events';fetch(url).then(response => {const reader = response.body.getReader();const decoder = new TextDecoder();// done 为数据是否接收完成 boolean 值// value 为接收到的数据, Uint8Array 格式return reader.read().then(function processMessage({ done, value }) {if (done) {return;}console.log(decoder.decode(value));return reader.read().then(processMessage);});});

在这个示例中,我们使用 fetch() 函数发起 HTTP 请求。然后,使用 response.body.getReader() 获取一个可读流的 reader,用来读取数据。还创建了一个 TextDecoder 对象,用来将二进制数据解码为文本,然后打印出来。然后,再次调用 reader.read() 方法,等待下一批数据。

这样,就可以使用 Fetch API 来接收服务器推送的实时更新,就像使用 SSE 一样,ChatGPT 采用的就是这种实现。

三、SSE 服务端

Server-Sent Events (SSE) 是一种服务器推送技术,允许服务器向客户端发送实时更新。在服务器端,我们需要创建一个 endpoint,发送正确的 HTTP 头部并持续推送数据。

func main() {http.HandleFunc("/v1/chat/completions", func(w http.ResponseWriter, r *http.Request) {flusher, ok := w.(http.Flusher)if !ok {http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)return}// 事件流媒体 (MIME 类型)w.Header().Set("Content-Type", "text/event-stream")// 阻止缓存w.Header().Set("Cache-Control", "no-cache")// 保持长连接w.Header().Set("Connection", "keep-alive")// 跨域支持w.Header().Set("Access-Control-Allow-Origin", "*")phrase := []string{"dolor ", "sit amet", ", consectetur", " adipiscing elit. ", "Ut consequat", " diam at ", "justo efficitur", " mattis."}for _, delta := range phrase {// 数据内容用 data 表示, 如果数据很长, 可以分成多行用 \n 结尾,fmt.Fprintf(w, "data: %s\n", delta)flusher.Flush()time.Sleep(200 * time.Millisecond)}// 最后一行使用 \n\n 结尾fmt.Fprintf(w, "data: %s\n\n", "[DONE]")})if err := http.ListenAndServe("127.0.0.1:8080", nil); err != nil {panic(err)}
}

在 Go 语言中,http.Flusher 是一个接口,它允许 HTTP 响应数据在写入后立即发送到客户端,而不是等待所有响应数据都写入后再一次性发送。这对于长连接和服务器推送的场景非常有用。

// Flush 将用户层的数据写入到 TCP 缓冲区,内核会尽快将 TCP 缓存区数据发送出去
type Flusher interface {Flush()
}

扩展:每个 TCP socket 连接在内核中都有一个发送缓存区和接收缓冲区

发送缓冲区用于暂存应用程序写入的数据,直到数据被发送出去并得到对方的确认。接收缓冲区用于暂存收到的数据,直到应用程序读取这些数据。

当应用程序调用发送数据的系统调用(如 write 或 send)时,数据会被复制到发送缓冲区。然后,内核会尽快将这些数据发送出去。但具体发送的时机取决于许多因素,包括但不限于以下几点:

  • Nagle 算法:为了减少小包在网络上的传输,Nagle 算法规定,除非上一个发送的数据包已经得到确认,否则不能发送新的数据包。所以,如果发送缓冲区中的数据量较小,并且上一个数据包还未得到确认,数据可能会在缓冲区中等待。
  • TCP 拥塞控制:TCP 协议通过拥塞控制算法,动态地调整发送速率,以避免网络拥塞。如果网络拥塞,数据可能会在发送缓冲区中等待,直到网络状况改善。
  • 接收方的接收窗口:接收方通过 TCP 的滑动窗口机制,告诉发送方它的接收缓冲区还有多少空间。如果接收方的接收窗口满了,数据必须在发送缓冲区等待,直到接收方的接收窗口有空间。

当数据成功发送并得到确认后,内核会从发送缓冲区中删除这些数据,释放缓冲区空间。

四、实现一个打字机效果

上面我们讨论下 SSE 的工作原理,也知道由于 Web API EventSource 的局限性,ChatGPT 采用了 Fetch API 来手动处理和解析 SSE 服务端端点接收的数据流。那么接下来通过一个简单的打字机案例,加深对所学内容的理解。

这里借鉴了 《ChatGPT 打字机消息回复实现原理》 文章中的前端代码,在其基础上增加了消息处理逻辑,用于适配上面的 SSE 服务端。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Chat Completion</title>
</head>
<body><button onclick="connectFetch()">建立 fetchSSE 连接</button><button onclick="closeSSE()">断开 fetchSSE 连接</button><br/><br/><div id="text"></div><script>const divTyping = document.getElementById('text')let ctrlconst connectFetch = () => {ctrl = new AbortController()fetchEventSource('http://127.0.0.1:8080/v1/chat/completions', {method: 'POST',body: JSON.stringify({prompt: 'Lorem ipsum',max_tokens: 20,stream: true,}),signal: ctrl.signal,onopen: () => {console.log('Connection successful.')},onclose: () => {console.log('Connection closed.')},onmessage: (delta) => {let prefix = 'data: 'if (!delta.startsWith(prefix)) {return}delta = delta.slice(prefix.length)delta = delta.replace(/\n$/, '')if (delta === '[DONE]\n') {return}divTyping.innerText += delta}})}const closeSSE = () => {if (ctrl) {ctrl.abort()ctrl = null}}const fetchEventSource = (url, options) => {fetch(url, options).then(resp => {if (resp.status === 200) {options.onopen && options.onopen()return resp.body}}).then(rb => {const reader = rb.getReader()const push = () => {// done 为数据是否接收完成 boolean 值// value 为接收到的数据, Uint8Array 格式return reader.read().then(({done, value}) => {if (done) {options.onclose && options.onclose()return}options.onmessage && options.onmessage(new TextDecoder().decode(value))return push()});}// 开始读取流信息return push()}).catch((e) => {options.error && options.error(e)})}</script>
</body>
</html>

五、参考资料

  • MDN - EventSource EventSource - Web APIs | MDN
  • MDN - Server-sent events Server-sent events - Web APIs | MDN
  • Server-Sent Events 教程 Server-Sent Events 教程 - 阮一峰的网络日志
  • Go 实现 SSE 服务端 Go实现SSE的方式和需要注意的事项 | Laravel China 社区
  • ChatGPT 打字机消息回复实现原理 ChatGPT 打字机消息回复实现原理 - 掘金
  • Create chat completion https://platform.openai.com/docs/api-reference/chat/create
  • ChatGPT Web 开源项目 https://github.com/Chanzhaoyu/chatgpt-web
  • Go clients for OpenAI API https://github.com/sashabaranov/go-openai

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/14110.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT调教指北

ChatGPT调教指北 ChatGPT某些对话需要通过特定的指示&#xff0c;才能让回复出满意的答案。以下是一些有趣且常用的调教信息。 如需更详细请查看&#xff1a;https://github.com/labi-xiaoxin/chatgpt-prompts-zh 如果还不会使用ChatGPT&#xff0c;请查看公众号【迷茫的21世纪…

我身边35+程序员,的真实现状,其实没那么惨...

1 不会笑青年 我和不会笑青年是在11年&#xff0c;第二家公司的时候遇到的&#xff0c;我们一起四个人同一天入职的&#xff0c;后来成为了四个好朋友。 今天就先拿&#xff0c;这4个人&#xff0c;给大家说说&#xff0c;他们现在都在干啥… 先聊不会笑青年吧&#xff0c;…

突破界限,解锁AIGC火爆出圈背后的驱动力

从2022年下半年开始&#xff0c;AI绘画工具Stable Diffusion、AI聊天机器人ChatGPT陆续在全球爆火&#xff0c;迭代速度更是呈现指数级发展&#xff0c;让普通用户直观感受到了AI技术的强大和AI技术发展的一日千里&#xff0c;也让AIGC逐渐接棒“元宇宙”成为全球关注的焦点和热…

AI可能造成人类灭绝,真的还是炒作?

作者 | 王瑞平 5月30日&#xff0c;一封由非营利组织人工智能安全中心&#xff08;Center for AI Safety&#xff09;发布的简短声明轰动了AI界&#xff0c;导致人工智能的地位可能会被动摇。 我们在该组织的官网上找到了这份声明。声明中仅有22个单词&#xff0c;却饱含了专家…

文心一言一把火,百度智能云盈利了!李彦宏诚不欺我?

鱼羊 发自 凹非寺量子位 | 公众号 QbitAI 文心一言发布后&#xff0c;百度的首份财报来了。 先说结论&#xff1a;以文心一言为代表的大模型技术&#xff0c;正在给百度带来新的增长契机。 文心一言发布前&#xff0c;李彦宏就曾判断&#xff1a; 中国AI市场即将迎来爆发性的需…

警惕AI换脸技术:近期诈骗事件揭示的惊人真相

大家好&#xff0c;我是可夫小子&#xff0c;《小白玩转ChatGPT》专栏作者&#xff0c;关注AIGC、读书和自媒体。 目录 1. deepswap 2. faceswap 3. swapface 总结 &#x1f4e3;通知 近日&#xff0c;包头警方公布了一起用AI进行电信诈骗的案件&#xff0c;其中福州科技公…

研报精选230215

目录 【行业230215开源证券】电力设备行业投资策略&#xff1a;特高压建设有望迎来高峰期&#xff0c;解决清洁能源跨区互济瓶颈 【行业230215浙商证券】计算机行业【AIGC算力时代系列报告】&#xff1a;ChatGPT研究框架 【个股230215国信证券_公牛集团】民用电工行业领军者&am…

巴比特 | 元宇宙每日必读:科技巨头们下场自研AI芯片,微软、谷歌、亚马逊已推出或计划发布8款服务器和AI芯片,Meta也在路上...

摘要&#xff1a;据澎湃新闻报道&#xff0c;当下&#xff0c;英伟达还是当之无愧的“AI算力王者”&#xff0c;A100、H100系列芯片占据金字塔顶尖位置&#xff0c;是ChatGPT这样的大型语言模型背后的动力来源。然而&#xff0c;不管是为了降低成本&#xff0c;还是减少对英伟达…

第十六届全国大学生信息安全竞赛创新实践赛初赛部分WP AGCTF战队

持续两天的比赛&#xff0c;打的很累&#xff0c;web没有出太多的题&#xff0c;比赛被pwn师傅带飞了&#xff0c;希望下此加油&#xff0c;下边是此次比赛排名。 文章目录 MISC签到卡被加密的生产流量国粹调查问卷pyshell CRYPTO基于国密SM2算法的密钥密文分发可信度量Sign_i…

AI 理论之父出生 | 历史上的今天

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2023 年 4 月 28 日&#xff0c;在 1994 年的今天&#xff0c;美国克林顿政府公布了一项价值数百万美元的计划&#xff0c;以帮助那些制造平板显示屏的美国公司维持生计…

公司老板 10 分钟被骗 430 万!骗子用 AI 换脸 + 换声,网友:这我怎么防啊!

整理 | 郑丽媛 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 在 ChatGPT 的“点火”下&#xff0c;这趟名为 AI 的列车已逐渐从幕后驶向台前&#xff0c;吸引了不少人的关注和“搭乘”——而科技&#xff0c;向来是一把双刃剑。 俗语有言&#xff0c;“耳听为虚…

华为MetaERP全球上线,15小时完成全球88个子公司切换;微软Win12最快明年问世;FerretDB 1.2发布|极客头条...

「极客头条」—— 技术人员的新闻圈&#xff01; CSDN 的读者朋友们早上好哇&#xff0c;「极客头条」来啦&#xff0c;快来看今天都有哪些值得我们技术人关注的重要新闻吧。 整理 | 梦依丹 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 一分钟速览新闻点&#…

科技周报 | AI诈骗430万,ChatGPT有APP版了

2023年5月17日 ~ 2023年5月24日 5月24日 | 历史上的今天 1954年5月24日&#xff0c;晶体管电子计算机诞生。 产业动态 01 AI诈骗10分钟骗走430万 5月22日&#xff0c;一起“AI网聊10分钟骗走430万”的典型案例冲上热搜。 据内蒙古包头警方发布&#xff0c;4月20日中午&…

马斯克宣布将卸任推特CEO:转战技术岗位 ;王坚正式回归阿里云;科大讯飞否认星火大模型套壳ChatGPT|极客头条...

「极客头条」—— 技术人员的新闻圈&#xff01; CSDN 的读者朋友们早上好哇&#xff0c;「极客头条」来啦&#xff0c;快来看今天都有哪些值得我们技术人关注的重要新闻吧。 整理 | 梦依丹 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 一分钟速览新闻点&#…

人工智能轨道交通行业周刊-第39期(2023.3.20-3.26)

本期关键词&#xff1a;综合运维智控中心、现场防护员、模型先验知识、机器视觉照明、国铁统计公报 1 整理涉及公众号名单 1.1 行业类 RT轨道交通人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路与城市轨道交通Rai…

电费竟然占了数据中心运维总成本的7成?

作为企业IT运维工作人员&#xff0c;我们最关心的往往是数据中心各项服务是否稳定运行&#xff0c;系统是否安全。然而&#xff0c;数据中心的运维人员、甚至公司领导和业务部门都几乎很少关心数据中心的能耗。 据相关单位统计&#xff0c;中国数据中心的电费竟然占了数据中心运…

USA获取实时电价数据

http://www.engieresources.com/ historical-data两次注册完成后可以调取实时电价&#xff0c;PJM电力市场的数据比较好 Hourly Real Time

4G无线预付费电表系统设计及其应用

摘要 针对目前市场上普遍以射频卡作为售电介质的预付费售电系统存在的问题&#xff0c;介绍 了一种新型的无线预付费售电系统及其构成&#xff0c;并给出了整个系统设计的完整方案。整个系统包括用户终端和电力管理系统端&#xff0c;它之前间通过RS485、NB、2G、4G、lora等通…

工大助手电费查询接口讲解

工大助手电费查询接口讲解 本人是工大的一名学生&#xff0c;平时没事就喜欢写写代码&#xff0c;今天我来教大家解析学校电费查询接口中的参数&#xff0c;首先打开工大助手的web端https://huthelper.cn/&#xff0c;先登录&#xff0c;进入电费查询栏&#xff0c;进去networ…

chatgpt赋能python:Python电费计算:简单高效的解决方案

Python电费计算: 简单高效的解决方案 随着智能家居技术的不断发展&#xff0c;人们越来越依赖电力。对于居家的人们来说&#xff0c;控制电费成本是一个重要的问题。智能计算机语言Python可以用来解决这个问题&#xff0c;为您的电费账单带来显著的改进。 简介 Python是一门…