Вариант D: параллельный BM25 + embedding
Поток
raw chunkText
-> BM25 top 50
-> embedding top 50
-> объединение кандидатов
-> смешивание оценок
-> возврат JSONL
-> проверка Qwen direct-evidenceРаспределение ролей
То, что захватывает BM25:
Input.is_action_pressed
AnimatedSprite2D
position.clamp
screen_size
Vector2.ZEROЧто захватывает embedding:
player movement
2D movement tutorial
moving inside screen
animation based on movementЧто делает валидатор прямых доказательств Qwen:
Проверьте, есть ли в полученном JSONL основание в виде строки/шаблона, непосредственно соответствующее текущему чанку.
Отбросьте несвязанные JSONL.Преимущества
- Сочетает слабые стороны поиска по строке и семантического поиска.
- Качество первого набора кандидатов улучшается даже без Qwen.
- Сохраняет условие raw chunk.
- Можно начать без жёстко закодированного извлекателя сигналов Godot API.
Недостатки
- Требуется настройка комбинирования оценок.
- Масштабы BM25 score и vector score различаются.
- При отсутствии reranker ранжирование может стать нестабильным.
- Не может полностью предотвратить ложные срабатывания.
Ожидаемый результат в базовом chunk
Верхние кандидаты:
first_2d_game / coding_the_player
same page / clamp sectionКандидаты, которые следует понизить или отбрасывать при проверке:
first_3d_game / player_movement_code
unrelated api_mapping
unrelated label_prototypesPoC симуляция
Ищем базовый chunk одновременно по двум путям.
raw chunkText
-> BM25 top 50
-> embedding top 50
-> объединение кандидатов
-> слияние дубликатов
-> проверка Qwen direct-evidenceПримеры топ‑кандидатов BM25:
| Кандидат | Причина, по которой BM25 выбрал |
|---|---|
first_2d_game / coding_the_player |
Input.is_action_pressed, move_left, move_right, AnimatedSprite2D.play/stop прямое совпадение |
first_2d_game / clamp section |
position.clamp, Vector2.ZERO, screen_size прямое совпадение |
first_3d_game / player_movement_code |
Обработка ввода и токен нормализованного перемещения перекрываются |
embedding top пример кандидата:
| Кандидат | Причина, по которой embedding сработал |
|---|---|
first_2d_game / coding_the_player |
Значение 2D перемещения игрока и анимации близко |
first_2d_game / clamp explanation |
значение близко к ограничению игрока в пределах экрана |
first_3d_game / player_movement_code |
значение перемещения игрока близко |
animation docs |
В состоянии moving значение animation play/stop близко |
После candidate union выглядит следующим образом.
candidate A:
source: BM25 + embedding
evidence: Input.is_action_pressed, AnimatedSprite2D.play/stop
expected: accept
candidate B:
source: BM25 + embedding
evidence: position.clamp, Vector2.ZERO, screen_size
expected: accept
candidate C:
source: BM25 + embedding
evidence: Input.is_action_pressed, move_left, move_right, normalized
missing: AnimatedSprite2D, Vector2, screen_size
expected: lower or reject
candidate D:
source: embedding only
evidence: semantic movement/animation similarity
direct string match: weak
expected: validator decision neededПри передаче в валидатор прямых доказательств Qwen применяется следующий критерий.
Реальные строки/API вызовы внутри `SOURCE_CODE` и
`source_api`, `source_pattern`, `match_terms`, `required_when_seen_in_code`, `before_code` в JSONL,
или `content/code_blocks/api_symbols` в `docs_chunks` соответствуют напрямую?Логи, проверяемые в PoC
Эта альтернатива важна из‑за процесса объединения, поэтому необходимо показать следующее.
1. Список кандидатов BM25
2. Список кандидатов embedding
3. Результат объединения с удалением дубликатов
4. Откуда пришёл каждый кандидат: из BM25 или из embedding
5. Список прямых строковых доказательств
6. Пример/нет валидатора QwenВидимый вывод:
BM25 напрямую размещает основание API,
embedding дополняет объяснительные варианты.
Однако только union оставляет ложные срабатывания, поэтому требуется валидатор.Оценка
Реалистичный промежуточный этап
Минимальная рекомендуемая граница для практикиЕсли подключать reranker сразу кажется обременительным, то можно сначала сравнить эту альтернативу.