1. 为什么选择 KAG:解决向量检索的痛点
做 RAG 时,我踩过一个典型坑:
- 向量召回对'典故/情节类问题'并不稳定:你搜'温酒斩华雄',但原文可能写成'其酒尚温'、人物可能是'云长/关公',词面变化导致召回波动。
- 分块策略难以平衡:如果分块策略偏大(窗口 512/overlap 80),章节内细粒度信息容易被稀释;如果分块过小,语义又不完整。
而知识图谱擅长的恰好是:
- 实体/事件/关系的结构化表示(谁在什么事件中做了什么)
- '章回定位'类问题可以走更确定的路径:通过
Event/Character -> APPEARS_IN -> Chapter精准落到具体章回
所以我最终选择:RAG 负责'文本证据'与'长上下文生成',KG 负责'结构化召回、强约束定位',二者组合形成 KAG。
2. 工程架构设计
这套闭环全部以 JUnit 测试类的形式提供,方便你在工程里反复迭代。
2.1 评测集结构
数据位于 doc/eval/sanguo-kg-eval.json。数据结构包含:
query:问题answers[]:标准答案集合chapterTitle:期望命中的章回标题accept[]:可接受关键词(用于判定命中)
2.2 核心流程模块
-
抽取 (
LlmKgExtractTest)- 输入:
doc/aigc_chunk_store_to_graph.csv - 输出:
doc/kg_extract_result.json - 逻辑:逐行读取 CSV(每行本质是一段'章回文本'),调用 LLM 抽取实体(Character/Location/Event/Item)及关系(relations[{type, head, tail}])。这里要求 LLM 输出中文关系短语,并附带写入章回元信息。
- 输入:
-
入库 (
KgNeo4jImportTest)- 输入:
doc/kg_extract_result.json - 输出:Neo4j 图数据库
- 核心写入逻辑:创建
(:Chapter {chapterKey})作为'章回锚点',创建实体节点,把实体与章回相连:(n)-[:APPEARS_IN]->(c:Chapter)。 - 注意:
APPEARS_IN的含义是实体/事件出现在某章回。这个关系非常关键,它把'结构化实体世界'挂回到'可以回答问题的章回证据'。
- 输入:
-
Schema 获取 (
Neo4jSchemaIntrospectTest)- LLM 要生成靠谱的 Cypher,必须知道你图谱里有哪些 label、关系类型以及每个 label 的关键属性。我用
CALL db.labels()/CALL db.relationshipTypes()做了 schema 探测。
- LLM 要生成靠谱的 Cypher,必须知道你图谱里有哪些 label、关系类型以及每个 label 的关键属性。我用
-
召回评测 (
SanguoKgRecallEvalTest)- 核心:把'问题→图谱查询→命中判定'做成评测流程。
- 链路:读取评测集 → 探测 Neo4j schema → 对每个 query 让 LLM 抽取意图/关键词 → 生成 Cypher → 预检(EXPLAIN )→ 若失败回灌错误信息修复 → 执行查询拿 TopK → 让 LLM 判定是否命中标准答案 → 汇总 Recall@5。

