方案 B:仅使用 BM25
流程
原始 chunkText
-> tokenizer
-> BM25
-> 返回 top JSONLBM25所看到的
BM25大致通过以下要素来计算得分。
TF: 在此文档中单词出现了多少次
IDF: 在整个语料库中该单词有多稀少
Length normalization: 对长文档进行校正,使其不会自动占优势所以基准块的后续单词变得重要。
animatedsprite2d
is_action_pressed
move_left
move_right
normalized
clamp
screen_size
vector2
zero在基准块中成功的原因
在原始笔记的模拟中,以下文档会出现在上方。
outputs/godot_docs_full/pages/getting_started__first_2d_game__03.coding_the_player__161d377b.md直接匹配的令牌如下。
animatedsprite2d
is_action_pressed
move_left
move_right
normalized
play
stop
input
speed
length
velocity
vector2
zero特别是以下标记在语料库中较为罕见,因此对得分贡献很大。
animatedsprite2d
move_left
move_right
is_action_pressed
screen_size
clamp失败候选
在 BM25 only 中,也可能出现 3D movement 文档。
原因是以下公共标记。
Input.is_action_pressed
move_right
move_left
normalized
speed但是基准块是二维的,以下线索很重要。
AnimatedSprite2D
Vector2
position.clamp
screen_sizeBM25是基于词分数的,因此无法完全理解2D/3D上下文。
PoC 模拟
将基准 chunk 作为 BM25 查询输入。
输入:
func _process(delta):
Input.is_action_pressed(...)
velocity.normalized() * speed
$AnimatedSprite2D.play()
position.clamp(Vector2.ZERO, screen_size)BM25会给出高分的词元:
animatedsprite2d
is_action_pressed
move_left
move_right
normalized
clamp
screen_size
vector2
zero预计候选:
| 排名 | 候选 | 为什么出现 | 判断 |
|---|---|---|---|
| 1 | first_2d_game / coding_the_player |
Input.is_action_pressed、move_left、move_right、velocity.normalized、AnimatedSprite2D.play/stop 直接匹配 |
accept |
| 2 | first_2d_game / clamp/screen section |
position.clamp、Vector2.ZERO、screen_size、AnimatedSprite2D 匹配 |
accept |
| 3 | first_3d_game / player_movement_code |
Input.is_action_pressed、move_left、move_right、normalized、speed 重叠 |
false positive |
第 1 名候选上榜的原因:
animatedsprite2d:
在整个文档中很少出现的 token,因此 IDF 很大
move_left / move_right:
在教程输入代码中直接出现
is_action_pressed:
与输入处理代码直接匹配
velocity.normalized:
与移动向量归一化流程直接匹配3位候选人一起出现的原因:
3D movement 文档也说明了输入处理和归一化移动流程。
因此在 BM25 的视角下,query token overlap 相当大。
但这与基准 chunk 的核心——AnimatedSprite2D、Vector2、screen_size、position.clamp——并不匹配。PoC中确认的日志
在 BM25 PoC 中,展示每个候选项的 token 贡献度是很重要的。
示例:
candidate: first_2d_game / coding_the_player
matched_terms:
animatedsprite2d high
is_action_pressed high
move_left high
move_right high
normalized medium
play medium
stop medium
candidate: first_3d_game / player_movement_code
matched_terms:
is_action_pressed high
move_left high
move_right high
normalized medium
missing_terms:
animatedsprite2d
screen_size
position.clamp眼前的结论:
BM25 能很好地检索相关文档。
但是也会一起检索到相似的输入/移动代码。
因此在 BM25 的下一阶段需要 reranker 或 validator。优点
- 原理透明。
- 调试容易。
- 没有模型费用。
- 可以直接使用原始块。
- 对代码/API 精确字符串搜索很强。
缺点
- 对同义词和说明文弱。
- 如果 API 名称未直接出现可能会错过。
- 像 3D movement 这样的相似代码可能会混入误报。
判定
必须审查的第一候选搜索
但是单独使用不足