Redis 是一个快速的开源内存数据存储。作为 Redis Stack, 的一部分, 是启用向量相似性语义搜索以及许多其他类型搜索的模块。
本指南提供了快速入门 Redis 向量存储的快速概述。若要获取所有 RedisVectorStore 功能和配置的详细文档,请前往 API 参考.
概述
集成详情
| Class | Package | PY 支持 | Downloads | Version |
|---|---|---|---|---|
RedisVectorStore | @langchain/redis | ✅ | !NPM - Downloads | !NPM - Version |
设置
要使用 Redis 向量存储,请设置一个启用 RediSearch 的 Redis Stack 实例,并安装 @langchain/redis 和 @langchain/core。安装 redis 在传递您自己的实例时使用 Node.js 客户端 createClient 实例到 RedisVectorStore.
本指南使用 OpenAI 嵌入 作为示例。您可以使用 其他支持的嵌入模型 instead.
npm install @langchain/redis @langchain/core redis @langchain/openai
yarn add @langchain/redis @langchain/core redis @langchain/openai
pnpm add @langchain/redis @langchain/core redis @langchain/openai
您可以通过以下方式使用 Docker 在本地设置 Redis 实例 这些说明.
凭据
设置 REDIS_URL 环境变量:
process.env.REDIS_URL = "your-redis-url";
如果您在本指南中使用 OpenAI 嵌入,也请设置您的 OpenAI 密钥:
process.env.OPENAI_API_KEY = "YOUR_API_KEY";
如果您想获取模型调用的自动追踪,您还可以设置您的 LangSmith API 密钥,方法是在下方取消注释:
// process.env.LANGSMITH_TRACING="true"
// process.env.LANGSMITH_API_KEY="your-api-key"
实例化
const embeddings = new OpenAIEmbeddings({
model: "text-embedding-3-small",
});
const client = createClient({
url: process.env.REDIS_URL ?? "redis://localhost:6379",
});
await client.connect();
const vectorStore = new RedisVectorStore(embeddings, {
redisClient: client,
indexName: "langchainjs-testing",
});
管理向量存储
向向量存储添加项目
const document1: Document = {
pageContent: "The powerhouse of the cell is the mitochondria",
metadata: { type: "example" },
};
const document2: Document = {
pageContent: "Buildings are made out of brick",
metadata: { type: "example" },
};
const document3: Document = {
pageContent: "Mitochondria are made out of lipids",
metadata: { type: "example" },
};
const document4: Document = {
pageContent: "The 2024 Olympics are in Paris",
metadata: { type: "example" },
};
const documents = [document1, document2, document3, document4];
await vectorStore.addDocuments(documents);
顶级文档 ID 当前不受支持,但您可以通过直接向向量存储提供其 ID 来删除文档。
查询向量存储
一旦您的向量存储已创建并且相关文档已添加,您很可能希望在链或代理运行期间对其进行查询。
直接查询
执行简单的相似性搜索可以按如下方式进行:
const similaritySearchResults = await vectorStore.similaritySearch(
"biology",
2
);
for (const doc of similaritySearchResults) {
console.log(`* ${doc.pageContent} [${JSON.stringify(doc.metadata, null)}]`);
}
过滤当前会查找包含所提供字符串的任何元数据键。
如果您想执行相似性搜索并接收相应的分数,您可以运行:
const similaritySearchWithScoreResults =
await vectorStore.similaritySearchWithScore("biology", 2);
for (const [doc, score] of similaritySearchWithScoreResults) {
console.log(
`* [SIM=${score.toFixed(3)}] ${doc.pageContent} [${JSON.stringify(
doc.metadata
)}]`
);
}
* [SIM=0.835] The powerhouse of the cell is the mitochondria [{"type":"example"}]
* [SIM=0.852] Mitochondria are made out of lipids [{"type":"example"}]
通过转换为检索器进行查询
您还可以将向量存储转换为 检索器 以便在链中更方便地使用。
const retriever = vectorStore.asRetriever({
k: 2,
});
await retriever.invoke("biology");
[
Document {
pageContent: 'The powerhouse of the cell is the mitochondria',
metadata: { type: 'example' },
id: undefined
},
Document {
pageContent: 'Mitochondria are made out of lipids',
metadata: { type: 'example' },
id: undefined
}
]
用于检索增强生成
有关如何使用此向量存储进行检索增强生成 (RAG) 的指南,请参阅以下部分:
- - 使用 LangChain 构建 RAG 应用.
- - 智能体 RAG
- - 检索文档
删除文档
您可以通过两种方式从向量存储中删除文档:
删除所有文档
您可以使用以下命令删除整个索引及其所有文档:
await vectorStore.delete({ deleteAll: true });
按 ID 删除特定文档
您还可以通过提供文档 ID 来删除特定文档。请注意,配置的键前缀将自动添加到您提供的 ID 中:
// The key prefix will be automatically added to each ID
await vectorStore.delete({ ids: ["doc1", "doc2", "doc3"] });
关闭连接
完成操作后请确保关闭客户端连接,以避免过多的资源消耗:
await client.disconnect();
高级功能
自定义架构和元数据过滤
Redis 向量存储支持元数据字段的自定义架构定义,从而实现更高效的过滤和搜索。此功能允许您为元数据定义特定的字段类型和验证规则。
定义自定义架构
创建向量存储时可以定义自定义架构,以指定字段类型、验证规则和索引选项:
const embeddings = new OpenAIEmbeddings({
model: "text-embedding-3-small",
});
const client = createClient({
url: process.env.REDIS_URL ?? "redis://localhost:6379",
});
await client.connect();
// Define custom schema for metadata fields
const customSchema:RedisVectorStoreConfig["customSchema"] = {
userId: {
type: SchemaFieldTypes.TEXT,
required: true,
SORTABLE: true,
},
category: {
type: SchemaFieldTypes.TAG,
SORTABLE: true,
SEPARATOR: ",",
},
score: {
type: SchemaFieldTypes.NUMERIC,
SORTABLE: true,
},
tags: {
type: SchemaFieldTypes.TAG,
SEPARATOR: ",",
CASESENSITIVE: true,
},
description: {
type: SchemaFieldTypes.TEXT,
NOSTEM: true,
WEIGHT: 2.0,
},
};
const vectorStoreWithSchema = new RedisVectorStore(embeddings, {
redisClient: client,
indexName: "langchainjs-custom-schema",
customSchema,
});
架构字段类型
自定义架构支持三种主要字段类型:
- TEXT:支持全文搜索的字段,可选配词干提取、加权和排序
- TAG:用于精确匹配的分类字段,支持多个值和自定义分隔符
- NUMERIC:支持范围查询和排序的数值字段
字段配置选项
每个字段都可以通过各种选项进行配置:
- -
required:该字段是否必须在元数据中存在(默认值:false) - -
SORTABLE:启用该字段的排序功能(默认值:undefined) - -
SEPARATOR:对于 TAG 字段,指定多个值的分隔符(默认值:",") - -
CASESENSITIVE:对于 TAG 字段,启用大小写敏感匹配(Redis 期望true,而非布尔值) - -
NOSTEM:对于 TEXT 字段,禁用词干提取(Redis 期望true,而非布尔值) - -
WEIGHT:对于 TEXT 字段,指定搜索权重(默认值:1.0)
使用架构验证添加文档
使用自定义架构时,文档会自动根据定义的架构进行验证:
const documentsWithMetadata: Document[] = [
{
pageContent: "Advanced JavaScript techniques for modern web development",
metadata: {
userId: "user123",
category: "programming",
score: 95,
tags: ["javascript", "web-development", "frontend"],
description: "Comprehensive guide to JavaScript best practices",
},
},
{
pageContent: "Machine learning fundamentals and applications",
metadata: {
userId: "user456",
category: "ai",
score: 88,
tags: ["machine-learning", "python", "data-science"],
description: "Introduction to ML concepts and practical applications",
},
},
{
pageContent: "Database optimization strategies for high performance",
metadata: {
userId: "user789",
category: "database",
score: 92,
tags: ["database", "optimization", "performance"],
description: "Advanced techniques for database performance tuning",
},
},
];
// This will validate each document's metadata against the custom schema
await vectorStoreWithSchema.addDocuments(documentsWithMetadata);
带元数据过滤的高级相似性搜索
自定义架构使用 similaritySearchVectorWithScoreAndMetadata method:
// Search with TAG filtering
const tagFilterResults =
await vectorStoreWithSchema.similaritySearchVectorWithScoreAndMetadata(
await embeddings.embedQuery("programming tutorial"),
3,
{
category: "programming", // Exact tag match
tags: ["javascript", "frontend"], // Multiple tag OR search
}
);
console.log("Tag filter results:");
for (const [doc, score] of tagFilterResults) {
console.log(`* [SIM=${score.toFixed(3)}] ${doc.pageContent}`);
console.log(` Metadata: ${JSON.stringify(doc.metadata)}`);
}
// Search with NUMERIC range filtering
const numericFilterResults =
await vectorStoreWithSchema.similaritySearchVectorWithScoreAndMetadata(
await embeddings.embedQuery("high quality content"),
5,
{
score: { min: 90, max: 100 }, // Score between 90 and 100
category: ["programming", "ai"], // Multiple categories
}
);
console.log("Numeric filter results:");
for (const [doc, score] of numericFilterResults) {
console.log(`* [SIM=${score.toFixed(3)}] ${doc.pageContent}`);
console.log(
` Score: ${doc.metadata.score}, Category: ${doc.metadata.category}`
);
}
// Search with TEXT field filtering
const textFilterResults =
await vectorStoreWithSchema.similaritySearchVectorWithScoreAndMetadata(
await embeddings.embedQuery("development guide"),
3,
{
description: "comprehensive guide", // Text search in description field
score: { min: 85 }, // Minimum score of 85
}
);
console.log("Text filter results:");
for (const [doc, score] of textFilterResults) {
console.log(`* [SIM=${score.toFixed(3)}] ${doc.pageContent}`);
console.log(` Description: ${doc.metadata.description}`);
}
数值范围查询选项
对于数值字段,您可以指定各种范围查询:
// Exact value match
{ score: 95 }
// Range with both min and max
{ score: { min: 80, max: 100 } }
// Only minimum value
{ score: { min: 90 } }
// Only maximum value
{ score: { max: 95 } }
错误处理和验证
自定义架构提供带有有用错误消息的自动验证:
try {
// This will fail validation - missing required userId field
const invalidDoc: Document = {
pageContent: "Some content without required metadata",
metadata: {
category: "test",
// Missing required userId field
},
};
await vectorStoreWithSchema.addDocuments([invalidDoc]);
} catch (error) {
console.log("Validation error:", error.message);
// Output: "Required metadata field 'userId' is missing"
}
try {
// This will fail validation - wrong type for score field
const wrongTypeDoc: Document = {
pageContent: "Content with wrong metadata type",
metadata: {
userId: "user123",
score: "not-a-number", // Should be number, not string
},
};
await vectorStoreWithSchema.addDocuments([wrongTypeDoc]);
} catch (error) {
console.log("Type validation error:", error.message);
// Output: "Metadata field 'score' must be a number, got string"
}
性能优势
使用自定义 schema 有几个性能优势:
- **索引元数据字段**:单独的元数据字段分别建立索引,支持快速过滤
- **类型优化查询**:数字和标签字段使用优化的查询结构
- **减少数据传输**:搜索结果中仅返回相关字段
- **更好的查询规划**:Redis 可以根据字段类型和索引优化查询
向后兼容性
自定义 schema 功能完全向后兼容。没有自定义 schema 的现有 Redis 向量存储将完全按照以前的方式继续工作。您可以逐步迁移到新索引或重建现有索引时的自定义 schema。
API 参考
有关所有 RedisVectorStore 功能和配置的详细文档,请访问 API 参考.