
LangChain.js 与 Neo4j 图数据库集成指南图谱、向量检索与对话记忆实战【免费下载链接】langchainjsThe agent engineering platform项目地址: https://gitcode.com/GitHub_Trending/la/langchainjs本篇指南围绕langchain/neo4j集成包展开介绍如何在 LangChain.js 应用中接入 Neo4j及兼容 Bolt 协议的 Memgraph图数据库包括图数据库封装Neo4jGraph、基于向量索引的Neo4jVectorStore、会话消息历史存储Neo4jChatMessageHistory以及自然语言 → Cypher → 答案的问答链GraphCypherQAChain。读完本文你将掌握从安装、初始化、写入图数据、混合检索到搭建完整图问答应用的完整方案。包概览与适用场景langchain/neo4j是 LangChain.js 官方提供的 Neo4j 图数据库集成包源码位于 libs/providers/langchain-neo4j核心入口统一从 src/index.ts 导出。它同时兼容 Memgraph一款同样使用 Bolt 协议的内存图数据库。该包提供的组件可分为四类组件类型典型用途Neo4jGraph/MemgraphGraph图数据库封装连接管理、Schema 自省、Cypher 查询、结构化图文档写入Neo4jVectorStore向量存储基于 Neo4j 向量索引的相似度检索、混合检索、元数据过滤Neo4jChatMessageHistory聊天历史存储将会话消息持久化到图数据库支持滑动窗口GraphCypherQAChain问答链面向图数据的自然语言问答LLM 生成 Cypher 查询从 package.json 可以看到该包将neo4j-driver^6.2.0作为直接依赖自动安装将langchain/core作为必要 peer dependency、langchain/classic作为可选 peer dependency仅GraphCypherQAChain需要。因此按文档安装时只需显式安装两个包即可npm install langchain/neo4j langchain/core如需使用GraphCypherQAChain额外安装langchain/classic。运行时要求 Node.js 20见 package.json。Neo4jGraph图数据库的基础封装Neo4jGraph是对 Neo4j 驱动的轻量封装提供连接管理、Schema 自省和查询执行三类能力。初始化与基本用法import { Neo4jGraph } from langchain/neo4j; const graph await Neo4jGraph.initialize({ url: bolt://localhost:7687, username: neo4j, password: password, database: neo4j, // 可选默认 neo4j }); // 获取数据库 schema console.log(graph.getSchema()); // 执行 Cypher 查询 const results await graph.query(MATCH (n:Person) RETURN n.name LIMIT 10); // 关闭连接 await graph.close();Neo4jGraph.initialize的完整配置项定义在 src/graphs/neo4j_graph.ts配置项类型默认值说明urlstring必填Bolt 连接地址如bolt://localhost:7687username/passwordstring必填数据库认证凭据databasestringneo4j目标数据库名Memgraph 默认为memgraphtimeoutMsnumber无事务超时时间毫秒透传给驱动的事务配置enhancedSchemabooleanfalse是否启用增强 Schema 自省从源码看initialize是一个异步工厂方法内部执行三步创建驱动实例若 URL/凭据非法会抛出 Could not create a Neo4j driver instance... 错误→verifyConnectivity()调用driver.getServerInfo()验证连通性→refreshSchema()刷新 Schema 缓存随后将实例返回。其中refreshSchema依赖 Neo4j 的 APOC 插件apoc.meta.data()若插件缺失会抛出明确提示要求安装 APOC 并在配置中放行该过程。query方法返回记录数组内部会把 Neo4j 的Int整数、Node、Relationship、Path等类型递归转换为普通 JS 对象方便直接消费默认使用WRITE路由可通过第三参数指定READ路由。Enhanced Schema更细粒度的元数据自省默认情况下getSchema()返回的是格式化后的精简 Schema 字符串如Person {name: STRING, age: INTEGER}。开启enhancedSchema: true后初始化过程会进一步调用apoc.meta.graphSample()并逐标签/关系类型执行统计分析产出更丰富的属性信息const graph await Neo4jGraph.initialize({ url: bolt://localhost:7687, username: neo4j, password: password, enhancedSchema: true, });从 src/graphs/neo4j_graph.ts 的实现看增强模式的行为由几个关键阈值控制DISTINCT_VALUE_LIMIT 10字符串属性的去重值数量小于等于 10 时Schema 中展示完整的Available options: ...取值列表超过 10 则只给出一个Example示例值避免 Schema 过长EXHAUSTIVE_SEARCH_LIMIT 10000标签对应节点数小于 1 万时走穷举统计收集去重值、min/max、distinct count否则只采样前 5 个节点控制自省开销LIST_LIMIT 128LIST 类型属性的最小尺寸超过 128 时跳过不纳入 Schema数字类型INTEGER/FLOAT/DATE 等输出Min/Max与去重计数BOOLEAN、POINT、DURATION属性不参与增强统计。增强 Schema 还支持利用数据库已有 RANGE 索引通过apoc.schema.properties.distinct快速获取去重值避免全表扫描。向图数据库写入结构化图文档Neo4jGraph支持将从文本中抽取出的节点与关系以结构化图文档的形式写入数据库这为构建知识图谱类应用例如从文档抽取实体与关系后入库提供了直接通路。import { Neo4jGraph, Node, Relationship, GraphDocument, } from langchain/neo4j; import { Document } from langchain/core/documents; const source new Document({ pageContent: Alice works at Acme Corp., metadata: { id: doc1 }, }); const alice new Node({ id: alice, type: Person, properties: { name: Alice }, }); const acme new Node({ id: acme, type: Company, properties: { name: Acme Corp }, }); const worksAt new Relationship({ source: alice, target: acme, type: WORKS_AT, }); const graphDoc new GraphDocument({ nodes: [alice, acme], relationships: [worksAt], source, }); await graph.addGraphDocuments([graphDoc]);三种数据结构定义在 src/graphs/document.tsNode{ id, type, properties }type默认Node即图中的标签LabelRelationship{ source, target, type, properties }连接两个节点type为关系类型GraphDocument{ nodes, relationships, source }source记录该图文档的来源Document。addGraphDocuments的底层实现src/graphs/neo4j_graph.ts有几个值得注意的细节若source.metadata.id缺失会自动用sha256(pageContent)生成稳定文档 ID节点写入使用apoc.merge.node以id为键做 MERGE存在即更新不存在则创建保证幂等关系类型会被replace(/ /g, _).toUpperCase()规范化空格转下划线、统一大写可选配置AddGraphDocumentsConfig支持两个开关await graph.addGraphDocuments([graphDoc], { baseEntityLabel: true, // 为所有实体附加统一的基础标签 __Entity__ includeSource: true, // 在图中同时创建 Document 节点并建立 (:Document)-[:MENTIONS]-(实体) 关系 });baseEntityLabel: true时写入前会自动创建__Entity__标签上的id唯一约束对应源码导出的常量BASE_ENTITY_LABEL并先 MERGE 实体节点、再通过apoc.create.addLabels追加其具体标签includeSource: true则通过INCLUDE_DOCS_QUERY将文档内容与元数据一并入库并建立MENTIONS关系便于溯源。Neo4jVectorStore基于向量索引的检索存储Neo4jVectorStore是 Neo4j 官方 vector index 之上的向量存储实现在初始化时会自动创建向量索引支持向量检索、混合检索向量 全文以及元数据过滤。从文档创建向量存储import { Neo4jVectorStore } from langchain/neo4j; import { OpenAIEmbeddings } from langchain/openai; const embeddings new OpenAIEmbeddings(); const vectorStore await Neo4jVectorStore.fromDocuments(docs, embeddings, { url: bolt://localhost:7687, username: neo4j, password: password, indexName: vector, nodeLabel: Chunk, textNodeProperty: text, embeddingNodeProperty: embedding, }); // 相似度检索 const results await vectorStore.similaritySearch(What is Neo4j?, 4); // 带分数的相似度检索 const resultsWithScore await vectorStore.similaritySearchWithScore( What is Neo4j?, 4 ); // 关闭连接 await vectorStore.close();Neo4jVectorStoreArgs的完整配置定义在 src/vectorstores/neo4j_vector.ts常用项及源码中的默认值如下配置项默认值说明url/username/password必填连接信息databaseneo4j目标数据库indexNamevector向量索引名nodeLabelChunk存储向量的节点标签textNodePropertytext文本内容属性名embeddingNodePropertyembedding向量属性名keywordIndexNamekeyword全文索引名hybrid 模式用searchTypevectorvector或hybridindexTypeNODENODE或RELATIONSHIP后者查询关系向量preDeleteCollectionfalse初始化时先删除同名索引与数据retrievalQuery自动生成自定义检索 Cypher返回 text/metadata/scoretextNodeProperties[]多文本属性fromExistingGraph等场景createIdIndextrue是否为节点id创建唯一约束底层初始化流程initialize会创建驱动 →verifyAuthentication验证凭据 → 用embeddings.embedQuery(foo)探测向量维度 → 检查同名索引是否存在不存在则通过db.index.vector.createNodeIndex创建相似度度量固定为cosine即DistanceStrategy默认值。写入文档时addVectors使用MERGE (c:\Chunk {id: row.id})按id幂等写入再通过db.create.setVectorProperty设置向量属性批量事务按 1000 行切分。fromTexts与fromDocuments 语义一致只是入参为纯文本数组。Hybrid Search向量 全文混合检索searchType: hybrid时检索同时执行向量查询与全文full-text查询两者各自按最高分归一化后取最大值融合排序const vectorStore await Neo4jVectorStore.fromDocuments(docs, embeddings, { url: bolt://localhost:7687, username: neo4j, password: password, searchType: hybrid, indexName: vector, keywordIndexName: keyword, nodeLabel: Chunk, });混合模式的实现细节src/vectorstores/neo4j_vector.ts初始化时若检测不到指定keywordIndexName的全文索引会自动执行CREATE FULLTEXT INDEX keyword FOR (n:\Chunk) ON EACH [n.text] 创建查询阶段先分别调用db.index.vector.queryNodes与db.index.fulltext.queryNodes各自将原始分数除以组内最大分实现 0–1 归一化再对两条结果取max(score)排序取 Top-K全文查询的输入会先经过removeLuceneChars源码位于 neo4j_vector.ts将 - | ! ( ) { } [ ] ^ ~ * ? : \等 Lucene 特殊字符替换为空格避免查询语法被意外注入。连接已有索引若索引已在 Neo4j 中预先创建例如由运维或其它流程建立用fromExistingIndex直接接入无需重新建索引const vectorStore await Neo4jVectorStore.fromExistingIndex(embeddings, { url: bolt://localhost:7687, username: neo4j, password: password, indexName: my_existing_index, });该方法会通过SHOW INDEXES校验索引存在性与维度匹配索引不存在会抛出提示核对索引名嵌入函数维度与索引维度不一致会明确报错。hybrid 模式则额外要求全文索引存在且向量索引与全文索引必须指向同一个节点标签。补充源码还提供了fromExistingGraph静态方法用于对已有图数据按指定文本属性批量生成向量并回填db.create.setVectorProperty适合对存量节点做离线向量化。元数据过滤similaritySearch/similaritySearchWithScore的第三个参数支持filter按节点属性过滤检索结果要求 Neo4j 5.18const results await vectorStore.similaritySearch(query, 4, { filter: { category: science, year: { $gte: 2020 }, }, });完整支持的操作符源码 neo4j_vector.ts 中SUPPORTED_OPERATORS操作符Cypher 映射说明$eq相等无操作符的裸值默认视为$eq$ne不等$lt/$lte/$gt/$gte大小比较$in/$ninIN/NOT IN集合包含/不包含元素须为 string/number/boolean$likeCONTAINS子串包含注意实现为 CONTAINS值尾部通配符会被截掉$iliketoLower(...) CONTAINS大小写不敏感的子串包含$between低值 n.field 高值区间过滤值为[low, high]$and/$orAND/OR逻辑组合值为子过滤条件数组过滤实现位于constructMetadataFilterneo4j_vector.ts多字段同时出现时自动以AND拼接字段名需符合合法标识符正则否则抛错参数名按位置自动编号param_1、param_2_low等杜绝 Cypher 注入。几个使用限制需要留意过滤仅支持searchType: vector与 hybrid 检索互斥组合使用会直接抛错依赖版本检查源码_verifyVersion向量索引要求 Neo4j5.11元数据过滤要求5.18Aura 版本会单独做版本解析Enterprise 版会为过滤查询附加CYPHER runtime parallel并行运行时前缀以提升性能。Neo4jChatMessageHistory图数据库中的对话记忆Neo4jChatMessageHistory将聊天消息持久化到 Neo4j适合多轮对话场景下的消息存取与 LangChain 的RunnableWithMessageHistory等组件可无缝组合。import { Neo4jChatMessageHistory } from langchain/neo4j; import { HumanMessage, AIMessage } from langchain/core/messages; const history await Neo4jChatMessageHistory.initialize({ url: bolt://localhost:7687, username: neo4j, password: password, sessionId: my-session-id, // 可选缺省时自动生成 UUID windowSize: 5, // 可选默认 3 }); // 追加消息 await history.addMessage(new HumanMessage(Hello!)); await history.addMessage(new AIMessage(Hi there! How can I help you?)); // 读取消息 const messages await history.getMessages(); // 清空历史 await history.clear(); // 关闭连接 await history.close();配置项定义在 src/stores/message/neo4j.ts除连接信息外还有三个可选参数配置项默认值说明sessionId自动生成uuidv4()会话标识同一会话共享历史sessionNodeLabelChatSession会话节点的标签messageNodeLabelChatMessage消息节点的标签windowSize3读取时保留的消息窗口大小读取最近消息条数从源码看其存储模型是一个双向链表式的图结构每个会话有一个ChatSession节点通过LAST_MESSAGE关系指向最后一条消息消息节点之间用NEXT关系串成链。addMessage会用一条 Cypher 完成创建新消息节点、断开旧 LAST_MESSAGE、建立新 LAST_MESSAGE、并让旧末条消息指向新消息的原子操作getMessages通过-[:NEXT*0..windowSize*2-1]-()沿链回溯最多windowSize条消息每次读写各占一个单位再借助langchain/core/messages的mapStoredMessagesToChatMessages还原为标准BaseMessage对象Human/AI/System 等类型由节点上的type属性区分。该组件继承自BaseListChatMessageHistory因此可以直接传给 LangChain 的RunnableWithMessageHistory等记忆机制用于多轮对话import { RunnableWithMessageHistory } from langchain/core/runnables; const withHistory new RunnableWithMessageHistory({ runnable: model, // 任意 Runnable如 ChatOpenAI getMessageHistory: () history, inputMessagesKey: input, historyMessagesKey: history, }); await withHistory.invoke( { input: 继续刚才的话题 }, { configurable: { sessionId: my-session-id } } );GraphCypherQAChain自然语言驱动的图问答GraphCypherQAChain是一个Text-to-Cypher问答链将用户问题交给 LLM 生成 Cypher 查询在图上执行查询再把结果交给 LLM 综合成自然语言答案。它继承自langchain/classic的BaseChain因此需要将langchain/classic作为可选依赖安装见 package.json 的 peerDependenciesMeta 声明。import { Neo4jGraph, GraphCypherQAChain } from langchain/neo4j; import { ChatOpenAI } from langchain/openai; const graph await Neo4jGraph.initialize({ url: bolt://localhost:7687, username: neo4j, password: password, }); const llm new ChatOpenAI({ model: gpt-4o-mini, temperature: 0 }); const chain GraphCypherQAChain.fromLLM({ graph, llm, returnIntermediateSteps: true, }); const result await chain.invoke({ query: Who played in Pulp Fiction? }); console.log(result.result);也可以拆分生成 Cypher与生成答案两个环节使用不同模型例如用更强的模型写 Cypher、用更经济的模型总结答案const chain GraphCypherQAChain.fromLLM({ graph, cypherLLM: new ChatOpenAI({ model: gpt-4o, temperature: 0 }), qaLLM: new ChatOpenAI({ model: gpt-4o-mini, temperature: 0 }), });fromLLM的可配置项源码 src/chains/graph_qa/cypher.ts配置项默认值说明graph必填Neo4jGraph实例链会读取getSchema()作为 Cypher 生成上下文llm-单模型同时承担 Cypher 生成与答案合成cypherLLM/qaLLM-分别指定两个模型与llm二选一cypherPrompt/qaPrompt内置模板自定义提示词模板returnIntermediateStepsfalse返回intermediateSteps含生成的 Cypher 与查询结果便于调试returnDirectfalse为true时只返回查询结果、跳过答案合成topK10限制查询返回的路径数量追加到生成的 Cypher 中inputKey/outputKeyquery/result输入输出键名链的执行分为三个阶段① 用内置的CYPHER_GENERATION_PROMPT将图 Schema 与问题喂给 LLM 生成 Cypher② 通过graph.query在图上执行③ 将结果连同原问题交给CYPHER_QA_PROMPT合成最终答案。两个提示词模板定义在 src/chains/graph_qa/prompts.ts均从 src/index.ts 导出可复用或覆盖。该链的实现与提示词均有对应测试 tests/cypher.test.ts 与 tests/prompts.test.ts。MemgraphGraphBolt 协议兼容的图数据库接入MemgraphGraph是Neo4jGraph的子类源码 src/graphs/memgraph_graph.ts用于接入同样基于 Bolt 协议的 Memgraph。与 Neo4j 的差异主要在 Schema 自省方式上Memgraph 通过其 LLM 工具过程CALL llm_util.schema(raw)获取原始 Schema再在客户端格式化为与Neo4jGraph一致的结构化形式。import { MemgraphGraph } from langchain/neo4j; const graph await MemgraphGraph.initialize({ url: bolt://localhost:7687, username: memgraph, password: password, }); console.log(graph.getSchema()); await graph.close();MemgraphGraphConfig仅含url/username/password/database默认memgraph不支持enhancedSchema其 Schema 输出格式为Node name: ..., Node properties: {...}与(:Start)-[:TYPE]-(:End)形式的文本。安全注意事项本文档涉及的数据库组件图封装、向量存储、聊天历史都接受连接凭据并且GraphCypherQAChain会执行 LLM 生成的 Cypher 语句。官方安全文档见 LangChain 安全文档与源码中各组件的安全注释均强调凭据最小化使用仅包含必要权限的窄范围凭据优先创建只读用户防止被诱导执行删除、变更数据或读取敏感数据的操作这尤其重要——Cypher 是强表达能力的查询语言一旦 LLM 生成的语句被注入或误用可能导致数据损坏或泄露。从 langchain/community 迁移若此前使用langchain/community中的 Neo4j 集成迁移只需将分散的导入收敛到新包// 迁移前 import { Neo4jGraph } from langchain/community/graphs/neo4j_graph; import { Neo4jVectorStore } from langchain/community/vectorstores/neo4j_vector; import { Neo4jChatMessageHistory } from langchain/community/stores/message/neo4j; import { GraphCypherQAChain } from langchain/community/chains/graph_qa/cypher; // 迁移后 import { Neo4jGraph, Neo4jVectorStore, Neo4jChatMessageHistory, GraphCypherQAChain, } from langchain/neo4j;本地开发与测试若要在本仓库内开发调试该包使用 pnpm 工作区命令对应 package.json 中的 scripts# 安装依赖 pnpm install # 构建 pnpm --filter langchain/neo4j build # 运行测试 pnpm --filter langchain/neo4j test # Lint pnpm --filter langchain/neo4j lint仓库为各组件提供了完整的单元测试与集成测试参考实现图与 Schema 相关见 graphs/tests/neo4j_graph.test.ts、graphs/tests/document.test.ts 与 graphs/tests/memgraph_graph.test.ts向量检索见 vectorstores/tests/neo4j_vector.test.ts消息历史见 stores/message/tests/neo4j.test.ts。阅读这些测试可以快速掌握各组件在真实或模拟数据库上的调用方式与边界行为。【免费下载链接】langchainjsThe agent engineering platform项目地址: https://gitcode.com/GitHub_Trending/la/langchainjs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考