話推理加速:語義緩存與KV Cache協(xié)同優(yōu)化實(shí)戰(zhàn))
1. 多輪對(duì)話越聊越慢重復(fù) prefill 才是真正的成本黑洞做 LLM 推理服務(wù)的人應(yīng)該都有這個(gè)體感單輪請(qǐng)求的時(shí)延很好控但一進(jìn)入多輪對(duì)話會(huì)話越聊越長響應(yīng)越來越慢顯存也越來越緊張。用戶反饋里最典型的一句話就是前面幾輪還好聊到十幾輪就開始轉(zhuǎn)圈圈了。這個(gè)問題的根源不在模型本身而在推理服務(wù)對(duì)歷史上下文的處理方式。大模型推理通常分成 prefill 和 decode 兩個(gè)階段prefill 階段要把用戶輸入的所有 token 并行計(jì)算一遍生成每個(gè) token 對(duì)應(yīng)的 K、V 向量也就是 KV Cache并緩存下來decode 階段則基于 KV Cache 逐個(gè)生成新 token。理論上只要服務(wù)端支持把歷史輪次的 KV Cache 保留在顯存里新一輪請(qǐng)求就不需要把整個(gè)會(huì)話從頭再算一遍。但真實(shí)生產(chǎn)環(huán)境沒有那么理想。很多業(yè)務(wù)場景的服務(wù)端并不做嚴(yán)格的逐輪 KV Cache 維護(hù)要么把完整對(duì)話歷史重新拼接后整段傳給模型要么因?yàn)椴渴鸺軜?gòu)的原因?qū)е虑熬Y緩存無法命中。這種情況下每一輪新請(qǐng)求都會(huì)把之前所有輪次的 token 重新做一遍 prefill。會(huì)話越長重復(fù)計(jì)算的量越大。1.1 KV Cache 的顯存賬本為什么長會(huì)話會(huì)拖垮資源先算一筆顯存賬。以一個(gè) 7B 規(guī)模、隱藏維度 4096、32 層、每層 32 個(gè)注意力頭的模型為例在 FP16 精度下每個(gè) token 的 KV Cache 大約占 512KB 顯存32 層乘以 32 個(gè)頭乘以 128 維再乘以 2 份 K/V 和 2 字節(jié)精度。這意味著上下文長度單會(huì)話 KV Cache 顯存占用估算100 個(gè)并發(fā)會(huì)話512 token約 256MB約 25GB2048 token約 1GB約 100GB8192 token約 4GB約 400GB這個(gè)量級(jí)說明兩個(gè)問題第一長會(huì)話的 KV Cache 本身就昂貴第二如果每一輪都重新 prefill 全部歷史那不只是浪費(fèi)顯存而是在成倍地浪費(fèi)算力。假設(shè)一個(gè)會(huì)話平均 2000 token用戶每輪新輸入只有 100 token那么模型實(shí)際有效計(jì)算量中的 95% 都花在歷史 token 的重復(fù)計(jì)算上。我之前在內(nèi)部做過一次簡單的 trace 統(tǒng)計(jì)在一個(gè)模擬的助手型產(chǎn)品里大約有 23% 的請(qǐng)求在語義上和歷史輪次高度近似——用戶換了個(gè)措辭問同一個(gè)問題或者把之前的請(qǐng)求微調(diào)后重發(fā)甚至直接復(fù)制粘貼追問。這些請(qǐng)求本不該重新消耗一次完整推理。1.2 精確緩存為什么救不了多輪場景最直觀的辦法是做精確匹配把整個(gè)對(duì)話上下文的文本拼起來算一個(gè)哈希再存一個(gè) KV Cache 索引。下一次請(qǐng)求如果哈希值完全一致就直接復(fù)用緩存。這個(gè)方案在單元測試?yán)锟雌饋砗芎侠硪簧暇€就露餡。因?yàn)檎鎸?shí)用戶不會(huì)原封不動(dòng)地重復(fù)一句話哪怕只是把謝謝改成非常感謝把標(biāo)點(diǎn)從半角變成全角哈希值就完全變了。更不用說多輪對(duì)話里大量出現(xiàn)的指代和改寫比如用戶上一輪說幫我對(duì)比這三款手機(jī)下一輪補(bǔ)充順便加上那個(gè)紅色那款這里的那款需要結(jié)合歷史上下文才能理解成某具體型號(hào)。字符串層面完全匹配是不可能的。精確前綴緩存則更脆弱它不僅要求當(dāng)前輪文本一致還要求之前所有輪次逐字一致。只要用戶在第三輪把問題改了一個(gè)字第四輪開始之前共享的上下文就無法復(fù)用了。這也是我決定做語義緩存這個(gè)方向的原因KV Cache 解決的是 token 級(jí)的重復(fù)計(jì)算但語言表達(dá)的多樣性讓 token 級(jí)復(fù)用永遠(yuǎn)存在盲區(qū)。真正想降低多輪推理的成本和時(shí)延需要在更抽象的語義層去做匹配。2. SmartCache 的緩存鍵設(shè)計(jì)從 token 哈希到分層語義指紋明確了目標(biāo)之后第一個(gè)要解決的問題是緩存鍵到底應(yīng)該是什么。在單輪語義緩存的常見做法里直接用當(dāng)前用戶問題文本的 embedding 做檢索命中就返回緩存答案。這個(gè)思路搬到多輪對(duì)話上會(huì)立刻出問題——多輪請(qǐng)求的語義不在當(dāng)前這一句話里而在系統(tǒng)提示詞 歷史對(duì)話 當(dāng)前問題的組合中。2.1 為什么緩存鍵不能只包含當(dāng)前問題舉一個(gè)我在實(shí)測中遇到的真實(shí)案例。用戶先問周末去杭州玩三天預(yù)算五千以內(nèi)幫我排一個(gè)行程助手給出行程后用戶追問那家酒店的早餐值不值得吃。單獨(dú)對(duì)那家酒店的早餐值不值得吃做 embedding模型根本不知道那家酒店指哪個(gè)向量也會(huì)落在完全無關(guān)的空間里。如果把整個(gè)歷史對(duì)話拼在一起做 embedding又會(huì)出現(xiàn)另一個(gè)問題歷史越長語義越被稀釋。前五輪都在聊旅行第六輪突然問明天的會(huì)議紀(jì)要幫我整理一下全量拼接后的 embedding 大概率會(huì)漂移到旅行主題附近檢索結(jié)果完全不可用。我在 SmartCache 里采用的做法是分層語義指紋把多輪上下文拆成粗粒度的結(jié)構(gòu)化標(biāo)簽和細(xì)粒度的向量兩個(gè)層級(jí)分別承擔(dān)范圍過濾和語義近似的職責(zé)。2.2 粗粒度標(biāo)簽可解釋的硬過濾條件粗粒度標(biāo)簽是從上下文中抽取的結(jié)構(gòu)化信息通常是 JSON 形式包括幾個(gè)核心字段意圖域比如旅行規(guī)劃代碼生成文檔總結(jié)售后咨詢。任務(wù)骨架描述整個(gè)多輪會(huì)話在圍繞什么主線進(jìn)行例如用戶要求推薦杭州市區(qū)酒店并對(duì)比價(jià)格?;钴S實(shí)體集合當(dāng)前會(huì)話中仍然生效的地名、人名、商品名、數(shù)字約束等。變更指令標(biāo)志這一輪是否包含不要改成加上去掉這類會(huì)讓舊答案失效的變更指令。話題切換標(biāo)記判斷當(dāng)前問題和最近歷史是否屬于同一主題如果是突然切換舊緩存必須全部失效。標(biāo)簽的作用是做硬過濾。向量相似度再高如果意圖域不同或者活躍實(shí)體集合沖突就不該命中。比如用戶問幫我寫一封請(qǐng)假郵件和幫我寫一封投訴郵件兩者的 embedding 距離很近但意圖域和應(yīng)用結(jié)果完全不同必須通過標(biāo)簽提前排除。2.3 細(xì)粒度向量裁剪后的上下文編碼細(xì)粒度向量負(fù)責(zé)在同一個(gè)主題范圍內(nèi)做近似匹配。這里的關(guān)鍵不是對(duì)全部歷史做 embedding而是構(gòu)造一個(gè)上下文編碼視圖規(guī)則很簡單系統(tǒng)提示詞單獨(dú)截?cái)嗟阶罱?512 字符參與向量化避免模型指令的冗長描述干擾語義歷史對(duì)話按輪次壓縮每輪只保留說話人身份 核心要點(diǎn)發(fā)言人標(biāo)記user/assistant會(huì)作為前綴拼進(jìn)文本當(dāng)前用戶的原始輸入全量參與并且在組合時(shí)抬高權(quán)重——我可以把當(dāng)前問題在文本里重復(fù)一遍比如按當(dāng)前問題 當(dāng)前問題 截?cái)鄽v史的拼接方式讓模型注意力天然偏向最新意圖超過 embedding 模型最大長度時(shí)優(yōu)先丟棄最老的、與當(dāng)前主題標(biāo)簽無關(guān)的輪次而不是簡單從頭截?cái)唷?.4 embedding 模型的選型與歸一化多輪對(duì)話場景對(duì) embedding 模型的要求和通用檢索不太一樣。通用 embedding 擅長捕捉單句語義但對(duì)誰在什么時(shí)候說了什么這種帶角色的結(jié)構(gòu)不敏感。我在實(shí)踐中的處理是不追求超大模型選一個(gè)百 MB 量級(jí)、支持較長輸入序列的通用 encoder 就夠關(guān)鍵是做好文本歸一化。我用的歸一化包括統(tǒng)一說話人分隔符、把系統(tǒng)消息里頻繁變化的指令模板做脫敏、將數(shù)字和單位統(tǒng)一格式、對(duì)用戶消息不做任何改寫直接在原文兩側(cè)加user:標(biāo)記。這套操作比換一個(gè)更大更貴的 embedding 模型帶來的收益穩(wěn)定得多。3. 命中判定與三層安全網(wǎng)整體相似度并不等于答案可復(fù)用語義緩存最大的風(fēng)險(xiǎn)不是緩存 miss而是錯(cuò)誤命中——返回了一個(gè)看似相關(guān)但實(shí)質(zhì)錯(cuò)誤的舊答案。這個(gè)風(fēng)險(xiǎn)在單輪緩存里已經(jīng)存在在多輪上下文下會(huì)被放大因?yàn)槎噍喺?qǐng)求可以因?yàn)橐粋€(gè)微小的變化就要求完全不同的答案。所以 SmartCache 把命中判定拆成三層候選召回、變更指令檢測、答案校驗(yàn)。3.1 第一層標(biāo)簽預(yù)篩與向量召回查詢先走粗粒度標(biāo)簽過濾。標(biāo)簽不匹配的候選直接丟棄然后在剩余候選中用向量檢索取 top-k。這里我使用的是一個(gè)基于 HNSW 圖索引的向量檢索組件單個(gè)節(jié)點(diǎn)就能支撐百萬量級(jí)指紋的召回P99 查詢時(shí)延在 10 毫秒左右。相似度分?jǐn)?shù)采用余弦相似度但分?jǐn)?shù)本身不會(huì)直接當(dāng)作命中依據(jù)而是映射成三個(gè)區(qū)間區(qū)間行為分?jǐn)?shù)高于接受閾值直接命中緩存返回緩存答案分?jǐn)?shù)高于候選閾值但低于接受閾值進(jìn)入變更指令檢測判定為半命中分?jǐn)?shù)低于候選閾值判定為 miss走完整模型推理閾值具體取多少不能拍腦袋我會(huì)在第五部分專門講調(diào)參時(shí)踩的坑和離線回放評(píng)估方法。3.2 第二層變更指令檢測這是多輪語義緩存和其他緩存的核心差異假設(shè)用戶上一輪問幫我推薦一款適合編程的輕薄本預(yù)算八千以內(nèi)助手給出了答案。下一輪用戶說預(yù)算提高到一萬重量再輕一點(diǎn)。此時(shí)上下文整體相似度可能高達(dá) 0.90如果直接命中緩存返回的老答案完全無效。SmartCache 的做法是當(dāng)候選分?jǐn)?shù)落在半命中區(qū)間時(shí)先對(duì)當(dāng)前用戶輸入做一輪輕量級(jí)變更意圖分析。檢測邏輯包括是否出現(xiàn)不要、取消、去掉、排除等否定型指令是否出現(xiàn)加上、補(bǔ)充、還有等新增型指令是否出現(xiàn)新實(shí)體、新數(shù)字約束并且和歷史參數(shù)沖突是否出現(xiàn)話題切換信號(hào)比如突然從旅行跳到會(huì)議。如果確認(rèn)沒有任何變更指令走直接命中如果檢測到變更走半命中路徑保留歷史上下文的 token 級(jí) KV Cache 復(fù)用讓模型只對(duì)新增和變化的片段做增量 prefill 和 decode。這個(gè)路徑仍然能省掉大量重復(fù)計(jì)算。我在實(shí)現(xiàn)里甚至把變更指令檢測做成了一個(gè)小模型分類器輸入當(dāng)前用戶消息和候選緩存的上下文摘要輸出一個(gè)是否修改歷史上下文的三分類結(jié)果。實(shí)測比純規(guī)則引擎的準(zhǔn)確率高出不少。3.3 第三層答案級(jí)校驗(yàn)即使相似度分?jǐn)?shù)很高、也沒有明顯的變更指令我仍然不直接信任緩存。答案級(jí)校驗(yàn)會(huì)抽取緩存答案中的關(guān)鍵信息點(diǎn)數(shù)字、名單、日期、清單項(xiàng)和當(dāng)前請(qǐng)求的約束做一一比對(duì)。校驗(yàn)邏輯是硬規(guī)則如果用戶當(dāng)前請(qǐng)求里明確提到預(yù)算八千但緩存答案中推薦的產(chǎn)品價(jià)格區(qū)間超出這個(gè)范圍校驗(yàn)一定失敗。校驗(yàn)失敗時(shí)的策略是降級(jí)不返回緩存直接走模型推理并把這條緩存的權(quán)重下調(diào)。這個(gè)設(shè)計(jì)很關(guān)鍵它可以保證語義緩存作為一個(gè)優(yōu)化層不會(huì)把錯(cuò)誤擴(kuò)散到用戶側(cè)。4. 落地實(shí)現(xiàn)從緩存寫入到召回驗(yàn)證的完整鏈路理論設(shè)計(jì)講完說說工程落地。我把 SmartCache 做成一個(gè)獨(dú)立的語義緩存服務(wù)掛在 LLM 推理網(wǎng)關(guān)旁路對(duì)業(yè)務(wù)側(cè)透明。4.1 核心組件與請(qǐng)求流程服務(wù)內(nèi)部有四個(gè)模塊上下文簽名器、向量索引、緩存存儲(chǔ)、答案校驗(yàn)器。請(qǐng)求進(jìn)來后的完整鏈路是網(wǎng)關(guān)收到多輪請(qǐng)求把當(dāng)前會(huì)話的完整上下文交給上下文簽名器簽名器生成粗粒度標(biāo)簽 細(xì)粒度向量查詢向量索引按標(biāo)簽過濾、向量召回 top-k 候選對(duì)候選做相似度區(qū)間判斷和變更指令檢測命中則通過答案校驗(yàn)器做關(guān)鍵信息比對(duì)通過后直接返回緩存答案未命中或校驗(yàn)失敗則進(jìn)入模型推理推理完成后把新結(jié)果寫入緩存。緩存寫入也有講究。我在設(shè)計(jì)中采用延遲寫入機(jī)制模型推理完成后先寫入一個(gè) pending 狀態(tài)此時(shí)該記錄不參與召回只有當(dāng)用戶沒有發(fā)起重新生成或?qū)Y(jié)果做負(fù)面反饋時(shí)才在下一個(gè)時(shí)間窗口把狀態(tài)置為 ready。這么做的原因是很多產(chǎn)品里用戶會(huì)反復(fù)點(diǎn)擊重新生成第一個(gè)結(jié)果未必是最終采納的答案如果急著寫緩存后續(xù)就會(huì)把垃圾答案反復(fù)曝光。4.2 緩存記錄結(jié)構(gòu)每條緩存記錄大概長這樣{ cache_id: fc3a8b..., context_fingerprint: sha256(system_version coarse_tags), coarse_tags: { intent_domain: travel_planning, active_entities: [hangzhou, 3_days, budget_8000], task_branch: hotel_recommendation, context_switch: false }, dense_vector_id: vec_7781f2, answer: { text: ..., key_facts: {budget: 7500, check_in_date: 2025-06-20} }, meta: { system_prompt_version: v3.1.0, ttl: 3600, hit_count: 128, feedback_score: 0.93, state: ready } }這里 context_fingerprint 不是全文本哈希而是系統(tǒng)版本 粗粒度標(biāo)簽的穩(wěn)定哈希用來在系統(tǒng)升級(jí)或會(huì)話主題切換時(shí)快速失效整批緩存。dense_vector_id 指向向量索引中的浮點(diǎn)向量。key_facts 是一個(gè)很關(guān)鍵的結(jié)構(gòu)化字段它讓答案校驗(yàn)不再依賴重新解析自然語言而是直接比對(duì)結(jié)構(gòu)化的關(guān)鍵約束。4.3 淘汰與失效策略緩存一定會(huì)臟關(guān)鍵是臟得可控。我用的淘汰策略有三條LRU 淘汰按命中率加權(quán)的 LRU長期不被命中的冷門上下文優(yōu)先踢出TTL 失效不同意圖域設(shè)置不同的生命周期比如天氣和政策類緩存 TTL 很短攻略類和代碼模板類可以長一些版本號(hào)失效系統(tǒng)提示詞模板一旦升級(jí)所有舊記錄通過 context_fingerprint 前綴全部失效避免模型行為變更后舊答案繼續(xù)污染線上。另外用戶在會(huì)話中明確說重新開始忘了之前的吧時(shí)網(wǎng)關(guān)會(huì)發(fā)送一個(gè)會(huì)話重置信號(hào)語義緩存層直接把該會(huì)話相關(guān)的記錄全量標(biāo)記為 invalid。這個(gè)信號(hào)比任何相似度算法都可靠因?yàn)樗俏夷馨盐盏挠脩粽鎸?shí)意圖。4.4 監(jiān)控指標(biāo)別只盯著命中率語義緩存上線后最容易犯的錯(cuò)誤是整天盯著命中率。我后來把監(jiān)控面板換成四個(gè)指標(biāo)組合hit_rate請(qǐng)求命中緩存的比例precisionhit抽樣評(píng)估命中結(jié)果是否真的被用戶采納后續(xù)是否繼續(xù)追問、是否修改而不是只看離線標(biāo)注saved_tokens因?yàn)槊卸苊庵貜?fù) prefill 的 token 總量這是成本收益的核心指標(biāo)cache_pollution一段時(shí)間內(nèi)出現(xiàn)緩存返回后被用戶糾正的比例這個(gè)指標(biāo)比 hit_rate 更能在早期反映閾值失控。只用 hit_rate 做績效考核團(tuán)隊(duì)一定會(huì)為了指標(biāo)好看把閾值無限調(diào)低最后換來一堆錯(cuò)誤復(fù)用的事故。5. 實(shí)測效果與三個(gè)典型調(diào)參踩坑SmartCache 在模擬項(xiàng)目 X 的離線會(huì)話集上做了回放測試又在兩個(gè)內(nèi)部業(yè)務(wù)場景里跑了小流量 A/B。先說結(jié)果再說踩過的坑。5.1 基線對(duì)比數(shù)據(jù)測試集包含 4 類多輪會(huì)話旅行規(guī)劃、售后咨詢、代碼問答、文檔改寫每類各約 5000 條完整會(huì)話鏈。三組對(duì)照組是無緩存、精確字符串前綴緩存、SmartCache 語義緩存。方案端到端 P50 時(shí)延端到端 P95 時(shí)延緩存命中率答案采納率抽樣無緩存1.85s4.2s0%基準(zhǔn)精確前綴緩存1.74s4.0s8.2%接近基準(zhǔn)SmartCache 語義緩存0.91s2.1s26.7%略低于基準(zhǔn)但差異不顯著時(shí)延降低主要來自兩處直接命中時(shí)省掉了完整 prefill 和大部分 decode半命中時(shí)雖然仍要走模型但歷史上下文只做增量計(jì)算。P95 的改善比 P50 更明顯因?yàn)殚L會(huì)話原本是時(shí)延拖尾的重災(zāi)區(qū)而語義緩存恰好最容易在長會(huì)話中命中。5.2 踩坑一閾值拍腦袋換來看似合理但實(shí)際錯(cuò)誤的高相似度命中第一個(gè)版本里我把接受閾值定在 0.85理由是看起來差不多。上線一天就出現(xiàn)了一次嚴(yán)重事故用戶先問客服電話為什么打不通得到一段關(guān)于客服時(shí)間表的回答后緊接著問退款申請(qǐng)多久能到賬系統(tǒng)直接命中了上一輪的緩存返回了客服時(shí)間表。事后分析發(fā)現(xiàn)這兩個(gè)問題在通用 embedding 模型里的余弦相似度竟然高達(dá) 0.87。原因是客服和退款這兩個(gè)詞在訓(xùn)練語料里頻繁共現(xiàn)模型把它們映射到了相近的語義區(qū)域。這給我兩個(gè)教訓(xùn)第一閾值永遠(yuǎn)不能用感覺定要用離線回放數(shù)據(jù)分布來定第二向量相似度在自然語言層面有多義詞和共現(xiàn)偏差粗粒度標(biāo)簽的硬過濾不是可選項(xiàng)而是必修課。后來我把接受閾值改成離線回放時(shí)誤命中率低于萬分之一來校準(zhǔn)。不同業(yè)務(wù)場景的值差異很大代碼生成類通常要 0.92 以上閑聊類可以放寬到 0.78。5.3 踩坑二全量歷史做 embedding新意圖被歷史稀釋這是多輪語義緩存最典型的問題。有一次測試?yán)锴拔遢営脩舳荚谝?guī)劃旅行第六輪突然問明天上午的會(huì)我不去了幫我寫一封請(qǐng)假郵件。這個(gè)請(qǐng)求的正確答案應(yīng)該是一封郵件但全量上下文 embedding 做出來的向量仍然離旅行規(guī)劃主題非常近召回排在前面的全是酒店和行程相關(guān)記錄。解決辦法就是我在第二章節(jié)提到的上下文編碼視圖歷史參與但必須壓縮當(dāng)前問題全量參與并提高權(quán)重同時(shí)用粗粒度標(biāo)簽里的 context_switch 信號(hào)強(qiáng)行切斷舊緩存。我還會(huì)對(duì)話題切換加了一個(gè)額外保護(hù)當(dāng)標(biāo)簽分類器認(rèn)為當(dāng)前問題和最近 3 輪歷史不屬于同一話題時(shí)直接跳過向量相似度評(píng)估把整條請(qǐng)求當(dāng)作全新會(huì)話處理不給任何歷史緩存機(jī)會(huì)。5.4 踩坑三embedding 模型長度限制下截?cái)辔恢脹Q定成敗第一次實(shí)現(xiàn)里上下文超過 embedding 模型最大長度時(shí)簡單地從開頭截?cái)唷=Y(jié)果長會(huì)話緩存幾乎全部失效因?yàn)樵诔^長度后最早的指令和目標(biāo)約束是全被截掉的留下的只有最近幾輪閑聊和用戶的操作記錄編碼視圖的語義完全變了。改成分塊-加權(quán)-匯總之后好很多把長上下文按輪次切成塊每個(gè)塊單獨(dú)編碼再按離當(dāng)前時(shí)間越近權(quán)重越高做加權(quán)平均。系統(tǒng)提示詞里真正影響行為的關(guān)鍵段落單獨(dú)編碼并保留最高權(quán)重。這個(gè)方案規(guī)避了 embedding 模型長度限制而且對(duì)舊輪次偶爾被擠掉的情況更魯棒。5.5 語義緩存適用的風(fēng)險(xiǎn)分級(jí)經(jīng)過這幾次踩坑我總結(jié)了一張調(diào)參參考表任務(wù)類型接受閾值參考是否允許直接命中半命中策略閑聊、生活建議0.78 - 0.82允許增量復(fù)用旅行攻略、產(chǎn)品推薦0.86 - 0.90允許但校驗(yàn)關(guān)鍵約束增量復(fù)用代碼生成、合同審查0.92 以上或關(guān)閉緩存謹(jǐn)慎需人工確認(rèn)只復(fù)用上下文不返回緩存答案這份表不是金科玉律但可以作為一個(gè)起步參考。核心原則是誤判的后果越嚴(yán)重閾值就要越嚴(yán)甚至可以直接關(guān)掉緩存寧可讓緩存命中率難看也不能犧牲正確率。6. 把兩層緩存真正疊起來語義緩存與 Token 級(jí) KV Cache 的協(xié)同語義緩存落地之后團(tuán)隊(duì)的注意力又回到了一個(gè)老問題語義緩存 miss 的時(shí)候多輪推理的性能依然會(huì)有長尾劣化。這兩個(gè)層次的緩存不應(yīng)該是對(duì)立關(guān)系而是接力關(guān)系。6.1 語義緩存的邊界正好是 KV Cache 的主場語義緩存能直接返回答案但只有高度近似的場景才能命中。更多的情況是用戶在同一個(gè)話題下改變一個(gè)條件比如預(yù)算從八千提到一萬——這個(gè)請(qǐng)求在語義上不應(yīng)該直接復(fù)用舊答案但它的歷史上下文城市、景點(diǎn)、主要訴求對(duì)新請(qǐng)求仍然有用。這種場景正是 token 級(jí) KV Cache 的用武之地。服務(wù)端如果能維護(hù)好會(huì)話級(jí)的 KV Cache并在每輪新請(qǐng)求時(shí)只對(duì)增量部分做 prefill模型推理的耗時(shí)可以從完整上下文 prefill降為增量 prefill 全部 decode整體時(shí)延收益也非??捎^。6.2 前綴重建與半命中路徑的配合我在上線 SmartCache 后把語義緩存的半命中路徑和前綴緩存徹底打通。流程變成語義緩存層判定當(dāng)前請(qǐng)求屬于半命中也就是歷史上下文基本成立但用戶新增了變更條件把變更后的請(qǐng)求交給推理服務(wù)推理服務(wù)檢查會(huì)話的 KV Cache 是否仍然有效如果 KV Cache 里的歷史前綴與當(dāng)前請(qǐng)求一致直接復(fù)用并增量 prefill模型只針對(duì)變更部分生成新的回答。這個(gè)組合鏈路帶來的收益比我預(yù)想的大。旅行規(guī)劃場景中完整上下文 1200 token用戶每輪新增只有 80 token半命中路徑下的模型 prefill 計(jì)算量大約只有原來的 6.7%。6.3 緩存預(yù)熱和反饋閉環(huán)語義緩存有一個(gè)冷啟動(dòng)期新會(huì)話模板上線前頭幾天命中率都很低。我在離線側(cè)做了一個(gè)預(yù)熱管道把歷史會(huì)話庫里高頻出現(xiàn)的多輪場景先批量打標(biāo)、編碼、寫入緩存等線上流量進(jìn)來時(shí)已經(jīng)有一部分候選可用。反饋閉環(huán)也很重要。我會(huì)把用戶對(duì)緩存答案的后續(xù)行為納入權(quán)重如果用戶緊接著追問不對(duì)我不是這個(gè)意思或者點(diǎn)擊了重新生成這條緩存記錄的 feedback_score 就會(huì)下調(diào)下調(diào)到一定程度后不再參與召回。這個(gè)機(jī)制比定期人工抽檢及時(shí)得多能自動(dòng)捕捉語義漂移和模型行為變化帶來的緩存污染。6.4 一些沒有繞過去的邊界問題語義緩存不是萬能的。我做的這個(gè)版本里依舊有幾個(gè)場景完全不建議開啟緩存強(qiáng)時(shí)效性內(nèi)容實(shí)時(shí)行情、天氣、庫存數(shù)量任何帶現(xiàn)在含義的請(qǐng)求都不該走緩存強(qiáng)正確性要求醫(yī)療建議、合同數(shù)字、法律條款這類場景除非有人工確認(rèn)環(huán)節(jié)否則收益遠(yuǎn)小于風(fēng)險(xiǎn)個(gè)性化強(qiáng)烈的內(nèi)容同樣是旅游攻略用戶 A 和用戶 B 的偏好差異很大跨用戶復(fù)用容易產(chǎn)生看似合理但不適合的錯(cuò)誤答案。我的處理是給每個(gè)緩存記錄加一個(gè) scope 字段標(biāo)識(shí)它是全局可復(fù)用還是僅限單會(huì)話復(fù)用。默認(rèn)嚴(yán)格按會(huì)話維度隔離緩存只有那些被證明跨用戶安全的系統(tǒng)級(jí)回答才允許進(jìn)入全局池。做完整套 SmartCache我最深的體會(huì)是語義緩存本質(zhì)上是在正確性可容忍的范圍內(nèi)用近似匹配換取延遲和算力。它不是存儲(chǔ)組件而是一個(gè)語義路由決策層。上線之前先花時(shí)間統(tǒng)計(jì)自己業(yè)務(wù)里的語義重復(fù)請(qǐng)求占比如果不足 5%這個(gè)方向帶來的收益會(huì)非常有限如果超過 20%那它大概率會(huì)是繼 KV Cache 之后又一個(gè)值得投入的性價(jià)比高地。離線回放評(píng)估閾值這一步尤其不要省拿歷史會(huì)話先跑一遍比上線后反復(fù)調(diào)參省力得多也安全得多。