RAG 示例:使用 langchain、Redis、llama.cpp 構建一個 kubernetes 知識庫問答

凌虚發表於2024-11-19

RAGRetrieval Augmented Generation 檢索增強生成)是目前業界中的一種主流方法,透過增加額外知識的方式來減少大語言模型(LLM)的幻覺問題(一本正經的胡說八道)。

RAG 系統概覽

如上圖所示,RAG 系統可以分為兩個部分:

  • Indexing:構建知識庫。
  • Retrieval & Generation:從知識庫中獲取相關資訊,然後生成結果。

Indexing 構建知識庫的過程可以分為四步:

  1. Load:載入 PDF、doc、markdown、web 等等形式的知識資料。
  2. Split:由於 LLM 上下文大小的限制,需要將文件進行切割。
  3. Embedding:將文字轉換為向量。
  4. store to VectorDB:將文字內容和向量儲存至向量資料庫,即知識庫。

Retrieval & Generation 的過程也是四步:

  1. Embedding:將使用者提出的問題轉換為向量。
  2. search VectorDB:從知識庫中查詢與問題語義相近的文字段落。
  3. prompt:將檢索出來的文字段落與使用者問題合併,生成 prompt。
  4. LLM:將 prompt 提交給大語言模型,得到最終答案。

從上述過程中可以看到,相較於直接把問題提交給 LLM 得到答案,RAG 系統額外構建了一個知識庫,並且會把問題跟已有知識相結合,生成新的 prompt 後再提交給 LLM 得到答案。
換句話說,RAG 系統就是在使用者提出的問題之外,額外增加了一些上下文/背景資訊,這些資訊可以是實時資訊、也可以是專業領域資訊,以此從 LLM 得到更好的回答。

RAG 系統示例

在本示例中,我將使用 langchainRedisllama.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,選擇哪種模型?
  • 選擇哪個向量資料庫?常見的技術選型問題。
  • 如何將檢索出來的資訊與使用者提問一起合併成新的 promptprompt 本來就可以五花八門。
  • 選擇哪個 LLM 以及執行時?就模型而言,Llama 系列算是最火的開源模型了;而執行時則有 llama.cpp(或者在其之上封裝的 Ollama)、HuggingFace/transformersvLLM 等等。

總結

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...

相關文章