生成實(shí)戰(zhàn):從文檔切分到檢索評估的完整指南)
1. 為什么RAG值得你花時間搞明白RAG這個詞這兩年在大模型圈子里出現(xiàn)的頻率高得離譜。不管你是做AI應(yīng)用的開發(fā)者還是剛?cè)腴T大模型的小白只要涉及到“讓模型回答得更準(zhǔn)”“讓模型知道它原本不知道的東西”“讓模型別瞎編”繞來繞去最終都會落到RAG上。RAG的全稱是Retrieval-Augmented Generation翻譯過來叫檢索增強(qiáng)生成。名字聽著挺學(xué)術(shù)但核心邏輯其實(shí)特別樸素——模型自己記不住或者不知道的東西你幫它去外面查資料查到了再讓它組織語言回答。我剛開始接觸RAG的時候也覺得這東西應(yīng)該不難不就是把文檔切一切、向量化、存進(jìn)數(shù)據(jù)庫、查詢的時候做相似度匹配、把匹配到的內(nèi)容塞進(jìn)提示詞里讓模型生成答案嗎但真正動手做起來才發(fā)現(xiàn)坑遠(yuǎn)比想象的多。切分粒度怎么定向量模型選哪個檢索回來一堆不相關(guān)的內(nèi)容怎么辦檢索評估怎么做這些問題不解決搭出來的RAG系統(tǒng)就是個花架子看著能用實(shí)際一問就露餡。這篇內(nèi)容適合誰看如果你是零基礎(chǔ)想入門RAG我會從最基礎(chǔ)的概念講起把每個環(huán)節(jié)的原理和實(shí)操都拆開揉碎如果你已經(jīng)搭過簡單的RAG流程但效果不理想我會重點(diǎn)講檢索評估和優(yōu)化策略這些是區(qū)分“能用”和“好用”的關(guān)鍵。整篇內(nèi)容會圍繞RAG的功能原理、系統(tǒng)構(gòu)建、檢索評估三條主線展開每一步都配上可復(fù)現(xiàn)的操作思路和參數(shù)選擇邏輯。注意RAG不是萬能藥。它解決的是“知識時效性”和“領(lǐng)域知識注入”的問題但解決不了模型本身推理能力不足的問題。搞清楚它的能力邊界比盲目上手更重要。2. RAG到底在解決什么問題2.1 大模型的三道硬傷要理解RAG的價值得先搞清楚大模型本身有哪些繞不過去的局限。我總結(jié)下來主要是三道硬傷。第一道是知識截止。任何大模型的訓(xùn)練數(shù)據(jù)都有時間邊界比如某個模型訓(xùn)練數(shù)據(jù)截止到2024年初那你問它2025年發(fā)生的事它要么說不知道要么就開始編。這不是模型笨是它確實(shí)沒見過。第二道是私有知識盲區(qū)。你公司內(nèi)部的文檔、產(chǎn)品手冊、客戶資料這些東西不可能出現(xiàn)在公開訓(xùn)練數(shù)據(jù)里。你直接問模型“我們公司產(chǎn)品的退貨政策是什么”它只能瞎猜。第三道是幻覺問題。大模型本質(zhì)上是概率模型它在生成每一個token的時候是在預(yù)測“下一個最可能出現(xiàn)的詞”。當(dāng)它沒有足夠信息支撐的時候它會用看起來合理但實(shí)際錯誤的內(nèi)容來填充答案。而且它說得特別自信你如果不了解情況根本分辨不出來。這三道硬傷靠重新訓(xùn)練模型或者微調(diào)成本高、周期長、效果還不一定好。RAG提供了一條更輕量的路徑不改模型參數(shù)通過外掛知識庫的方式讓模型在生成回答之前先“查資料”。2.2 RAG的核心工作流拆解RAG的完整流程可以拆成兩個階段索引階段和查詢階段。索引階段是離線的你先把所有知識文檔處理好存進(jìn)向量數(shù)據(jù)庫。具體步驟包括文檔加載、文本切分、向量化、存入向量數(shù)據(jù)庫。這個階段相當(dāng)于你給模型建了一個“圖書館”把所有的書都編好目、上好書架。查詢階段是在線的用戶提問之后系統(tǒng)先把問題向量化然后去向量數(shù)據(jù)庫里找最相似的文本片段把這些片段和原始問題一起塞進(jìn)提示詞最后交給大模型生成答案。這個階段相當(dāng)于用戶來圖書館問問題你先去書架上找到相關(guān)的幾本書翻到相關(guān)頁碼然后基于這些內(nèi)容來回答。聽起來很簡單對吧但每個環(huán)節(jié)都有大量細(xì)節(jié)需要做決策。比如文本切分你切得太碎語義不完整切得太粗檢索精度下降。比如向量模型你選中文效果差的模型檢索出來的東西驢唇不對馬嘴。比如檢索策略你只用向量相似度可能漏掉關(guān)鍵詞精確匹配的情況。2.3 RAG和微調(diào)怎么選經(jīng)常有人問RAG和微調(diào)到底用哪個我的經(jīng)驗(yàn)是它們解決的不是同一類問題。微調(diào)適合改變模型的行為模式比如讓模型的輸出風(fēng)格更正式、更簡潔或者讓模型學(xué)會某種特定的輸出格式。微調(diào)是在教模型“怎么說話”。RAG適合給模型補(bǔ)充知識內(nèi)容比如讓模型知道最新的政策法規(guī)、公司內(nèi)部流程、特定領(lǐng)域的專業(yè)知識。RAG是在告訴模型“說什么”。實(shí)際項目中兩者經(jīng)常配合使用。先用RAG解決知識注入的問題如果發(fā)現(xiàn)模型在特定任務(wù)上的輸出格式或推理方式不理想再考慮用微調(diào)來調(diào)整行為。但絕大多數(shù)場景下RAG的投入產(chǎn)出比遠(yuǎn)高于微調(diào)因?yàn)槲⒄{(diào)需要標(biāo)注數(shù)據(jù)、需要GPU資源、需要反復(fù)實(shí)驗(yàn)而RAG的迭代周期短得多。實(shí)操心得如果你剛開始做RAG不要一上來就追求完美。先用最簡單的方案跑通全流程哪怕切分策略很粗糙、向量模型用的是默認(rèn)的先看到效果再逐步優(yōu)化每個環(huán)節(jié)。我見過太多人卡在“選哪個向量模型”這一步糾結(jié)好幾天結(jié)果全流程都沒跑通。3. 動手搭建RAG系統(tǒng)從文檔到向量庫3.1 文檔加載與預(yù)處理搭建RAG的第一步是把你的知識文檔加載進(jìn)來。文檔格式可能五花八門PDF、Word、Markdown、HTML、Excel、數(shù)據(jù)庫導(dǎo)出等等。不同格式需要不同的加載器。PDF是最麻煩的格式之一。有些PDF是掃描件需要OCR有些PDF有復(fù)雜的表格和圖表直接提取文本會丟失結(jié)構(gòu)信息有些PDF是多欄排版提取出來的文本順序是亂的。我的建議是如果PDF質(zhì)量太差寧可手動整理成Markdown或純文本也不要硬用自動提取因?yàn)槔M(jìn)垃圾出后面檢索效果一定好不了。Word文檔相對好處理用python-docx之類的庫可以提取段落和表格。Markdown和純文本最簡單直接讀取就行。HTML需要去掉標(biāo)簽保留正文內(nèi)容。預(yù)處理階段還需要做幾件事去掉頁眉頁腳、去掉重復(fù)內(nèi)容、統(tǒng)一編碼格式、處理特殊字符。這些看起來是小事但如果不做后面切分出來的文本塊會包含大量噪音影響檢索質(zhì)量。# 以PDF加載為例的偽代碼思路 from langchain.document_loaders import PyPDFLoader loader PyPDFLoader(knowledge_base.pdf) pages loader.load() # 檢查每頁內(nèi)容質(zhì)量 for i, page in enumerate(pages): text page.page_content.strip() if len(text) 50: print(f第{i}頁內(nèi)容過短可能是掃描件或空白頁需要單獨(dú)處理)3.2 文本切分粒度決定成敗文本切分是RAG系統(tǒng)中最容易被低估的環(huán)節(jié)。很多人隨便設(shè)個chunk_size1000、chunk_overlap200就完事了結(jié)果檢索效果一塌糊涂。切分的核心矛盾在于塊太小語義不完整塊太大噪音太多。你想想如果一個文本塊只有一句話“該政策自2024年1月1日起施行”檢索出來之后模型根本不知道這是什么政策。但如果一個文本塊有3000字里面涵蓋了五個不同的主題你檢索“退貨政策”的時候可能匹配到的是這個塊里關(guān)于“換貨政策”的那部分但模型看到的是整個3000字容易被無關(guān)信息干擾。我的經(jīng)驗(yàn)是按語義邊界切分比按固定字?jǐn)?shù)切分效果好得多。具體來說對于結(jié)構(gòu)化文檔如Markdown、HTML按標(biāo)題層級切分每個小節(jié)作為一個塊如果小節(jié)太長再按段落細(xì)分。對于非結(jié)構(gòu)化文檔如純文本、對話記錄按段落切分如果段落太長再按句子切分。對于代碼文檔按函數(shù)或類切分。對于表格把表頭和每一行組合成一個完整的描述塊。chunk_size的設(shè)置沒有標(biāo)準(zhǔn)答案但有一個經(jīng)驗(yàn)范圍中文文本建議在300-800字之間英文文本建議在200-500詞之間。chunk_overlap建議設(shè)為chunk_size的10%-20%目的是讓相鄰塊之間有上下文銜接避免在邊界處丟失信息。# 按標(biāo)題層級切分的思路 from langchain.text_splitter import MarkdownHeaderTextSplitter headers_to_split_on [ (#, 一級標(biāo)題), (##, 二級標(biāo)題), (###, 三級標(biāo)題), ] splitter MarkdownHeaderTextSplitter(headers_to_split_onheaders_to_split_on) chunks splitter.split_text(markdown_content) # 如果某個塊超過800字再用遞歸切分器細(xì)分 from langchain.text_splitter import RecursiveCharacterTextSplitter recursive_splitter RecursiveCharacterTextSplitter( chunk_size600, chunk_overlap100, separators[\n\n, \n, 。, , , , , ] )注意事項切分的時候一定要保留元數(shù)據(jù)。比如每個塊屬于哪個文檔、哪個章節(jié)、哪個頁碼。這些元數(shù)據(jù)在檢索階段可以用來做過濾在生成階段可以用來做引用標(biāo)注。我見過有人切完只保留文本內(nèi)容后面想加過濾功能的時候發(fā)現(xiàn)元數(shù)據(jù)全丟了只能重新處理一遍。3.3 向量化選對模型比選貴的更重要向量化就是把文本轉(zhuǎn)成一串?dāng)?shù)字向量這串?dāng)?shù)字代表了文本的語義信息。語義相近的文本向量距離就近語義無關(guān)的文本向量距離就遠(yuǎn)。向量模型的選擇直接決定了檢索質(zhì)量的上限。如果向量模型本身對中文語義理解不好后面再怎么優(yōu)化檢索策略都是白搭。選向量模型的時候我主要看幾個維度語言支持是否支持中文中文效果如何。有些模型英文很強(qiáng)但中文拉胯。維度向量維度越高表達(dá)能力越強(qiáng)但存儲和計算成本也越高。常見的有384維、768維、1024維、1536維。最大輸入長度模型能處理多長的文本。如果你的chunk_size是800字模型最大輸入只有512個token那超出的部分會被截斷。推理速度如果你有大量文檔需要向量化推理速度直接影響索引構(gòu)建時間。是否開源開源模型可以本地部署數(shù)據(jù)不出內(nèi)網(wǎng)閉源API模型通常效果更好但需要聯(lián)網(wǎng)調(diào)用。目前中文場景下常用的向量模型有幾類一類是專門針對中文優(yōu)化的開源模型一類是多語言通用模型還有一類是商業(yè)API。我的建議是如果你的數(shù)據(jù)敏感度不高可以先用商業(yè)API快速驗(yàn)證效果如果數(shù)據(jù)不能出內(nèi)網(wǎng)就選開源模型本地部署。# 向量化示例以開源模型為例 from sentence_transformers import SentenceTransformer model SentenceTransformer(your-chinese-embedding-model) texts [文本塊1的內(nèi)容, 文本塊2的內(nèi)容] embeddings model.encode(texts, normalize_embeddingsTrue) # normalize_embeddingsTrue 很重要 # 歸一化之后余弦相似度計算可以用點(diǎn)積代替速度更快實(shí)操心得不要盲目追求高維度。我實(shí)測下來768維和1536維在大多數(shù)中文檢索場景下的效果差異并不明顯但存儲成本差了一倍。先用768維跑起來如果發(fā)現(xiàn)檢索效果確實(shí)不夠再考慮升級。3.4 向量數(shù)據(jù)庫選型與入庫向量數(shù)據(jù)庫是專門用來存儲和檢索向量的。選型的時候主要考慮幾個因素數(shù)據(jù)量級、查詢延遲要求、是否需要持久化、是否需要分布式、運(yùn)維成本。小規(guī)模場景幾萬到幾十萬條向量用FAISS就夠了。FAISS是Facebook開源的向量檢索庫輕量、快、不需要額外部署服務(wù)直接嵌在Python代碼里就能用。缺點(diǎn)是它本質(zhì)上是個索引文件不支持增刪改查的實(shí)時操作每次更新都需要重建索引。中等規(guī)模場景百萬到千萬級可以考慮Milvus、Qdrant、Weaviate這類專門的向量數(shù)據(jù)庫。它們支持實(shí)時增刪改查、支持分布式部署、有完善的API和監(jiān)控。缺點(diǎn)是部署和運(yùn)維復(fù)雜度上來了。如果已經(jīng)有PostgreSQL可以用pgvector擴(kuò)展直接在關(guān)系型數(shù)據(jù)庫里存向量。好處是不用額外維護(hù)一套數(shù)據(jù)庫壞處是性能和功能不如專門的向量數(shù)據(jù)庫。大規(guī)模場景億級以上那就需要考慮分布式向量數(shù)據(jù)庫了比如Milvus集群版。這個量級一般公司也碰不到這里不展開。入庫的時候除了向量本身還要存原始文本和元數(shù)據(jù)。原始文本用于后續(xù)塞進(jìn)提示詞元數(shù)據(jù)用于過濾和引用。# 以FAISS為例的入庫思路 import faiss import numpy as np dimension 768 # 向量維度 index faiss.IndexFlatIP(dimension) # IP Inner Product內(nèi)積 # 假設(shè)embeddings是numpy數(shù)組shape為(n, 768) embeddings np.array(embeddings).astype(float32) index.add(embeddings) # 保存索引 faiss.write_index(index, vector_index.faiss) # 同時保存文本和元數(shù)據(jù) import json with open(chunks.json, w, encodingutf-8) as f: json.dump(chunks, f, ensure_asciiFalse)4. 檢索策略與效果評估4.1 向量檢索的局限與補(bǔ)充方案向量檢索的核心是語義相似度它擅長處理“意思相近但用詞不同”的情況。比如用戶問“怎么退錢”文檔里寫的是“退款流程”向量檢索能匹配上。但向量檢索也有明顯的短板。第一它對精確匹配不敏感。比如用戶問“產(chǎn)品型號X200的保修期”如果文檔里寫的是“X200型號保修期為兩年”向量檢索可能匹配到其他型號的保修信息因?yàn)檎Z義上都是“保修期”。第二它對否定語義處理不好。比如用戶問“哪些情況不支持退貨”向量檢索可能匹配到“支持退貨的情況”因?yàn)檎Z義相似度很高。第三它對數(shù)字和專有名詞不敏感。比如“2024年政策”和“2023年政策”向量可能很接近但實(shí)際內(nèi)容完全不同。解決這些問題的常見方案是混合檢索向量檢索 關(guān)鍵詞檢索如BM25然后把兩路結(jié)果融合。融合策略有幾種加權(quán)求和、RRFReciprocal Rank Fusion、先向量后關(guān)鍵詞過濾等。# RRF融合策略的偽代碼 def rrf_fusion(vector_results, keyword_results, k60): scores {} for rank, doc_id in enumerate(vector_results): scores[doc_id] scores.get(doc_id, 0) 1 / (k rank 1) for rank, doc_id in enumerate(keyword_results): scores[doc_id] scores.get(doc_id, 0) 1 / (k rank 1) # 按分?jǐn)?shù)降序排列 sorted_docs sorted(scores.items(), keylambda x: x[1], reverseTrue) return [doc_id for doc_id, _ in sorted_docs]RRF的好處是不需要調(diào)權(quán)重對兩路檢索的分?jǐn)?shù)尺度不敏感。我實(shí)測下來RRF在大多數(shù)場景下比加權(quán)求和更穩(wěn)定。4.2 重排序讓最相關(guān)的結(jié)果排到最前面檢索回來Top-K個結(jié)果之后還有一個優(yōu)化空間重排序。向量檢索用的是雙塔模型查詢和文檔分別編碼然后算相似度。這種方式速度快但精度有限。重排序用的是交叉編碼器把查詢和文檔拼在一起輸入模型模型直接輸出相關(guān)性分?jǐn)?shù)。這種方式精度高但速度慢所以只適合對少量候選結(jié)果做精排。典型流程是向量檢索召回Top-50然后用重排序模型對50個結(jié)果精排取Top-5塞進(jìn)提示詞。這樣既保證了召回率又保證了精度。重排序模型的選擇和向量模型類似也要看中文支持、推理速度、是否開源。有些向量模型本身就提供了配套的重排序模型搭配使用效果更好。注意事項重排序不是必須的。如果你的檢索結(jié)果本身已經(jīng)很好Top-5都是相關(guān)的加不加重排序差別不大。但如果你的檢索結(jié)果噪音比較多重排序能顯著提升效果。建議先做檢索評估看看當(dāng)前的問題出在召回階段還是排序階段再決定要不要加重排序。4.3 檢索評估怎么知道你的RAG好不好這是很多人忽略的環(huán)節(jié)。搭完RAG系統(tǒng)隨便問幾個問題覺得“好像還行”就上線了。結(jié)果用戶一問稍微偏一點(diǎn)的問題就露餡了。檢索評估需要一套系統(tǒng)的指標(biāo)和方法。核心指標(biāo)包括召回率相關(guān)文檔有多少被檢索出來了。召回率低說明你的檢索策略漏掉了重要信息。精確率檢索出來的文檔有多少是相關(guān)的。精確率低說明噪音太多會干擾模型生成。MRR第一個相關(guān)文檔排在第幾位。MRR高說明最相關(guān)的內(nèi)容排在最前面。NDCG考慮排序位置的相關(guān)性指標(biāo)越相關(guān)的內(nèi)容排得越靠前分?jǐn)?shù)越高。做評估需要標(biāo)注數(shù)據(jù)。你需要準(zhǔn)備一批查詢每個查詢標(biāo)注哪些文檔是相關(guān)的。標(biāo)注數(shù)據(jù)不用很多50-100個查詢就能看出問題。關(guān)鍵是覆蓋不同類型的查詢事實(shí)型、對比型、否定型、多跳推理型等。# 簡單的檢索評估示例 def evaluate_retrieval(queries, ground_truth, retriever, k5): recall_scores [] precision_scores [] mrr_scores [] for query, relevant_ids in zip(queries, ground_truth): retrieved retriever.search(query, top_kk) retrieved_ids [doc.id for doc in retrieved] # 召回率 hit len(set(retrieved_ids) set(relevant_ids)) recall hit / len(relevant_ids) if relevant_ids else 0 recall_scores.append(recall) # 精確率 precision hit / k precision_scores.append(precision) # MRR for rank, doc_id in enumerate(retrieved_ids): if doc_id in relevant_ids: mrr_scores.append(1 / (rank 1)) break else: mrr_scores.append(0) return { recallk: sum(recall_scores) / len(recall_scores), precisionk: sum(precision_scores) / len(precision_scores), mrr: sum(mrr_scores) / len(mrr_scores) }評估結(jié)果怎么用如果召回率低說明你的切分粒度、向量模型、檢索策略有問題需要調(diào)整。如果精確率低但召回率高說明檢索回來的東西太多太雜需要加重排序或者調(diào)整Top-K。如果MRR低說明排序有問題最相關(guān)的內(nèi)容沒有排到前面。4.4 生成階段的優(yōu)化技巧檢索做完了最后一步是把檢索結(jié)果和用戶問題一起塞給大模型生成答案。這一步也有不少優(yōu)化空間。提示詞設(shè)計是關(guān)鍵。你需要明確告訴模型只根據(jù)提供的參考資料回答如果參考資料里沒有相關(guān)信息就說不知道不要自己編。這個約束能大幅降低幻覺。上下文長度控制也很重要。檢索回來的內(nèi)容不是越多越好。塞太多內(nèi)容進(jìn)去一是可能超出模型的上下文窗口二是無關(guān)信息會干擾模型。我的經(jīng)驗(yàn)是Top-3到Top-5通常就夠了具體看chunk_size和模型上下文窗口。引用標(biāo)注能提升可信度。在提示詞里要求模型在回答中標(biāo)注信息來源比如“根據(jù)文檔A第3節(jié)的內(nèi)容...”。這樣用戶能驗(yàn)證答案的可靠性也方便排查問題。# 提示詞模板示例 PROMPT_TEMPLATE 你是一個知識助手。請根據(jù)以下參考資料回答用戶問題。 參考資料 {context} 用戶問題{question} 回答要求 1. 只根據(jù)參考資料回答不要使用你自己的知識 2. 如果參考資料中沒有相關(guān)信息直接說根據(jù)現(xiàn)有資料無法回答該問題 3. 回答時標(biāo)注信息來源格式為[來源文檔名] 4. 回答要簡潔準(zhǔn)確不要展開無關(guān)內(nèi)容 回答5. 常見問題與排查技巧實(shí)錄5.1 檢索效果差的排查思路檢索效果差是最常見的問題。排查的時候我一般按這個順序來第一步檢查切分質(zhì)量。隨便抽幾個chunk出來看看是不是語義完整有沒有被切斷的句子有沒有包含大量噪音如果切分質(zhì)量差后面怎么優(yōu)化都是白搭。第二步檢查向量模型。拿幾個查詢和對應(yīng)的相關(guān)文檔手動算一下向量相似度。如果相關(guān)文檔的相似度還不如無關(guān)文檔高說明向量模型不適合你的場景。第三步檢查檢索策略。是不是只用了向量檢索有沒有考慮混合檢索Top-K設(shè)的是多少K太小可能漏掉相關(guān)結(jié)果K太大噪音太多。第四步檢查評估方法。你的評估指標(biāo)合理嗎標(biāo)注數(shù)據(jù)準(zhǔn)確嗎有時候不是系統(tǒng)效果差是評估方法有問題。5.2 模型回答不準(zhǔn)確的原因分析檢索回來的內(nèi)容是對的但模型回答還是不對這種情況通常有幾個原因提示詞約束不夠模型沒有嚴(yán)格遵循“只根據(jù)參考資料回答”的指令摻雜了自己的知識。上下文太長塞了太多內(nèi)容模型注意力被分散關(guān)鍵信息被淹沒。參考資料格式混亂檢索回來的文本沒有清晰的邊界模型分不清哪些是參考資料、哪些是問題。模型本身能力不足有些小模型在長上下文場景下表現(xiàn)確實(shí)差換更大的模型可能就解決了。5.3 性能優(yōu)化的幾個方向RAG系統(tǒng)的性能優(yōu)化主要從兩個維度考慮延遲和成本。延遲優(yōu)化向量檢索本身很快瓶頸通常在向量化和重排序。如果向量模型推理慢可以考慮用更小的模型或者做量化。如果重排序慢可以減少候選數(shù)量或者用更快的重排序模型。成本優(yōu)化如果用的是商業(yè)API向量化和生成都是按量計費(fèi)的。優(yōu)化方向包括減少不必要的向量化比如增量更新而不是全量重建、壓縮上下文長度、緩存常見查詢的結(jié)果。實(shí)操心得我踩過最大的坑是忽略了增量更新。一開始每次文檔有更新就全量重建索引幾萬條數(shù)據(jù)要跑好幾個小時。后來改成只對新增和修改的文檔做向量化刪除的文檔從索引里移除更新時間縮短到幾分鐘。如果你的知識庫更新頻繁一定要設(shè)計好增量更新機(jī)制。5.4 常見問題速查表問題現(xiàn)象可能原因排查方向解決思路檢索結(jié)果完全不相關(guān)向量模型不匹配檢查向量模型的中文效果換用中文優(yōu)化的向量模型檢索結(jié)果漏掉關(guān)鍵信息切分粒度過粗或過細(xì)檢查chunk_size和切分邊界調(diào)整切分策略按語義邊界切分相似問題檢索結(jié)果不穩(wěn)定向量模型對語義變化敏感測試不同表述的相似度增加查詢改寫或混合檢索模型回答包含幻覺提示詞約束不夠檢查提示詞模板強(qiáng)化“只根據(jù)參考資料回答”的約束系統(tǒng)響應(yīng)慢向量化或重排序耗時分階段計時優(yōu)化模型選擇或減少候選數(shù)量新增文檔檢索不到索引未更新檢查索引更新機(jī)制實(shí)現(xiàn)增量更新流程6. 從能用走向好用持續(xù)迭代的思路RAG系統(tǒng)不是搭完就完事了它需要持續(xù)迭代。迭代的依據(jù)來自兩個方面用戶反饋和評估數(shù)據(jù)。用戶反饋是最直接的信號。用戶點(diǎn)了“答案不準(zhǔn)”的按鈕或者追問“你確定嗎”這些都是優(yōu)化線索。把這些問題收集起來分析是檢索問題還是生成問題然后針對性優(yōu)化。評估數(shù)據(jù)是更系統(tǒng)的依據(jù)。定期跑一遍評估集看各項指標(biāo)的變化趨勢。如果召回率在下降可能是知識庫內(nèi)容老化了如果精確率在下降可能是文檔噪音增加了。迭代的優(yōu)先級建議是先解決檢索問題再解決生成問題。因?yàn)闄z索是根基檢索不準(zhǔn)生成再優(yōu)化也沒用。檢索問題里先解決切分和向量模型的問題再考慮混合檢索和重排序。還有一個容易被忽略的點(diǎn)知識庫的維護(hù)。文檔會過期、會更新、會刪除。你需要一套機(jī)制來保證知識庫和實(shí)際業(yè)務(wù)保持一致。我見過一些RAG系統(tǒng)剛上線效果很好過了半年就越來越差因?yàn)橹R庫沒人維護(hù)里面全是過時信息。最后分享一個我在實(shí)際項目中總結(jié)的小技巧給每個chunk打上時間戳和版本號。檢索的時候可以優(yōu)先返回最新版本的內(nèi)容。如果同一個問題有多個版本的答案模型可以基于時間戳來判斷哪個是最新的。這個小小的元數(shù)據(jù)字段在知識頻繁更新的場景下能省很多事。