1. 项目概述:基于《三国演义》的KAG实战系统
这个项目构建了一个完整的知识图谱增强生成(KAG)系统,以《三国演义》为案例,实现了从文本到知识图谱再到智能问答的全流程闭环。不同于传统的RAG(检索增强生成)方案,我们通过结构化知识图谱解决了文学作品问答中的几个关键痛点:
- 典故变体问题:同一事件在原文中可能有多种表述(如"温酒斩华雄"与"其酒尚温")
- 实体指代问题:人物有字号、别称等多种称呼方式(如"关羽"、"云长"、"关公")
- 章节定位问题:需要精确关联事件与具体章回位置
系统采用Neo4j作为知识图谱存储引擎,通过大语言模型(LLM)自动完成以下关键步骤:
- 从原始文本抽取实体和关系
- 构建带章回锚点的知识图谱
- 生成可执行的Cypher查询
- 实现基于图谱的问答评测
关键创新点:将传统的向量检索与知识图谱的结构化查询相结合,形成混合检索方案。图谱负责精准定位章回,RAG负责证据文本的生成,二者协同提升问答质量。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构与核心组件
2.1 整体数据处理流程
系统采用清晰的五阶段处理流水线:
code复制原始文本 → [知识抽取] → 知识图谱JSON → [Neo4j导入] → 图数据库 → [查询生成] → Cypher执行 → [答案生成] → 最终回答
每个阶段都有对应的JUnit测试类实现,确保工程可复现性。
2.2 关键数据文件说明
-
输入数据:
aigc_chunk_store_to_graph.csv:预处理后的章回文本,每行包含章节标题、索引和内容sanguo-kg-eval.json:评测数据集,包含问题、标准答案和可接受关键词
-
中间产物:
kg_extract_result.json:LLM抽取的知识图谱结构(实体+关系)
2.3 核心Java测试类
系统通过5个测试类实现完整流程:
LlmKgExtractTest:知识抽取KgNeo4jImportTest:图谱构建Neo4jSchemaIntrospectTest:结构探测SanguoKgRecallEvalTest:召回评测KagGraphLLMQATest:问答应用
3. 知识抽取与图谱构建
3.1 实体关系抽取实现
知识抽取阶段采用特定设计的Prompt指导LLM输出结构化结果:
java复制// 示例Prompt核心部分
String prompt = """
从以下文本中提取知识图谱要素:
1. 实体类型:人物(Character)、事件(Event)、地点(Location)、物品(Item)
2. 关系:用中文短语描述(如"效忠于"、"发生于")
3. 输出格式:{
"entities": [{"type":..., "name":...}],
"relations": [{"type":..., "head":..., "tail":...}]
}""";
关键设计考量:
- 关系类型强制使用中文短语,避免英文带来的schema膨胀问题
- 实体名称尽量保留原文表述,不进行归一化处理
- 显式关联实体与章回信息(documentName/chapterTitle等)
3.2 Neo4j图谱建模方案
图谱采用"星型"结构设计,以章回节点为核心锚点:
code复制(:Chapter {chapterKey})
↑
(:Character|Event|Location|Item)-[:APPEARS_IN]->(:Chapter)
这种设计的优势:
- 所有实体通过APPEARS_IN关系关联到具体章回
- 便于实现"事件→章回"的精准定位
- 支持多跳查询扩展(如人物→事件→地点→章回)
导入代码示例:
java复制// 创建章回节点
String cypher = "MERGE (c:Chapter {chapterKey: $chapterKey}) " +
"SET c += $properties";
Map<String, Object> params = Map.of(
"chapterKey", chapterKey,
"properties", Map.of(
"title", chapterTitle,
"index", chapterIndex
)
);
session.run(cypher, params);
4. 查询生成与评测体系
4.1 Cypher生成关键技术
系统采用schema引导的查询生成策略:
-
先通过Neo4j内置过程获取元数据:
cypher复制CALL db.labels() YIELD label CALL db.relationshipTypes() YIELD relationshipType -
将schema信息注入Prompt:
code复制已知图谱包含以下要素: - 节点标签:Character, Event, Chapter... - 关系类型:APPEARS_IN, 发生于, 效忠于... 请生成查询"桃园结义相关章节"的Cypher... -
实现自动修复机制:
java复制// 预检机制实现 String explainCypher = "EXPLAIN " + generatedCypher; try { session.run(explainCypher); } catch (Exception e) { // 将错误信息反馈给LLM进行修复 fixCypherWithError(e.getMessage(), generatedCypher); }
4.2 召回评测方案设计
评测集设计原则:
- 聚焦"章回定位"类问题(如"X事件发生在哪一回")
- 每个问题配置:
- 标准答案章节
- 可接受关键词列表(应对表述差异)
评测指标计算:
java复制int hits = 0;
for (TestItem item : evalSet) {
List<Chapter> results = executeQuery(item.question());
if (isHit(results, item.answers())) {
hits++;
}
}
double recall = (double)hits / evalSet.size();
关键判定逻辑:
- 标题模糊匹配(考虑"第X回"等变体)
- 正文关键词匹配(accept列表中的任一关键词)
- 章节索引范围匹配
5. 工程实践与优化经验
5.1 性能优化技巧
-
批量写入优化:
java复制// 使用UNWIND实现批量写入 String batchCypher = """ UNWIND $entities AS entity MERGE (e:Character {name: entity.name}) MERGE (c:Chapter {chapterKey: entity.chapterKey}) MERGE (e)-[:APPEARS_IN]->(c)"""; -
索引优化:
cypher复制CREATE INDEX chapter_title_index IF NOT EXISTS FOR (c:Chapter) ON (c.title); -
查询参数化:
java复制// 避免Cypher注入同时提升性能 Map<String, Object> params = Map.of( "keywords", List.of("桃园", "结义"), "limit", 5 ); String cypher = """ MATCH (c:Chapter) WHERE c.title CONTAINS $keywords[0] RETURN c LIMIT $limit""";
5.2 常见问题排查
-
LLM输出解析失败:
- 原因:响应结构不符合预期
- 解决:严格校验choices[0].message.content路径
-
Cypher执行超时:
- 原因:未加LIMIT或索引缺失
- 解决:强制所有查询添加LIMIT 5
-
关系类型混乱:
- 原因:中英文混用导致schema膨胀
- 解决:在Prompt中强制指定中文关系短语
6. 扩展应用方向
6.1 多模态知识图谱
扩展方案:
- 添加人物形象节点,关联影视剧图片
- 构建战役地图的空间关系
- 关联经典诗词评注
6.2 混合检索增强
结合向量检索的优势:
- 图谱查询先确定相关章回范围
- 在限定章回内进行向量相似度搜索
- 综合两种结果生成最终答案
实现示例:
java复制// 先执行图谱查询
List<Chapter> chapters = neo4jQuery("温酒斩华雄");
// 在相关章回内做向量检索
List<Chunk> chunks = vectorSearch(
"其酒尚温",
chapters.stream().map(c -> c.text()).toList()
);
6.3 复杂推理问答
支持的问题类型扩展:
- 比较类:"诸葛亮与周瑜的战术风格有何不同"
- 因果类:"为什么曹操会在赤壁战败"
- 假设类:"如果关羽没有失荆州会怎样"
实现路径:
- 构建事件的时间线关系
- 添加人物属性(性格、阵营等)
- 设计多跳查询模板
7. 完整实现建议
对于想要完整实现该系统的开发者,建议按照以下步骤进行:
-
环境准备:
- Neo4j 4.4+ 本地安装
- JDK 17+ 开发环境
- 可用的LLM API(如阿里云通义千问)
-
代码获取:
bash复制git clone https://gitee.com/zhangjq123/langchain4j-spring-agent.git cd langchain4j-spring-agent/langchain4j-spring-ai/langchain4j-spring-ai-seg-flow -
执行顺序:
java复制// 1. 知识抽取 LlmKgExtractTest.extractAndSave(); // 2. 图谱构建 KgNeo4jImportTest.importToNeo4j(); // 3. 结构验证 Neo4jSchemaIntrospectTest.printSchema(); // 4. 评测执行 SanguoKgRecallEvalTest.runEval(); // 5. 问答测试 KagGraphLLMQATest.testQA("温酒斩华雄出自哪一回?"); -
关键配置:
application.yml中配置Neo4j连接- 环境变量设置LLM_API_KEY
- 评测集路径检查(doc/eval/)
8. 项目价值与行业应用
该系统的技术方案可复用于多个领域:
-
文学研究:
- 构建人物关系图谱
- 分析情节发展模式
- 发现隐藏叙事结构
-
教育应用:
- 智能文学问答系统
- 互动式学习助手
- 自动生成阅读测试题
-
商业场景:
- 企业知识管理系统
- 产品文档智能查询
- 客户服务知识库
项目的核心创新价值在于:
- 验证了LLM+KG+RAG的可行架构
- 提供了完整的工程实现参考
- 设计了可量化的评测方案
- 解决了Cypher生成稳定性问题
对于企业用户,可以重点关注:
- 知识抽取的领域适配方法
- 混合检索的性能优化
- 复杂问答的扩展方案
9. 开发者实践建议
基于项目实践经验,给开发者的具体建议:
-
增量开发策略:
- 先实现单章回的知识抽取
- 验证基础查询功能
- 再扩展全文本处理
-
Prompt设计技巧:
- 提供清晰的输出示例
- 限制关系类型词汇表
- 要求保留原文实体表述
-
性能监控指标:
- 知识抽取耗时/章回
- Cypher生成成功率
- 查询响应时间P99
-
效果评估方法:
- 人工抽查实体抽取质量
- 对比纯RAG与KAG效果
- 记录典型失败案例
-
团队协作建议:
- 知识工程师负责schema设计
- 数据工程师优化Neo4j性能
- 算法工程师调优Prompt
10. 技术演进展望
该系统的技术路线还可向以下方向发展:
-
自动化schema演进:
- 动态发现新实体类型
- 自动调整关系定义
- 增量图谱更新机制
-
多源知识融合:
- 整合《三国志》等史料
- 关联地理信息系统
- 融合学术研究成果
-
推理能力增强:
- 时间推理(事件先后)
- 因果推理(为什么)
- 反事实推理(如果...会)
-
交互体验优化:
- 可视化查询构建
- 问答结果溯源
- 用户反馈学习
-
部署架构升级:
- 分布式Neo4j集群
- 向量检索专用硬件
- 模型服务网格
在实际业务落地时,建议根据具体场景需求选择最适合的技术演进路径,不必追求所有方向的全面升级。核心是保持架构的扩展性,确保能够按需引入新的能力模块。
