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