利用 MongoDB Atlas 的向量搜尋功能,結合 LangChain 和 OpenAI,可以有效率地建構 RAG 應用。首先,將資料文字嵌入向量化後儲存至 MongoDB,接著運用 LangChain 簡化向量搜尋流程,並結合 OpenAI 的大語言模型,實作根據語義相似度的檔案檢索和問答系統。透過調整提示工程技巧,可以更精準地控制模型輸出,滿足不同應用場景的需求。此方法有效提升了資訊檢索效率,並降低了開發成本。

步驟2:計算嵌入

接下來,我們需要計算每個文字的嵌入(embedding)。由於 玄貓 的API有速率限制,我們需要將資料分成小批次進行處理。每個批次的大小為100。

step = int(np.ceil(df['final'].shape[0]/100))
embeddings_t = []
lines = []

for x, y in list(map(lambda x: (x, x+step), list(range(0, df.shape[0], step)))):
    lines += [df.final.values[x:y].tolist()]

for i in tqdm(lines):
    embeddings_t += openai.embeddings.create(
        model='text-embedding-ada-002', input=i).data

步驟3:提取嵌入

然後,我們需要從API的回應中提取嵌入資料。

out = []
for ele in embeddings_t:
    out += [ele.embedding]

步驟4:儲存嵌入

最後,我們需要將提取的嵌入資料儲存回原始的DataFrame中。

df['embedding'] = out

步驟5:初始化MongoDB Atlas

現在,我們需要初始化MongoDB Atlas並插入資料到集合中。

from pymongo import MongoClient
import os
mongo_client = MongoClient(os.environ["MONGODB_CONNECTION_STR"])
output_collection = mongo_client["sample_movies"]["embed_movies"]

步驟6:插入資料

最後,我們可以將資料插入到MongoDB集合中。

output_collection.insert_many(df.to_dict('records'))

圖表翻譯:

以下是使用Mermaid語法繪製的流程圖,描述了上述步驟的執行流程。

  flowchart TD
    A[準備資料] --> B[計算嵌入]
    B --> C[提取嵌入]
    C --> D[儲存嵌入]
    D --> E[初始化MongoDB Atlas]
    E --> F[插入資料]

內容解密:

上述程式碼的作用是計算文字的嵌入,並將其儲存到MongoDB集合中。這個過程包括了資料的準備、嵌入的計算、嵌入的提取、儲存嵌入、初始化MongoDB Atlas和插入資料等步驟。每個步驟都非常重要,缺少任何一步驟都可能導致最終結果的錯誤。

建立向量搜尋索引

在上一步驟中,我們已經將測試資料匯入 MongoDB Atlas,以建立向量搜尋功能。現在,讓我們建立向量搜尋索引。

建立向量索引定義

首先,我們需要建立向量索引定義。這可以在 MongoDB Atlas Vector Search UI 中完成。所需的向量索引定義如下:

{
  "fields": [
    {
      "type": "vector",
      "numDimensions": 1536,
      "path": "embedding",
      "similarity": "cosine"
    },
    {
      "type": "filter",
      "path": "year"
    }
  ]
}

一旦向量索引定義被新增到 MongoDB Atlas UI 中,向量搜尋索引就會被建立在指定的路徑欄位中。

執行向量搜尋查詢

現在,我們可以使用 $vectorSearch 查詢 MongoDB 向量索引。MongoDB Atlas 提供了使用向量搜尋和搜尋過濾器的靈活性。此外,我們可以使用聚合管道應用範圍、字串和數值過濾器。

以下程式碼示範如何執行向量搜尋查詢,同時對 year 欄位進行預過濾,以取得 1990 年後發布的電影:

def query_vector_search(q, prefilter={}, postfilter={}, path="embedding", topK=2):
    #...
    vs_query = {
        "index": "default",
        "path": path,
        "queryVector": query_embedding,
        "numCandidates": 10,
        "limit": topK,
    }
    if len(prefilter) > 0:
        vs_query["filter"] = prefilter
    #...
    new_search_query = {"$vectorSearch": vs_query}
    project = {"$project": {"score": {"$meta": "vectorSearchScore"}, "_id": 0, "title": 1, "release_date": 1, "overview": 1, "year": 1}}
    #...
    res = list(output_collection.aggregate([new_search_query, project]))
    return res

# 範例查詢
query_vector_search("I like Christmas movies, any recommendations for movies release after 1990?", prefilter={"year": {"$gt": 1990}}, topK=5)

這個查詢會傳回 1990 年後發布的電影,同時考慮向量相似度。

使用 LangChain 進行向量搜尋

LangChain 提供了一個簡單的方式來使用 MongoDB Atlas Vector Search 建立語義相似度檢索器。以下示範如何使用 LangChain 進行向量搜尋:

from langchain_mongodb.vectorstores import MongoDBAtlasVectorSearch
from langchain_openai import OpenAIEmbeddings

import json
embedding_model = OpenAIEmbeddings(model="text-embedding-ada-002")
vector_search = MongoDBAtlasVectorSearch(output_collection, embedding_model, text_key='final')

這個例子展示瞭如何使用 LangChain wrapper 類別來建立向量搜尋功能。

建立RAG架構系統

在現代商業的快速變化中,企業不斷追求效率和準確性,導致自動化技術成為核心。然而,傳統方法在面對大量複雜資料時往往難以應對,人工介入則容易產生錯誤。因此,瞭解RAG(Retrieval-Augmented Generation)架構的重要性便浮現出來。

RAG架構的組成

  1. 檔案載入:首先從資料儲存中載入檔案,包括文字提取、解析、格式化和清理,以準備檔案分割。
  2. 檔案分割:將檔案分割成較小、可管理的段落或塊。分割策略可以從固定大小的塊到內容感知的分割,考慮內容結構。
  3. 文字嵌入:使用OpenAI嵌入、句子嵌入等技術將檔案塊轉換為向量表示。這一步對於理解塊的語義內容至關重要。
  4. 向量儲存:生成的向量與檔案塊一起儲存在向量儲存中,連同其他從MongoDB Atlas集合中提取的檔案塊和相關資料。
  5. 查詢處理:當使用者提交查詢時,查詢也被轉換為向量表示,使用與步驟3相同的嵌入技術。
  6. 檔案檢索:檢索元件定位和擷取語義上與查詢相似的檔案塊。這個過程使用向量相似度搜尋技術和MongoDB Atlas的HNSW演算法,快速找到鄰近的向量而不犧牲搜尋結果的準確性。
  7. 檔案塊後過濾:相關檔案塊從MongoDB集合中檢索,並可以輕易地後過濾以轉換輸出檔案塊為所需格式。
  8. LLM提示建立:檢索的檔案塊和查詢結合以建立LLM的上下文和提示。
  9. 答案生成:最終,LLM根據提示生成回應,完成RAG過程。

RAG系統型別

  • 簡單RAG:實作了一種天真的方法,根據查詢的相似度從知識函式庫中檢索固定數量的檔案。這些檔案與查詢一起輸入語言模型以生成回應。
  • 高階RAG:根據具體工作流程和使用者群體的需求,選擇合適的RAG型別。

建立RAG架構系統的關鍵點

  • 工作流程特異性:定義要自動化的具體工作流程,可能與問答、資料增強、摘要、推理或斷言相關。
  • 使用者經驗:與目標使用者群體合作,以瞭解他們可能提出的查詢型別,從而確定使用者旅程。
  • 資料來源:識別資料來源的性質(結構化或非結構化),並將其對映到位置。然後,根據是否為操作或分析目的進行分類別,並觀察資料模式以確定答案是否容易獲得或需要從多個來源聚合。

檔案分割策略

檔案分割是RAG系統中的一個關鍵步驟,尤其是在處理大型檔案時。有多種分割策略可供選擇,包括:

  • 遞迴分割:遞迴地將輸入文字分割成較小的塊,使用不同的分隔符或標準。
  • 句子分割:使用基本標點符號(如句號和新行)或更先進的NLP函式庫(如spaCy和NLTK)進行句子分割。
  • 結構化內容:針對具有特定格式(如Markdown或LaTeX)的檔案,使用專門的技術。

使用LangChain建立簡單RAG應用

以下示範如何使用LangChain和OpenAI API建立一個簡單的RAG應用。這個應用使用前面載入到MongoDB Atlas集合中的資料集,並允許對可用的電影進行查詢和推薦。

from openai import OpenAI
client = OpenAI()

def invoke_llm(prompt, model_name='gpt-3.5-turbo-0125'):
    # 實作LLM邏輯
    pass

瞭解Prompt的重要性

在與大語言模型(LLM)互動時,prompt扮演著至關重要的角色。它是使用者提供的指令或輸入,引導模型的回應。一個好的prompt應該是清晰、具體和結構化的,以便能夠有效地將使用者的意圖傳達給LLM,從而生成最準確和最有用的回應。

結論:建構根據向量資料函式庫的 RAG 系統,實作高效知識檢索與應用

隨著資料量的爆炸式增長,傳統的關鍵字搜尋已無法滿足企業對知識檢索的效率和精準度要求。本文深入探討瞭如何利用 MongoDB Atlas 向量資料函式庫和 LangChain 框架構建 RAG 系統,實作根據語義理解的知識檢索和應用。透過 OpenAI 嵌入模型將文字轉換為向量,並結合 HNSW 索引演算法,大幅提升了搜尋效率。同時,LangChain 的整合簡化了開發流程,降低了技術門檻。

然而,向量資料函式庫的建置並非一蹴可幾。資料的清洗、分割策略的選擇、向量維度的設定等都會影響最終的搜尋效果。此外,LLM 提示的設計也至關重要,一個清晰、具體且結構化的提示才能引導模型生成準確的答案。目前,RAG 系統的應用仍面臨一些挑戰,例如計算資源的消耗、模型的偏差以及資料的隱私安全等。

展望未來,隨著向量資料函式庫技術的持續發展和 LLM 模型的效能提升,RAG 系統的應用場景將更加廣泛。預計未來 3-5 年內,RAG 系統將成為企業知識管理的核心元件,並在智慧客服、商業分析、決策支援等領域發揮更大的價值。對於企業而言,及早佈局向量資料函式庫技術,探索 RAG 系統的最佳實踐,將有助於提升競爭力並在數位化轉型中取得領先地位。玄貓認為,結合向量資料函式庫和 LLM 的 RAG 架構代表了未來知識檢索和應用的主流方向,值得企業深入研究和應用。