Skip to main content

Pinecone Hybrid Search

Pinecone 是一个具有广泛功能的向量数据库。

本笔记本介绍了如何使用一个底层使用 Pinecone 和混合搜索的检索器。

该检索器的逻辑取自此文档

要使用 Pinecone,您必须拥有一个 API 密钥和一个环境。以下是安装说明

#!pip install pinecone-client pinecone-text
import os
import getpass

os.environ["PINECONE_API_KEY"] = getpass.getpass("Pinecone API Key:")
from langchain.retrievers import PineconeHybridSearchRetriever
os.environ["PINECONE_ENVIRONMENT"] = getpass.getpass("Pinecone Environment:")

我们想要使用 OpenAIEmbeddings,所以我们需要获取 OpenAI API 密钥。

os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:")

设置 Pinecone

您只需要执行此部分一次。

注意:确保元数据中保存文档文本的 "context" 字段不被索引。目前,您需要明确指定要索引的字段。有关更多信息,请查看 Pinecone 的文档

import os
import pinecone

api_key = os.getenv("PINECONE_API_KEY") or "PINECONE_API_KEY"
# 在 Pinecone 控制台中找到与您的 API 密钥相邻的环境
env = os.getenv("PINECONE_ENVIRONMENT") or "PINECONE_ENVIRONMENT"

index_name = "langchain-pinecone-hybrid-search"

pinecone.init(api_key=api_key, environment=env)
pinecone.whoami()
    WhoAmIResponse(username='load', user_label='label', projectname='load-test')
# 创建索引
pinecone.create_index(
name=index_name,
dimension=1536, # 密集模型的维度
metric="dotproduct", # 仅支持 dotproduct 的稀疏值
pod_type="s1",
metadata_config={"indexed": []}, # 请参阅上面的解释
)

现在已经创建了索引,我们可以使用它了。

index = pinecone.Index(index_name)

获取嵌入和稀疏编码器

嵌入用于密集向量,分词器用于稀疏向量。

from langchain.embeddings import OpenAIEmbeddings

embeddings = OpenAIEmbeddings()

要将文本编码为稀疏值,您可以选择 SPLADE 或 BM25。对于领域外任务,我们建议使用 BM25。

有关稀疏编码器的更多信息,请查看 pinecone-text 库的文档

from pinecone_text.sparse import BM25Encoder

# 或者从 pinecone_text.sparse 导入 SpladeEncoder,如果您希望使用 SPLADE

# 使用默认的 tf-idf 值
bm25_encoder = BM25Encoder().default()

上述代码使用了默认的 tf-idf 值。强烈建议将 tf-idf 值拟合到您自己的语料库中。您可以按照以下方式进行操作:

corpus = ["foo", "bar", "world", "hello"]

# 在您的语料库上拟合 tf-idf 值
bm25_encoder.fit(corpus)

# 将值存储到一个 json 文件中
bm25_encoder.dump("bm25_values.json")

# 加载到您的 BM25Encoder 对象中
bm25_encoder = BM25Encoder().load("bm25_values.json")

加载检索器

现在我们可以构建检索器了!

retriever = PineconeHybridSearchRetriever(
embeddings=embeddings, sparse_encoder=bm25_encoder, index=index
)

添加文本(如果需要)

我们可以选择将文本添加到检索器中(如果它们尚未存在)

retriever.add_texts(["foo", "bar", "world", "hello"])
    100%|██████████| 1/1 [00:02<00:00,  2.27s/it]

使用检索器

现在我们可以使用检索器了!

result = retriever.get_relevant_documents("foo")
result[0]
    Document(page_content='foo', metadata={})