
LangChain.js Redis 集成指南从 RedisVectorStore 迁移到 FluentRedisVectorStore 的完整实战【免费下载链接】langchainjsThe agent engineering platform项目地址: https://gitcode.com/GitHub_Trending/la/langchainjs本文基于langchain/redis包系统讲解 LangChain.js 与 RedisRediSearch向量存储的集成方式重点覆盖从旧版RedisVectorStore迁移到新版FluentRedisVectorStore的完整流程包括元数据 Schema 改造、类型安全过滤表达式Tag / Num / Text / Geo / Timestamp的使用、数据库迁移与业务代码改写。读完本文你将掌握如何在新项目中落地更强大、类型安全的 Redis 混合向量检索方案并能平滑迁移存量代码。一、langchain/redis 包概览langchain/redis是 LangChain.js 官方仓库中针对 Redis 的集成包通过 Redis 官方 SDK 提供向量存储、聊天历史与 LLM 缓存三类能力。从包的源码入口 src/index.ts 可以看出它统一导出以下模块模块文件提供能力vectorstores.ts基础版RedisVectorStore旧版、简单过滤vectorstores_fluent.ts进阶版FluentRedisVectorStore推荐、类型安全过滤filters.ts过滤器表达式体系Tag/Num/Text/Geo/Timestamp/Customschema.ts元数据 Schema 定义、序列化与推断工具chat_histories.tsRedisChatMessageHistory会话消息历史caches.tsRedisCache基于 Redis 的 LLM 结果缓存该包依赖redis^6.2.1见 package.json并以langchain/core作为 peer 依赖适用于 Node.js 20 环境。注意FluentRedisVectorStore依赖 RediSearch 模块FT.SEARCH、FT.CREATE等命令。若 Redis 实例不支持 RediSearch执行FT.INFO会抛出 unknown command 错误源码在 vectorstores_fluent.ts 的checkIndexState中对此有明确校验。二、安装与开发环境2.1 安装在项目中使用 Redis 向量存储需要同时安装集成包与核心包npm install langchain/redis langchain/core2.2 本地开发本包若要在当前仓库中开发或调试langchain/redis包可依次执行# 安装依赖在仓库根目录 pnpm install # 构建包 pnpm build # 或者只构建本包 pnpm build --filter langchain/redis测试约定单元测试文件以.test.ts结尾集成测试以.int.test.ts结尾均放在src/tests/目录下运行命令为pnpm test # 单元测试 pnpm test:int # 集成测试质量检查pnpm lint pnpm format新增导出入口时要么在 src/index.ts 中 import 并 re-export要么在package.json的exports字段中登记新入口后重新pnpm build。三、两大核心类RedisVectorStore 与 FluentRedisVectorStore3.1 演进背景RedisVectorStore是基础实现元数据以 JSON blob 形式存储在单个字段中metadataKey默认值为metadata过滤能力仅支持字符串数组或原始查询字符串条件之间只能用 AND 拼接。源码中该类已被标注为deprecated见 vectorstores.ts新项目推荐直接使用FluentRedisVectorStore。FluentRedisVectorStore是推荐方案源码中RedisVectorStoreAdvanced只是它的向后兼容别名见 vectorstores_fluent.ts。它要求显式定义MetadataFieldSchema将每个元数据字段作为独立的被索引字段存储并提供类型安全的FilterExpression过滤 API支持 AND / OR / 嵌套组合以及 Tag、Numeric、Text、Geo、Timestamp 五种条件类型。3.2 关键差异对照特性RedisVectorStoreFluentRedisVectorStore元数据 Schema 定义Recordstring, CustomSchemaFieldMetadataFieldSchema[]元数据 Schema 推断不支持仅支持自定义 Schema支持可根据添加文档时的元数据自动推断预过滤定义方式字符串数组或原始查询字符串类型安全的FilterExpression对象预过滤嵌套条件所有条件仅按单个 AND 连接支持 AND、OR、嵌套预过滤条件类型Numeric、Tag、TextNumeric、Tag、Text、Geo、Timestamp元数据存储JSON blob 可选索引字段独立索引字段无 JSON blob对比结论同样可以从源码中验证RedisVectorStoreConfig.customSchema类型为Recordstring, CustomSchemaField见 vectorstores.ts而FluentRedisVectorStoreConfig.customSchema类型为MetadataFieldSchema[]见 vectorstores_fluent.ts写入时前者调用escapeSpecialChars(JSON.stringify(metadata))存 JSON blob后者则逐字段serializeMetadataField后multi.hSet到独立的 hash 字段见 vectorstores_fluent.ts。四、从 RedisVectorStore 迁移到 FluentRedisVectorStore六步指南Step 1更新导入语句迁移前RedisVectorStoreimport { RedisVectorStore } from langchain/redis;迁移后FluentRedisVectorStoreimport { FluentRedisVectorStore, Tag, Num, Text, Geo } from langchain/redis;Step 2转换元数据 Schema 格式Schema 格式从“对象键值结构”改为“数组结构”。字段类型从SCHEMA_FIELD_TYPE.TAG这类枚举值变为小写字符串字面量tag/numeric/text/geo旧版大写选项如SORTABLE则收拢进options对象。迁移前RedisVectorStoreconst customSchema { userId: { type: SchemaFieldTypes.TAG, required: true }, price: { type: SchemaFieldTypes.NUMERIC, SORTABLE: true }, description: { type: SchemaFieldTypes.TEXT }, location: { type: SchemaFieldTypes.GEO }, };迁移后FluentRedisVectorStoreconst customSchema [ { name: userId, type: tag }, { name: price, type: numeric, options: { sortable: true } }, { name: description, type: text }, { name: location, type: geo }, ];其中MetadataFieldSchema支持的全部选项见源码 schema.ts字段适用类型说明默认值name全部元数据字段名必填type全部tag/text/numeric/geo必填options.separatortagTag 字段的多值分隔符,DEFAULT_TAG_SEPARATORoptions.caseSensitivetagTag 是否大小写敏感匹配falseoptions.weighttext全文检索评分权重1.0options.noStemtext是否禁用词干提取falseoptions.sortablenumerictext 亦可是否开启排序falseoptions.noindex全部是否不建立索引false时间戳字段没有独立的 timestamp 类型应声明为type: numeric并存储 Unix 纪元秒见 filters.ts。Step 3更新实例化配置迁移前const vectorStore await RedisVectorStore.fromDocuments( documents, embeddings, { redisClient: client, indexName: products, customSchema: { category: { type: SchemaFieldTypes.TAG }, price: { type: SchemaFieldTypes.NUMERIC, SORTABLE: true }, }, } );迁移后const vectorStore await FluentRedisVectorStore.fromDocuments( documents, embeddings, { redisClient: client, indexName: products, customSchema: [ { name: category, type: tag }, { name: price, type: numeric, options: { sortable: true } }, ], } );FluentRedisVectorStoreConfig其余配置项见 vectorstores_fluent.tsindexOptions向量索引算法配置。默认{ ALGORITHM: HNSW, DISTANCE_METRIC: COSINE }可选CreateSchemaFlatVectorFieldFLAT 暴力检索小数据集精确或CreateSchemaHNSWVectorFieldHNSW 近似检索大数据集高效支持M、EF_CONSTRUCTION、EF_RUNTIME见 schema.ts。createIndexOptions索引创建选项其中PREFIX必须通过keyPrefix设置。keyPrefix文档 key 前缀默认doc:${indexName}:。contentKey正文存储字段名默认content。metadataKey元数据字段名默认metadataFluent 版不再存 JSON blob该字段仅用于兼容检测。vectorKey向量存储字段名默认content_vector。filter可选的全局FilterExpression在每次检索时生效。ttl文档过期时间秒写入时通过multi.expire设置。customSchema必填未提供时createIndex会直接抛错见 vectorstores_fluent.ts。Step 4改写带过滤条件的检索查询过滤 API 变化最大不再传元数据对象或字符串数组而是用流式过滤表达式。迁移前RedisVectorStore// 简单的元数据过滤 const results await vectorStore.similaritySearchVectorWithScoreAndMetadata( queryVector, 5, { category: electronics, price: { min: 100, max: 1000 } } ); // 或者使用字符串数组过滤 const results await vectorStore.similaritySearchVectorWithScore( queryVector, 5, [electronics, gadgets] );迁移后FluentRedisVectorStore// 自定义过滤表达式 const results await vectorStore.similaritySearchVectorWithScore( queryVector, 5, Tag(category).eq(electronics).and(Num(price).between(100, 1000)) ); // 基础过滤表达式 const results await vectorStore.similaritySearchVectorWithScore( queryVector, 5, Tag(metadata).eq(electronics, gadgets) );注意FluentRedisVectorStore的similaritySearchVectorWithScore只接受FilterExpression传入其他类型会抛出明确错误见 vectorstores_fluent.ts旧版特有的similaritySearchVectorWithScoreAndMetadata方法在 Fluent 版中已不存在。Step 5数据库 Schema 迁移FluentRedisVectorStore只支持“元数据存独立字段与向量数据、正文数据并列”的存储布局与旧版“元数据以 JSON blob 存在单一字段”的布局不兼容。为规避歧义结果官方建议以新 Schema 创建新索引并迁移存量数据。旧版customSchema可按 Step 2 的方式转换成新版数组格式后复用。Step 6更新业务代码将应用中所有RedisVectorStore实例替换为FluentRedisVectorStore并同步调整过滤用法迁移前async function searchProducts(query: string, category?: string) { const results await vectorStore.similaritySearchVectorWithScoreAndMetadata( await embeddings.embedQuery(query), 5, category ? { category } : undefined ); return results; }迁移后async function searchProducts(query: string, category?: string) { const filter category ? Tag(category).eq(category) : undefined; const results await vectorStore.similaritySearchVectorWithScore( await embeddings.embedQuery(query), 5, filter ); return results; }五、过滤器体系源码级解析FluentRedisVectorStore的过滤能力全部来自 filters.ts。所有过滤器继承抽象基类FilterExpression该基类提供and()与or()组合方法分别生成 RediSearch 的空格连接(a b)与竖线连接(a|b)语法并通过toString()输出最终 RediSearch 查询串。查询构建时buildQuery会把过滤串拼入 KNN 查询${filter} [KNN ${k} ${vectorKey} $vector AS vector_score]见 vectorstores_fluent.ts。5.1 五种过滤器与便利函数过滤器类便利函数用途生成的 RediSearch 语法示例TagFilterTag(field)分类数据的精确匹配多值用\|表示 ORcategory:{electronics}NumericFilterNum(field)数值范围/精确比较区间[ ]含端点、( )不含price:[(50 inf]TextFilterText(field)全文检索精确短语、通配、模糊、分词匹配title:(wireless headphones)GeoFilterGeo(field)经纬度半径检索location:[-122.4194 37.7749 10 km]TimestampFilterTimestamp(field)时间范围自动把Date转 Unix 秒created_at:[1672531200 1703980800]CustomFilterCustom(query)直接透传原始 RediSearch 查询串原样返回各过滤器的方法签名均支持.and()/.or()组合与ne取反Tag(category).eq(electronics)/.eq([a,b])/.ne(archived)Num(price).eq(99.99)/.ne/.gt/.gte/.lt/.lte/.between(50, 200)Text(title).exact(wireless headphones)/.match(...)/.wildcard(*phone*)/.fuzzy(blutooth)Geo(location).within(lon, lat, radius, km | mi | m | ft)/.outside(...)Timestamp(created_at).gt(new Date(2023-01-01))/.between(start, end)/.gte(1672531200)Custom((brand:{Apple} year:[2020 inf]))5.2 安全机制字段名校验assertSafeRedisearchFieldName只允许^[a-zA-Z0-9_.-]$防止注入非法字段见 query_safety.ts。值转义escapeRedisearchValue会转义 RediSearch 特殊字符{ } [ ] : ; ! # $ % ^ * ( ) - ~ \ | ?等通配/空白场景可分别通过preserveWildcard、preserveWhitespace选项放行。六、Schema 推断与一致性校验FluentRedisVectorStore支持根据文档元数据自动推断 SchemainferMetadataSchema见 schema.ts推断规则如下形如lon,lat的字符串 →geo数字或Date对象 →numeric任意类型的数组 →tag其余类型 →text当传入文档时createIndex会调用checkForSchemaMismatch将自定义 Schema 与推断 Schema 做顺序无关、仅比较 name 与 type的一致性比对不一致时打印警告提示可能配置了非法 Schema见 vectorstores_fluent.ts。序列化/反序列化同样按字段类型处理serializeMetadataField/deserializeMetadataField见 schema.tstag数组用分隔符默认,join 存储读取时按分隔符拆回数组numericDate自动转 Unix 纪元秒读取回数字需要时可手动new Date(v * 1000)还原geo[lon, lat]数组存为lon,lat字符串读取时解析回数组text原样字符串。七、数据增删与常用操作7.1 写入fromTexts/fromDocuments静态方法负责“建索引 批量写入”。写入逻辑见 vectorstores_fluent.ts要点向量以Float32Array的 Buffer 形式写入vectorKey字段每次写入前自动检查索引不存在则按 Schema 创建默认批量大小batchSize 1000通过multi.exec()分批提交设置ttl时对每个 key 执行expire。7.2 删除// 删除全部丢弃索引及其关联文档 await vectorStore.delete({ deleteAll: true }); // 按 ID 删除自动拼接 keyPrefix await vectorStore.delete({ ids: [doc1, doc2] });删除逻辑见 vectorstores_fluent.tsdeleteAll走ft.dropIndex(..., { DD: true })ids走del命令key 自动加上keyPrefix。也可直接调用dropIndex(deleteDocuments)管理索引生命周期。7.3 检索similaritySearchVectorWithScore(query, k, filter)返回[Document, number][]文档与相似度分数。内部使用DIALECT: 2、SORTBY: vector_score、LIMIT 0..k并自动在 RETURN 中带上所有自定义 Schema 字段以便重建元数据见 vectorstores_fluent.ts。若同时传入了方法参数filter与构造配置this.filter会抛出 cannot provide both 错误。八、同类能力延伸聊天历史与 LLM 缓存langchain/redis还提供两个常用组件源码同样位于本包内RedisChatMessageHistorychat_histories.ts以 sessionId 为 key、List 结构存储会话消息支持sessionTTL过期与clear()清空可接入ConversationChain的 memory适合多轮对话记忆场景。RedisCachecaches.ts实现BaseCache以prompt llmKey 序号为 key 缓存 LLM 生成结果命中后直接复用响应以降低成本与延迟当前源码标注为已废弃可关注后续版本替代方案。九、总结langchain/redis的演进方向非常清晰以FluentRedisVectorStore取代RedisVectorStore用显式MetadataFieldSchema替代隐式 JSON blob 元数据用类型安全的FilterExpressionTag / Num / Text / Geo / Timestamp / Custom替代脆弱的字符串过滤。迁移时只需按本文六步依次完成导入、Schema、配置、查询、数据库与业务代码的改造即可获得支持 AND/OR 嵌套组合、五类条件的混合向量检索能力。需要深入阅读实现细节时可参考本仓库内的 vectorstores_fluent.ts、filters.ts、schema.ts 及对应的单元/集成测试src/tests。【免费下载链接】langchainjsThe agent engineering platform项目地址: https://gitcode.com/GitHub_Trending/la/langchainjs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考