接下來幾天我們會介紹各種不同的向量資料庫。
FAISS 是 Facebook AI Research(FAIR)開發的一個高效的相似度搜索和密集向量聚類庫。它專為高維向量相似度搜索而設計,並且能在大型數據集上提供快速和準確的結果。FAISS 支援多種距離度量,並提供了多種優化的索引結構來實現快速搜索。
安裝時需要注意他有 CPU 版和 GPU 版,我們窮人就先用 CPU 版本。
使用指令 poetry add faiss-cpu
我們先來建立一個檔案 faiss_tutorial.py
,寫一個 FAISS 的 function。
def add_to_faiss_index(embeddings):
vector = np.array(embeddings)
index = faiss.IndexFlatL2(vector.shape[1])
index.add(vector)
return index
這個函式負責將 embeddings 加入到 FAISS 索引(index)中。一開始是先將 embeddings 轉換為 numpy 的陣列,然後用 vector.shape[1]
取得每個 embedding 的維度,放進 IndexFlatL2
裡,這是一種暴力搜尋法(因為 FAISS 不直接支援 Cosine Similarity,要再換算)。最後再加入索引裡面。
def vector_search(index, query_embedding, text_array, k=1):
distances, indices = index.search(
np.array([query_embedding]), k)
return [(text_array[i], float(dist)) for dist, i in zip(distances[0], indices[0])]
這個是把想要問的問題做了 embedding 後,放進去給 FAISS 搜尋。並且 return 一個 list ,將距離和索引組合成一個新的 list ,其中包含與查詢相似的文本和其對應的距離。
def get_embedding(text, model_name):
response = openai.Embedding.create(
input=text,
engine=model_name
)
return response['data'][0]['embedding']
def main():
EMBEDDING_MODEL_NAME = "embedding-ada-002" # 你前幾天在 Azure OpenAI 上建立的模型名稱
openai.api_base = "https://japanopenai2023ironman.openai.azure.com/"
openai.api_key = "your_key"
openai.api_type = "azure"
openai.api_version = "2023-03-15-preview"
text_array = ["我會披星戴月的想你,我會奮不顧身的前進,遠方煙火越來越唏噓,凝視前方身後的距離",
"而我,在這座城市遺失了你,順便遺失了自己,以為荒唐到底會有捷徑。而我,在這座城市失去了你,輸給慾望高漲的自己,不是你,過分的感情"]
embedding_array = [get_embedding(
text, EMBEDDING_MODEL_NAME) for text in text_array]
faiss_index = add_to_faiss_index(embedding_array)
# 輸入問題來搜譣
query_text = "工程師寫城市"
query_embedding = get_embedding(query_text, EMBEDDING_MODEL_NAME)
search_results = vector_search(faiss_index, query_embedding, text_array)
print(f"尋找 {query_text}:", search_results)
if __name__ == '__main__':
main()
跑起來後,應該就會看到結果如下:
尋找 工程師寫城市: [('而我,在這座城市遺失了你,順便遺失了自己,以為荒唐到底會有捷徑。而我,在這座城市失去了你,輸給慾望高漲的自己,不是你,過分的感情', 0.41394227743148804)]
工程師寫城市是一個諧音的錯字,我們透過這個來尋找的話,找到「在這座城市遺失了你」這首歌是最接近,但是距離也只有 0.41。
然而,FAISS 不是一個資料庫,它是一個專門用於高效進行大規模向量搜索的套件。在 FAISS 中,索引通常存儲在記憶體中,以達到高速搜索的目的。當然你也可以用 faiss.write_index(index, "my_index.faiss")
來把資料存在本地端。明天開始我們會來講更像資料庫的向量資料庫。