[AI] RAG 實作會踩到的雷與解法
前言
這陣子 LLM 應用紅翻天,其中最實用也最常被拿來解決「幻覺」(Hallucination)問題的,大概就是 RAG(Retrieval Augmented Generation,檢索增強生成)了。白話來說,就是讓 LLM 在回答問題前,先去參考一些「課外讀物」,這樣它就比較不會憑空捏造,回答也能更精確。
RAG 聽起來很美好,架構圖看起來也好像很直觀,但實際下去做,你會發現裡面眉角超多,一不小心就踩到雷。我最近在玩 RAG 應用也遇到不少坑,今天就來跟大家分享一下,實作 RAG 會碰到哪些常見問題,以及一些我整理出來的實戰解法。
RAG 的基本流程,我們快速複習一下
為了確保大家在同一個頻道上,我們先用一張圖快速回顧一下 RAG 的基本流程。其實就是三大塊:
- 資料準備(Ingestion):把你的原始文件(PDF、網頁、資料庫內容等等)切成小塊(Chunk),然後轉成向量(Embedding),存到向量資料庫裡。
- 檢索(Retrieval):使用者提問後,把問題轉成向量,去向量資料庫裡找出最相關的「小塊」(也就是前面切好的 Chunk)。
- 生成(Generation):把使用者問題跟找出來的相關資料,一起餵給 LLM,讓 LLM 根據這些資料來生成答案。
1 | graph TD |
好,概念清楚了,那我們來看看實作上最容易卡關的地方在哪裡。
第一雷:文件處理不當,Embedding 效果差
這是 RAG 的基石,如果這邊沒做好,後面怎麼補救都有限。
踩雷點
- Chunking 策略沒想清楚:文件切太大,LLM Context Window 塞不下或噪音太多;切太小,語意破碎,LLM 讀不懂前後文。
- PDF 轉文字的坑:PDF 檔案結構複雜,轉出來的文字可能斷行錯誤、表格亂掉、文字順序錯亂,導致 Embedding 亂七八糟。
- 忽略 Metadata:沒有把資料的來源、建立時間、作者等資訊存下來,後面篩選就沒辦法用。
解法
- 多樣化的 Chunking 策略:
- 固定大小重疊(Fixed-size with overlap):最簡單,固定字數切,保留一點重疊部分確保語意連貫。例如
chunk_size=500, chunk_overlap=50。 - 語意切割(Semantic Chunking):用 LLM 或其他模型判斷語意段落再切,保持每個 Chunk 的完整語意。這比較進階,但效果通常更好。
- 父子 Chunking(Parent-Child Chunking):儲存兩種 Chunk,一種是小而精確的 Chunk 用來檢索,另一種是包含更多前後文的「父 Chunk」給 LLM 閱讀。這樣可以兼顧檢索效率和 LLM 的理解力。
- 固定大小重疊(Fixed-size with overlap):最簡單,固定字數切,保留一點重疊部分確保語意連貫。例如
- 高品質的文件前處理:
- 針對 PDF,試試不同的函式庫(如
pypdf,unstructured)或服務,看看哪個轉文字效果最好。記得人工檢查幾份。 - 清理多餘空白、特殊符號、合併斷裂的句子。
- 針對 PDF,試試不同的函式庫(如
- 善用 Metadata:
- 在 Embedding 時,將 Chunk 的來源、主題、章節、時間等資訊一併存入向量資料庫。這對於後續的精準檢索超級重要。
第二雷:檢索策略不夠聰明,召回率低
就算你的 Chunking 完美,如果檢索邏輯不夠力,一樣找不到對的資料。
踩雷點
- 只用單純的 Top-K 向量搜尋:這種方式容易受到 Embedding 模型的限制,有時候語意上很相關的詞,實際向量距離可能沒那麼近。
- 沒有考慮使用者意圖:使用者可能問「2023 年財報」,但你的檢索只會找「財報」,而忽略了時間限制。
- 關鍵字和語意搜尋的取捨:有些問題很適合關鍵字(例如找產品型號),有些適合語意(例如問概念)。只用其中一種會偏廢。
解法
- **Metadata Filtering (前過濾)**:結合向量搜尋和結構化篩選。例如,先用 Metadata 篩選出「2023 年」且「文件類型是財報」的資料,再對這些資料做向量搜尋。
1
2
3
4
5
6
7# 範例:先篩選出2023年的「財報」文件,再做向量搜尋
query_embedding = embedding_model.embed(user_query)
results = vector_db.search(
query_embedding,
filter={'year': 2023, 'doc_type': 'financial_report'},
top_k=10
) - 混合搜尋(Hybrid Search):同時利用關鍵字搜尋(如 BM25、Elasticsearch)和向量搜尋。兩者各有優勢,結合起來效果更好。常見做法是將兩邊的結果加權合併。
- Reranking(重排序):在檢索出 Top-K 的結果後,再用一個更精準(但通常也更慢)的模型(如 Cohere Rerank、Sentence Transformers)對這些結果進行二次排序,把最相關的 Chunk 往前排。
- Multi-query / Query Expansion:讓 LLM 自己對原始問題進行多角度改寫(例如把「今年公司營收如何?」改成「2024年公司營收報告」、「公司財務表現」等),再用這些多個問題去檢索,增加召回率。
第三雷:Prompt 設計不良,LLM 回答走鐘
即使你給了 LLM 最好的資料,Prompt 沒寫好,它還是可能給你亂七八糟的答案。
踩雷點
- Prompt 太籠統:沒有明確指示 LLM 該怎麼利用這些檢索到的資料。
- 沒有要求引用來源:LLM 有時候會自己腦補一些內容,但又說不出來源。
- 溫度(Temperature)設定不對:太高容易發散,太低又可能太死板。
解法
- 明確的系統指令(System Prompt):告訴 LLM 你的角色和預期的行為。例如:
1
你是一個專業的知識顧問,請根據我提供的「參考資料」來回答問題。如果參考資料中沒有足夠的資訊,請禮貌地說明資料不足。回答時請引用參考資料的段落或標題。
- 具體的使用者指令(User Prompt):在每次提問時,清楚告知 LLM 哪些是問題,哪些是參考資料,以及希望的輸出格式。
1
2
3
4
5
6
7參考資料如下:
--- START REFERENCE ---
{retrieved_chunks_here}
--- END REFERENCE ---
請根據上面的參考資料,回答以下問題:「{user_question}」
回答時請務必從參考資料中提取資訊,並標註來源。如果資料不足,請直接說明。你的回答必須簡潔扼要。 - 調整 Temperature:對於需要精確事實的 RAG 應用,建議將 Temperature 設得低一些(例如
0.1到0.5),減少模型「創造」的機會。
第四雷:效能與成本考量
RAG 應用實際跑起來,錢跟時間都是考量點。
踩雷點
- Embedding 速度慢或成本高:每次文件更新或新增都要重新 Embedding,如果資料量大,會花很多時間和錢。
- 向量資料庫查詢慢:資料量爆炸性增長,查詢延遲飆高。
- LLM API 費用:檢索到的 Chunk 太多,塞給 LLM 的 Context Window 太長,Input Token 成本飆升。
解法
- Embedding 批次處理與快取:
- 將多個 Chunk 組合成一個批次(Batch)送去 Embedding 模型,通常會比單個送效率高。
- 已經 Embedding 過的 Chunk 存起來,避免重複計算。可以用 Hash 值來判斷 Chunk 是否變更。
- 選擇適合的 Embedding 模型:
- 不一定都要用最貴或最大的模型。評估你的應用場景,選擇性價比高的開源模型或較便宜的商用模型。
- 快取檢索結果:
- 對於頻繁出現的相同問題,可以快取檢索到的 Chunk 甚至 LLM 的生成結果。
- 最佳化檢索結果數量:
- 透過 Reranking 或更精準的檢索策略,確保只將最相關的少量 Chunk 傳給 LLM,減少 LLM 的 Input Token 量。
第五雷:評估與監控,不知道 RAG 到底好不好用
部署上去了,怎麼知道你的 RAG 表現如何?這是一個持續優化的過程。
踩雷點
- 沒有明確的評估指標:不知道 RAG 的答案「準不準」、「有沒有幻覺」、「跟不跟資料」。
- 缺乏使用者回饋機制:沒有辦法收集到使用者對答案滿不滿意的資訊。
解法
- 建立 RAG 評估指標:
- 忠實性(Faithfulness):LLM 的答案有多少內容是來自檢索到的資料?(避免幻覺)
- 答案相關性(Answer Relevance):LLM 的答案是否真的回答了使用者的問題?
- 上下文相關性(Context Relevance):檢索到的資料 Chunk 是否真的跟使用者的問題相關?
- 這些指標可以透過人工評分,或是用另一個 LLM 來輔助評估(例如用 GPT-4 判斷 GPT-3.5 的回答)。
- A/B 測試不同的 RAG 策略:
- 當你調整了 Chunking、檢索或 Prompt 策略後,用 A/B 測試比較不同版本的效果,用數據說話。
- 使用者回饋機制:
- 在應用介面提供「讚/爛」按鈕或意見回饋表單,直接收集使用者對答案的滿意度,這是最直接的優化方向。
小結
RAG 應用看似只是把檢索和生成串起來,但實際魔鬼藏在細節裡。從文件處理、檢索策略、Prompt 設計到效能和評估,每個環節都充滿了優化的空間。
一開始你可能會覺得很挫折,但別灰心,這些問題都是可以透過持續測試、調整和學習來解決的。掌握了上面這些踩雷點和解法,相信你的 RAG 應用會變得更穩健、更聰明,也能提供更可靠的資訊給使用者!
希望這篇對正在開發 RAG 應用的你有所幫助,我們下篇文章見囉!
本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Hikari 的工程筆記!
如果您喜歡我寫的文章,幫我按個5下讚吧!感謝您的鼓勵和支持!
評論



![[AI] RAG 實作會踩到的雷與解法](/img/covers/rag-pitfalls-and-solutions.jpg)
![[後端] 資料庫交易與隔離等級白話講:為什麼你轉帳不能只做一半?](/img/covers/database-transaction-isolation-level-explained.jpg)