RAG系列:一文讓你由淺到深搞懂RAG實現
1. RAG簡介
RAG(檢索增強生成)是一種結合檢索與生成的技術,通過實時檢索外部知識庫中的信息,動態增強大語言模型(LLM)的生成能力,是用于解決幻覺問題、知識時效問題、超長文本問題等各種大模型本身制約或不足的必要技術。
RAG核心流程包括:
- 問題理解階段:對用戶問題進行改寫、擴寫和重構,讓用戶問題更利于檢索;
- 檢索召回階段:從外部知識庫(如企業文檔、行業數據庫)中篩選與用戶問題相關的片段,并將檢索結果與原始問題整合為增強提示詞,輸入給LLM;
- 答案生成階段:LLM基于增強后的提示詞,生成精準、可靠的答案。
RAG具有以下優點:
- 實時性:動態接入最新數據(如新聞、更新文檔),突破模型訓練數據的時間限制;
- 專業性:通過連接領域知識庫(如醫療指南、法律條文)提升回答的準確性;
- 成本效益:無需全量微調模型,僅維護輕量級知識庫即可擴展能力;
- 可信度增強:生成答案基于可追溯的檢索證據,減少“一本正經胡說八道”的幻覺風險。
但是,不少人提出RAG的“原罪”--一周出demo,半年用不好。這里主要存在如下5方面的問題:
問題1:內容缺失
當用戶問題不清晰或者知識庫未及時更新導致檢索內容缺失,LLM可能會無中生有地回答問題。
例如:用戶詢問“2025年杭州新能源車補貼政策”,但文檔庫僅更新至2024年數據,此時LLM卻生成“2025年補貼政策將延續現有標準”的錯誤答案。
問題2:未正確排序
問題的答案在知識庫中,但由于包含答案的文檔沒有被正確的排序,導致沒有在被召回的前K個文檔中(K在實際操作中不可能被設置的無限大,會基于大模型能力、成本等因素折中選擇一個值)。
例如:用戶查詢“阿司匹林與布洛芬的副作用差異”,知識庫中某篇研究論文第8頁明確對比了兩者差異,但該文檔在檢索排序中位列第12名(K=10),導致未被召回。
問題3:未在上下文中
整合策略局限性。從知識庫中檢索到了包含答案的文檔,但在生成答案的過程中,這些文檔并未被納入上下文。當返回許多文檔時,會進行文檔整合以獲取答案,此時會發生這種情況。
例如:用戶提問“青藏高原年平均降水量”,檢索到一篇地理研究報告包含該數據(第3章第2節),但系統整合時僅保留第1章氣候特征概述,導致答案缺失。
問題4:未提取答案
包含答案的文檔存在于上下文中,但LLM未能提取出正確的答案。通常,這是因為上下文中存在太多噪聲或矛盾信息。簡而言之,檢索是正確的,但是LLM根據檢索的文檔回答問題出錯。睜眼說瞎話的概率明顯大于用戶可以接受的概率(用戶一般只能接受0.1%的錯誤概率)。
例如:上下文明確標注“2024年全球光伏裝機容量為550GW”,但LLM受其他段落“2030年預測達1200GW”干擾,錯誤回答“當前裝機容量接近1000GW”。
問題5:答案不完整
包含答案的文檔存在于上下文中,但是LLM回答時也可能遺漏一些關鍵信息。
例如:上下文包含“火山噴發原因包括板塊運動、巖漿房壓力、地下水汽化”,LLM僅回答“板塊運動導致噴發”。
2. RAG分類
RAG的特點是依賴外部數據來準確解決用戶提出的問題,因此根據與外部數據的交互復雜度和認知處理深度,當前主流研究將RAG系統劃分為以下四個層次:
層次1:顯性事實查詢
此類用戶問題是外部數據中直接存在的明確事實,無需任何額外推理。
例如:根據給定的一系列關于奧運會的文檔,回答:2024年夏季奧運會將在哪里舉行?
層次2:隱性事實查詢
此類用戶問題是外部數據中的隱性事實,這些事實不是顯而易見的或者分布在多個文檔片段中,可能需要一定程度的常識推理或基本的邏輯推理。
例如:根據給定的一系列醫療記錄,回答:最常提及的前3個癥狀是什么?
層次3:可解釋原理查詢
對此類用戶問題的回答,不僅要求掌握事實內容,還需要理解和應用與數據上下文密不可分的領域特定原理的能力。這些原理通常在外部資源中明確提供,在一般大型語言模型的預訓練階段通常不存在或很少遇到。
例如:根據給定的胸痛管理指南,回答:應該如何診斷和治療有特定癥狀描述的胸痛患者?
層次4:隱式原理查詢
對此類用戶問題的回答涉及更具挑戰性的領域,其中原理沒有明確記錄,但必須從外部數據中觀察到的模式和結果中推斷出來。
例如:根據給定的一系列財務報告,回答:經濟形勢將如何影響公司未來的發展?
論文:https://arxiv.org/html/2409.14924?_immersive_translate_auto_translate=1
3. 產品架構
RAG產品架構包含四層:
- 模型層:在模型層屏蔽掉了模型的差異,不僅可以支持自有私域的LLM,也可以支持線上商用大模型,第三方的模型。此外,embedding的優化,有效的解決語言表達差異導致的檢索問題,同時提高了模型的效果;
- 離線理解層:該層主要圍繞知識庫和搜索增強兩個模塊設計的。關于智能知識庫主要負責將非結構化的文本進行處理,從而轉化為檢索知識庫,主要包括文本解析,表格讀取,OCR識別等。搜索增強通過引入問句改寫、重排等模塊,保證檢索的精準度;
- 在線問答層:為了滿足產品設計和交互體驗需要,這里支持多文檔、多輪次、多模態等;
- 應用層:針對不同行業的特點,預制多種場景類角色,降低產品使用門檻。
4. 技術架構
RAG技術框架分為三個主要組成部分:問題理解模塊、檢索召回模塊和答案生成模塊。
- 問題理解模塊:該模塊旨在對用戶的問題進行理解或者將用戶的問題生成結構化的查詢,既可以查詢結構化的數據庫也可以查詢非結構化的數據,進而提高召回率。該模塊主要包括意圖識別、問題改寫和問題擴寫;
- 檢索召回模塊:該模塊旨在從給定的知識庫中檢索與用戶問題最相關的信息。該模塊主要包括文檔加載、文檔轉換、文檔嵌入&檢索和文檔后處理;
- 答案生成模塊:該模塊旨在將檢索結果與原始問題整合后的增強提示詞輸入給LLM,讓LLM生成精準、可靠的答案。該模塊主要包括Prompt拼接和LLM生成策略。
4.1. 問題理解模塊
在RAG應用中,可能會遇到從知識庫中檢索到與用戶問題不相關的內容,這是由于:
- 用戶問題過于簡單,沒有更多的上下文信息;
- 用戶問題可能混雜無關內容;
- 用戶問題有模糊詞匯、歧義詞匯和縮寫詞;
- 用戶問題沒有生成結構化查詢。
為了解決上述問題,在RAG應用中可能需要引入問題理解模塊。
4.1.1. 意圖識別
對用戶問題進行意圖識別,解析出用戶問題的隱含需求,使RAG系統能自適應地組合檢索策略,平衡效率與精度。
核心方法如下:
- 數據源選擇優化
通過實體識別提取用戶問題中的關鍵要素(如產品型號、時間范圍),動態匹配對應領域的知識庫;
若問題包含視覺關鍵詞(如“CT影像分析”),自動切換到醫學圖像庫,文本類問題則調用文檔數據庫。
- 查詢策略決策
當用戶需求為宏觀概覽(如“概括新能源政策要點”),觸發摘要引擎對長文檔進行壓縮提取;
當用戶需要詳細的技術細節(如“如何修復手機充電接口接觸不良”),啟用向量索引進行深度語義匹配。
- 多路由協同執行
對開放式問題(如“人工智能發展趨勢分析”),同時調用行業報告庫、學術論文庫和新聞數據庫,合并檢索結果;
在金融風控場景中,既檢索合同條款庫又調用法律條文庫,綜合生成合規建議。
4.1.2. 問題改寫
對用戶問題進行語義等價的重構與優化,保持核心意圖不變,提升問題表達清晰度與檢索精準性。
核心方法如下:
- 同義詞替換:將口語化詞匯轉換為專業術語(如“蘋果手機”→“iPhone 15 Pro Max”);
- 消除歧義:通過上下文補全明確模糊表述(如“蘋果”補充為“蘋果公司產品”);
- 結構優化:拆分復合問題(如“Python安裝和數據分析”拆分為Python安裝和Python數據分析兩個子查詢)。
4.1.3. 問題擴寫
在原問題基礎上增加關聯信息或限定條件以擴展覆蓋范圍,提高檢索召回率與長尾信息覆蓋能力。
核心方法如下:
- 關鍵詞拓展:添加相關術語(如“學習Python”擴展為“Python編程教程+實戰項目資源”);
- 條件補充:增加時間/空間約束(如“新能源車續航”補充為“2024年特斯拉Model Y冬季續航數據”);
- 領域知識注入:融入專業參數(如“拍照好”擴展為“索尼IMX989傳感器+光學防抖”)。
4.2. 檢索召回模塊
本文只針對文本數據進行講解,多模態數據(圖像、音頻和視頻)的處理比較復雜,這里先不展開講。
4.2.1. 文檔檢索
在實際應用中,一般需要獲取到與用戶問題最相關的那些文檔數據,而不是將整個文檔全部檢索出來。因此檢索技術的選擇和實現就至關重要了,這個直接影響到RAG系統的應用效果。
不同的應用場景對應不同的檢索技術,主要有傳統RAG、GraphRAG以及DeepSearcher,傳統RAG和GraphRAG是成熟的范式,分別適合文檔檢索和關系查詢,而DeepSearcher代表未來方向,通過深度學習優化搜索過程,適合復雜、個性化的需求。
傳統RAG
傳統RAG適用于單點的事實查詢,采用的是扁平化的向量空間形式,讓信息之間的關系更加直觀,然后通過比較文本向量之間的相似度來找到最相關的信息。
這里的技術要求是如何將一個大型的文檔數據進行分割,以便可以更精確的檢索到與用戶問題相關的文檔片段,然后放到LLM的上下文中。常見的分割方法有:
- 遞歸分割 (Recursive):基于用戶定義的字符列表遞歸分割文本,旨在保持相關文檔片段相鄰。推薦作為初始分割方法;
- HTML 分割:基于HTML特定字符分割文本,并添加關于文本來源的元數據(基于HTML結構);
- Markdown 分割:基于Markdown特定字符分割文本,并添加關于文本來源的元數據(基于Markdown結構);
- 代碼分割:基于編程語言(如Python、JS等)特定字符分割文本,支持15種不同語言;
- 詞元分割 (Token):基于token分割文本,存在幾種不同的token測量方式;
- 字符分割 (Character):基于用戶定義的單個字符分割文本,是一種較為簡單的方法;
- 語義塊分割 (Semantic Chunker):首先按句子分割文本,然后如果相鄰句子在語義上足夠相似,則將它們合并。
文檔數據分割好了一個個小的片段之后,在使用文本嵌入模型(如 text-embedding-ada-002)將文本塊轉換成固定維度的向量,然后存儲到向量數據庫(如 Milvus)中。
文檔數據示例:
哪吒是一個天生反骨的少年英雄,具有雷電屬性,屬于闡教。
他的父親是李靖(陳塘關總兵),母親是殷夫人。
他的師父是太乙真人,是闡教弟子。
敖丙是東海三太子,具有冰雪屬性,屬于龍族。
...
GraphRAG
GraphRAG適用于需跨實體關聯的復雜問題,引入知識圖譜技術構建實體關系網絡,通過圖數據庫(如 NebulaGraph)實現多跳推理與結構化知識關聯。
該技術結合了圖結構的數據遍歷和路徑查詢技術,能夠更精準地定位相關信息,然后結合向量相似度檢索補充局部語義信息,形成混合結果集給到LLM。
這里的技術要求是要在傳統RAG的基礎之上構建知識圖譜:
- 實體與關系抽?。?/span>調用LLM識別文本塊中的實體(如人名、機構名)和關系(如因果關系、隸屬關系),輸出為(實體、關系、實體)三元組,然后對提取的實體生成抽象描述性摘要,解決實體引用不一致問題(如別名歸一化);
- 圖結構生成:構建同質無向加權圖(節點:表示實體,權重反映實體出現頻率與重要性,邊:表示關系,權重通過關系實例的標準化計數計算),然后通過圖數據庫(如 NebulaGraph)存儲圖譜數據,支持分布式擴展。
節點(VERTEX)數據示例:
INSERT VERTEX role (name, meteorological, faction, role_desc, voice_actor) VALUES
"哪吒": ("哪吒", "雷電", "闡教", "天生反骨的少年英雄", "呂艷婷"),
"敖丙": ("敖丙", "冰雪", "龍族", "東海三太子,哪吒的摯友", "瀚墨"),
"太乙真人": ("太乙真人", "云霧", "闡教", "哪吒的師父,闡教弟子", "張珈銘"),
"殷夫人": ("殷夫人", "細雨", "人類", "哪吒的母親,溫柔賢惠", "綠綺"),
"李靖": ("李靖", "木", "人類", "哪吒的父親,陳塘關總兵", "陳浩"),
"申公豹": ("申公豹", "風暴", "截教", "截教弟子,野心勃勃", "楊衛"),
"敖光": ("敖光", "海浪", "龍族", "東海龍王,敖丙之父", "雨辰"),
"敖閏": ("敖閏", "空間系", "龍族", "東海龍王之女", "周泳汐"),
"敖順": ("敖順", "毒", "龍族", "東海龍王之子", "韓雨澤"),
"敖欽": ("敖欽", "火", "龍族", "東海龍王之子", "南嶼"),
"石磯娘娘": ("石磯娘娘", "沙塵", "截教", "截教弟子", "小薇"),
"結界獸": ("結界獸", "霧靄", "中立", "守護結界的神獸", "");
邊(EDGE)數據示例:
// 家庭關系
INSERT EDGE father_of VALUES "李靖" -> "哪吒": (NOW());
INSERT EDGE mother_of VALUES "殷夫人" -> "哪吒": (NOW());
INSERT EDGE father_of VALUES "敖光" -> "敖丙": (NOW());
INSERT EDGE father_of VALUES "敖光" -> "敖閏": (NOW());
INSERT EDGE father_of VALUES "敖光" -> "敖順": (NOW());
INSERT EDGE father_of VALUES "敖光" -> "敖欽": (NOW());
// 師徒關系
INSERT EDGE teacher_of VALUES "太乙真人" -> "哪吒": (NOW());
// 朋友關系
INSERT EDGE friend_of VALUES "哪吒" -> "敖丙": (NOW());
INSERT EDGE friend_of VALUES "敖丙" -> "哪吒": (NOW());
// 敵對關系
INSERT EDGE enemy_of VALUES "申公豹" -> "太乙真人": (NOW());
INSERT EDGE enemy_of VALUES "申公豹" -> "哪吒": (NOW());
// 兄妹關系
INSERT EDGE brother_sister_of VALUES "敖丙" -> "敖閏": (NOW());
INSERT EDGE brother_sister_of VALUES "敖丙" -> "敖順": (NOW());
INSERT EDGE brother_sister_of VALUES "敖丙" -> "敖欽": (NOW());
DeepSearcher
DeepSearcher適用于需動態調整的多維度需求,通過樹形層次結構來組織數據,并逐步反饋迭代,使得查找特定信息時能夠像瀏覽文件夾一樣方便快捷。
該技術采用多層次并行搜索加上智能過濾的方式從大量數據中快速準確地獲取所需信息,然后結合多模態檢索(向量+關鍵詞+圖),最終得到最精準的信息。
分層數據示例:
# 角色基本信息
## 哪吒- 名稱: 哪吒- 屬性: 雷電- 陣營: 闡教- 描述: 天生反骨的少年英雄,擁有超凡的力量和勇氣- 配音: 呂艷婷- 性格特點: 叛逆不羈,重情重義,敢于挑戰命運
### 哪吒的關系網絡- 父親: 李靖(陳塘關總兵,嚴厲正直)- 母親: 殷夫人(溫柔慈愛,理解包容)- 師父: 太乙真人(循循善誘,關愛弟子)- 摯友: 敖丙(東海三太子,冰雪之力)- 敵人: 申公豹(截教弟子,處處作梗)
### 哪吒的劇情發展- 初遇敖丙: 在東海邊緣的相遇,兩個不同世界的少年- 修行歷程: 在太乙真人門下學習法術,逐漸掌握雷電之力- 友情萌芽: 與敖丙從互不理解到成為摯友- 身份困擾: 面對闡教弟子和凡人雙重身份的矛盾- 成長蛻變: 在各種挑戰中突破自我,尋找真我
### 哪吒的能力特點- 主要法術: 雷電操控,混天綾,乾坤圈- 戰斗風格: 靈活多變,攻擊凌厲- 特殊天賦: 天生具有超凡力量- 成長軌跡: 從初學者到掌握強大法力
## 敖丙- 名稱: 敖丙- 屬性: 冰雪- 陣營: 龍族- 描述: 東海三太子,溫潤如玉的貴族少年- 配音: 瀚墨- 性格特點: 溫和有禮,重情重義,內心堅韌
### 敖丙的關系網絡- 父親: 敖光(東海龍王,威嚴莊重)- 兄弟姐妹: - 敖閏(龍女,擅長空間法術) - 敖順(二皇子,精通毒術) - 敖欽(大皇子,掌控火焰)- 摯友: 哪吒(闡教弟子,雷電之力)- 屬下: 結界獸(守護東海結界)
### 敖丙的劇情發展- 身份困擾: 作為龍族繼承人的責任與壓力- 友情抉擇: 在族群立場與個人情誼間的掙扎- 能力覺醒: 冰雪之力的不斷提升與掌控- 性格成長: 從謹慎拘謹到開朗自信- 守護之道: 保護東海與親友的決心
### 敖丙的能力特點- 主要法術: 冰雪操控,水系法術- 戰斗風格: 優雅從容,防守反擊- 特殊天賦: 天生親和水元素- 成長軌跡: 從單純的王子到獨當一面
## 太乙真人- 名稱: 太乙真人- 屬性: 云霧- 陣營: 闡教- 描述: 闡教重要弟子,哪吒的師父- 配音: 張珈銘- 性格特點: 智慧通達,慈悲為懷
### 太乙真人的關系網絡- 弟子: 哪吒(得意門生)- 同門: 其他闡教仙人- 對手: 申公豹(截教弟子)
### 太乙真人的劇情參與- 收徒教導: 發現哪吒天賦,悉心培養- 化解危機: 多次調解哪吒與各方矛盾- 守護正道: 對抗截教勢力的滲透
# 陣營勢力分析
## 闡教- 代表人物: 太乙真人、哪吒- 特點: 崇尚正統,重視秩序- 立場: 維護天地秩序,抵制混亂- 修行特色: 注重心性修養,講究循序漸進
### 闡教的理念- 修行觀: 重視內在修養- 處世態度: 主動干預,匡扶正義- 對待人間: 既重視規則,也關注個體
## 龍族- 代表人物: 敖光、敖丙- 特點: 高貴優雅,重視傳統- 立場: 守護東海,維護龍族利益- 統治方式: 等級分明,講究禮制
### 龍族的傳統- 治理理念: 重視血脈傳承- 對外態度: 謹慎自守,避免沖突- 內部規則: 等級森嚴,重視禮法
## 截教- 代表人物: 申公豹- 特點: 包容駁雜,手段靈活- 立場: 追求變革,不拘一格- 行事風格: 靈活多變,善用權謀
### 截教的特點- 修行方式: 講究實用- 處世態度: 積極進取,不拘形式- 發展策略: 廣收門徒,擴張勢力
# 重要事件與劇情發展
## 東海危機### 事件起因- 結界異常- 勢力沖突- 個人恩怨
### 事件發展- 哪吒與敖丙的相遇- 各方勢力的介入- 矛盾的激化與升級
### 事件影響- 個人成長- 勢力變化- 關系轉變
## 人物關系演變### 友情的考驗- 立場差異- 信任建立- 共同成長
### 師徒情誼- 教導方式- 互相理解- 成長蛻變
4.2.2. 檢索后處理
經過前面的檢索過程可能會得到很多相關文檔,就需要進行篩選和排序。常用的篩選和排序策略包括:
- 基于相似度分數進行過濾和排序;
- 基于關鍵詞進行過濾,比如限定包含或者不包含某些關鍵詞;
- 讓 LLM 基于返回的相關文檔及其相關性得分來重新排序;
- 基于時間進行過濾和排序,比如只篩選最新的相關文檔;
- 基于時間對相似度進行加權,然后進行排序和篩選。
4.3. 答案生成模塊
檢索召回模塊基于用戶問題檢索出相關的文檔片段,答案生成模塊則是讓LLM利用檢索出的相關信息來生成對用戶問題的回復。該模塊依賴于LLM的能力以及prompt的拼接和調試。
4.3.1. Prompt拼接
用于將提示的不同部分組合在一起。您可以使用字符串提示或聊天提示來執行此操作。
- 字符串提示:使用模板將所有查詢到的文檔片段和原始問題拼接在一起作為提示(如 langchain 的promptTemplate);
- 聊天上下文提示:將歷史對話記錄、用戶偏好等上下文信息、所有查詢到的文檔片段和原始問題拼接在一起作為提示(如 langchain 的 ChatPromptTemplate)。
4.3.2. LLM生成策略
- 策略1:是依次結合每個檢索出的相關文檔片段,每次不斷修正生成的回復。這樣的話,有多少個獨立的相關文檔片段,就會產生多少次的LLM調用;
- 策略2: 是在每次LLM調用時,盡可能多地在Prompt中填充文檔片段。如果一個Prompt中填充不下,則采用類似的操作構建多個Prompt,多個Prompt的調用可以采用和前一種相同的回復修正策略。