idea_world_labDEV JOURNAL
2026년 6월 28일 일요일

대안 F: BM25 + embedding + reranker + validator

흐름

raw chunkText
  -> BM25 top 80
  -> embedding top 80
  -> 후보 union
  -> reranker가 raw chunk와 각 JSONL 후보를 직접 비교
  -> top JSONL 반환
  -> Qwen direct-evidence validator가 직접근거 검증

역할 분담

BM25:

정확 문자열/API 토큰 후보를 찾는다.

code embedding:

표현이 다르지만 의미가 가까운 후보를 보완한다.

reranker:

BM25와 embedding이 가져온 후보를 raw chunk와 비교해 다시 정렬한다.

Qwen direct-evidence validator:

JSONL 안에 현재 chunk와 직접 맞는 문자열/패턴 근거가 있는지 확인한다.
근거 없는 JSONL은 폐기한다.

기준 chunk에서 기대되는 정렬

높게 올라가야 할 후보:

first_2d_game / coding_the_player
same page / clamp and AnimatedSprite2D explanation

낮아져야 할 후보:

first_3d_game / player_movement_code
unrelated api_mapping
unrelated label_prototypes

PoC 시뮬레이션

기준 chunk를 최종 추천 흐름에 넣는다고 가정한다.

raw chunkText
  -> BM25 top 80
  -> voyage-code-3 embedding top 80
  -> 후보 union
  -> reranker
  -> Qwen direct-evidence validator

1단계: BM25 후보

BM25가 가져올 후보:

A. first_2d_game / coding_the_player
   reason: Input.is_action_pressed, move_left, move_right, AnimatedSprite2D.play/stop

B. first_2d_game / clamp section
   reason: position.clamp, Vector2.ZERO, screen_size

C. first_3d_game / player_movement_code
   reason: Input.is_action_pressed, move_left, move_right, normalized

2단계: embedding 후보

embedding이 가져올 후보:

D. first_2d_game / movement explanation
   reason: 2D movement, keyboard input, animation

E. first_2d_game / screen bounds explanation
   reason: keep player inside screen

F. first_3d_game / movement
   reason: player movement semantic similarity

3단계: 후보 union

union 후에는 중복을 합친다.

A/D -> first_2d_game / coding_the_player
B/E -> first_2d_game / clamp/screen bounds
C/F -> first_3d_game / player_movement

4단계: reranker 재정렬

reranker가 raw chunk와 후보를 함께 본다.

예상 rerank:

rerank 후보 이유
1 first_2d_game / coding_the_player 입력 처리, velocity, AnimatedSprite2D play/stop이 직접 맞음
2 first_2d_game / clamp/screen bounds position.clamp, Vector2.ZERO, screen_size가 직접 맞음
3 first_3d_game / player_movement 입력/이동은 비슷하지만 3D 문맥이고 AnimatedSprite2D/screen_size가 없음

5단계: Qwen direct-evidence validator

Qwen validator에는 다음처럼 묻는다.

SOURCE_CODE와 retrieved JSONL을 보고,
JSONL 안에 SOURCE_CODE와 직접 맞는 문자열/API 호출/패턴 근거가 있는가?
예 또는 아니오로 먼저 판정하라.

예상 결과:

first_2d_game / coding_the_player:
  validator = 예
  direct evidence = Input.is_action_pressed, AnimatedSprite2D.play, AnimatedSprite2D.stop

first_2d_game / clamp/screen bounds:
  validator = 예
  direct evidence = position.clamp, Vector2.ZERO, screen_size

first_3d_game / player_movement:
  validator = 아니오 또는 낮은 관련
  reason = movement input은 비슷하지만 3D 문서이며 AnimatedSprite2D/screen_size 직접 근거가 없음

PoC에서 확인할 로그

이 대안은 단계가 많으므로 다음을 한 화면에서 봐야 한다.

1. raw chunkText
2. BM25 후보와 matched terms
3. embedding 후보와 similarity
4. union 결과
5. reranker 점수와 순위 변화
6. Qwen validator 예/아니오
7. 최종 accept/reject JSONL

눈에 보이는 결론:

BM25와 embedding은 후보를 넓게 모은다.
reranker는 비슷한 후보의 순서를 바로잡는다.
Qwen validator는 직접근거 없는 JSONL을 최종 폐기한다.

장점

  • 품질이 가장 좋을 가능성이 높다.
  • BM25 false positive를 줄일 수 있다.
  • embedding false positive도 줄일 수 있다.
  • raw chunk 조건을 유지한다.
  • 하드코딩 의존이 낮다.
  • Qwen validator로 직접근거 없는 JSONL을 마지막에 제거할 수 있다.

단점

  • 비용이 든다.
  • latency가 생긴다.
  • 후보를 너무 많이 넣으면 느리다.
  • reranker도 근거 검증기는 아니므로 마지막 validator가 필요하다.

판정

품질 최우선 최종 추천안

원문 메모의 최종 추천은 이 구조에 가깝다.