idea_world_labDEV JOURNAL
2026年6月28日日曜日

代替 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

基準チャンクで成功する理由

原文メモのシミュレーションでは、次の文書が上位に出てくる。

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_size

BM25は単語スコアベースのため、2D/3D コンテキストを完全に理解できません。

PoC シミュレーション

基準チャンクを 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_pressedmove_leftmove_rightvelocity.normalizedAnimatedSprite2D.play/stop が直接一致 accept
2 first_2d_game / clamp/screen section position.clampVector2.ZEROscreen_sizeAnimatedSprite2D が一致 accept
3 first_3d_game / player_movement_code Input.is_action_pressedmove_leftmove_rightnormalizedspeed が重複 false positive

1位の候補が上がる理由:

animatedsprite2d:
  文書全体で稀なトークンなのでIDFが大きい

move_left / move_right:
  チュートリアルの入力コードに直接登場

is_action_pressed:
  入力処理コードと直接一致

velocity.normalized:
  移動ベクトルの正規化フローと直接一致

3位候補が一緒に上がってくる理由:

3D movement 文書も入力処理と正規化された移動フローを説明します。  
だから BM25 の観点では query token overlap がかなり大きいです。  
しかし、基準チャンクの核心である AnimatedSprite2D、Vector2、screen_size、position.clamp とは合致しません。

PoCで確認するログ

BM25 PoCでは各候補ごとにトークン貢献度を示すことが重要です。

例:

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 のように似たコードが false positive として混入することがある。

判定

必ず検討すべき一次候補検索  
しかし単独使用では不十分