Kitex Thrift Streaming 在字節(jié)跳動(dòng) Prompt 平臺(tái)的實(shí)踐
01、概述
字節(jié)跳動(dòng) Prompt 平臺(tái)旨在為用戶提供全面的 Prompt 開(kāi)發(fā)、調(diào)優(yōu)、評(píng)測(cè)及應(yīng)用等全生命周期功能。在這些功能中,打字機(jī)效果的流式輸出大模型結(jié)果是一項(xiàng)至關(guān)重要的特性。基于 SSE(Server-Sent Events) 實(shí)現(xiàn)雖然可行,但需要額外編寫 HTTP 服務(wù),這增加了開(kāi)發(fā)的復(fù)雜性。而輪詢方式雖然簡(jiǎn)單,但用戶體驗(yàn)并不理想,顯得過(guò)于笨拙。至于 gRPC,雖然性能出色,但可能引入兼容性問(wèn)題,使得部署和維護(hù)變得復(fù)雜。因此,我們借助 Kitex 的 Thrift streaming 能力,成功實(shí)現(xiàn)了流式接口的落地,從而為用戶提供了流暢、高效的打字機(jī)效果大模型結(jié)果輸出體驗(yàn)。
02、業(yè)務(wù)背景
隨著 AI 技術(shù)的不斷發(fā)展,人們的生活正在發(fā)生深刻的變化。以字節(jié)旗下的 AI 產(chǎn)品豆包為例,其中的智能體給人們帶來(lái)了許多新奇的體驗(yàn)。其中,AI 男友、AI 女友等趣味智能機(jī)器人尤其受歡迎,它們不僅能夠以風(fēng)趣幽默的方式與用戶互動(dòng),還能展現(xiàn)出溫柔體貼的一面。
這一切都離不開(kāi)一個(gè)與大模型緊密相連的概念——提示詞(Prompt)。簡(jiǎn)單來(lái)說(shuō),Prompt 就是向預(yù)訓(xùn)練模型輸入的文本,用以引導(dǎo)模型生成符合特定需求的文本輸出。形象地講,Prompt 就像是為大模型打造一個(gè)專屬的夢(mèng)境,通過(guò)它,我們能夠引導(dǎo)大模型在特定場(chǎng)景下給出更貼切、更有針對(duì)性的回答。
以 AI 女友為例,我們會(huì)通過(guò)精心設(shè)計(jì)的 Prompt 來(lái)告訴大模型,它的角色是一個(gè)溫柔體貼的虛擬女友。同時(shí),我們還會(huì)設(shè)定一些限制條件,比如要求它以溫柔體貼的方式與用戶交流,并具備傾聽(tīng)、理解、鼓勵(lì)和建議等技能。此外,我們還會(huì)詳細(xì)描述它的工作流程,比如在問(wèn)候時(shí)引導(dǎo)用戶說(shuō)出自己的名字,為用戶起一個(gè)合適的昵稱,然后與用戶進(jìn)行深入的溝通交流,并提供有益的建議。
通過(guò)這樣的 Prompt,我們?yōu)榇竽P蜆?gòu)建了一個(gè)完整的“夢(mèng)境”,讓它明白自己是一個(gè) AI 女友,并清楚自己應(yīng)該如何與用戶互動(dòng)。當(dāng)這個(gè) Prompt 被激活后,我們與大模型進(jìn)行問(wèn)答時(shí),它就會(huì)根據(jù)我們的提示給出相應(yīng)的回復(fù)。比如,當(dāng)我們向它問(wèn)好時(shí),它會(huì)引導(dǎo)我們說(shuō)出自己的名字,并為我們?nèi)∫粋€(gè)可愛(ài)的昵稱,然后給予我們鼓勵(lì)和寬慰。
從這個(gè)例子中可以看出,Prompt 在特定場(chǎng)景下對(duì)大模型的輸出起著決定性的作用。更進(jìn)一步地說(shuō),它還會(huì)影響到大模型在輸出過(guò)程中 token 的消耗以及響應(yīng)時(shí)間的快慢。因此,一個(gè)優(yōu)秀的 Prompt 對(duì)于提升模型輸出效果至關(guān)重要。
03、需求場(chǎng)景
字節(jié)跳動(dòng) Flow 團(tuán)隊(duì)正致力于構(gòu)建一個(gè)全面而成熟的平臺(tái)/方法,旨在幫助 Prompt 開(kāi)發(fā)者設(shè)計(jì)、迭代、評(píng)測(cè)及優(yōu)化其 Prompt,從而增強(qiáng) LLM(大型語(yǔ)言模型)的表現(xiàn)力。在開(kāi)發(fā)階段,我們計(jì)劃提供結(jié)構(gòu)化生成和引導(dǎo)式生成的方式,以輔助用戶編寫出高效且精準(zhǔn)的 Prompt,并進(jìn)行相應(yīng)的調(diào)試運(yùn)行。
隨著開(kāi)發(fā)的深入,我們將進(jìn)一步引入 COT(Chain of Thought)、Few shots 等自動(dòng)調(diào)優(yōu)技術(shù),以及 APO(Auto Prompt Optimization) 方法,幫助 Prompt 提高回答的正確率。同時(shí),我們還將提供 Prompt 擴(kuò)縮寫的能力,以優(yōu)化大模型在 token 消耗方面的效率。
此外,為了全面評(píng)估 Prompt 的效果,我們將結(jié)合多樣化的數(shù)據(jù)集對(duì) Prompt 進(jìn)行打分,并深入分析其性能瓶頸,以便進(jìn)行針對(duì)性的改進(jìn)。最終,我們將提供一鍵部署的功能,使開(kāi)發(fā)者能夠輕松地將 Prompt 能力及其背后的大模型集成到他們的應(yīng)用中。
當(dāng)然,這些功能的實(shí)現(xiàn)都離不開(kāi)對(duì)實(shí)時(shí)流式傳輸技術(shù)的支持。就像你體驗(yàn)過(guò)的 GPT、豆包、百度 AI 搜索等 AI 能力一樣,它們?cè)谟脩籼釂?wèn)后,都采用了打字機(jī)形式的回復(fù)方式,讓用戶感受到數(shù)據(jù)在不斷流入屏幕,從而提高了聊天的流暢性和響應(yīng)速度。這種實(shí)時(shí)流式傳輸技術(shù)正是我們 Prompt 平臺(tái)需要提供的最基礎(chǔ)能力。通過(guò)將數(shù)據(jù)分成多個(gè)數(shù)據(jù)流進(jìn)行網(wǎng)絡(luò)傳輸,我們可以有效減少網(wǎng)絡(luò)延遲,提高性能,確保用戶在與大型語(yǔ)言模型交互時(shí)獲得更好的體驗(yàn)。
04、解決方案
為了實(shí)現(xiàn)流式輸出功能,我們進(jìn)行了深入的調(diào)研,綜合考慮了多種方案:
- 輪詢
- HTTP SSE
- Kitex gRPC Streaming(protobuf)
- Kitex Thrift Streaming
首先,輪詢方案由于其呆板性,不符合我們的需求,因此被排除在外。其次,雖然基于 HTTP 的 SSE 是一種可行的方案,但考慮到我們對(duì) RPC(遠(yuǎn)程過(guò)程調(diào)用)同樣有嚴(yán)格的要求,因此也需要尋找更為合適的方案。另外,我們發(fā)現(xiàn) Protobuf 協(xié)議的流式處理支持并不能完全滿足我們的需求,尤其是在 Thrift 接口方面。最后,我們注意到了 Kitex 對(duì)于 Thrift Streaming 的支持。當(dāng)時(shí),Kitex Thrift Streaming 正處于開(kāi)發(fā)階段,我們果斷決定成為其首批用戶,并以此為基礎(chǔ)構(gòu)建整個(gè) Prompt 平臺(tái)的基本框架。
在架構(gòu)設(shè)計(jì)上,我們首先對(duì)標(biāo) LangChain,建立 LLM 工程化服務(wù)。在此基礎(chǔ)上,我們進(jìn)一步構(gòu)建 Prompt 服務(wù),以提供最基本的 Prompt 管理及應(yīng)用能力。為了與前端進(jìn)行交互,我們通過(guò) API Gateway 提供 HTTP 接口。而在微服務(wù)之間的通信方面,我們采用了 Kitex 框架,以提供流式接口和非流式接口的支持,確保數(shù)據(jù)的高效傳輸和處理。
通過(guò)這一解決方案,我們成功實(shí)現(xiàn)了流式輸出功能,為用戶提供了更加流暢、高效的 AI 交互體驗(yàn)。同時(shí),我們也為未來(lái)的擴(kuò)展和優(yōu)化打下了堅(jiān)實(shí)的基礎(chǔ)。
05、實(shí)踐與踩坑
流式調(diào)用的流程
流式調(diào)用的流程起始于用戶發(fā)起提問(wèn)。這一請(qǐng)求首先被發(fā)送至網(wǎng)關(guān),網(wǎng)關(guān)隨后與下游的 Prompt RPC 接口建立連接。Prompt RPC 接口進(jìn)一步與 LLM 工程化服務(wù)建立通信,該服務(wù)負(fù)責(zé)持續(xù)與模型交互,并獲取模型的輸出結(jié)果。這些結(jié)果通過(guò)流式的方式逐層向上傳遞,直至到達(dá)網(wǎng)關(guān)層,并最終實(shí)現(xiàn)流式上屏展示給用戶。
在此過(guò)程中,我們?cè)?Prompt 服務(wù)中編寫了一個(gè)流式接口,用于處理流式調(diào)用。該接口首先通過(guò)調(diào)用下游接口建立與下游的連接,然后通過(guò)一個(gè) for 循環(huán)不斷地去接收下游吐給我們的這個(gè)流式的包的結(jié)果。一旦接收到數(shù)據(jù)包,我們通過(guò) send 方法將其向上層透?jìng)鳎敝劣龅藉e(cuò)誤或流關(guān)閉為止,循環(huán)隨之結(jié)束。
在實(shí)現(xiàn)過(guò)程中,我們體驗(yàn)到了 Kitex Thrift Streaming 的簡(jiǎn)潔性。然而,我們也遇到了一些問(wèn)題。尤其是在錯(cuò)誤處理方面,我們發(fā)現(xiàn)代碼運(yùn)行時(shí)無(wú)法獲取預(yù)期結(jié)果,甚至導(dǎo)致 CPU 負(fù)載過(guò)高。
進(jìn)一步分析錯(cuò)誤日志后,我們發(fā)現(xiàn)在單個(gè)請(qǐng)求中存在錯(cuò)誤信息,特別是關(guān)于首包的 QPM(查詢每秒)超限問(wèn)題。按照我們的代碼邏輯,遇到這類錯(cuò)誤應(yīng)該快速退出 for 循環(huán),但實(shí)際情況并非如此。于是,我們開(kāi)始利用 Kitex 提供的排查手段進(jìn)行問(wèn)題定位。Kitex 提供了 RPCStart 和 RPCEnd 的埋點(diǎn),以及更細(xì)粒度的包接收和發(fā)送事件埋點(diǎn)。通過(guò)對(duì)這些埋點(diǎn)的分析,我們發(fā)現(xiàn) Kitex 將整個(gè)請(qǐng)求識(shí)別為正常響應(yīng),并且在調(diào)用鏈路上有大量的數(shù)據(jù)包在發(fā)送。進(jìn)一步查看單個(gè)包的打點(diǎn)信息,也顯示被 Kitex 識(shí)別為正常響應(yīng)。
經(jīng)過(guò)初步判斷,我們認(rèn)為 Kitex 的流式處理中可能忽略了業(yè)務(wù)錯(cuò)誤,導(dǎo)致錯(cuò)誤未被正確識(shí)別。與 Kitex 團(tuán)隊(duì)溝通后,他們進(jìn)行了相應(yīng)的調(diào)整,例如在代碼中增加了對(duì) biz status error(業(yè)務(wù)狀態(tài)錯(cuò)誤)的識(shí)別。
基于這次錯(cuò)誤處理的經(jīng)驗(yàn),我們進(jìn)一步分析了流式調(diào)用中可能遇到的其他異常場(chǎng)景,如建聯(lián)階段的權(quán)限報(bào)錯(cuò)、首包階段的 TPM/QPM 超限、中間包階段的流超時(shí)以及內(nèi)容審核錯(cuò)誤等。我們重點(diǎn)關(guān)注了 Kitex Thrift Streaming 在這些場(chǎng)景下的錯(cuò)誤處理表現(xiàn),如建聯(lián)時(shí)是否能快速返回錯(cuò)誤信息,以及在首包和中間包返回錯(cuò)誤時(shí)是否能迅速停止流等待。經(jīng)過(guò)與 Kitex 團(tuán)隊(duì)的共同調(diào)整和測(cè)試,最終這些場(chǎng)景下的錯(cuò)誤處理均符合預(yù)期。
在服務(wù)治理方面
在服務(wù)治理方面,我們特別關(guān)注超時(shí)和限流兩個(gè)關(guān)鍵環(huán)節(jié)。
首先,超時(shí)管理至關(guān)重要。由于我們的模塊與大模型進(jìn)行交互,這種交互可能涉及秒級(jí)甚至分鐘級(jí)的響應(yīng)時(shí)間。因此,在 HTTP 層和 RPC 層,我們都對(duì)流處理設(shè)置了分鐘級(jí)的超時(shí)限制。這樣做可以避免因無(wú)法退出 for 循環(huán)而導(dǎo)致的服務(wù)阻塞,確保服務(wù)的穩(wěn)定性和可用性。
在限流方面,雖然 Kitex 支持在創(chuàng)建流時(shí)進(jìn)行限流,但對(duì)于 LLM 場(chǎng)景來(lái)說(shuō),我們的關(guān)注點(diǎn)不僅在于建立連接時(shí)的 QPM 限流,更在于大模型 token 消耗的限流。大模型的推理過(guò)程中會(huì)產(chǎn)生大量的 token 消耗,如果不加以限制,可能會(huì)導(dǎo)致資源耗盡和服務(wù)崩潰。因此,我們利用 Kitex 實(shí)現(xiàn)了建聯(lián)的限流,同時(shí)借助自己的分布式組件來(lái)計(jì)算不同模型下的 token 消耗,并據(jù)此實(shí)現(xiàn) token 級(jí)別的限流。這樣做可以有效地控制資源使用,避免服務(wù)過(guò)載。
然而,我們也對(duì) Kitex 抱有期待。我們希望未來(lái) Kitex 能夠提供包粒度上的自定義限流能力。這樣,我們可以更靈活地定義限流規(guī)則,更精確地控制資源使用,從而進(jìn)一步提升服務(wù)的穩(wěn)定性和性能。
06、未來(lái)的期待
便捷性
首先,在便捷性方面,我們期待微服務(wù)框架能夠支持更多的測(cè)試工具接入,尤其是針對(duì)流式接口的測(cè)試。目前,對(duì)于 Kitex Thrift streaming 接口的測(cè)試還存在一定的局限性,主要依賴于編寫非流式接口進(jìn)行包裝調(diào)用。未來(lái),我們希望能夠通過(guò)泛化調(diào)用等方式,使得流式接口能夠更方便地支持各種測(cè)試工具,提高開(kāi)發(fā)效率。
AI 場(chǎng)景下的能力
隨著 AI 技術(shù)的蓬勃發(fā)展,越來(lái)越多的產(chǎn)品開(kāi)始融入 AI 能力以優(yōu)化用戶體驗(yàn)和功能。在 AI 場(chǎng)景下,我們對(duì)微服務(wù)框架如 Kitex 提出了更高的期待,期望它能更好地支持 AI 組件的集成與編排,以及適配傳統(tǒng)的框架能力。
- 開(kāi)箱即用的 AI 組件編排能力
在當(dāng)前的開(kāi)發(fā)實(shí)踐中,當(dāng)需要集成AI能力時(shí),開(kāi)發(fā)人員通常需要自行處理復(fù)雜的邏輯,如調(diào)用 prompt、解析大模型輸出、以及將結(jié)果轉(zhuǎn)換為機(jī)器語(yǔ)言等。這不僅增加了開(kāi)發(fā)難度,也降低了開(kāi)發(fā)效率。因此,我們期待 Kitex 框架能夠提供開(kāi)箱即用的 AI 組件編排能力。
具體來(lái)說(shuō),我們期望框架能夠預(yù)置一系列封裝好的 AI 組件,如 prompt 組件、大模型組件、結(jié)果解析組件以及 RPC調(diào)用組件等。這些組件應(yīng)該具備高度的可配置性和可擴(kuò)展性,以便能夠適應(yīng)不同的業(yè)務(wù)需求。開(kāi)發(fā)人員只需將業(yè)務(wù)邏輯傳入這些組件,而無(wú)需關(guān)心組件內(nèi)部的實(shí)現(xiàn)細(xì)節(jié),從而能夠更專注于業(yè)務(wù)邏輯的實(shí)現(xiàn)。
- 靈活的 AI 組件編排能力
除了提供預(yù)置的 AI 組件外,我們還期待 Kitex 框架能夠支持靈活的AI組件編排能力。這意味著框架應(yīng)該提供一種表達(dá)式語(yǔ)言或可視化工具,使得開(kāi)發(fā)人員能夠輕松地按照業(yè)務(wù)需求編排這些 AI 組件。通過(guò)這種方式,開(kāi)發(fā)人員可以定義組件之間的執(zhí)行順序、通信方式以及并行處理策略等,而無(wú)需深入了解組件之間的交互細(xì)節(jié)。這將大大提高 AI 應(yīng)用的開(kāi)發(fā)效率和可維護(hù)性。
- 傳統(tǒng)框架能力在 LLM 鏈路上適配
在 AI 場(chǎng)景下,傳統(tǒng)的框架能力如服務(wù)治理、元數(shù)據(jù)透?jìng)饕约翱捎^測(cè)性等仍然具有重要意義。因此,我們期待 Kitex 框架能夠在這些方面做出適配和優(yōu)化。
首先,在服務(wù)治理方面,由于 AI 應(yīng)用可能涉及長(zhǎng)時(shí)間的推理過(guò)程,因此框架需要提供針對(duì)秒級(jí)甚至分鐘級(jí)響應(yīng)時(shí)間的超時(shí)和限流策略。同時(shí),還需要考慮如何處理與 AI 組件相關(guān)的異常情況。
其次,在元數(shù)據(jù)透?jìng)鞣矫妫覀兤谕蚣苣軌蛑С衷?AI 組件之間傳遞元數(shù)據(jù),以便進(jìn)行更精細(xì)化的監(jiān)控和調(diào)試。這將有助于我們更好地理解 AI 應(yīng)用的運(yùn)行狀況,并快速定位問(wèn)題。
最后,在可觀測(cè)性方面,我們期待 Kitex 框架能夠提供全面的日志、追蹤和指標(biāo)收集功能,以便對(duì) AI 鏈路進(jìn)行全方位的監(jiān)控和分析。這將有助于我們及時(shí)發(fā)現(xiàn)潛在的性能瓶頸和優(yōu)化點(diǎn),從而提升 AI 應(yīng)用的性能和穩(wěn)定性。
綜上所述,我們對(duì) Kitex 框架在 AI 場(chǎng)景下的未來(lái)期待主要集中在開(kāi)箱即用的 AI 組件編排能力、靈活的 AI 組件編排能力以及傳統(tǒng)框架能力在 LLM 鏈路上的適配等方面。我們相信隨著技術(shù)的不斷進(jìn)步和團(tuán)隊(duì)的深入合作,這些期待將逐漸變?yōu)楝F(xiàn)實(shí),為 AI 應(yīng)用的開(kāi)發(fā)帶來(lái)更大的便利和效率。
實(shí)際上,我們團(tuán)隊(duì)已經(jīng)與 Kitex 團(tuán)隊(duì)展開(kāi)了深入的合作,共同探討如何在微服務(wù)框架中更好地支持 AI 場(chǎng)景。我們相信,在不久的將來(lái),我們將能夠推出一個(gè) MVP 版本的解決方案,為業(yè)務(wù)開(kāi)發(fā)人員提供一個(gè)簡(jiǎn)單、無(wú)縫地與 AI 能力結(jié)合的框架。這將是一個(gè)激動(dòng)人心的時(shí)刻,我們期待著這一天的到來(lái)。
項(xiàng)目地址
GitHub:https://github.com/cloudwego
官網(wǎng):www.cloudwego.io