Вариант B: только BM25
Поток
raw chunkText
-> tokenizer
-> BM25
-> top JSONL возвратЧто видит BM25
BM25 примерно рассчитывает оценку на основе следующих элементов.
TF: сколько раз слово встречается в этом документе
IDF: насколько редким является слово во всём корпусе
Length normalization: корректировка, чтобы длинный документ не был автоматически выгоднееТак что следующие слова в базовом чанке становятся важными.
animatedsprite2d
is_action_pressed
move_left
move_right
normalized
clamp
screen_size
vector2
zeroПочему это работает в базовом chunk
В симуляции оригинальной заметки следующая документация появляется выше.
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Однако базовый чанк является 2D, и следующая подсказка важна.
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:
Весь документ содержит редкий токен, поэтому IDF велик
move_left / move_right:
Появляется непосредственно в коде ввода учебного пособия
is_action_pressed:
Точно совпадает с кодом обработки ввода
velocity.normalized:
Точно соответствует процессу нормализации вектора перемещенияПричина, по которой кандидат третьего места появляется вместе:
Документ **3D movement** также описывает обработку ввода и нормализованный поток перемещения.
Поэтому с точки зрения BM25, перекрытие токенов запроса довольно велико.
Однако это не соответствует ключевому элементу базового чанка — AnimatedSprite2D, Vector2, screen_size, position.clamp.Логи, которые нужно проверить в PoC
В BM25 PoC важно показывать вклад токенов для каждого кандидата.
(No content to translate.)
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.Преимущества
- Принцип прозрачен.
- Отладка проста.
- Нет затрат на модель.
- Можно использовать raw chunk как есть.
- Сильный в точном поиске строк кода/API.
Недостатки
- Слаб в синонимах и описаниях.
- Можно пропустить, если имя API не указано явно.
- Подобный код, как 3D movement, может попасть в ложные срабатывания.
Оценка
Необходимо обязательно проверить поиск первого кандидата
Однако использование в одиночку недостаточно