文字分塊技術將長文字分割成小塊,有效提升搜尋效率,但分塊大小和重疊度需仔細調整以平衡搜尋結果的相關性和完整性。利用 FAISS 這個高效的向量資料函式庫,可以儲存和查詢大量的向量嵌入,提升搜尋效能。程式碼範例展示瞭如何使用 FAISS 建立索引、執行向量搜尋,並結合 LangChain 和 LCEL 進行更進階的向量檢索和問答。更進一步,文章也探討了主機向量資料函式庫如 Pinecone 的優勢,包含維護、擴充套件性、可靠性、效能、支援和安全性等方面,並分析了使用主機服務的成本和風險,例如供應商鎖定和資料隱私等議題。
文字分塊與向量資料函式庫
文字分塊是一種將大段文字拆分成小塊的技術,能夠有效地提高文字搜尋的效率。然而,分塊的大小和重疊程度對於搜尋結果的相關性有著重要影響。過短的分塊可能無法包含正確的答案,而過長的分塊可能會導致搜尋結果中出現太多無關緊要的內容。
使用 FAISS 進行記憶檢索
為了儲存和查詢向量,我們可以使用一個名為 FAISS 的開源函式庫。FAISS 是一個由 Facebook 開發的函式庫,能夠高效地儲存和查詢大規模的向量資料函式庫。首先,我們需要安裝 FAISS,然後使用 pip 安裝 faiss-cpu。
import numpy as np
import faiss
# 定義一個函式來取得向量嵌入
def get_vector_embeddings(text):
# 在這裡實作你的向量嵌入邏輯
pass
# 將文字分塊轉換為向量嵌入
chunks = ["文字分塊1", "文字分塊2", "文字分塊3"]
emb = [get_vector_embeddings(chunk) for chunk in chunks]
vectors = np.array(emb)
# 建立一個 FAISS 索引
index = faiss.IndexFlatL2(vectors.shape[1])
index.add(vectors)
# 定義一個函式來進行向量搜尋
def vector_search(query_text, k=1):
query_vector = get_vector_embeddings(query_text)
distances, indices = index.search(np.array([query_vector]), k)
return [(chunks[i], float(dist)) for dist, i in zip(distances[0], indices[0])]
# 範例搜尋
user_query = "我們能夠免費騎獨角獸嗎?"
search_results = vector_search(user_query)
print(f"搜尋結果為 {user_query}:", search_results)
內容解密:
在上述程式碼中,我們首先定義了一個函式 get_vector_embeddings 來取得文字的向量嵌入。然後,我們將文字分塊轉換為向量嵌入,並建立了一個 FAISS 索引。接著,我們定義了一個函式 vector_search 來進行向量搜尋,該函式接受一個查詢文字和一個可選引數 k,代表傳回的搜尋結果數量。最後,我們進行了一個範例搜尋,輸出了搜尋結果。
圖表翻譯:
flowchart TD
A[文字分塊] --> B[向量嵌入]
B --> C[FAISS 索引]
C --> D[向量搜尋]
D --> E[搜尋結果]
在這個流程圖中,我們展示了從文字分塊到搜尋結果的整個過程。首先,文字分塊被轉換為向量嵌入,然後被新增到 FAISS 索引中。接著,當使用者輸入查詢文字時,系統會進行向量搜尋,並傳回相關的搜尋結果。
瞭解向量搜尋的基本原理
向量搜尋是一種用於尋找相似向量的技術,常見於自然語言處理、影像搜尋等領域。以下是對向量搜尋的基本原理的介紹:
1. 載入必要的函式庫
首先,需要載入必要的函式庫,例如 Facebook AI Similarity Search (FAISS) 函式庫,使用 import faiss。
2. 取得向量嵌入
然後,需要取得向量嵌入,這可以透過將文字或影像等資料轉換為數值向量的形式實作。例如,使用 get_vector_embeddings 函式來取得每個文字塊的向量嵌入,並將其儲存在 vectors 陣列中。
3. 建立 FAISS 索引
接下來,需要建立一個 FAISS 索引,以便於高效地搜尋相似向量。這可以透過 faiss.IndexFlatL2 類別實作,該類別會根據向量的維度建立一個索引。
4. 新增向量到索引
然後,需要將向量新增到索引中,以便於搜尋。這可以透過 index.add 方法實作。
5. 定義向量搜尋函式
最後,需要定義一個向量搜尋函式,該函式接受一個查詢文字和一個可選引數 k,並傳回最相似的 k 個向量。該函式可以透過以下步驟實作:
- 對查詢文字進行向量嵌入,獲得查詢向量。
- 使用查詢向量搜尋索引,獲得最相似的
k個向量。
示例程式碼
以下是示例程式碼:
import faiss
import numpy as np
# 載入必要的函式庫
# 定義取得向量嵌入的函式
def get_vector_embeddings(text):
# 實作取得向量嵌入的邏輯
pass
# 建立 FAISS 索引
index = faiss.IndexFlatL2(128) # 128 是向量的維度
# 新增向量到索引
vectors = np.array([get_vector_embeddings(chunk) for chunk in chunks])
index.add(vectors)
# 定義向量搜尋函式
def vector_search(query_text, k=1):
query_vector = get_vector_embeddings(query_text)
# 使用查詢向量搜尋索引
D, I = index.search(np.array([query_vector]), k)
return D, I
# 測試向量搜尋函式
query_text = "示例查詢文字"
D, I = vector_search(query_text, k=3)
print("最相似的 3 個向量的距離:", D)
print("最相似的 3 個向量的索引:", I)
注意:上述程式碼僅為示例,需要根據具體需求修改和實作。
瞭解向量搜尋和對話功能
向量搜尋是一種強大的技術,能夠在大型資料函式庫中找到最相似的向量。以下是使用FAISS和Pinecone實作向量搜尋和對話功能的步驟。
步驟1:進行向量搜尋
首先,需要使用vector_search函式進行向量搜尋。這個函式接受使用者查詢和k值作為輸入,k值代表要傳回的最相似向量的數量。函式傳回兩個陣列:distances和indices,分別代表查詢向量的平方L2距離和索引。
distances, indices = index.search(np.array([query_vector]), k)
步驟2:處理搜尋結果
然後,需要處理搜尋結果。這涉及到建立一個包含查詢結果和對應距離的元組列表。注意,距離需要轉換為浮點數。
return [(chunks[i], float(dist)) for dist, i in zip(distances[0], indices[0])]
步驟3:執行向量搜尋
現在,可以執行向量搜尋了。這涉及到呼叫vector_search函式並傳入使用者查詢和k值。
search_results = vector_search(user_query, k)
步驟4:建立提示
搜尋結果可以注入到提示中,以提供有用的上下文。同時,需要設定系統訊息,以便模型根據提供的上下文進行回答,而不是自己編造答案。
prompt_with_context = f"""Context:{search_results}\
Answer the question: {user_query}"""
步驟5:建立聊天訊息
需要建立一個包含系統訊息和使用者提示的聊天訊息列表。
messages = [
{"role": "system", "content": """Please answer the questions provided by 玄貓. Use only the context provided to you to respond to the user, if you don't know the answer say "I don't know"."""},
{"role": "user", "content": prompt_with_context},
]
步驟6:取得模型回應
最後,需要取得模型的回應。
response = model("gpt-3.5-turbo", messages=messages)
步驟7:列印回應
最終,需要列印模型的回應。
print(f"""Response:
{response}""")
以下是完整的程式碼示例:
def search_and_chat(user_query, k=1):
# 執行向量搜尋
search_results = vector_search(user_query, k)
# 列印搜尋結果
print(f"Search results: {search_results}\n\n")
# 建立提示
prompt_with_context = f"""Context:{search_results}\
Answer the question: {user_query}"""
# 建立聊天訊息
messages = [
{"role": "system", "content": """Please answer the questions provided by 玄貓. Use only the context provided to you to respond to the user, if you don't know the answer say "I don't know"."""},
{"role": "user", "content": prompt_with_context},
]
# 取得模型回應
response = model("gpt-3.5-turbo", messages=messages)
# 列印回應
print(f"""Response:
{response}""")
# 示例使用
search_and_chat("What is Unicorn Enterprises' mission?")
這個程式碼示例展示瞭如何使用FAISS和Pinecone實作向量搜尋和對話功能。它首先執行向量搜尋,然後處理搜尋結果,建立提示,建立聊天訊息,取得模型回應,最終列印模型的回應。
使用FAISS和Pinecone構建向量資料函式庫
在前面的章節中,我們已經學習瞭如何使用FAISS和Pinecone構建向量資料函式庫。現在,我們將更深入地探討如何最佳化和管理向量資料函式庫。
最佳化向量資料函式庫
當我們使用FAISS或Pinecone構建向量資料函式庫時,需要考慮到資料函式庫的大小和查詢效率。為了最佳化向量資料函式庫,我們可以使用以下方法:
- 儲存索引: 我們可以使用
faiss.write_index函式儲存FAISS索引到檔案中,這樣可以在不同會話或環境之間分享索引。 - 載入索引: 我們可以使用
faiss.read_index函式載入儲存的索引到記憶體中。 - 合並索引: 如果我們有多個儲存的向量資料函式庫,我們可以使用
faiss.IndexFlatL2索引的add方法合並它們。
合並FAISS索引
合並FAISS索引可以使用以下程式碼實作:
# 假設index1和index2是兩個IndexFlatL2索引
index1.add(index2.reconstruct_n(0, index2.ntotal))
這段程式碼使用reconstruct_n方法從index2中提取所有向量,然後使用add方法將這些向量新增到index1中,從而合並兩個索引。
保留向量ID
當合並索引時,需要注意的是,向量ID可能會發生變化。如果需要保留向量ID,需要外部管理ID對映。然後,在合並索引時,也需要合並這些對映。
使用LangChain實作RAG
LangChain是一個流行的AI工程框架,支援RAG技術。其他框架,如LlamaIndex,也專注於RAG,適合複雜的使用案例。由於我們已經熟悉了LangChain,所以我們將繼續使用它來實作RAG。
內容解密:
在上面的程式碼中,我們使用faiss.write_index函式儲存FAISS索引到檔案中,然後使用faiss.read_index函式載入儲存的索引到記憶體中。這樣可以在不同會話或環境之間分享索引。合並索引可以使用faiss.IndexFlatL2索引的add方法實作。
圖表翻譯:
以下是合並FAISS索引的流程圖:
flowchart TD
A[儲存索引] --> B[載入索引]
B --> C[合並索引]
C --> D[更新ID對映]
D --> E[傳回合並後的索引]
這個流程圖展示瞭如何儲存FAISS索引、載入儲存的索引、合並索引、更新ID對映,最終傳回合並後的索引。
程式碼示例:
以下是使用LangChain實作RAG的程式碼示例:
import langchain
# 建立一個LangChain會話
session = langchain.Session()
# 定義一個RAG模型
model = langchain.RAGModel()
# 定義一個查詢
query = "What is the meaning of life?"
# 執行RAG查詢
response = model(query)
# 列印查詢結果
print(response)
這個程式碼示例展示瞭如何使用LangChain建立一個RAG模型,定義一個查詢,執行RAG查詢,最終列印查詢結果。
使用LCEL和FAISS進行向量檢索
在上一章中,我們瞭解瞭如何使用RAG(Retrieval-Augmented Generation)根據所需的上下文進行查詢。現在,讓我們使用LCEL(LangChain Embeddings with FAISS)在四個小型文字檔案上進行類別似的示例。
首先,我們需要建立檔案列表:
documents = [
"James Phoenix worked at JustUnderstandingData.",
"James Phoenix currently is 31 years old.",
"""Data engineering is the designing and building systems for collecting,
storing, and analyzing data at scale.""",
]
接下來,我們建立一個向量儲存(vector store):
from langchain_community.vectorstores.faiss import FAISS
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
vectorstore = FAISS.from_texts(texts=documents, embedding=OpenAIEmbeddings())
retriever = vectorstore.as_retriever()
這裡,我們使用FAISS函式庫從檔案列表中建立了一個向量儲存,並將其轉換為一個可用的檢索器(retriever)。
然後,我們建立一個提示範本(prompt template):
template = """Answer the question based only on the following context:
---
Context: {context}
---
Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
這個提示範本要求模型根據提供的上下文回答問題。
接下來,我們建立一個聊天模型(chat model):
model = ChatOpenAI()
現在,我們可以建立一個LCEL鏈(chain):
chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| model
| StrOutputParser()
)
這個鏈包含了檢索器、提示範本、聊天模型和輸出解析器。當我們呼叫這個鏈時,它會自動從檢索器中取得上下文,並根據提供的問題生成答案。
最後,我們可以呼叫這個鏈並傳入我們的問題:
chain.invoke("What is data engineering?")
這將傳回一個字串答案,根據提供的上下文和問題。
內容解密:
在這個例子中,我們使用LCEL和FAISS進行向量檢索。首先,我們建立了一個檔案列表和一個向量儲存。然後,我們建立了一個提示範本和一個聊天模型。接下來,我們建立了一個LCEL鏈,包含了檢索器、提示範本、聊天模型和輸出解析器。最後,我們呼叫這個鏈並傳入我們的問題,得到一個字串答案。
圖表翻譯:
flowchart TD
A[檔案列表] --> B[向量儲存]
B --> C[檢索器]
C --> D[提示範本]
D --> E[聊天模型]
E --> F[輸出解析器]
F --> G[答案]
這個圖表展示了LCEL鏈的流程。從檔案列表開始,到向量儲存、檢索器、提示範本、聊天模型、輸出解析器,最終得到答案。
使用 Pinecone 的主機向量資料函式庫
隨著人工智慧的應用案例不斷增多,各種主機向量資料函式庫提供者也逐漸出現,例如 Chroma、Weaviate 和 Pinecone。其他型別的資料函式庫主機也開始提供向量搜尋功能,例如 Supabase 的 pgvector 外掛。由於 Pinecone 目前是領先者,本文將以 Pinecone 為例進行介紹,但各個提供者的使用模式相對一致,概念也可以應用於其他提供者。
主機向量資料函式庫的優勢
使用主機向量資料函式庫有以下幾個優點:
- 維護:您不需要自己設定、管理和維護資料函式庫,可以節省大量時間和資源,特別是對於沒有專門 DevOps 或資料函式倉管理團隊的企業。
- 可擴充套件性:主機向量資料函式庫可以根據您的需求進行擴充套件,當您的資料增長時,資料函式庫可以自動擴充套件以處理增加的負載,確保您的應用程式保持高效執行。
- 可靠性:管理服務通常提供高用性,具有服務等級協定,以及自動備份和災難還原功能,可以提供安心感並避免潛在的資料損失。
- 效能:主機向量資料函式庫通常具有最佳化的基礎設施和演算法,可以提供比自行管理的開源解決方案更好的效能,特別是對於依賴實時或近實時向量搜尋功能的應用程式。
- 支援:使用主機服務,您通常可以獲得提供服務的公司的支援,如果您遇到問題或需要幫助最佳化資料函式庫的使用,可以非常有幫助。
- 安全性:管理服務通常具有強大的安全措施來保護您的資料,包括加密、存取控制和監控。主要的主機提供者更有可能具有必要的合規證書,並遵守歐盟等地區的隱私立法。
考量和風險
雖然主機向量資料函式庫提供了許多優點,但也有一些需要考慮的因素:
- 成本:額外的功能和服務會產生成本,存在過度消費的風險,就像使用 Amazon Web Services、Microsoft Azure 或 Google Cloud 時可能因為錯誤組態或程式碼錯誤而意外花費數千美元一樣。
- 供應商鎖定:雖然各個供應商具有相似的功能,但在某些領域存在差異,因此在供應商之間遷移並不完全直接。另一個主要考慮的是隱私,因為與第三方分享資料存在安全風險和潛在的法律影響。
從技術架構視角來看,本文深入探討了文字分塊、向量嵌入以及向量資料函式庫的構建與應用,涵蓋了從本地方案如FAISS到雲端託管服務如Pinecone的完整技術堆疊。透過多維比較分析,我們發現,FAISS 提供了高效的向量搜尋能力,適用於本地佈署和小型專案,而 Pinecone 等雲端服務則更具可擴充套件性和可靠性,適合大型應用和企業級佈署。然而,技術限制深析顯示,無論是本地還是雲端方案,都需要仔細考量向量維度、索引型別以及分塊策略等因素,才能達到最佳效能。技術演進預測顯示,向量資料函式庫技術將持續向高效能、低延遲、易用性方向發展,與深度學習模型的整合也將更加緊密。隨著 AI 應用場景的擴充套件,向量資料函式庫的市場規模將持續增長,更多專業化的解決方案也將不斷湧現。玄貓認為,技術團隊應根據自身需求和資源狀況,選擇合適的向量資料函式庫方案,並持續關注相關技術的發展趨勢,才能在激烈的市場競爭中保持領先地位。