RAG
(Retrieval Augmented Generation
檢索增強生成)是目前業界中的一種主流方法,透過增加額外知識的方式來減少大語言模型(LLM
)的幻覺問題(一本正經的胡說八道)。
RAG 系統概覽
如上圖所示,RAG
系統可以分為兩個部分:
Indexing
:構建知識庫。Retrieval & Generation
:從知識庫中獲取相關資訊,然後生成結果。
Indexing
構建知識庫的過程可以分為四步:
Load
:載入 PDF、doc、markdown、web 等等形式的知識資料。Split
:由於LLM
上下文大小的限制,需要將文件進行切割。Embedding
:將文字轉換為向量。store to VectorDB
:將文字內容和向量儲存至向量資料庫,即知識庫。
Retrieval & Generation
的過程也是四步:
Embedding
:將使用者提出的問題轉換為向量。search VectorDB
:從知識庫中查詢與問題語義相近的文字段落。prompt
:將檢索出來的文字段落與使用者問題合併,生成 prompt。LLM
:將 prompt 提交給大語言模型,得到最終答案。
從上述過程中可以看到,相較於直接把問題提交給 LLM
得到答案,RAG
系統額外構建了一個知識庫,並且會把問題跟已有知識相結合,生成新的 prompt
後再提交給 LLM
得到答案。
換句話說,RAG
系統就是在使用者提出的問題之外,額外增加了一些上下文/背景資訊,這些資訊可以是實時資訊、也可以是專業領域資訊,以此從 LLM
得到更好的回答。
RAG 系統示例
在本示例中,我將使用 langchain
、Redis
、llama.cpp
構建一個 kubernetes
知識庫問答。
langchain
是一個工具包,Redis
被我用作向量資料庫,llama.cpp
是一個開源的載入大語言模型的執行時程式。
我在本地使用了 Docker 容器環境進行開發,透過以下 docker-compose 檔案拉取依賴的服務:
version: "3.9"
services:
redis:
image: redis/redis-stack:7.4.0-v1
container_name: redis
ports:
- "6379:6379" # 對映 Redis 預設埠
- "8001:8001" # 對映 RedisInsight 預設埠
llama_cpp_server:
image: ghcr.io/ggerganov/llama.cpp:server
container_name: llama_cpp_server
ports:
- "8080:8080"
volumes:
- ~/ai-models:/models # 對映主機路徑到容器
environment:
LLAMA_ARG_MODEL: /models/llama3.2-1B.gguf
LLAMA_ARG_CTX_SIZE: 4096
LLAMA_ARG_HOST: "0.0.0.0"
LLAMA_ARG_PORT: 8080
程式碼示例如下:
程式碼釋義:
- 載入文件:使用
langchain
抓取kubernetes
官方文件頁面內容。 - 切割文件:使用
langchain
切割文件。 向量化:使用
sentence_transformers
將文字轉換為向量:from sentence_transformers import SentenceTransformer sentences = ["This is an example sentence"] model = SentenceTransformer('sentence-transformers/all-mpnet-base-v2') embeddings = model.encode(sentences) print(embeddings)
- 儲存至向量資料庫:將文字和向量儲存至
Redis
,你也可以使用其它向量資料庫。 - 使用者提問向量化:使用同樣的模型將使用者提出的問題轉換為向量。
- 向量相似性檢索:從向量資料庫中檢索出與提問相似的文字段落。
- 組合生成
prompt
:將檢索出來的資訊與使用者提問一起合併生成新的prompt
。 - 將
prompt
提交給LLM
得到答案。
最終的測試結果如下:
可以看到,加了上下文之後,LLM
給出的答案更好了。
RAG 面臨的挑戰
RAG
的每一步幾乎都面臨挑戰:
- 如何載入不同形式的文件資料?這一步問題倒不大。
- 如何切割文件?切割的效果影響了
prompt
的上下文資訊,因此也會影響LLM
生成的結果。 - 如何做
embedding
,選擇哪種模型? - 選擇哪個向量資料庫?常見的技術選型問題。
- 如何將檢索出來的資訊與使用者提問一起合併成新的
prompt
?prompt
本來就可以五花八門。 - 選擇哪個
LLM
以及執行時?就模型而言,Llama
系列算是最火的開源模型了;而執行時則有llama.cpp
(或者在其之上封裝的Ollama
)、HuggingFace/transformers
、vLLM
等等。
總結
RAG
系統透過引入知識庫,擴充套件了 LLM
對專業領域和實時資訊的支援能力,使其在回答專業問題時更加準確高效。
(我是凌虛,關注我,無廣告,專注技術,不煽動情緒,歡迎與我交流)
參考資料:
- https://python.langchain.com/docs/tutorials/rag/
- https://huggingface.co/sentence-transformers/all-mpnet-base-v2
- https://github.com/ggerganov/llama.cpp/blob/master/examples/server/README.md
- https://redis.io/docs/latest/develop/interact/search-and-quer...