速递!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 的主要步骤如下:
客户端创建一个新的EventSource对象,参数是服务器的URL。let source = new EventSource("http://xxx/chat/completions");
服务器返回一个 HTTP 响应,Content-Type 为 "text/event-stream",并保持连接打开。HTTP/1.1 200 OKContent-Type: text/event-streamConnection: keep-aliveCache-Control: no-cache
服务器通过打开的连接向客户端发送消息。每个消息都包含一些数据,数据可以是任何格式的文本,比如 JSON。消息以两个连续的换行符结束。data: This is a message\n\n
客户端监听 "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 服务端。
Chat Completion
<script> const divTyping = document.getElementById("text") let ctrl const 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>
五、参考资料MDN - EventSource https://developer.mozilla.org/en-US/docs/Web/API/EventSourceMDN - Server-sent events https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_eventsServer-Sent Events 教程 https://www.ruanyifeng.com/blog/2017/05/server-sent_events.htmlGo 实现 SSE 服务端 https://learnku.com/articles/75392ChatGPT 打字机消息回复实现原理 https://juejin.cn/post/7229632570374783034Create chat completion https://platform.openai.com/docs/api-reference/chat/createChatGPT Web 开源项目 https://github.com/Chanzhaoyu/chatgpt-webGo clients forOpenAI API https://github.com/sashabaranov/go-openai
标签:
推荐
- 速递!ChatGPT 打字机效果原理
- 吸塑字是什么材料_吸塑字是什么|当前快看
- 五一街道开展道路交通安全进校园宣传活动
- 家常酱汁豆腐,外焦里嫩,营养好吃,太入味了 今日播报
- 天天头条:巴勒斯坦呼吁国际社会对以色列施压 迫使其重新开放过境点
- 车臣部队前往俄乌冲突区!乌军称在巴赫穆特推进2公里,俄方否认:防线未被突破 当前独家
- 焦点热议:鹤壁市淇滨区金山街道持续开展安全生产、环境保护专项督导检查
- 世界观点:全国防灾减灾日到来之际,各地开展宣传教育活动——普及自救技能,防范灾害风险
- 男子深陷刷单骗局反怼警察 结果被骗后终于老实了!!|世界热点
- 武学胡同(关于武学胡同介绍)
- 【新视野】单身期限泰剧(单身期限)
- 明阳智能:5月12日融券卖出11.05万股,融资融券余额19.04亿元|今日最新
- 【全球快播报】深圳市同洲电子股份有限公司 关于2023年股票期权激励计划首次授予登记完成的公告
- 佞臣是指什么_人名_佞臣是什么意思 环球快资讯
- 数字视觉概念股有哪些?数字视觉概念股相关股票名单 天天新资讯
- ps怎么改图片大小kb尺寸不变_ps怎么改图片大小kb 环球热点
- 罗马诺:布莱顿接近与多特中场达胡德达成口头协议,今夏免签
- 世界今亮点!丝瓜炒肉的做法_怎么做丝瓜炒肉
- 气温即将起飞,你准备好了吗? 当前关注
- 国芯科技股东拟合计减持不超5.99%股份 全球热门
- 网传“榴莲变贵”?广州市场监管局:假的|环球速看料
- 2022六一儿童节主题嘉年华活动策划方案:萌趣童心,欢乐童享
- 三尚传媒董事何志涛被纳入失信被执行人名单且公司未能规范履行信息披露义务 天天关注
- 高仙芝_高仙芝是个怎样的人
- 三节15中0,决胜时刻命中关键3分,科比11年前就给獭兔打了样!
- 福斯公司和新闻集团续租纽约曼哈顿中城办公室,为期20年
- 连云港攻略一日游_连云港攻略
- 环球动态:河流为什么不走直路?(受益匪浅)
- 环球新动态:安徽工程大学数理与金融学院举办数学建模报告会
- 世界快看点丨宁夏银川:住房公积金可支付购房首付
- 新动态:华语电影票房排名_华语电影:理论
- 【世界独家】中牟县司法局组织召开行政规范性文件管理工作培训会
- 每日资讯:标普:中国海外宏洋能够经受住房地产行业波动的考验
- 如何建造精益极谷仓_小生日礼物送什么好小学生简单手工
- 精彩看点:05.12 上證指數、創業板指數 實戰技術應用
- 美国债务上限谈判无进展 拜登可能取消G7行程_报资讯
- 热推荐:T3出行“五一”大数据:00后最多一日打车39次
- 世界微资讯!“鱼和熊掌”可以兼得!索尼Xperia 1 V兼顾轻薄与拍照高画质
- 破壁灵芝孢子粉的食用方法和功效 破壁灵芝孢子粉的食用方法-当前独家
- 中汽协:4月乘用车产销环比分别下降17.3%和10.2%,需求动力仍然偏弱-全球快播报
- 全球资讯:利好!浓眉检查无脑震荡,离开球馆表情轻松+走路稳当,可出战G6
- 8月4日是什么星座女 8月4日是什么星座
- 六福内地铂金多少钱一克(2023年05月11日)_热门
- 2023年5月11日云南省南瓜批发价格行情-全球微资讯
- 环球热讯:国际数字经济创新论坛在北京丰台举办
- 中央商场三跌停,祝义财部分质押股份已逾期-焦点热讯
- 烧烤火爆出圈 激发经济活力-环球热点
- 中国制造业品牌闯出新天地 全球品牌不断涌现
- 年内多家上市公司面临易主 业绩承压或是主因
- 天天快讯:“跑马季”来临 赛前赛后拉伸方法有区别
- 焦点速看:充电桩出海大爆发,深圳大卖第一年就赚了近亿元
- 环球热头条丨安徽:打造聚才引才强磁场
- 自证成熟:《孤星》中的“辩论”本质上是什么|热推荐
- 手机外置声卡什么牌子好性价比高 外置声卡哪种牌子好 世界即时看
- 山东台儿庄:“理响讲台”传递干事创业信心决心 速递
- 环球报道:电脑卡慢反应慢怎么解决_电脑卡慢
- 王亚平太空授课2021视频_王亚平太空授课2021
- 影视帝国论坛网址_影视帝国悠悠鸟论坛
- 范-汉克_关于范-汉克的简介|全球热门
- 失眠的自我疗法有什么_失眠的自我疗法
- 猪企连亏4个月,养一头亏168元!主动“去产能”快来了?
- 宁波龙山山下书院: 优质阅读空间助力乡村精神共富 天天热资讯
- 夏天好用的包包都在这里,通勤休闲必备,小个子也友好
- 用文本文档做小程序_用文本文档怎么写程序
- 2023年5月10日湖北省异丁醇价格最新行情预测
- 撇点的字有哪些_撇点
- 世界视点!稳中向好势头延续!今年前4个月我国外贸进出口同比增长5.8%
- 新疆生产建设兵团第八师第一期科技成果推介会在石河子举行
- 环球滚动:最新高ROE个股来了!8股超50% 这两行业较集中
- 每日热闻!《领航优配》实力强大炒股平台:持有银行股享受股息可以吗?
- 每日动态!浙江富豪栽了!百强房企遭强制清盘,中融信托疑踩雷,有投资人300万未兑付
- 全球今亮点!仰望U8申报信息发布 预售109.8万元
- ?旺达对着镜头摆弄自拍,不少网友提到伊卡尔迪…… 焦点讯息
- 环球快消息!弘瞻怎么读_弘瞻
- 【全球时快讯】万得凯(301309)报收于26.33元,上涨0.65%
- 第七届“温暖微行动”体育舞蹈公益百校行活动启动
- 全球观焦点:马斯克:推特推出加密私信 未来将推出音频和视频通话功能
- 北京保障房中心有限公司:万科泊寓草桥项目面向毕业大学生开展专项配租 热点评
- 焦点要闻:聚焦人才培养,服务国家需求——高校学科专业迈向分类发展特色发展
- 减少乘客走行时间!今年北京部分地铁站实施高低峰差异化换乘
- 小米神机发布:搭载骁龙7 Gen 2/骁龙8 Gen 1芯片
- 焦点热讯:设计总院5月10日快速上涨
- 【全球报资讯】明月镜片5月10日快速上涨
- 焦点热讯:苏州出台产业投资新政!26条措施力撑实体经济再跃升
- 棉花:关注产区天气变化
- 5月10日盘前重要产业新闻
- 世界实时:卡纳瓦罗:03欧冠半决赛我们客场进球少被淘汰,希望这次会很精彩
- 安切洛蒂:德布劳内进球前球出界了 裁判不是很细心还判了我黄牌_百事通
- 今日播报!诺诚健华(688428)2023年一季报财务简析:营收净利润双双增长,债务压力大
- 商用车板块5月9日跌0.35%,中国重汽领跌,主力资金净流出9801.04万元
- 小儿七星茶颗粒用量_小儿七星茶颗粒多大的小孩可以吃
- 羞辱勇士?ESPN称湖人G5或许该轮休主力 球迷炸锅|天天新动态
- 世界滚动:“列车持刀杀人”被害人家属:已和广铁谈成赔偿!凶手曾隐瞒精神病史入职
- 农行以“亲”“清”之水浇灌青年
- 【全球独家】未来出行黑科技?北京可以刷掌坐地铁啦!
- 零点有数:公司两大核心优势技术为:在线数据集成技术以及垂直应用算法技术
- 东京奥运会回放完整版乒乓球(东京奥运会乒乓球有几个金牌)
- ipmph人卫医学网_ipmp_世界实时
- 天天速看:竞价顺序、摇号时间定了!南京第二批次10幅地块明日出让
- 全球观热点:2023年秋冬牛仔女装流行趋势
X 关闭
行业规章
X 关闭