01 RAG · 导入与检索基线
先让检索过程可以被观察
Retrieval-Augmented Generation / 検索拡張生成
《水浒传》的知识探索实验,先从词法检索开始:把问题和原文变成词项,再计算哪些原文块更相关。
RAG(检索增强生成)先检索资料,再用资料帮助生成答案。GraphRAG(Graph-based Retrieval-Augmented Generation,图增强检索生成)则利用图结构支持这个过程;具体怎样用图,仍有不同实现。
初期 MVP 使用字符二元 / 三元片段与 BM25,没有直接把向量检索或图数据库接入主路径。这样做的价值是可解释:命中了哪些词、每一块得到多少分、哪里被筛掉,都可以记录和比较。
这不是一次“BM25 战胜向量检索”的选型实验。项目并未做过完整的两者 A/B 对照。是否需要语义检索,要看词法方案留下了什么失败,以及引入后的实际收益。
- 词项怎样匹配N-gram / Analyzer
- 排序谁更靠前BM25 / RRF
- 选择哪些能装下证据预算
- 回答证据是否足够核对原文与引文
初期已经有抽取的人物与关系,随后也有答案中心的局部图谱。但“有图数据”“展示一张图”和“用图决定检索哪些证据”,是三件不同的事。关系检索专题会回到这条分界。
PART 01 / FOUNDATIONS
基础技术
从词项匹配到融合排名:先弄清四个常见环节各自解决什么问题。
02 BM25 · 相关性评分
BM25|让关键词匹配变成相关性排名
Best Matching 25 / 関連度スコアリング
搜索“林冲 宝刀”时,可能找到很多包含这些词的文本。BM25 根据词语出现次数、稀有程度和文本长度,判断哪些结果应该排在前面。
搜索词:宝刀
林冲买了一口宝刀。
林冲看见宝刀,又仔细端详这口宝刀。
TF|词频
Term Frequency
词语出现得更多,通常会提供更强的匹配信号。
BM25 的词频贡献会逐渐饱和,不会随重复次数无限线性增长。
条长表示包含该词的文本比例,不表示相关性分数。
IDF|逆文档频率
Inverse Document Frequency
越少见的词,通常越能区分哪些结果真正相关。
“林冲”在许多文本里都出现,相较于稀有词,其统计区分力可能更弱。稀有程度不等于语义重要程度。
短文本“宝刀”出现 1 次
林冲把宝刀拿在手里,翻来覆去地看。
长文本“宝刀”出现 1 次
林冲清早出门,经过街边的店铺,和熟人说了几句话。路上人来人往,有人挑着担子,有人停下歇脚。走到街角时,他看见一口宝刀,拿起来仔细查看。随后他又沿街走了一段,听见附近酒家传来谈笑声,便转身向家中走去。
长度归一化
Length Normalization
避免长文本只因为内容更多,就天然获得评分优势。
BM25 会参考文档长度及语料平均长度修正评分。这里固定命中次数,只比较词项在长短文本中的集中程度。
排名第二的证据,终于能够被选中
修改前 · 固定阈值 5
3.39 < 5相关证据排第 2,仍被排除。
修改后 · 取消绝对阈值
仍排第 2不再被分数门槛挡掉,继续按容量与预算筛选。
31 道有答案的问题中,至少一块核心证据进入上下文
取消阈值让证据获得入选机会,并不保证它必然进入上下文;候选数量、容量和预算仍会限制选择。
进一步了解:BM25 评分与历史阈值实验核对 S0 / S1 数据、评测条件,以及评分与证据选择的区别。
| 历史策略 | Hit@3 | 上下文含 ≥1 核心 |
|---|---|---|
| S0 · 阈值 5 | 0.65 | 18/31 ≈ 0.58 |
| S1 · 去阈值 | 0.65 | 20/31 ≈ 0.65 |
第 7–11 回、59 块,31 道有答案题;预算 2000、最多 4 块,装不下则跳过继续。Hit@3 检查前 3 名是否含至少一个核心块;上下文覆盖检查最终入选块,二者不同。
3.39、排名第 2 与阈值 5 来自历史诊断。旧通道以 BM25 为基础,还含实体与相邻块加分,因此这里的 3.39 严谨地称为历史检索总分。样本小、单人标注,结果不宜泛化到全部查询。
03 N-gram · 连续字符片段
N-gram|把文字切成连续片段
Character N-gram / 文字 N-gram
中文没有天然的空格分词边界。字符 N-gram 不需要先判断完整词语,而是通过滑动窗口生成固定长度的字符片段。
这是一段简化字符切分示意,不是项目原始检索输出。三种切分的全部词项始终可读,无需操作。
N 代表连续字符的数量。标准字符 N-gram 通常每次滑动一个字符,所以相邻词项会重叠。
N-gram 的重叠发生在词项生成时,Chunk Overlap 则发生在文本分块时。
- 优点:无需词典,也能匹配未知词中的连续字符。
- 局限:可能生成没有实际语义的片段,也不能自然理解近义表达。
项目实践 · Python 二 / 三元片段检索实现说明 · 实验数据OpenSearch · N-gram tokenizer ↗
04 Analyzer · 文本分析
Analyzer · 文本分析
Tokenizer / Text Analyzer / トークナイザー / アナライザー
Analyzer 把原始文本处理成可搜索的词项。
Character Filter
字符预处理 · 清理原始文本中的标点
林冲→!!买了一把宝刀!!!林冲买了一把宝刀Tokenizer
词项切分 · 将连续文本拆成可检索词项
林冲买了一把宝刀→[林冲] [买] [了] [一把] [宝刀]Token Filter
词项过滤 · 根据规则删除部分词项
[林冲] [买]→[了][一把][宝刀][林冲] [买] [宝刀]
本例的分词与过滤规则人为设定:过滤“了”和“一把”,不代表所有 Analyzer 都会这样处理。
Character Filter 处理原始字符,Tokenizer 生成词项,Token Filter 进一步筛选词项。
03 · N-gram:了解不同字符切分方式。
下一步研究:了解词项过滤及查询扩展的后续研究方向。
项目通过 Python 自定义代码实现了部分文本分析与过滤功能。
05 RRF · 排名融合
RRF · 排名融合
Reciprocal Rank Fusion / 逆順位融合
同一批内容经过不同检索方法,可能得到不同排名。RRF 根据它们在各个排行榜中的名次,计算最终顺序。
文章 A 在两份榜单分别排第 1 和第 2,融合后成为最终第 1 名。
教学示意 · 自拟 A / B / C,等权 RRF,k = 60排行榜 1
- 第 1 名文章 A
- 第 2 名文章 B
例如,二元 / 三元字符 BM25。
排行榜 2
- 第 1 名文章 C
- 第 2 名文章 A
例如,单字 BM25。
最终排行榜
- 第 1 名文章 A0.03252
- 第 2 名文章 C0.01639
- 第 3 名文章 B0.01613
A 为什么排第一?
排行榜 1:第 1 名。
排行榜 2:第 2 名。
1/61 + 1/62 ≈ 0.03252两路贡献相加,因此获得最高融合分数。
RRF 使用排名融合,不直接相加不同检索器的原始分数。
历史实测 · 双词法 RRF · Hit@3
“前 3 名是否找到至少一块核心证据”的有答案问题比例提高。
这是增加单字通道并融合后的整体结果,不能把全部收益归因于 RRF 本身。融合排名也不代表答案一定正确。
进一步了解:RRF 公式参数与完整评测数据查看 k = 60、未入榜候选的处理,以及历史三种检索策略的对照。
每路贡献为 1 / (k + 名次),本图等权融合,k = 60;未出现在某路候选中的文章,该路贡献为 0,不视作排在最后。分数统一保留五位小数。
第 7–11 回、59 块、31 道有答案题。旧通道含二 / 三元词 BM25、实体与相邻块加分;单字 BM25 Hit@3 为 0.71,双词法等权 RRF(k = 60)为 0.77。去阈值、通道粒度和融合的贡献需要分开控制。
依据检索策略实验 · 实验数据预算对照实验 · 实验数据多章节知识检索设计 · 实验数据Cormack 等 · SIGIR 2009 ↗
PART 02 / FIELD NOTES
真实项目实践
前面介绍了文本分析、相关性评分与排名融合。接下来看看这些技术如何组成实际检索系统,以及我们怎样沿着检索链路定位问题、调整方案。
S 系统检索链路
从基础技术,到实际检索流程
Retrieval Pipeline / 検索パイプライン
前面的技术不是并列的知识点,而是一次回答背后同一条链路上的不同环节。
- 用户提问“鲁智深和林冲怎么认识?”
- 文本分析与词项生成参照 03 N-gram04 Analyzer
问题与原文块都被处理成两套词项:二 / 三元字符片段,以及去掉高频虚字的单字。
- 候选检索与相关性评分参照 02 BM25
通道 1二 / 三元词项 → BM25 排名
通道 2单字词项 → BM25 排名
- 多路结果融合参照 05 RRF
只按名次合并两份排名,得到一份候选顺序。
- 证据选择与 Context 组装实践 A 检索与证据
按融合名次,把完整原文块依次装入 Context,受 Token 预算与块数上限约束。
Context 边界:模型只看得到已经装进来的证据。
模型生成回答只根据实际收到的 Context 作答;回答后,系统再按原文核对引文。
图为当前主线的简化,不是完整调用链。实践 A 的 2,000 / 4,000 / 8,000 是不同时期的实验配置(旧策略 → RRF);当前默认配置是 RRF · 8,000 估算 Token · 最多 12 块。
进一步了解:这张图没有展开的部分当前主线与历史实验的差别、知识探索支线、事件骨架,以及关系查询与 RRF 的关系。
主线与历史配置。主线对原文块做两路 BM25,以 RRF(k = 60,等权)融合,再按名次依次装入完整块;某块放不下就停止,不跳过它去填更低名次的块。旧策略是阈值 5、最多 4 块、2,000 估算 Token,且会跳过放不下的块继续填。第一部分的 0.65 → 0.77 对应旧通道到双词法 RRF 的历史实验,不是这张图里各环节的单独收益。
知识探索支线。项目另有一条旁挂的知识探索链路:预先整理的人物画像、事件 / 关系 / 状态记录与章节概要作为“知识”,原文块作为另一个来源,两者分别设预算。知识候选同样用两路词法排名做 RRF 融合;问题里出现两个以上有区分力的人物时,再加一路按人物参与度的排名。这一路是对已有知识记录排名,与实践 B 中早期的“关系边排名通道”不是同一个实验。
事件骨架与关系查询。问到人物经历路径时,事件骨架在调用模型之前由知识库确定,再作为上下文交给模型写每个阶段的说明。“两个人物之间有什么关系 / 共同事件”这类查询按记录 ID 读取,不排名,也不是 RRF 的通道。
引文核验。回答之后会核对引文能否在所引原文中逐字找到;这只证明引文可以定位,不等于语义上支持了结论。
图里省略了会话中的证据记忆、追问处理与查询词清理等细节。
这些环节组合起来后,即使检索已经找到相关内容,回答仍可能出现遗漏。那么问题究竟发生在哪一步?看实践 A ↓
A 检索与证据选择
检索结果与最终证据
Evidence Selection / Token Budget / 根拠の選択 / トークン予算
检索似乎找到了相关内容,回答却仍缺少关键信息。问题出在链路的哪一步?
01回答不完整,先确认问题发生在哪一步
实际回答漏掉了重要信息。先不急着调参数,沿着上面的链路从后往前查:先看模型实际收到的 Context 里有没有这条信息;再回到原文确认必要事实;最后对照候选检索(BM25 评分与 RRF 融合后的排名)和证据装填记录,判断它是没被检索到,还是检索到了却没有装进来。
- 最后对照候选检索与证据装填
- 先检查Context
- 发现问题模型回答
02关键证据已被检索,却没有进入 Context
回看“鲁智深和林冲怎么认识”的离线记录:结义原文已经在候选里,旧通道排第 8,改用 RRF 后升到第 4。但在 2,000 Token 的证据预算下,装填规则仍然挡住了它,Context 里没有这条原文。对这一题来说,名次变好还不够,它还要有机会被装进来。
模型只看到已入选的块第 4 名即使有用,也没有送入这一档上下文。
第 4 名属于 RRF 离线排序,不是旧策略的第 4 名。图按“超预算即停”解释机制,块宽和其他块的截断点仅作示意;这不是下方某次真实模型调用的完整 Trace。
辅助信息 · 初期真实配置 · 第 7–11 回评测集
旧策略 · 2,000 Token
- 平均原文长度
- 639 字 / Chunk
- 实际通常只能装入
- 约 2–3 块原文
配置来源检索策略实验 · 实验数据
03改变检索策略与预算,再观察实际回答
真实问题:“鲁智深和林冲怎么认识?”我们把检索策略从旧通道改为 RRF 融合,同时扩大证据预算,让更多必要证据有机会进入 Context,再检查回答能否区分相识、结义与野猪林救助。
检索策略与预算→Context 的证据覆盖→实际回答
旧策略 · 2,000
Token · 证据预算(保守估算)
Context:缺少结义原文。
必要证据不足,未能回答。
返回 insufficient。
RRF · 4,000
Token · 证据预算(保守估算)
Context:已有结义证据,也带入排名靠前的野猪林情节。
有更多证据,但仍混淆事件。
把第 7 回结义与第 9 回野猪林相认混合;3 条引文仅 1 条可定位。
RRF · 8,000
Token · 证据预算(保守估算)
Context:预算扩大,更多证据有机会进入。
这次回答更完整,未再混淆,引用可定位。
报告记为街头相见、认识林父、结义为兄;两条引文均可定位。
各组同时涉及检索策略、预算及选择规则差异,不能把全部效果归因于增加预算。每种配置仅一次真实模型调用,n = 1,不是统计性因果证明。此处未逐块核实本题 4000 → 8000 的 Context 差异,不推断具体新增了哪一块;引文可定位也不等于语义支持已验证。
更多证据,不等于更正确的回答。
扩大预算能改善证据覆盖的机会,同时也可能带来噪声;它不会让模型自动更会理解证据。
Context 还缺必要事实:继续检查检索、候选排序与证据装填。如果词面本来就对不上(例如问“报仇”,原文写“杀”“搠”),见下一步研究。
证据已充分,回答仍混淆:检查证据理解、事件关联、Prompt 设计与回答生成,不能只靠不断增加预算。
进一步了解:候选装填与预算实验记录查看完整覆盖与噪声统计、候选上限,以及不同装填规则。
预算扩大可能同时引入噪声。整个评测集中,RRF 从 4000 到 8000 档,全部核心被选齐的题数由 21/31 增至 27/31,未被标为核心或相关的入选块占比也由 61% 增至 79%。
Context Selection / Context Packing(上下文选择 / 装配,上下文選択 / コンテキスト構成)负责挑选与组织上下文。本文以证据覆盖和预算说明这层职责,不把它当作独立基础评分算法。
离线逐题记录中,“认识”一题的核心块 ch007_chunk_004 从旧通道第 8 名前移至 RRF 第 4 名;RRF 2000 档未入选,4000 档已入选。另一次真实回答对照记录了野猪林情节与结义的混淆;两类记录不能拼成同一次调用的完整 Trace。
| 预算 估算 Token | 全部核心 题数 / 31 | 平均 入选块数 | 无关块 占比 |
|---|---|---|---|
| 2,000 | 12 / 31 | 2.3 | 45% |
| 4,000 | 21 / 31 | 5.0 | 61% |
| 8,000 | 27 / 31 | 10.6 | 79% |
| 16,000 | 30 / 31 | 21.6 | 89% |
“全部核心”检查人工标注 core 是否全入选;无关块按不属于 core∪rel 统计,是噪声上界,未标注不代表一定有害。表格是全评测集结果,不是只统计“认识”一题。
从 4000 到 8000 档,共新增 6 个核心块、176 个无关块。语料仅 59 块,结果不能直接当成更大语料上的推荐预算。
Top-K 限制候选,块数上限与 Token Budget 限制入选。仍限 4 块时,提高预算也不能继续改善。旧策略会跳过装不下的块继续“填缝”;超预算即停能抑制某些噪声,但不是所有任务的最优规则。
B 图关系检索的曲折
图关系检索的曲折
Graph Retrieval / グラフ検索
加入图关系后,检索命中率反而下降了。
前面的检索链路主要靠词项匹配、相关性评分和排名融合寻找证据。那么,已经抽取的人物、事件和关系,能否为这条链路增加新的检索能力?
01让关系边参与排名,未能带来改善
项目已经具备人物、事件和关系知识。最初的尝试,是把关系边作为第三路检索信号,通过 RRF 与原来的两路词法排名等权融合。
Hit@3:0.77 → 0.68
0.77:原有双词法 RRF。
0.68:加入关系边排名通道。
高频人物关联大量关系边,关系描述又未必与问题用词一致;等权融合可能把这些噪声推到前面,扰动原有排名。
这是特定关系文本、匹配规则与等权融合方案的结果,不能解释为图检索本身无效;上面的噪声原因来自报告分析,不是普遍因果结论。
02失败的是图关系,还是使用方法?
这次失败说明直接增加关系排名通道没有达到预期,但并不能证明结构化关系本身无效。研究没有因此放弃,而是开始寻找另一种使用方式。
能否不让所有关系边直接竞争排名,而是用它们查找关联人物和事件,再追踪对应的原文证据?
03让关系辅助证据探索
后续系统已经让结构化关系承担另一种职责:帮助发现相关人物和事件,再回到对应的原文证据,而不是再增加一张排行榜。
关系边→排名通道→RRF 融合→与词法结果竞争名次
人物 / 事件 / 关系记录→查询关联→出处原文→证据展示与事件路径
- 人物关系查询读取两个人物之间的关系记录。
- 关联事件查找找出两人共同参与的事件。
- 原文证据定位关系与事件记录带有出处,可回到对应的原文片段。
- 经历路径与事件组织问到人物经历时,知识库先把事件按顺序分成阶段,再交给模型写每个阶段的说明。
实现核对检索实现说明 · 实验数据
ch007_chunk_004“林沖大喜,就當結義智深為兄。”
人物相遇与结义的原文证据。
ch009_chunk_001“林沖方纔閃開眼看時,認得是魯智深。”
这里的“认得”不能当作首次相识。
事件标题是教学概括,连线表达组织关系,不冒充实际查询路径或原始 Schema。引文保留原文繁体。
一次失败,不代表整个研究方向没有价值。
最初的排名策略没有成功,但后续系统已经把结构化关系用于证据关联和事件组织。关系承担什么职责,要由问题与实验效果决定,增加一个通道并不保证更好。
上述查询、出处关联与事件组织能力已经实现;它们对回答准确性、完整性的稳定贡献仍需验证,也不意味着全部多跳问题已解决。验证方向见下一步研究。
进一步了解:关系检索实验及实现边界查看早期等权融合条件、后续已实现的查询与经历路径组织,以及效果验证边界。
检索策略报告 S4 / S6,31 道有答案题。枢纽人物名字命中会引入噪声,“认识”与关系类型“结义”也未必字面匹配;本次下降只针对该实验方案。
现有服务的 kb_pair 查询人物关系与共同事件,kb_record 关联事件、关系、状态与出处;经历路径由 plan_for_question 构建事件骨架。人物对查询是按 ID 读取,不参与排名,也不会自动进入模型 Context。可查询和可组织不等于已证明回答质量提升。
依据检索策略实验 · 实验数据逐题排名与失败归因 · 实验数据多章节知识检索设计 · 实验数据Python 知识探索引擎 · 实验数据答案中心局部图谱 · 实验数据Python / FalkorDB Provider · 实验数据
PART 03 / OPEN QUESTIONS
下一步研究
实践留下两类问题:表达与原文用词不同时,证据仍可能找不到;关系与结构化知识对回答质量的贡献,也还没有验证。
→ 下一步优化
下一步:让查询更准确地找到证据
Query Expansion / Query Rewrite / クエリ拡張 / クエリ書き換え
现有词法检索仍然难以处理部分表达差异,例如用户说“报仇”,原文却使用“杀”“搠”等动作描述。
Analyzer / Token Filter · 词项处理与过滤
调整词项处理、领域词典和过滤规则,观察是否能改善检索匹配与噪声。
Query Expansion / Rewrite · 查询扩展与改写
尝试保留原问题、补充相关检索表达,检查能否找回以前遗漏的证据,同时防止查询漂移。
这些方向仍是待验证的假设,需要使用相同评价集与原始策略做对照。结构化关系对回答准确性与完整性的贡献,同样要先对照评估,再下结论。
问题依据检索策略实验 · 实验数据预算对照实验 · 实验数据多章节知识检索设计 · 实验数据
回到工程判断
先定位失败发生在哪一层,再选择技术。
词项没有匹配,改预算无济于事;证据排得靠前却被挤掉,增加图关系也未必解决。更可靠的起点,是让匹配、排名、选择与证据支持都能被检查。
进一步了解:证据来源与文章边界了解实测、教学示意与待验证方向的区别,以及实验规模和独立性的限制。
实验数字来自已提交的历史报告;这些报告和代码在私有仓库里,不对外开放,所以本文不链接到它们。方法、数字和限制集中记录在文末的实验数据与验证依据里。本文没有重跑 LLM 实验,也没有完成独立复评。
Analyzer 的独立例子、N-gram、RRF 数值例子、预算截断与关系组织图均为教学示意。负面实验不泛化为技术优劣,未来研究不视为现有成果。
实验规模小(第 7–11 回、59 个原文块、31 道有答案题)且为单人标注,差一两题就能改变数值,结果不宜推广到其他语料或更大规模。
实验数据与验证依据
这一节只做一件事:把文章引用的实验数字、方法和限制放在可公开访问的地方。完整的内部报告和源代码不公开,也没有复制到这里。
评测设定与检索效果对比评测集与指标口径,以及检索策略、去阈值和关系边通道的 Hit@3 对照。
评测设定
| 语料 | 《水浒传》第 7–11 回,59 个原文块(Chunk),平均约 639 字 / 块。 |
|---|---|
| 评测集 | 33 题:31 题有答案,2 题无答案。核心证据块由一人标注;Hit@3 与核心覆盖指标主要针对 31 道有答案题。 |
| 指标 | Hit@3:前 3 名是否含至少一个核心块。上下文覆盖:最终入选上下文的块里是否含核心块。两者不同。 |
| 预算口径 | 按 1 字 ≈ 1 Token 的保守估算,不是模型实测 Token;容量随块长度与选择规则变化。 |
| 真实回答 | 每种配置只调用一次模型(n = 1),不是统计性实验;引文“可定位”指能在所引块中逐字找到。 |
| 规模与独立性 | 小语料、单人标注,差一两题就能改变数值;没有独立复评,也没有重复调用的方差。 |
检索策略对照
三种检索配置在 31 道有答案题上的 Hit@3(只用词法检索,没有向量检索):
| 配置 | Hit@3 | 说明 |
|---|---|---|
| 旧通道 | 0.65 | 二 / 三元词 BM25,加实体与相邻块加分。 |
| 单字 BM25 | 0.71 | 另一种词项粒度。 |
| 双词法 RRF | 0.77 | 二 / 三元词与单字两路名次融合,k = 60,等权。 |
0.65 → 0.77 是增加单字通道并融合后的整体结果;去阈值、通道粒度与融合各自的贡献没有被分开控制,不能把收益全部归因于 RRF。
去掉分数阈值
S0 与 S1 的评分和排序相同,只改是否应用绝对阈值。预算 2,000,最多 4 块,装不下的块跳过后继续。
| 策略 | Hit@3 | 上下文含 ≥1 核心块 |
|---|---|---|
| S0 · 阈值 5 | 0.65 | 18/31 ≈ 0.58 |
| S1 · 去阈值 | 0.65 | 20/31 ≈ 0.65 |
诊断个例:“买刀”证据块 ch007_chunk_012 的历史检索总分为 3.39,排第 2,被阈值 5 排除。这个分数以 BM25 为基础,还含实体与相邻块加分,所以严格说是“历史检索总分”,不是纯 BM25 分。
加入关系边通道
在双词法 RRF 之外再加一路“关系边”排名,等权融合(报告中的 S4 / S6),31 道有答案题:
| 配置 | Hit@3 |
|---|---|
| 双词法 RRF | 0.77 |
| 加入关系边通道 | 0.68 |
报告对下降的分析:高频人物关联大量关系边;关系描述与问题用词不一定一致;等权融合可能把这些噪声推到前面。这是该方案(特定关系文本、匹配规则与等权融合)的结果,不能解释为图检索本身无效。
证据预算与真实回答不同预算下的核心块覆盖与噪声,以及同一问题三种配置的回答记录。
证据预算对照
双词法 RRF,不限块数,超预算即停(某块放不下就停止,不再跳过它去填更低名次的块)。整个评测集的结果:
| 预算(估算 Token) | 全部核心块入选的题数 | 平均入选块数 | 无关块占比 |
|---|---|---|---|
| 2,000 | 12 / 31 题 | 2.3 | 45% |
| 4,000 | 21 / 31 题 | 5.0 | 61% |
| 8,000 | 27 / 31 题 | 10.6 | 79% |
| 16,000 | 30 / 31 题 | 21.6 | 89% |
“无关块”指不属于人工标注 core ∪ rel 的块,是噪声的上界,未标注不代表一定有害。
从 4,000 档到 8,000 档,共新增 6 个核心块和 176 个无关块。语料只有 59 块,结果不能直接当作更大语料的推荐预算。
旧策略(阈值 5、最多 4 块、2,000 估算 Token)会跳过装不下的块继续填;块数上限为 4 时,提高预算也无法继续改善。
真实回答与排名记录
同一个真实问题“鲁智深和林冲怎么认识?”,三种配置各调用一次模型:
| 配置 | Context | 回答记录 | 引文可定位 |
|---|---|---|---|
| 旧策略 · 2,000 | 缺少结义原文。 | 证据不足,返回 insufficient。 | — |
| RRF · 4,000 | 有结义证据,也带入排名靠前的野猪林情节。 | 能回答,但把第 7 回结义与第 9 回野猪林相认混合。 | 1 / 3 |
| RRF · 8,000 | 预算扩大,更多证据有机会进入。 | 此次回答更完整,未再出现之前观察到的情节混淆:街头相见、认识林父、结义为兄。 | 2 / 2 |
核心块 ch007_chunk_004 的排名:旧通道第 8,RRF 第 4;RRF 的 2,000 档未入选,4,000 档入选。这是离线逐题记录,与上面的真实回答不是同一次调用的完整 Trace,不能拼成一条因果链。
三种配置同时在检索策略、预算与选择规则上不同,不能把效果全部归因于增加预算;也没有逐块核实 4,000 → 8,000 在这一题上具体新增了哪个块。
“引文可定位”只表示片段能在所引块中逐字找到,不表示语义上支持结论;每种配置只调用一次,没有测重复调用的方差。
实现说明、限制与来源检索实现的核对说明、实验的限制与可信度,以及数字的来源。
检索实现说明
文章里的系统图是对下面实现的简化,核对的是 2026-10 的代码(私有仓库,提交 0d26b5c)。
| 部分 | 说明 |
|---|---|
| 当前问答主线 | 只检索原文块:二 / 三元词项与单字词项各做 BM25,以 RRF(k = 60,等权)融合;按名次装入完整块,块数达上限或某块超预算即停止;默认 8,000 估算 Token、最多 12 块。每次提问一次检索、一次模型调用,回答后核验引文。 |
| 旧策略(历史) | 单路 BM25 通道(含实体与相邻块加分),阈值 5、最多 4 块、2,000 估算 Token,跳过装不下的块继续填。 |
| 知识探索支线 | 预先整理的人物画像、事件 / 关系 / 状态记录与章节概要作为“知识”,原文块是另一个来源,两者各设预算。知识候选同样做两路词法排名并用 RRF 融合;问题含两个以上有区分力的人物时,再加一路人物参与度排名。 |
| 事件骨架 | 问人物经历路径时,事件骨架由知识库在调用模型前确定,作为上下文的一部分交给模型写每个阶段的说明。 |
| 关系查询 | 两个人物之间的关系与共同事件、记录与出处的查询按记录 ID 读取,不排名,不是 RRF 的通道,也不会自动进入模型 Context。 |
| 多章节检索设计 | 知识探索支线的检索设计来自一次覆盖第 7–11 回的多章节离线实验;本文没有使用它的数字。 |
| 演进记录 | 初始 BM25 MVP(2061743)→ 答案中心局部图谱(e32245a)→ Python 知识探索引擎(0b36e0c)→ Relation Provider(Python / FalkorDB,d687c29)→ 本次核对的主线版本(0d26b5c)。这些是私有仓库的提交标识,仅供识别,不提供链接。 |
能查询、能组织不等于已经证明回答的准确性与完整性有稳定提升;这一点没有被实验验证。
限制与可信度
- 语料小(59 块)、评测集小(31 道有答案题)、核心块由一人标注:差一两题就能改变数值。
- 没有向量检索与词法检索的完整 A/B 对照,所以文章不主张“BM25 优于向量检索”。
- 真实回答每种配置只调用一次(n = 1),没有重复调用的方差;回答由作者对照标注与原文判断,不是第三方评分。
- 预算是按字数的保守估算,不是模型实测 Token。
- 没有重跑实验,也没有独立复评。
- 关系边通道的失败只说明该方案;已实现的关系查询与事件组织对回答质量的贡献尚待验证。
来源说明
这些数字来自 graphrag-shuihu 项目中已提交的实验报告和代码。该仓库目前是私有的,所以本站不链接到它;本节就是这些数字与方法的公开记录。
本节只摘录方法、结果和限制,没有复制完整内部报告或源代码。若本节与原报告的数字不一致,以原报告为准,并应更正本节。
BM25、N-gram、Analyzer 与 RRF 的通用说明,见下列公开文档:
依据Elastic · BM25 similarity ↗OpenSearch · Text analysis ↗OpenSearch · N-gram tokenizer ↗Cormack 等 · SIGIR 2009 · RRF ↗