WeKnora 知识图谱(GraphRAG)功能深度解析:从 Neo4j 配置到实体关系抽取与图谱增强检索
2026/9/13 17:17:07 网站建设 项目流程

WeKnora 知识图谱(GraphRAG)功能深度解析:从 Neo4j 配置到实体关系抽取与图谱增强检索

【免费下载链接】WeKnoraOpen-source LLM knowledge platform: turn raw documents into a queryable RAG, an autonomous reasoning agent, and a self-maintaining Wiki.项目地址: https://gitcode.com/GitHub_Trending/we/WeKnora

导读

本文基于 WeKnora 开源仓库的官方特性文档,系统讲解知识图谱(Knowledge Graph / GraphRAG)功能的完整技术脉络:如何通过两级开关启用该能力、文档入库时如何借助 LLM 抽取实体与关系并写入 Neo4j、问答时又如何沿"实体 → 关联片段"补充关系上下文,与向量检索、关键词检索协同工作。读完本文,你将掌握 WeKnora 知识图谱的配置方法、构建与检索两条核心链路、Neo4j 存储层的底层实现,以及 Agent 模式下query_knowledge_graph工具的使用方式。

知识图谱在文档入库时提取实体与关系,并在问答时沿关联关系检索更多相关片段,可与向量和关键词检索共同使用,为回答补充关系上下文。该功能适用于人物、组织、产品或条款之间关系较多的资料;启用后会增加入库阶段的模型调用,并需要部署 Neo4j。

一、功能概述与适用场景

WeKnora 的知识图谱功能解决的是传统 RAG 的"关系盲区"问题:向量检索擅长语义相似匹配,关键词检索擅长字面命中,但两者都无法直接回答"A 与 B 是什么关系""谁影响了谁"这类需要跨片段串联的问题。图谱功能在文档入库时将散落在各个 chunk 中的实体与关系结构化抽取出来存入图数据库,查询阶段再从用户问题中抽取实体、沿图的一跳邻居关系召回关联片段,从而为生成答案补充关系上下文。

适用场景包括:

  • 人物关系密集的资料:如传记、组织架构、合作网络;
  • 产品与条款关联:如技术文档中多个产品版本、API 模块之间的依赖与从属关系;
  • 跨文档聚合:同一实体出现在多个知识库/多个文件中时,通过chunks属性实现"一实体多出处"的聚合召回。

需要明确的是,启用图谱是有成本的:入库阶段每个文本 chunk 都会触发一次额外的 LLM 抽取调用(源码注释称之为"管线中最昂贵的增强扇出"),同时必须部署 Neo4j 数据库(依赖 APOC 插件)。

二、开启配置:两级开关

图谱功能需要两级开关同时满足才会真正生效——全局的 Neo4j 环境变量开关 + 知识库级别的索引策略开关。

2.1 全局开关:Neo4j 环境变量

NEO4J_ENABLE是知识图谱的唯一全局开关。需要注意版本演进:docker-compose.yml注释明确说明ENABLE_GRAPH_RAG自 v0.1.6 起已被NEO4J_ENABLE取代,Go 主应用不再读取旧变量。

名称类型默认值说明
NEO4J_ENABLEstring空(关闭)置为true启用图谱;container.go 的initNeo4jClient与任务入队、检索管线都会检查它
NEO4J_URIstringbolt://neo4j:7687Neo4j 连接地址(Bolt 协议)
NEO4J_USERNAMEstringneo4j用户名
NEO4J_PASSWORDstringpassword密码

源码层面的两个关键实现细节:

  1. 启动重试与降级initNeo4jClientNEO4J_ENABLE != "true"时直接返回nildriver(不报错),此时Neo4jRepository的所有方法降级为 no-op,仅打印NOT SUPPORT RETRIEVE GRAPH日志;启用时最多重试 30 次(每次间隔 2s)创建 driver 并调用VerifyAuthentication验证连接。
  2. 状态上报GET /system信息接口通过 system.go 的getGraphDatabaseEngine()报告当前图数据库引擎为"Neo4j""Not Enabled",便于运维确认开关是否真正生效。

docker-compose 的neo4j服务预装 APOC 插件(NEO4JLABS_PLUGINS=["apoc"]):图谱写入依赖apoc.merge.node/apoc.merge.relationship,删除依赖apoc.periodic.iterate

2.2 知识库级开关:IndexingStrategy + ExtractConfig

全局开关之外,每个知识库还需在索引策略中打开图谱抽取。核心判断逻辑位于 internal/types/knowledgebase.go:

// IsGraphEnabled checks if knowledge graph extraction is enabled. // Requires both the IndexingStrategy flag and a valid ExtractConfig. func (kb *KnowledgeBase) IsGraphEnabled() bool { return kb != nil && kb.IndexingStrategy.GraphEnabled && kb.ExtractConfig != nil && kb.ExtractConfig.Enabled }

两个组成部分:

  • IndexingStrategy.GraphEnabled(internal/types/indexing_strategy.go):知识库索引策略中的图谱开关,字段名为graph_enabled,默认false;旧字段ExtractConfig.Enabled会在读取时向IndexingStrategy.GraphEnabled单向同步(legacy sync),保证存量配置平滑迁移。
  • ExtractConfiginternal/types/knowledgebase.go):承载抽取的 few-shot 配置,各字段含义如下:
名称类型默认值说明
enabledboolfalse是否启用抽取
textstringfew-shot 示例原文
tags[]stringnil关系类型标签集合
nodes[]*GraphNodenil示例实体节点(name / attributes)
relations[]*GraphRelationnil示例关系(node1 / node2 / type)
custom_instructionsstring领域自定义抽取指令(追加进系统提示,结构化输出协议仍由系统控制)

2.3 配置向导辅助 API

为帮助用户快速搭建ExtractConfig,initialization.go(路由注册见 router.go)提供了三个辅助接口:

  • POST /initialization/extract/text-relationExtractTextRelations):对一段文本(≤5000 字符)按选定标签试跑关系抽取,用于预览效果;
  • POST /initialization/extract/fabri-textFabriText):让 LLM 生成示例文本,辅助填充text字段;
  • POST /initialization/extract/fabri-tagFabriTag):让 LLM 推荐标签,辅助填充tags字段。

三、实体关系抽取流程(图谱构建)

3.1 触发与任务编排

文档解析完成后,knowledge_post_process.go 在增强扇出阶段对每个文本 chunk 计数(启用图谱时graphChunkCount = len(textChunks)),并调用 extract.go 的NewChunkExtractTask逐 chunk 入队:

func NewChunkExtractTask(...) (bool, error) { if strings.ToLower(os.Getenv("NEO4J_ENABLE")) != "true" { logger.Warn(ctx, "NEO4J is not enabled, skip chunk extract task") return false, nil } ... task := asynq.NewTask(types.TypeChunkExtract, payload, asynq.Queue(types.QueueGraph), asynq.MaxRetry(3), asynq.Timeout(30*time.Minute)) ... }

关键工程细节:

  • 任务走独立的 asynqQueueGraph队列,与向量化、摘要等队列隔离;
  • 每个任务MaxRetry=3Timeout=30min,即单 chunk 的抽取有三次重试机会,超时上限半小时;
  • NEO4J_ENABLE未开启时入队函数返回(false, nil)调用方必须释放已占用的pending_subtasks_count计数,否则父知识会永远停留在 "finalizing" 状态(源码注释明确警告了这一死锁风险);
  • 被取消、被删除或被新解析尝试取代(attemptSuperseded)的任务会跳过执行并释放父任务的子任务计数;
  • 每个 chunk 一次 LLM 调用,受模型级后台并发限流(limiter)约束,避免打爆模型服务。

3.2 抽取执行(ChunkExtractService.Handle)

internal/application/service/extract.goChunkExtractService.Handle的执行流程分为五步:

  1. 加载上下文:加载 chunk、知识库与文件级ProcessOverrides,用ResolveProcessConfig求出生效的ExtractConfig(未启用则跳过该 chunk)。
  2. 组装结构化提示:系统协议部分来自config.ExtractManager.ExtractGraph(即 config.yaml 的extract.extract_graph),它是一个分步指令——先"实体抽取 + 属性丰富",再"关系抽取与验证"(关系类型只能从指定列表%s中选择),随后叠加知识库的custom_instructionstagsExtractConfig的 few-shot 示例(Text/Nodes/Relations)。
  3. 调用模型并解析chatpipeline.NewExtractor(chatModel, template).Extract(ctx, chunk.Content)调用 Chat 模型,参数为temperature 0.3max_tokens 4096、关闭 thinking,随后由Formater.ParseGraph解析为types.GraphData(internal/types/extract_graph.go):
type GraphNode struct { Name string `json:"name,omitempty"` Chunks []string `json:"chunks,omitempty"` Attributes []string `json:"attributes,omitempty"` } type GraphRelation struct { Node1 string `json:"node1,omitempty"` Node2 string `json:"node2,omitempty"` Type string `json:"type,omitempty"` }
  1. 回填与写入:为每个节点回填node.Chunks = []string{chunk.ID},随后调用graphEngine.AddGraph(ctx, NameSpace{KnowledgeBase, Knowledge}, ...)写入 Neo4j——这样每个实体都记录了它"出自哪个 chunk",为查询阶段的关联召回奠定基础。
  2. 可观测性:全程由 SpanTracker 追踪,产生postprocess.graph.chunk[i]子 span,记录 nodes/relations 数量与样例,便于在 Langfuse 等追踪平台排障。

3.3 存储后端:Neo4j 仓库实现

internal/application/repository/retriever/neo4j/repository.go 实现interfaces.RetrieveGraphRepositoryAddGraph/DelGraph/SearchNode三个方法),几个关键设计:

  • 命名空间即标签NameSpace{KnowledgeBase, Knowledge}映射为节点标签ENTITY<kb_id>ENTITY<knowledge_id>(连字符替换为下划线),即实体在库中被双层标签命名空间隔离,不同知识库/不同文件的同名实体可共存;
  • 节点属性:含name(实体名)、kg(knowledge_id)、attributes(属性列表)、chunks(来源 chunk ID 列表);
  • 幂等写入:用 APOC 做合并写入,同名实体的chunks取并集,重复解析同一文档不会产生重复节点:
UNWIND $data AS row CALL apoc.merge.node(row.labels, {name: row.name, kg: row.knowledge_id}, row.props, {}) YIELD node SET node.chunks = apoc.coll.union(node.chunks, row.chunks)
  • 级联删除:删除知识/知识库时(knowledge_delete.goknowledgebase.go)调用DelGraph,用apoc.periodic.iterate按 1000 批并行删除边与点,保证大图删除时不会拖垮事务。

四、检索时的图谱增强(GraphRAG)

图谱的价值体现在查询阶段。传统聊天管线(internal/application/service/chat_pipeline)中挂载了两个插件完成"查询实体抽取 + 图谱关联召回"。

4.1 PluginExtractEntity:从用户查询中抽取实体

extract_entity.go挂在QUERY_UNDERSTAND事件上。NEO4J_ENABLE=true时,它先筛选出ExtractConfig.Enabled的知识库(存入chatManage.EntityKBIDs/EntityKnowledge),再使用ExtractManager.ExtractEntity模板(config.yaml 的extract.extract_entity,包含"分析逻辑连接 → 提取关键实体 → 按关联紧密程度排序"三步指令)+ Chat 模型,从用户查询中抽取实体名列表,存入chatManage.Entity

4.2 PluginSearchEntity:图谱关联召回

search_entity.go挂在ENTITY_SEARCH事件上,执行"实体 → 关联 chunk"的补充召回:

  1. 对每个启用图谱的知识库/文件并行调用graphRepo.SearchNode
  2. 底层 Cypher 用n.name CONTAINS nodeText做实体名的模糊匹配,并返回实体的一跳邻居与关系MATCH (n)-[r]-(m) WHERE ANY(...) RETURN n, r, m),合并为chatManage.GraphResult
  3. filterSeenChunk取出图谱节点携带的chunks去掉向量检索已命中的部分,避免重复召回;
  4. chunkRepo拉取对应原文并转换为SearchResult并入候选集。

最终图谱召回的片段与向量、关键词结果一起进入重排与生成阶段,为回答提供关系上下文。

4.3 Agent 模式的 query_knowledge_graph 工具

Agent 模式下,WeKnora 提供query_knowledge_graph工具(internal/agent/tools/query_knowledge_graph.go):

  • 校验各知识库是否配置了图谱(ExtractConfig.Nodes/Relations非空,见Execute中 L177 附近的判定);
  • 并发对多个知识库执行检索,按 chunk 去重排序;
  • 输出中附带各库的图谱配置状态(graph_configs字段,包含实体类型 / 关系类型清单,由summarizeGraphConfig/uniqueSortedNodeNames等辅助函数生成);
  • 未配置图谱的知识库回落为普通混合检索结果,保证 Agent 链路不中断。

五、构建与查询流程图

5.1 构建流程

5.2 查询流程

六、可视化与相关实现边界

关于图谱可视化,需要厘清几个容易混淆的实现:

  • Mermaid 图生成:internal/application/service/graph.go 的graphBuildertypes.GraphBuilder接口的内存版实现(LLM 抽实体 → 抽关系 → 按 PMI×0.6 + Strength×0.4 计算关系权重并归一到 1-10 → 计算实体度数 → 构建 chunk 关联图),其generateKnowledgeGraphDiagram用 DFS 找连通分量并输出 Mermaidgraph TD子图(高频实体高亮、强度 >7 的关系用粗箭头)。注意NewGraphBuilder目前没有被容器装配调用(仓库内无其他引用),属于独立/遗留的图构建与可视化实现,生成的 Mermaid 图输出到日志。
  • prompt 模板:config/prompt_templates/graph_extraction.yaml 提供default_extract_entities等模板(含实体类型枚举 Person/Organization/Location/... 与 JSON 输出协议),经 internal/config/config.go 的extract_entities_prompt_id/extract_relationships_prompt_id解析进Conversation.ExtractEntitiesPrompt/ExtractRelationshipsPrompt,供上述内存版graphBuilder使用;生产异步抽取路径使用的是 config.yaml 中extract.extract_graph/extract.extract_entity模板(ExtractManagerConfig),两者不要混淆。
  • 对外 API:知识图谱本身没有专门的可视化 REST 端点;query_knowledge_graph工具的结构化输出(graph_configs、结果列表)供 Agent 前端渲染。GET /wiki/graphwikiHandler.GetGraph)是 Wiki 功能自己的图接口,与本文的实体关系图谱无关。

七、排查要点速查

现象排查方向
入库后图谱无数据确认两级开关:NEO4J_ENABLE=true且知识库IndexingStrategy.GraphEnabled+ExtractConfig.Enabled同时为真;检查GET /system返回的图引擎是否"Neo4j"
文档卡在 finalizing检查任务是否因NEO4J_ENABLE未开启而未被入队,父任务的pending_subtasks_count计数是否被正确释放
查询不返回图谱结果确认查询实体是否能被name CONTAINS模糊命中;确认该知识库ExtractConfig.Enabled为真
Neo4j 连接失败启动日志查看initNeo4jClient的重试输出,确认NEO4J_URI/账号密码正确、APOC 插件已启用

结语

WeKnora 的知识图谱功能是一套完整的"构建-存储-检索"闭环:以两级开关精确控制启用范围,以独立 asynq 队列承载高成本的 LLM 抽取,以 Neo4j + APOC 实现幂等的图写入与批量删除,最终在查询阶段通过实体抽取与一跳邻居召回为 RAG 答案补充关系上下文。对于人物、组织、产品、条款间关系密集的知识库,这套能力与向量、关键词检索形成了互补的三角检索格局。相关源码可继续深入:存储层 neo4j/repository.go、任务编排 extract.go、容器装配 container.go、Agent 工具 query_knowledge_graph.go。

【免费下载链接】WeKnoraOpen-source LLM knowledge platform: turn raw documents into a queryable RAG, an autonomous reasoning agent, and a self-maintaining Wiki.项目地址: https://gitcode.com/GitHub_Trending/we/WeKnora

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询