RAG,讓模型讀你的資料
從零搭一個檢索增強生成系統:切分文件、向量檢索、關鍵詞檢索、查詢改寫、重排、帶引用的回答和評估,最後讓 RepoBot 讀懂 httpx 的文件。
各課
- 01為什麼需要 RAG
同一個問題,不給資料時模型答錯,把相關的一段文件放進提示詞後就答對了。講清楚 RAG 的基本流程、它解決什麼問題,以及它不適合的場景。
25 分鐘 · 進階 - 02文件切分
用 httpx 的文件實際比較三種切分方法:按固定長度、按標題、按標題並限制長度。還會遇到一個真實的坑:程式碼塊裡的註釋被當成了標題。
35 分鐘 · 進階 - 03從零寫一個向量檢索
用 numpy 寫一個幾十行的向量檢索:把文件塊變成向量矩陣,查詢時算相似度取前幾名。再用 20 道題評估它,結果只有一半能找對,看看問題出在哪。
45 分鐘 · 進階 - 04混合檢索和重排
從零寫一個 BM25 關鍵詞檢索,用 RRF 把它和向量檢索融合,先把中文問題改寫成英文檢索詞,最後加一個重排模型。每一步都用同一套 20 道題量化效果。
50 分鐘 · 進階 - 05帶引用的回答
把檢索到的文件塊編號交給模型,要求它每句話註明出處、資料裡沒有就說沒有。再用程式檢查引用是否有效,並看看它在文件沒有答案的問題上會不會編。
35 分鐘 · 進階 - 06怎麼知道 RAG 好不好
把 RAG 的評估拆成檢索和回答兩半。檢索看命中率,回答讓另一個模型當評委,對照參考答案判斷對錯、對照資料判斷是否忠實。評委判了 60 次,我逐條核對,發現它自己也會錯。
45 分鐘 · 進階 - 07專案:讓答疑助手讀懂專案文件
把切分、混合檢索、查詢改寫、帶引用的回答裝進 RepoBot,做出 v2。它在 v1 答錯的問題上答對了,還解決了多輪對話裡"那非同步呢"這種追問的檢索問題。
60 分鐘 · 進階
RepoBot v1 答錯了"httpx 預設會不會跟隨重定向",還編了一段版本歷史。這個模組解決這個問題:讓它在回答之前,先去 httpx 的官方文件裡找到相關的段落,照著文件回答,並告訴使用者出處。
整個模組幾乎不用框架。切分、向量檢索、BM25、融合、引用檢查,都是自己寫的,每個幾十行。所有檢索方法都用同一套 20 道題評估,你會看到每加一樣東西,數字具體變了多少。其中有些結果和常見的說法不一樣,比如在我們的資料上,混合檢索並沒有比單用關鍵詞檢索更好,最大的提升來自一次便宜的查詢改寫。
為什麼是這個順序
第 1 課先用一個手動的例子證明"給資料就能答對",並講清楚 RAG 的流程和適用範圍。第 2 到 4 課按流程的順序,把"找資料"這一步做好:先切分,再檢索,再改進檢索。第 5 課處理"用資料"這一步:讓模型帶著引用回答,不知道時老實說不知道。第 6 課評估整個系統,不只是檢索,還有回答本身。第 7 課把這些裝進 RepoBot。
學完的標準
- 能按文件的結構切分,並能發現和修正切分中的問題(比如程式碼塊被切斷)。
- 不用任何框架,寫出向量檢索和 BM25,並用 RRF 把它們融合。
- 能為自己的文件準備一套檢索評估題,算出命中率和 MRR,並據此選擇檢索方法。
- 能讓模型只根據檢索到的資料回答、註明出處,並用程式檢查引用是否有效。
- RepoBot v2 能正確回答 v1 答錯的問題,並給出文件來源。
本模組的程式碼
程式碼和執行結果保留原樣(簡體中文),與實際執行時完全一致。
- code/04-rag/chunking.py
- code/04-rag/citations.py
- code/04-rag/eval_qa.jsonl
- code/04-rag/hybrid.py
- code/04-rag/rag_eval_results.json
- code/04-rag/rag_eval.py
- code/04-rag/rerank.py
- code/04-rag/rewrites.json
- code/04-rag/vector_search.py
- code/04-rag/why_rag.py
- projects/repobot/v2/eval_qa.jsonl
- projects/repobot/v2/eval_retrieval.py
- projects/repobot/v2/llm.py
- projects/repobot/v2/README.md
- projects/repobot/v2/repobot.py
- projects/repobot/v2/requirements.txt
- projects/repobot/v2/retrieval.py