대안 B: BM25 only
흐름
raw chunkText
-> tokenizer
-> BM25
-> top JSONL 반환BM25가 보는 것
BM25는 대략 다음 요소로 점수를 만든다.
TF: 이 document 안에서 단어가 몇 번 나왔는가
IDF: 전체 corpus에서 이 단어가 얼마나 드문가
Length normalization: 긴 document가 무조건 유리해지지 않게 보정그래서 기준 chunk의 다음 단어들이 중요해진다.
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특히 다음 토큰은 corpus에서 드문 편이라 점수에 강하게 기여한다.
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하지만 기준 chunk는 2D이고 다음 단서가 중요하다.
AnimatedSprite2D
Vector2
position.clamp
screen_sizeBM25는 단어 점수 기반이라 2D/3D 문맥을 완벽히 이해하지 못한다.
PoC 시뮬레이션
기준 chunk를 BM25 query로 넣는다.
입력:
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:
이동 벡터 정규화 흐름과 직접 일치3위 후보가 같이 올라오는 이유:
3D movement 문서도 입력 처리와 normalized 이동 흐름을 설명한다.
그래서 BM25 입장에서는 query token overlap이 꽤 크다.
하지만 기준 chunk의 핵심인 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로 섞일 수 있다.
판정
반드시 검토해야 하는 1차 후보 검색
하지만 단독 사용은 부족