向量存储
为了简单起见,此概念概述侧重于基于文本的索引和检索。然而,嵌入模型可以是多模态的,向量存储可以用来存储和检索文本以外的各种数据类型。
概述
向量存储是专门的数据存储,它支持基于向量表示对信息进行索引和检索。
这些向量,被称为嵌入,捕获了已被嵌入的数据的语义含义。
向量存储经常用于搜索非结构化数据,例如文本、图像和音频,以基于语义相似性而不是精确的关键字匹配来检索相关信息。
集成
LangChain 拥有大量的向量存储集成,允许用户轻松切换不同的向量存储实现。
接口
LangChain 为使用向量存储提供了一个标准接口,允许用户轻松切换不同的向量存储实现。
该接口包含用于在向量存储中写入、删除和搜索文档的基本方法。
关键方法是
add_documents
:将文本列表添加到向量存储。delete_documents
:从向量存储中删除文档列表。similarity_search
:搜索与给定查询相似的文档。
初始化
LangChain 中的大多数向量在初始化向量存储时接受嵌入模型作为参数。
我们将使用 LangChain 的InMemoryVectorStore 实现来说明 API。
from langchain_core.vectorstores import InMemoryVectorStore
# Initialize with an embedding model
vector_store = InMemoryVectorStore(embedding=SomeEmbeddingModel())
添加文档
要添加文档,请使用 add_documents
方法。
此 API 使用Document对象的列表。 Document
对象都具有 page_content
和 metadata
属性,使其成为存储非结构化文本和相关元数据的通用方法。
from langchain_core.documents import Document
document_1 = Document(
page_content="I had chocalate chip pancakes and scrambled eggs for breakfast this morning.",
metadata={"source": "tweet"},
)
document_2 = Document(
page_content="The weather forecast for tomorrow is cloudy and overcast, with a high of 62 degrees.",
metadata={"source": "news"},
)
documents = [document_1, document_2]
vector_store.add_documents(documents=documents)
您通常应该为添加到向量存储的文档提供 ID,这样您就可以更新现有文档,而不是多次添加同一文档。
vector_store.add_documents(documents=documents, ids=["doc1", "doc2"])
删除
要删除文档,请使用 delete_documents
方法,该方法接受要删除的文档 ID 列表。
vector_store.delete_documents(ids=["doc1"])
搜索
向量存储嵌入并存储添加的文档。如果我们传入一个查询,向量存储将嵌入该查询,对嵌入的文档执行相似性搜索,并返回最相似的文档。这捕捉了两个重要的概念:首先,需要有一种方法来衡量查询与任何嵌入式文档之间的相似性。其次,需要一种算法来有效地对所有嵌入的文档执行此相似性搜索。
相似性指标
嵌入向量的一个关键优势是可以使用许多简单的数学运算进行比较
- 余弦相似度:测量两个向量之间角度的余弦值。
- 欧几里得距离:测量两点之间的直线距离。
- 点积:测量一个向量在另一个向量上的投影。
有时可以在初始化向量存储时选择相似性指标。请参考您正在使用的特定向量存储的文档,以查看支持哪些相似性指标。
相似性搜索
给定一个用于测量嵌入查询和任何嵌入文档之间距离的相似性指标,我们需要一种算法来有效地搜索所有嵌入文档,以找到最相似的文档。有很多方法可以做到这一点。例如,许多向量存储实现HNSW(分层可导航小世界),这是一种基于图的索引结构,可以实现高效的相似性搜索。无论底层使用哪种搜索算法,LangChain 向量存储接口都为所有集成提供了一个 similarity_search
方法。这将获取搜索查询、创建嵌入、查找相似的文档,并将它们作为文档列表返回。
query = "my query"
docs = vectorstore.similarity_search(query)
许多向量存储支持将搜索参数与 similarity_search
方法一起传递。请参阅您正在使用的特定向量存储的文档,以查看支持哪些参数。例如,Pinecone有几个重要的通用概念参数:许多向量存储支持k
,它控制要返回的文档数量,以及 filter
,它允许按元数据过滤文档。
query (str) – 要查找与之相似的文档的文本。
k (int) – 要返回的文档数量。默认为 4。
filter (dict | None) – 要在元数据上过滤的参数字典。
元数据过滤
虽然向量存储实现了一种搜索算法来有效地搜索所有嵌入的文档以找到最相似的文档,但许多向量存储还支持按元数据进行过滤。这允许使用结构化过滤器来减小相似性搜索空间的大小。这两个概念配合得很好
- 语义搜索:直接查询非结构化数据,通常通过嵌入或关键字相似性进行。
- 元数据搜索:将结构化查询应用于元数据,过滤特定文档。
向量存储对元数据过滤的支持通常取决于底层向量存储的实现。
这是使用Pinecone的示例用法,显示我们过滤了元数据键 source
值为 tweet
的所有文档。
vectorstore.similarity_search(
"LangChain provides abstractions to make working with LLMs easy",
k=2,
filter={"source": "tweet"},
)
- 请参阅 Pinecone 关于使用元数据进行过滤的文档。
- 请参阅支持元数据过滤的LangChain 向量存储集成列表。
高级搜索和检索技术
虽然诸如 HNSW 之类的算法为许多情况下的高效相似性搜索提供了基础,但可以使用其他技术来提高搜索质量和多样性。例如,最大边际相关性是一种重新排序算法,用于使搜索结果多样化,该算法在初始相似性搜索之后应用,以确保更多样化的结果集。第二个示例,一些向量存储提供内置的混合搜索来结合关键字和语义相似性搜索,这结合了两种方法的优点。目前,没有使用 LangChain 向量存储执行混合搜索的统一方法,但它通常作为关键字参数公开,该参数与 similarity_search
一起传递。有关更多详细信息,请参阅此关于混合搜索的操作指南。
名称 | 何时使用 | 描述 |
---|---|---|
混合搜索 | 当组合基于关键字和语义相似性时。 | 混合搜索结合了关键字和语义相似性,结合了两种方法的优点。论文。 |
最大边际相关性 (MMR) | 当需要使搜索结果多样化时。 | MMR 试图使搜索结果多样化,以避免返回相似和冗余的文档。 |