根據大語言模型(LLM)的檢索增強生成(RAG)技術已成為提升資訊檢索效率的重要手段。本文介紹如何結合Hugging Face的Llama模型與Chroma向量資料函式庫,構建一個動態RAG系統,用於特定科學主題的問答和資訊檢索。系統利用SciQ資料集進行訓練,並透過向量化技術實作高效的相似度搜尋。文章將探討資料預處理、向量嵌入、查詢最佳化、效能評估以及即時查詢等關鍵環節,並提供程式碼範例和技術細節說明,以幫助讀者理解和應用動態RAG技術。
強化檢索系統的動態生成技術整合與實作
前言
本章節將探討如何將準備好的資料集整合到檢索系統中,利用查詢增強技術來提升針對特定科學主題或問題格式的相關問題檢索效率。該系統根據Hugging Face的Llama模型,能夠動態生成增強的即時完成內容。
資料集準備與預處理
首先,我們從Hugging Face載入SciQ資料集,並對其進行過濾和預處理,以確保資料品質。
載入與過濾資料集
# 匯入必要的函式庫
from datasets import load_dataset
import pandas as pd
# 從Hugging Face載入SciQ資料集
dataset = load_dataset("sciq", split="train")
# 過濾資料集以保留具有支援內容的問題
filtered_dataset = dataset.filter(lambda x: x["support"] != "" and x["correct_answer"] != "")
# 顯示過濾後的資料數量
print("具有支援內容的問題數量:", len(filtered_dataset))
輸出結果顯示我們有10,481個檔案:
具有支援內容的問題數量:10481
資料預處理
接下來,我們將過濾後的資料轉換為Pandas DataFrame,並移除不必要的欄位。
# 將過濾後的資料集轉換為Pandas DataFrame
df = pd.DataFrame(filtered_dataset)
# 定義需要移除的欄位
columns_to_drop = ['distractor3', 'distractor1', 'distractor2']
# 移除指定的欄位
df.drop(columns=columns_to_drop, inplace=True)
合併正確答案與支援內容
我們建立一個新的欄位completion,將正確答案與支援內容合併。
# 合併正確答案與支援內容到新的欄位'completion'
df['completion'] = df['correct_answer'] + " 因為 " + df['support']
# 移除'completion'欄位中包含NaN值的列
df.dropna(subset=['completion'], inplace=True)
資料集狀態確認
# 顯示DataFrame的形狀
print(df.shape)
# 顯示DataFrame的欄位名稱
print(df.columns)
輸出結果:
(10481, 4)
Index(['question', 'correct_answer', 'support', 'completion'], dtype='object')
將資料嵌入並上傳至Chroma集合
接下來,我們將建立Chroma客戶端,並定義一個集合名稱。
初始化Chroma客戶端
# 匯入Chroma並例項化客戶端
import chromadb
client = chromadb.Client()
# 定義集合名稱
collection_name = "sciq_supports6"
檢查集合是否存在
# 列出所有集合
collections = client.list_collections()
# 檢查特定集合是否存在
collection_exists = any(collection.name == collection_name for collection in collections)
print("集合是否存在:", collection_exists)
輸出結果:
集合是否存在:False
建立或取得集合
# 如果集合不存在,則建立新的集合
if not collection_exists:
collection = client.create_collection(collection_name)
else:
print("集合 ", collection_name, " 已存在。")
檢視集合結構
# 取得集合內容
results = collection.get()
# 列印集合中的每個專案
for result in results:
print(result)
輸出結果顯示了集合中的關鍵欄位,包括ids、embeddings、documents等。
簡要說明關鍵欄位
ids:每個專案在集合中的唯一識別碼。embeddings:檔案的嵌入向量。documents:合併了正確答案和支援內容的completion欄位。
選擇模型
我們選擇all-MiniLM-L6-v2作為我們的輕量級LLM模型,用於動態RAG環境。
# 定義模型名稱
model_name = "all-MiniLM-L6-v2"
模型壓縮與知識蒸餾
all-MiniLM-L6-v2模型透過Wang et al. (2021)提出的方法進行模型壓縮,專注於在Transformer模型元件之間提煉自注意力關係。這種方法在教師模型和學生模型之間的注意力頭數量上具有靈活性,提高了壓縮效率。該模型透過ONNX完全整合到Chroma中。
嵌入與儲存完成內容
接下來,我們將df中的completion欄位提取出來並嵌入到Chroma集合中。
# 取得DataFrame的長度
ldf = len(df)
nb = ldf # 要嵌入和儲存的問題數量
import time
start_time = time.time() # 開始計時
# 將Series轉換為字串列表
completion_list = df["completion"][:nb].astype(str).tolist()
# 使用collection_exists狀態避免重複載入資料
嵌入與上傳資料
# 將completion_list嵌入並上傳至Chroma集合
# 省略具體實作程式碼以保持簡潔
內容解密:
上述程式碼片段展示瞭如何利用Hugging Face的資料集和Chroma向量資料函式庫來構建一個動態的檢索增強生成(RAG)系統。關鍵步驟包括資料集的載入與預處理、資料嵌入以及上傳至Chroma集合。這些步驟為後續的查詢增強和動態生成奠定了基礎。
未來方向
未來的工作可以集中在以下幾個方面:
- 最佳化模型選擇:探索其他輕量級LLM模型,以進一步提升系統的效率和準確性。
- 改進資料預處理:最佳化資料預處理流程,以提高資料品質和系統的整體效能。
- 擴充套件應用場景:將該系統應用於其他科學領域或問題格式,以驗證其泛化能力。
透過這些努力,我們可以進一步提升RAG系統的效能和適用範圍,為科學研究和應用提供更有力的支援。
動態RAG中的Chroma向量儲存應用實務與效能分析
在動態檢索增強生成(Dynamic RAG)系統中,向量儲存扮演著至關重要的角色。本篇文章將探討如何利用Chroma向量資料函式庫進行檔案向量化處理、查詢最佳化以及效能評估。我們將詳細分析程式碼實作、技術細節以及實際應用中的考量因素。
Chroma向量儲存初始化與檔案向量化
首先,我們需要建立Chroma向量儲存並進行初始化設定。以下程式碼展示瞭如何建立一個名為my_collection的集合並進行檔案向量化處理:
if collection_exists != True:
# 嵌入並儲存初始的nb個支援檔案
collection.add(
ids=[str(i) for i in range(0, nb)],
documents=completion_list,
metadatas=[{"type": "completion"} for _ in range(0, nb)],
)
內容解密:
- 檢查
collection_exists變數判斷集合是否已存在,避免重複建立 - 使用
collection.add()方法新增檔案到向量儲存中 ids引數使用字串格式的連續數字作為檔案IDdocuments引數儲存實際的檔案內容metadatas引數記錄檔案的型別資訊(本例中為"completion")
完成向量化後,我們可以測量整個過程的回應時間:
response_time = time.time() - start_time
print(f"Response Time: {response_time:.2f} seconds")
內容解密:
- 使用
time.time()函式記錄開始和結束時間 - 計算差值得到總共花費的時間
- 以秒為單位顯示結果,保留兩位小數
輸出結果顯示系統成功載入超過10,000份檔案,並且使用了all-MiniLM-L6-v2模型進行向量化:
Response Time: 234.25 seconds
向量嵌入結果檢視與分析
接下來,我們可以檢視產生的向量嵌入結果:
result = collection.get(include=['embeddings'])
first_embedding = result['embeddings'][0]
embedding_length = len(first_embedding)
print("First embedding:", first_embedding)
print("Embedding length:", embedding_length)
內容解密:
- 使用
collection.get()方法擷取向量嵌入結果 - 提取第一個嵌入向量進行檢視
- 計算並顯示嵌入向量的維度
輸出結果顯示向量維度為384:
First embedding: [0.03689068928360939, -0.05881563201546669, ...]
Embedding length: 384
這表明all-MiniLM-L6-v2模型將文字資料對映到384維的向量空間中。相較於某些其他模型(如OpenAI的text-embedding-ada-002使用1,526維),這種表示方法大大降低了維度,同時保留了重要的語義資訊。
查詢效能測試與結果分析
使用建立好的向量儲存,我們可以進行查詢操作:
results = collection.query(
query_texts=df["question"][:nb],
n_results=1
)
內容解密:
- 使用
collection.query()方法執行查詢操作 - 將資料集中的問題轉換為向量進行相似度搜尋
- 設定
n_results=1來檢索最相關的檔案
查詢操作的回應時間同樣令人滿意:
Response Time: 199.34 seconds
結果驗證與相似度分析
為了評估查詢結果的品質,我們使用spaCy函式庫進行相似度分析:
def simple_text_similarity(text1, text2):
doc1 = nlp(text1)
doc2 = nlp(text2)
vector1 = doc1.vector
vector2 = doc2.vector
if np.linalg.norm(vector1) == 0 or np.linalg.norm(vector2) == 0:
return 0.0
else:
similarity = np.dot(vector1, vector2) / (np.linalg.norm(vector1) * np.linalg.norm(vector2))
return similarity
內容解密:
- 使用spaCy的預訓練模型將文字轉換為向量表示
- 計算兩個向量之間的餘弦相似度
- 處理零向量情況以避免除以零的錯誤
透過這個函式,我們可以評估原始答案和檢索到的檔案之間的相似度,從而評估系統的效能。
- 探索使用不同向量化模型對系統效能的影響
- 最佳化查詢引數以提高檢索精確度
- 在實際應用場景中測試系統的穩定性和可擴充套件性
透過這些改進,我們可以進一步提升動態RAG系統的整體效能,使其在更多領域中發揮作用。
技術選型考量
在實作過程中,我們選擇了Chroma作為向量資料函式庫,主要根據以下考量:
- 高效的向量相似度搜尋能力
- 良好的可擴充套件性和效能表現
- 與現有技術堆疊的相容性
未來,我們可以進一步評估其他向量資料函式庫方案,如Faiss或Pinecone,以確定最適合特定應用需求的解決方案。
效能最佳化建議
- 考慮使用GPU加速向量化過程
- 最佳化查詢批次大小以平衡效能和資源利用率
- 探索使用更先進的向量表示模型以提高語義理解能力
透過這些最佳化措施,我們可以進一步提升系統的整體效能和使用者經驗。
RAG系統評估與即時查詢實作
在前述章節中,我們已經探討了RAG系統的基本原理與實作方法。本章節將進一步探討如何評估RAG系統的效能,並實作即時查詢功能。
系統效能評估
為了評估RAG系統的效能,我們設計了一套完整的評估機制。首先,我們需要定義一個相似度函式來衡量原始檔案與檢索結果之間的相關性。在本實作中,我們採用了simple_text_similarity函式來計算兩者之間的相似度得分。
# 計算相似度得分
similarity_score = simple_text_similarity(original_completion, retrieved_document)
接著,我們設定了一個門檻值(threshold)為0.7,以判斷檢索結果是否足夠精確。如果相似度得分大於0.7,我們認為該檢索結果是準確的,並將acc_counter加一。
if similarity_score > 0.7:
acc_counter += 1
同時,我們也設計了一個顯示計數器display_counter,用於控制輸出結果的數量。只有當display_counter小於等於nbqd(最大顯示結果數)或大於nb-nbqd時,才會輸出詳細的檢索資訊。
display_counter += 1
if display_counter <= nbqd or display_counter > nb - nbqd:
print(i, " ", f"Question: {q}")
print(f"Retrieved document: {retrieved_document}")
print(f"Original completion: {original_completion}")
print(f"Similarity Score: {similarity_score:.2f}")
print() # 空行以提高可讀性
內容解密:
此段程式碼的主要功能是輸出檢索結果的詳細資訊,包括原始問題、檢索到的檔案、原始完成內容以及相似度得分。其中,q代表原始問題,retrieved_document是檢索到的檔案,original_completion是資料集中的原始完成內容,而similarity_score則是兩者之間的相似度得分。
整體準確率計算
在完成所有查詢的分析後,我們計算了整體的準確率。準確率的計算公式如下:
if nb > 0:
acc = acc_counter / nb
其中,acc代表整體準確率,acc_counter是相似度得分大於0.7的總數,而nb則是查詢的總數。在本例中,nb等於資料集的大小。
print(f"Number of documents: {nb:.2f}")
print(f"Overall similarity score: {acc:.2f}")
內容解密:
此段程式碼輸出檢索的檔案數量以及整體相似度得分。結果顯示,所有查詢都傳回了相關的結果,整體相似度得分達到1.00,表明該系統在封閉環境中運作良好。
即時查詢實作
在即時查詢會議中,我們需要一個能夠快速回應的系統。以下是一個即時查詢的實作範例:
import time
import textwrap
# 初始問題
prompt = "Millions of years ago, plants used energy from the sun to form what?"
# 開始計時
start_time = time.time()
# 查詢集合
results = collection.query(
query_texts=[prompt], # 使用提示列表
n_results=1 # 檢索結果數量
)
# 計算回應時間
response_time = time.time() - start_time
# 輸出回應時間
print(f"Response Time: {response_time:.2f} seconds\n")
# 檢查是否檢索到檔案
if results['documents'] and len(results['documents'][0]) > 0:
# 使用textwrap格式化輸出結果
wrapped_question = textwrap.fill(prompt, width=70)
wrapped_document = textwrap.fill(results['documents'][0][0], width=70)
# 輸出格式化結果
print(f"Question: {wrapped_question}")
print("\n")
print(f"Retrieved document: {wrapped_document}")
print()
else:
print("No documents retrieved.")
內容解密:
此段程式碼實作了即時查詢功能。首先,它記錄了查詢開始的時間,接著呼叫collection.query方法進行查詢,並計算回應時間。查詢結果經過格式化後輸出,包括原始問題和檢索到的檔案內容。結果顯示,回應時間極短(0.03秒),且檢索到的檔案內容相關。
圖表翻譯:
graph LR
A[開始查詢] --> B[計算相似度]
B --> C{相似度 > 0.7?}
C -->|是| D[增加準確率計數]
C -->|否| E[繼續下一個查詢]
D --> E
E --> F[輸出結果]
此圖示呈現了RAG系統評估流程。首先,系統開始查詢並計算相似度得分。接著,根據相似度得分是否大於0.7,決定是否增加準確率計數。最後,輸出結果。
圖表翻譯: 此圖表呈現了RAG系統的評估流程,包括查詢、相似度計算、準確率判斷以及結果輸出等步驟。