字人+混元大模型知識(shí)引擎:RAG架構(gòu)落地與調(diào)優(yōu)實(shí)戰(zhàn))
1. 從數(shù)字人到知識(shí)引擎這套組合拳到底在解決什么問(wèn)題數(shù)字人這兩年熱度一直沒(méi)降過(guò)但真正在一線(xiàn)做過(guò)落地的人都知道早期的數(shù)字人項(xiàng)目大多停留在“能說(shuō)會(huì)動(dòng)”的階段——嘴型對(duì)得上、表情不僵硬、語(yǔ)音合成聽(tīng)起來(lái)像真人就算交差了。可一旦客戶(hù)問(wèn)出“你們這個(gè)數(shù)字人能不能回答我關(guān)于產(chǎn)品保修政策的具體問(wèn)題”很多項(xiàng)目就露餡了。原因很簡(jiǎn)單數(shù)字人的“大腦”和“嘴巴”是兩套系統(tǒng)嘴巴做得再好大腦里沒(méi)有對(duì)應(yīng)的知識(shí)回答就只能靠預(yù)設(shè)腳本硬撐。騰訊這套數(shù)字人與大模型知識(shí)引擎的產(chǎn)品組合本質(zhì)上就是在補(bǔ)“大腦”這一環(huán)。它把混元大模型作為推理內(nèi)核把向量數(shù)據(jù)庫(kù)作為知識(shí)存儲(chǔ)和檢索的底座再通過(guò)RAG檢索增強(qiáng)生成的架構(gòu)把兩者串起來(lái)最終讓數(shù)字人具備“基于企業(yè)私有知識(shí)進(jìn)行準(zhǔn)確問(wèn)答”的能力。這不是一個(gè)單點(diǎn)工具而是一條從知識(shí)入庫(kù)、向量化、檢索召回、到大模型生成、再到數(shù)字人播報(bào)的完整鏈路。這套東西適合誰(shuí)看如果你是企業(yè)側(cè)的AI應(yīng)用開(kāi)發(fā)者正在評(píng)估數(shù)字人項(xiàng)目的技術(shù)選型或者你已經(jīng)在做RAG相關(guān)的應(yīng)用但苦于不知道怎么和數(shù)字人前端打通那這篇內(nèi)容就是為你準(zhǔn)備的。我會(huì)從整體架構(gòu)講到每個(gè)環(huán)節(jié)的實(shí)操細(xì)節(jié)包括向量數(shù)據(jù)庫(kù)怎么選、知識(shí)切分怎么做、召回效果怎么調(diào)、數(shù)字人接口怎么對(duì)接盡量把踩過(guò)的坑和驗(yàn)證過(guò)的方案都攤開(kāi)來(lái)說(shuō)。2. 整體架構(gòu)拆解為什么是“混元向量數(shù)據(jù)庫(kù)RAG”這個(gè)組合2.1 數(shù)字人項(xiàng)目的核心瓶頸從來(lái)不在“人”而在“知”我做過(guò)好幾個(gè)數(shù)字人項(xiàng)目早期用過(guò)的方案無(wú)非是兩種一種是純腳本驅(qū)動(dòng)把所有可能的問(wèn)答對(duì)寫(xiě)死在配置文件里數(shù)字人根據(jù)關(guān)鍵詞匹配來(lái)播報(bào)對(duì)應(yīng)內(nèi)容另一種是接一個(gè)通用大模型API讓模型自由發(fā)揮。前者的問(wèn)題是知識(shí)更新極其痛苦每加一個(gè)產(chǎn)品型號(hào)就要改一遍腳本維護(hù)成本隨知識(shí)量線(xiàn)性增長(zhǎng)后者的問(wèn)題是模型會(huì)“胡說(shuō)”尤其是在企業(yè)場(chǎng)景下編造一個(gè)不存在的保修期限或者錯(cuò)誤的價(jià)格信息后果比不回答還嚴(yán)重。騰訊這套方案的核心思路是用RAG來(lái)解決這個(gè)矛盾。RAG的全稱(chēng)是Retrieval-Augmented Generation翻譯過(guò)來(lái)就是“檢索增強(qiáng)生成”。它的邏輯是用戶(hù)提問(wèn)后系統(tǒng)先去知識(shí)庫(kù)里檢索出最相關(guān)的幾段內(nèi)容把這些內(nèi)容作為“參考資料”塞給大模型讓模型基于這些資料來(lái)生成回答。這樣既保留了大模型的語(yǔ)言組織能力又把回答的內(nèi)容邊界限制在了企業(yè)提供的知識(shí)范圍內(nèi)。2.2 向量數(shù)據(jù)庫(kù)在鏈路中扮演什么角色向量數(shù)據(jù)庫(kù)是整個(gè)RAG鏈路里的“檢索器”。傳統(tǒng)的關(guān)鍵詞搜索是靠字面匹配你搜“保修期”它只能找到包含“保修期”這三個(gè)字的文檔。但用戶(hù)實(shí)際提問(wèn)可能是“這個(gè)東西壞了能免費(fèi)修多久”字面上和“保修期”沒(méi)有任何重疊。向量數(shù)據(jù)庫(kù)解決的就是這個(gè)問(wèn)題它把文本通過(guò)嵌入模型轉(zhuǎn)換成高維向量語(yǔ)義相近的文本在向量空間里的距離就近檢索時(shí)按距離排序就能找到語(yǔ)義相關(guān)的內(nèi)容而不依賴(lài)字面匹配。騰訊的大模型知識(shí)引擎底層支持多種向量數(shù)據(jù)庫(kù)接入包括騰訊自研的、也兼容開(kāi)源的Milvus等。Milvus是目前社區(qū)里用得比較多的開(kāi)源向量數(shù)據(jù)庫(kù)支持十億級(jí)向量的檢索延遲控制在毫秒級(jí)對(duì)于大多數(shù)企業(yè)知識(shí)庫(kù)場(chǎng)景來(lái)說(shuō)性能是綽綽有余的。選型的時(shí)候主要看幾個(gè)維度數(shù)據(jù)量級(jí)、查詢(xún)并發(fā)、是否需要分布式部署、以及和現(xiàn)有技術(shù)棧的兼容性。2.3 混元大模型在其中的定位混元大模型在這套架構(gòu)里承擔(dān)的是“最終生成”的角色。檢索模塊把相關(guān)的知識(shí)片段找出來(lái)之后這些片段加上用戶(hù)的原始問(wèn)題一起組成一個(gè)Prompt送給混元混元負(fù)責(zé)把碎片化的知識(shí)組織成一段通順、準(zhǔn)確、符合企業(yè)話(huà)術(shù)規(guī)范的回復(fù)。這里有個(gè)關(guān)鍵點(diǎn)混元的輸出質(zhì)量很大程度上取決于檢索模塊給它的“參考資料”質(zhì)量。如果檢索出來(lái)的內(nèi)容不相關(guān)或者不完整再?gòu)?qiáng)的模型也生成不出正確答案。所以整個(gè)鏈路的優(yōu)化重點(diǎn)其實(shí)在檢索側(cè)而不在生成側(cè)。3. 知識(shí)入庫(kù)與向量化從原始文檔到可檢索的知識(shí)庫(kù)3.1 文檔預(yù)處理切分粒度直接決定召回質(zhì)量知識(shí)入庫(kù)的第一步是把企業(yè)的原始文檔PDF、Word、網(wǎng)頁(yè)、FAQ表格等轉(zhuǎn)換成純文本然后進(jìn)行切分。切分這一步看似簡(jiǎn)單實(shí)際上對(duì)最終效果影響極大。切得太粗一個(gè)片段里混了好幾個(gè)主題檢索時(shí)噪音大切得太細(xì)一個(gè)完整的答案被拆成好幾段模型拿到的是殘缺信息。我的經(jīng)驗(yàn)是對(duì)于FAQ類(lèi)內(nèi)容一條問(wèn)答作為一個(gè)切分單元不要拆。對(duì)于產(chǎn)品手冊(cè)這類(lèi)長(zhǎng)文檔按段落切分每段控制在200到500字之間。如果一段超過(guò)500字優(yōu)先找自然的分段點(diǎn)比如標(biāo)題、換行、句號(hào)來(lái)切不要硬切。騰訊的知識(shí)引擎支持自定義切分規(guī)則你可以配置按標(biāo)題層級(jí)切、按固定長(zhǎng)度切、或者按語(yǔ)義相似度切。語(yǔ)義切分的效果通常最好但計(jì)算成本也最高適合知識(shí)量不大但精度要求高的場(chǎng)景。注意切分后的每個(gè)片段最好保留其來(lái)源文檔的元信息如文檔標(biāo)題、章節(jié)名、頁(yè)碼這樣在檢索召回后可以把元信息一起送給大模型幫助模型理解上下文。3.2 向量化模型的選擇與調(diào)用切分完成后每個(gè)文本片段需要通過(guò)嵌入模型轉(zhuǎn)換成向量。騰訊知識(shí)引擎默認(rèn)使用的是其自研的嵌入模型也支持接入第三方嵌入模型。嵌入模型的選擇主要看兩個(gè)指標(biāo)一是語(yǔ)義表征能力也就是它能不能準(zhǔn)確地把語(yǔ)義相近的文本映射到相近的向量位置二是維度維度越高表征能力越強(qiáng)但存儲(chǔ)和計(jì)算成本也越高。目前主流的嵌入模型維度在768到1536之間。騰訊默認(rèn)的嵌入模型維度是1024在效果和成本之間取得了比較好的平衡。如果你有自己的嵌入模型也可以通過(guò)API接入但要注意嵌入模型一旦確定后續(xù)所有入庫(kù)和查詢(xún)都必須用同一個(gè)模型否則向量空間不一致檢索結(jié)果會(huì)完全亂掉。3.3 向量數(shù)據(jù)庫(kù)的寫(xiě)入與索引構(gòu)建向量寫(xiě)入Milvus或者騰訊自研向量庫(kù)之后需要構(gòu)建索引來(lái)加速檢索。Milvus支持的索引類(lèi)型有好幾種常用的有IVF_FLAT、IVF_SQ8、HNSW等。簡(jiǎn)單說(shuō)一下選型邏輯索引類(lèi)型適用場(chǎng)景召回率檢索速度內(nèi)存占用IVF_FLAT數(shù)據(jù)量中等追求高召回高中等高IVF_SQ8數(shù)據(jù)量大內(nèi)存有限中高快低HNSW數(shù)據(jù)量中等追求低延遲高很快高IVF_PQ數(shù)據(jù)量極大可接受一定精度損失中很快很低對(duì)于大多數(shù)企業(yè)知識(shí)庫(kù)場(chǎng)景數(shù)據(jù)量在百萬(wàn)級(jí)以下我一般推薦用HNSW檢索延遲可以控制在10毫秒以?xún)?nèi)召回率也很理想。如果數(shù)據(jù)量到了千萬(wàn)級(jí)考慮IVF_SQ8來(lái)平衡內(nèi)存和速度。4. 檢索與生成RAG鏈路的核心調(diào)優(yōu)環(huán)節(jié)4.1 檢索策略Top-K怎么定閾值怎么設(shè)用戶(hù)提問(wèn)后系統(tǒng)會(huì)把問(wèn)題也轉(zhuǎn)成向量然后在向量數(shù)據(jù)庫(kù)里做相似度搜索返回最相似的K個(gè)片段。這個(gè)K值的選擇很關(guān)鍵K太小可能漏掉關(guān)鍵信息K太大會(huì)引入無(wú)關(guān)內(nèi)容干擾模型判斷。我的經(jīng)驗(yàn)值是K3到5之間具體取決于知識(shí)庫(kù)的密度。如果知識(shí)庫(kù)內(nèi)容比較稀疏同一個(gè)問(wèn)題相關(guān)的片段可能分散在多個(gè)文檔里K可以適當(dāng)放大到8到10。除了K值還要設(shè)一個(gè)相似度閾值。低于閾值的片段即使被召回了也不應(yīng)該送給模型因?yàn)槟腔臼窃胍簟i撝狄话阍O(shè)在0.7到0.8之間余弦相似度具體值需要根據(jù)你的嵌入模型和實(shí)際測(cè)試來(lái)調(diào)。騰訊知識(shí)引擎的控制臺(tái)里可以實(shí)時(shí)看到每次查詢(xún)的召回片段和相似度分?jǐn)?shù)調(diào)優(yōu)的時(shí)候盯著這個(gè)面板調(diào)就行。4.2 Prompt工程怎么讓混元“照著資料說(shuō)”檢索出來(lái)的片段需要和用戶(hù)問(wèn)題一起組裝成Prompt送給混元。Prompt的設(shè)計(jì)直接決定了模型會(huì)不會(huì)“跑偏”。一個(gè)經(jīng)過(guò)驗(yàn)證的Prompt模板大概長(zhǎng)這樣你是一個(gè)企業(yè)客服助手請(qǐng)根據(jù)以下參考資料回答用戶(hù)問(wèn)題。 如果參考資料中沒(méi)有相關(guān)信息請(qǐng)直接說(shuō)“抱歉我暫時(shí)沒(méi)有找到相關(guān)信息”不要編造答案。 參考資料 {retrieved_context} 用戶(hù)問(wèn)題{user_query} 請(qǐng)用簡(jiǎn)潔、準(zhǔn)確的語(yǔ)言回答這個(gè)模板里有幾個(gè)關(guān)鍵設(shè)計(jì)第一明確角色定位讓模型知道自己是客服助手而不是通用聊天機(jī)器人第二明確知識(shí)邊界告訴模型只能基于參考資料回答第三給出兜底話(huà)術(shù)避免模型在找不到答案時(shí)胡編。實(shí)測(cè)下來(lái)這三條約束能擋掉90%以上的幻覺(jué)問(wèn)題。4.3 多輪對(duì)話(huà)中的上下文管理數(shù)字人場(chǎng)景下用戶(hù)往往會(huì)追問(wèn)。比如先問(wèn)“你們的旗艦款手機(jī)保修多久”得到回答后再問(wèn)“那電池呢”。這時(shí)候如果只把第二個(gè)問(wèn)題單獨(dú)拿去檢索很可能召回的是通用電池保修政策而不是旗艦款的。解決辦法是在檢索前先做一輪“查詢(xún)改寫(xiě)”把多輪對(duì)話(huà)的上下文合并成一個(gè)完整的查詢(xún)語(yǔ)句再去做向量檢索。騰訊知識(shí)引擎支持開(kāi)啟多輪對(duì)話(huà)改寫(xiě)功能底層也是用混元來(lái)做查詢(xún)改寫(xiě)。開(kāi)啟后系統(tǒng)會(huì)自動(dòng)把“那電池呢”改寫(xiě)成“旗艦款手機(jī)的電池保修多久”檢索準(zhǔn)確率會(huì)有明顯提升。這個(gè)功能在實(shí)際項(xiàng)目里是必開(kāi)的不開(kāi)的話(huà)多輪對(duì)話(huà)的體驗(yàn)會(huì)差很多。5. 數(shù)字人前端對(duì)接從文本回復(fù)到“人”的表達(dá)5.1 數(shù)字人驅(qū)動(dòng)接口的調(diào)用方式知識(shí)引擎生成文本回復(fù)后需要把文本送給數(shù)字人驅(qū)動(dòng)模塊讓它用對(duì)應(yīng)的口型、表情、動(dòng)作把內(nèi)容“說(shuō)”出來(lái)。騰訊數(shù)字人提供了標(biāo)準(zhǔn)的API接口你只需要把文本傳進(jìn)去指定數(shù)字人形象和音色它就會(huì)返回一段帶口型同步的視頻流或者直接推流到前端。對(duì)接的時(shí)候有幾個(gè)參數(shù)需要關(guān)注語(yǔ)速、音調(diào)、停頓。語(yǔ)速太快會(huì)顯得機(jī)械太慢又會(huì)讓用戶(hù)等得不耐煩。我的經(jīng)驗(yàn)是中文場(chǎng)景下語(yǔ)速設(shè)在每分鐘220到260字之間比較自然。停頓方面句號(hào)后停300毫秒逗號(hào)后停150毫秒段落之間停500毫秒這樣聽(tīng)起來(lái)最接近真人說(shuō)話(huà)的節(jié)奏。5.2 流式輸出與首字延遲的優(yōu)化用戶(hù)最直觀(guān)的體驗(yàn)指標(biāo)是“從問(wèn)完到數(shù)字人開(kāi)口”的延遲。如果這個(gè)延遲超過(guò)2秒用戶(hù)就會(huì)覺(jué)得卡頓。優(yōu)化這個(gè)指標(biāo)的關(guān)鍵在于流式輸出不要讓大模型把整段話(huà)生成完再送給數(shù)字人而是生成一個(gè)句子就送一個(gè)句子數(shù)字人收到第一個(gè)句子就開(kāi)始播報(bào)后面的句子邊生成邊播報(bào)。騰訊知識(shí)引擎支持流式返回混元生成第一個(gè)Token的延遲通常在300到500毫秒之間加上檢索和網(wǎng)絡(luò)傳輸整體首字延遲可以控制在1秒以?xún)?nèi)。這個(gè)體驗(yàn)已經(jīng)非常接近真人對(duì)話(huà)的節(jié)奏了。5.3 多模態(tài)知識(shí)的呈現(xiàn)有些知識(shí)用純文本表達(dá)效率很低比如產(chǎn)品外觀(guān)、操作步驟、數(shù)據(jù)圖表。騰訊數(shù)字人支持在播報(bào)的同時(shí)展示圖片、視頻、PPT等輔助材料。實(shí)現(xiàn)方式是在知識(shí)庫(kù)的元信息里標(biāo)注該片段關(guān)聯(lián)的多媒體資源ID檢索命中后系統(tǒng)除了返回文本還會(huì)返回資源ID前端根據(jù)資源ID去加載對(duì)應(yīng)的圖片或視頻在數(shù)字人旁邊的區(qū)域展示。這個(gè)功能在培訓(xùn)場(chǎng)景下特別有用。比如新員工問(wèn)“這個(gè)設(shè)備的開(kāi)關(guān)在哪里”數(shù)字人一邊說(shuō)“在設(shè)備背面右下角”一邊在旁邊展示一張標(biāo)注了開(kāi)關(guān)位置的圖片理解成本瞬間降低。6. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄6.1 檢索召回不準(zhǔn)的排查思路召回不準(zhǔn)是最常見(jiàn)的問(wèn)題表現(xiàn)是數(shù)字人回答的內(nèi)容和用戶(hù)問(wèn)題對(duì)不上。排查的時(shí)候按這個(gè)順序來(lái)先看切分是否合理有沒(méi)有把一個(gè)完整的答案切成了兩半再看嵌入模型是否適合你的領(lǐng)域通用嵌入模型在垂直領(lǐng)域如醫(yī)療、法律、金融的表現(xiàn)可能不夠好需要考慮微調(diào)或者換用領(lǐng)域?qū)S媚P妥詈罂聪嗨贫乳撝凳欠裨O(shè)得過(guò)高或過(guò)低過(guò)高會(huì)漏召回過(guò)低會(huì)引入噪音。我遇到過(guò)一個(gè)典型案例客戶(hù)的知識(shí)庫(kù)里有一份產(chǎn)品對(duì)比表切分的時(shí)候按固定長(zhǎng)度切結(jié)果每個(gè)片段里都混了好幾個(gè)產(chǎn)品的信息。用戶(hù)問(wèn)“A產(chǎn)品和B產(chǎn)品的區(qū)別”檢索出來(lái)的片段里既有A也有B還有C模型生成的時(shí)候就被干擾了。后來(lái)改成按表格行切分每個(gè)片段只包含一個(gè)產(chǎn)品的信息召回準(zhǔn)確率立刻上去了。6.2 模型回答“太啰嗦”或“太簡(jiǎn)短”怎么調(diào)混元的輸出長(zhǎng)度可以通過(guò)Prompt來(lái)控制。如果覺(jué)得回答太啰嗦在Prompt里加一句“請(qǐng)用不超過(guò)三句話(huà)回答”如果覺(jué)得太簡(jiǎn)短加一句“請(qǐng)?jiān)敿?xì)說(shuō)明包括具體步驟和注意事項(xiàng)”。另外知識(shí)引擎的控制臺(tái)里也可以設(shè)置最大輸出Token數(shù)硬性限制長(zhǎng)度。不過(guò)要注意限制長(zhǎng)度不能太死。有些問(wèn)題確實(shí)需要詳細(xì)回答硬壓到三句話(huà)反而說(shuō)不清楚。我的做法是在Prompt里給一個(gè)長(zhǎng)度范圍比如“請(qǐng)用50到150字回答”讓模型在這個(gè)范圍內(nèi)自行判斷。6.3 數(shù)字人口型與語(yǔ)音不同步的處理口型不同步通常是因?yàn)槲谋竞鸵纛l的時(shí)間對(duì)齊沒(méi)做好。排查的時(shí)候先確認(rèn)音頻采樣率和視頻幀率是否匹配騰訊數(shù)字人默認(rèn)要求音頻16kHz采樣、視頻25幀每秒。如果音頻是其他采樣率需要先轉(zhuǎn)碼再送入驅(qū)動(dòng)模塊。另外如果文本里包含英文單詞或數(shù)字中文音色引擎的發(fā)音時(shí)長(zhǎng)可能和口型動(dòng)畫(huà)的時(shí)長(zhǎng)對(duì)不上需要在文本預(yù)處理階段把英文和數(shù)字轉(zhuǎn)成中文讀法比如“iPhone 15”轉(zhuǎn)成“蘋(píng)果十五”。6.4 知識(shí)更新后檢索結(jié)果沒(méi)變化知識(shí)更新后需要重新走一遍“切分-向量化-寫(xiě)入”的流程并且要確保新向量寫(xiě)入后索引被刷新。Milvus在數(shù)據(jù)寫(xiě)入后需要手動(dòng)觸發(fā)索引重建或者等待自動(dòng)刷新如果用的是騰訊自研向量庫(kù)控制臺(tái)里有一個(gè)“重建索引”的按鈕點(diǎn)一下就行。另外如果開(kāi)了緩存更新后要清一下緩存否則查詢(xún)還是走舊數(shù)據(jù)。問(wèn)題現(xiàn)象可能原因排查動(dòng)作回答與問(wèn)題無(wú)關(guān)切分粒度過(guò)粗或過(guò)細(xì)檢查切分規(guī)則調(diào)整片段長(zhǎng)度回答內(nèi)容不完整Top-K太小或閾值太高增大K值降低相似度閾值模型編造答案Prompt未限制知識(shí)邊界檢查Prompt模板加入兜底話(huà)術(shù)多輪對(duì)話(huà)答非所問(wèn)未開(kāi)啟查詢(xún)改寫(xiě)開(kāi)啟多輪對(duì)話(huà)改寫(xiě)功能首字延遲高未開(kāi)啟流式輸出檢查流式配置確認(rèn)逐句推送口型不同步音頻格式不匹配轉(zhuǎn)碼為16kHz采樣率7. 一些實(shí)操中的個(gè)人體會(huì)這套方案我從早期版本一直跟到現(xiàn)在的成熟版本最大的感受是RAG系統(tǒng)的效果上限取決于檢索質(zhì)量而不是模型大小。很多人一上來(lái)就想著換更大的模型但實(shí)際調(diào)優(yōu)下來(lái)把切分策略調(diào)好、把嵌入模型換成領(lǐng)域適配的、把Top-K和閾值調(diào)到最優(yōu)效果提升比換模型明顯得多。另外數(shù)字人場(chǎng)景對(duì)延遲的敏感度遠(yuǎn)高于純文本問(wèn)答。純文本場(chǎng)景下用戶(hù)等兩三秒還能接受但數(shù)字人場(chǎng)景下超過(guò)1.5秒用戶(hù)就會(huì)覺(jué)得“這個(gè)數(shù)字人反應(yīng)好慢”。所以流式輸出和首字延遲優(yōu)化是必做的功課不是錦上添花。最后說(shuō)一個(gè)容易被忽略的點(diǎn)知識(shí)庫(kù)的維護(hù)成本。很多項(xiàng)目上線(xiàn)時(shí)效果很好但運(yùn)行三個(gè)月后效果明顯下降原因是業(yè)務(wù)知識(shí)更新了但知識(shí)庫(kù)沒(méi)同步。建議在項(xiàng)目規(guī)劃階段就把知識(shí)更新的流程和責(zé)任人定好最好能做到業(yè)務(wù)系統(tǒng)更新后自動(dòng)觸發(fā)知識(shí)庫(kù)同步否則再好的系統(tǒng)也會(huì)慢慢“變笨”。