Retriever 검색 대안 분해 문서
작성일: 2026년 6월 28일
이 디렉토리는 Retriever 검색 대안 ChatGPT 원문 메모를 보기 쉽게 다시 나눈 문서 묶음이다.
원문 메모는 그대로 보존한다. 이 README에는 공통 맥락, 현재 방식, 모델 후보, 선택 가이드를 합쳤다. 하위 문서는 대안별 문서만 둔다.
종합 비교표
이 표들은 아직 최종 선택지가 아니라, 6월 28일에 비교해야 할 검색 대안을 한 화면에서 판단하기 위한 관찰표다. 기준은 “코드 chunk를 그대로 Retriever에 넣었을 때 어떤 JSONL 후보가 올라오고, 그 후보가 Qwen 검증 단계에서 직접 근거로 인정될 수 있는가”다.
한눈에 보는 결론
| 대안 | 위치 | 기대 역할 | 바로 쓸 수 있는 정도 | 핵심 장점 | 핵심 위험 | 현재 판단 |
|---|---|---|---|---|---|---|
| A. PostgreSQL full-text 유지 | 현재 /api/retrieve 기준선 |
지금 구현된 검색이 어느 정도까지 되는지 확인 | 높음 | 이미 붙어 있고 로그를 바로 볼 수 있음 | 긴 코드 chunk가 query가 되면 관련 문서도 누락될 수 있음 | 기준선으로 남기되, 최종 검색 방식으로 단정하지 않는다 |
| B. BM25 only | 1차 검색 후보 | 코드/API 문자열이 직접 들어간 문서를 찾기 | 중간 | KinematicBody2D, move_and_slide, AnimatedSprite2D 같은 직접 문자열에 강함 |
2D/3D처럼 넓은 단어가 섞이면 false positive가 남음 | 첫 PoC로 가장 관찰하기 좋다 |
| C. embedding only | 의미 기반 recall 확장 | 문자열이 정확히 같지 않아도 관련 설명 문서를 찾기 | 중간 | 문장 의미, 튜토리얼 설명, 유사한 사용 맥락을 넓게 가져옴 | 버전/API 정확도 판정에는 단독 사용 위험이 큼 | 단독 사용보다 보조 recall로 둔다 |
| D. BM25 + embedding | 현실적인 중간안 | 문자열 근거와 의미 근거를 함께 모으기 | 중간 | BM25의 정확성과 embedding의 recall을 같이 씀 | 점수 결합, 중복 제거, 상위 후보 기준이 필요함 | 실사용 최소안에 가깝다 |
| E. Qwen query profile | 검색 보조 실험 | 코드 chunk에서 검색 의도를 JSON으로 만들기 | 낮음 | 사람이 보는 query profile은 읽기 쉬움 | 검색 전에 LLM이 없는 API/의도를 만들어낼 수 있음 | 1차 검색 핵심으로 쓰기보다 실험/보조로 둔다 |
| F. BM25 + embedding + reranker + validator | 최종 후보 구조 | 후보 생성, 재정렬, 직접 근거 검증까지 연결 | 낮음 | 품질과 관찰성이 가장 좋음 | 비용, latency, 단계 수가 많음 | 최종 목표 후보로 둔다 |
PoC 시뮬레이션 결과 비교
| 대안 | 입력 chunk | 검색 후보가 나오는 방식 | 관련 JSONL이 올라올 가능성 | 관련 없는 JSONL이 섞일 가능성 | Qwen 검증 전 기대 상태 | Qwen 검증 후 기대 상태 |
|---|---|---|---|---|---|---|
| A | chunkText 전체 |
plainto_tsquery('simple', chunkText)로 긴 query 생성 |
낮거나 불안정 | 낮을 수도 있지만, 0건이면 관찰할 후보가 없음 | 후보가 없거나 일부만 반환 | 직접근거 검증까지 가기 전에 누락 가능 |
| B | chunkText 전체 |
토큰별 BM25 점수로 문서 순위화 | 높음 | 중간 | Input.is_action_pressed, AnimatedSprite2D, clamp 문서가 올라올 수 있음 |
직접 문자열이 없으면 탈락 |
| C | chunkText 전체 |
code/document embedding 유사도 | 중간 | 높음 | “movement”, “2D”, “player” 설명 문서가 넓게 올라옴 | JSONL 안 직접 문자열이 없으면 탈락 |
| D | chunkText 전체 |
BM25 후보와 embedding 후보를 합침 | 높음 | 중간 | 문자열 후보와 의미 후보가 함께 보임 | 직접근거 있는 후보만 남김 |
| E | chunkText 전체를 Qwen이 해석 |
Qwen이 만든 검색 profile로 검색 | profile이 맞으면 중간 | 높음 | profile에 없는 API가 섞일 수 있음 | profile 자체가 실제 코드와 맞는지도 검증 필요 |
| F | chunkText 전체 |
BM25 + embedding 후보를 reranker가 재정렬 | 높음 | 낮음 | 후보가 많아도 상위가 정리됨 | Qwen이 “예/아니오”로 직접근거만 남김 |
데모 판정에서 드러난 차이
| 관찰 상황 | 처음 단순 프롬프트 | 개선한 직접근거 프롬프트 | 검색 구조에 주는 의미 |
|---|---|---|---|
| Godot 3 코드 + 관련 JSONL | “예”가 나올 수 있음 | “예”가 나와야 함 | 관련 근거가 실제 문자열/API와 맞으면 통과 |
| Godot 3 코드 + 무관 JSONL | 넓은 Godot 단어 때문에 “예”가 나올 수 있음 | “아니오”가 나와야 함 | 검색 후보가 올라와도 직접근거 검증 없이는 위험 |
KinematicBody2D 코드 + 3D Spatial mapping |
Godot migration이라는 넓은 의미로 관련 있다고 볼 수 있음 | “아니오”가 맞음 | embedding only나 느슨한 LLM 판단은 false positive를 만들 수 있음 |
yield(...) 코드 + await prototype |
직접 패턴이 있으면 “예” | “예” | label_prototypes는 통째 사용 패턴 변경을 잡는 근거가 될 수 있음 |
AnimatedSprite2D.play() 코드 + 일반 animation docs |
의미상 관련 있어 보일 수 있음 | JSONL에 직접 문자열/패턴이 없으면 “아니오” | docs_chunks도 최종 판단에는 직접근거 확인이 필요 |
후보 반환 양상 비교
| 대안 | 상위에 잘 올라오는 후보 | 놓치기 쉬운 후보 | 잘못 섞이기 쉬운 후보 | 눈으로 확인할 포인트 |
|---|---|---|---|---|
| A | 한 row 안에 query 토큰을 많이 가진 문서 | 관련 토큰이 여러 문서에 나뉜 경우 | query가 너무 엄격하면 거의 없음 | 왜 0건인지, 어떤 토큰 때문에 매칭이 깨졌는지 |
| B | API 이름, 함수명, 노드명이 직접 들어간 row | 표현이 바뀐 설명형 문서 | 같은 단어를 가진 다른 시스템 문서 | match_terms와 실제 source chunk 문자열 일치 여부 |
| C | 의미가 비슷한 튜토리얼/설명 문서 | 짧은 exact API mapping | Godot 버전이나 2D/3D가 다른 문서 | cosine 점수보다 직접 문자열 근거가 있는지 |
| D | exact 후보 + semantic 후보 | 점수 결합에서 밀린 후보 | 두 검색이 모두 약하게 맞은 후보 | 후보가 BM25에서 왔는지 embedding에서 왔는지 |
| E | Qwen이 뽑은 의도와 맞는 후보 | Qwen이 profile에 넣지 않은 실제 코드 단서 | Qwen이 상상한 API/의도 관련 후보 | profile의 각 필드가 실제 chunk 안에 존재하는지 |
| F | reranker가 chunk와 맞다고 본 후보 | reranker 모델이 모르는 Godot 특수 케이스 | reranker 점수는 높지만 JSONL 직접근거가 없는 후보 | rerank score와 validator 판정이 갈리는 지점 |
False Positive / False Negative 비교
| 대안 | false positive 예 | false negative 예 | 줄이는 방법 |
|---|---|---|---|
| A | 드물지만 query가 넓게 풀리면 일반 movement 문서가 섞임 | 관련 문서가 여러 row에 나뉘면 0건 | query 생성 방식을 바꾸거나 BM25 후보를 추가 |
| B | movement, player, 2d 때문에 다른 movement 문서가 섞임 |
API 이름이 문서에는 설명형으로만 있으면 누락 | stopword/약한 토큰 분리, 직접 API 토큰 가중 |
| C | 의미가 비슷한 3D/다른 버전 문서가 섞임 | 짧은 API rename row를 못 잡음 | BM25와 병렬로 쓰고 validator를 붙임 |
| D | BM25와 embedding 양쪽에서 약하게 맞은 후보가 섞임 | fusion 기준이 잘못되면 한쪽 후보가 밀림 | union source flag와 direct evidence log를 남김 |
| E | Qwen이 없는 migration_intent를 만들어 후보를 오염시킴 |
Qwen이 실제 코드 단서를 profile에 누락 | profile을 검색 전 신뢰하지 않고 보조로만 사용 |
| F | reranker가 말이 되는 설명을 과대평가 | 후보 생성 단계에서 아예 못 가져온 문서 | 후보 수를 충분히 확보하고 Qwen 검증을 마지막에 둠 |
테이블별 적합도
| 대안 | docs_chunks |
api_mapping |
label_prototypes |
비고 |
|---|---|---|---|---|
| A | 긴 설명 문서에서 불안정 | exact mapping row가 짧으면 놓칠 수 있음 | pattern row가 짧으면 놓칠 수 있음 | 현재 방식의 한계를 확인하는 기준선 |
| B | API/heading/token 검색에 좋음 | source/target API exact 검색에 좋음 | source/target pattern 검색에 좋음 | 세 테이블 모두 첫 검색 후보로 관찰하기 좋음 |
| C | 설명형 문서 recall에 좋음 | API rename처럼 짧은 row에는 약함 | 사용 패턴 의미가 비슷하면 보조 가능 | docs_chunks 보조에 가장 자연스러움 |
| D | 설명/문자열 후보를 모두 확보 | exact mapping과 semantic 후보를 함께 확보 | 통째 사용 패턴 후보를 넓게 확보 | 세 테이블 공통 구조로 가장 무난 |
| E | query profile이 잘 나오면 설명 문서 검색 가능 | hallucinated API가 들어가면 위험 | prototype 의도를 만들 수 있지만 오염 가능 | 검색 핵심이 아니라 관찰/보조 실험에 가깝다 |
| F | 최종 설명 근거 정제에 좋음 | migration 근거 정제에 좋음 | 사용 방식 변경 근거 정제에 좋음 | 세 테이블을 같은 파이프라인으로 다루기 좋음 |
로그로 반드시 봐야 하는 것
| 대안 | 검색 전 로그 | 검색 중 로그 | 검색 후 로그 | 실패 원인 확인 포인트 |
|---|---|---|---|---|
| A | raw chunkText, 생성된 tsquery |
search_tsv @@ query hit 수, ts_rank_cd |
반환 row, score | query가 너무 길어졌는지, 어떤 토큰이 row에 없는지 |
| B | raw chunkText, token list |
term frequency, matched terms, BM25 score | table별 top-k | 강한 토큰과 약한 토큰이 구분되는지 |
| C | raw chunkText, embedding model |
vector distance/cosine score | semantic top-k | 실제 문자열 없이 의미만 맞는 후보인지 |
| D | BM25 top-k, embedding top-k | union, duplicate merge, score fusion | source flags가 붙은 후보 목록 | 한쪽 검색만 가져온 후보가 왜 살아남았는지 |
| E | Qwen에 보낸 raw chunk | Qwen query profile JSON | profile 기반 검색 결과 | profile 필드가 실제 source에 존재하는지 |
| F | BM25/embedding 후보 전체 | rerank score, rerank order | Qwen 예/아니오, reject reason |
reranker 통과 후보가 직접근거 검증에서 왜 탈락했는지 |
구현 복잡도와 운영 비용
| 대안 | 구현량 | DB 변경 | 외부 모델 비용 | latency | 디버깅 난이도 | 실패했을 때 고치기 쉬운 정도 |
|---|---|---|---|---|---|---|
| A | 낮음 | 거의 없음 | 없음 | 낮음 | 낮음 | 낮음. 다만 성능 한계가 구조적일 수 있음 |
| B | 중간 | BM25 검색 엔진/인덱스 선택 필요 | 없음 또는 낮음 | 낮음 | 낮음 | 높음. 토큰/가중치 조정이 가능 |
| C | 중간 | embedding 컬럼/인덱스 필요 | 있음 | 중간 | 중간 | 중간. 모델/차원/threshold 조정 필요 |
| D | 중간~높음 | BM25 + vector 둘 다 필요 | 있음 | 중간 | 중간 | 높음. 어느 검색 경로가 실패했는지 분리 가능 |
| E | 중간 | profile 저장은 선택 | 있음 | 높음 | 높음 | 낮음. LLM profile이 왜 틀렸는지 재현이 어려울 수 있음 |
| F | 높음 | BM25 + vector + rerank log 필요 | 있음 | 높음 | 높음 | 높음. 단계별 로그가 있으면 고칠 지점이 보임 |
Qwen을 어디에 둘지 비교
| 위치 | 장점 | 위험 | 현재 더 맞는 사용 방식 |
|---|---|---|---|
| 검색 전 query 생성 | 하드코딩 없이 검색 의도를 만들 수 있음 | 없는 단서를 만들어 검색을 오염시킬 수 있음 | 실험용으로만 둔다 |
| 검색 후보 후 직접근거 검증 | 검색 결과가 실제 코드와 맞는지 걸러낼 수 있음 | 호출 비용이 듦 | 가장 중요하게 본다 |
| 최종 답변 생성 | 코드 설명/마이그레이션 응답을 만들 수 있음 | 근거가 틀리면 답변도 틀림 | 검증된 JSONL 후보 이후에 둔다 |
| 전체 판단 통합 | 사람이 읽기 좋은 결론을 만들 수 있음 | 중간 실패를 숨길 수 있음 | 로그가 충분히 쌓인 뒤 검토한다 |
선택 우선순위
| 우선순위 | 선택지 | 이유 | 이 단계에서 확인할 질문 |
|---|---|---|---|
| 1 | A를 기준선으로 측정 | 현재 구현이 어디서 깨지는지 알아야 함 | 지금 방식이 실제로 몇 건을 반환하는가 |
| 2 | B를 별도 PoC로 붙임 | 코드/API 문자열 검색이 가장 설명 가능함 | KinematicBody2D, yield, move_and_slide가 올바른 row를 찾는가 |
| 3 | C를 보조 recall로 비교 | docs_chunks 설명형 후보를 넓힐 수 있음 | 의미 후보가 직접근거 검증에서 얼마나 탈락하는가 |
| 4 | D로 병렬 후보 생성 | 현실적인 최소 구조 | BM25와 embedding 후보를 합쳤을 때 품질이 좋아지는가 |
| 5 | F로 reranker/validator 추가 | 최종 품질 확인 | Qwen 직접근거 판정이 무관 JSONL을 안정적으로 버리는가 |
| 보류 | E | 검색 전 LLM은 오염 위험이 큼 | profile이 실제 코드 문자열만 기반으로 만들어지는가 |
PoC 체크리스트
| 체크 항목 | 봐야 하는 화면/로그 | 성공 기준 |
|---|---|---|
같은 chunkText를 여러 대안에 넣기 |
웹 디버거의 chunk 입력 영역 | 입력이 대안별로 달라지지 않는다 |
| 테이블별 검색 버튼 | docs_chunks, api_mapping, label_prototypes 버튼 |
같은 chunk로 테이블별 후보 차이가 보인다 |
| raw 후보 확인 | 반환된 JSONL payload | source chunk 안 실제 문자열과 맞는 필드가 보인다 |
| Qwen 검증 확인 | prompt + chunk + jsonl 디버그 영역 |
관련 후보는 “예”, 무관 후보는 “아니오”가 나온다 |
| reject reason 확인 | validator 결과 로그 | Godot, migration, 2D 같은 넓은 단어만 맞은 후보가 탈락한다 |
| false positive 수집 | 탈락 후보 목록 | 나중에 query/token/validator 규칙 개선에 쓸 수 있다 |
| 대안별 비교 저장 | 관찰일지 또는 결과 JSON | 같은 입력에 대한 A-F 차이가 남는다 |
대안 문서
- 대안 A: PostgreSQL full-text 유지
- 대안 B: BM25 only
- 대안 C: embedding only
- 대안 D: BM25 + embedding 병렬
- 대안 E: Qwen query profile 생성
- 대안 F: BM25 + embedding + reranker + validator
현재 전제
현재 기준은 다음과 같다.
1. zip 안에는 markdown 원본, 스키마, 디버거, 설계 문서가 있다.
2. 로컬에는 이미 markdown -> JSONL -> DB 변환본이 들어가 있다.
3. 지금 볼 수 있는 것은 변환 전 markdown과 DB 스키마/검색 흐름이다.
4. PoC는 zip 안 markdown을 JSONL chunk처럼 쪼개서, 로컬 DB에 들어갔을 법한 검색 대상을 시뮬레이션해야 한다.
5. 필요한 것은 코드 뼈대가 아니라, chunk가 들어갔을 때 각 검색 방식이 어떻게 점수를 만들고 왜 성공/실패하는지 추적하는 것이다.JSONL/DB 기준
문서 기준 산출물은 다음이다.
work/godot_rag/jsonl/docs_chunks.jsonl
work/godot_rag/jsonl/api_mapping.jsonl
work/godot_rag/jsonl/label_prototypes.jsonl
work/godot_rag/jsonl/ingest_report.jsonlDB는 JSONL 한 줄을 통째로 payload jsonb에 넣는 구조가 아니라, JSONL 필드가 테이블 컬럼으로 펼쳐지는 구조로 이해한다.
docs_chunks
chunk_id
doc_version
source_url
source_file
source_sha256
doc_type
symbol
section_path
heading
content
code_blocks
language_tags
godot_version_tags
api_symbols
token_count
metadata
embedding
search_tsvapi_mapping
mapping_id
source_api
target_api
change_type
godot_from
godot_to
confidence
evidence_chunk_ids
match_terms
notes
negative_patternslabel_prototypes
prototype_id
label
task_type
input_pattern
expected_finding
recommended_action
evidence_mapping_ids
evidence_chunk_ids
severity
validator_rules
embedding
search_tsv기준 chunk
대안 비교에서 기준으로 삼은 chunk는 다음 Godot 코드다.
func _process(delta):
var velocity = Vector2.ZERO
if Input.is_action_pressed(&"move_right"):
velocity.x += 1
if Input.is_action_pressed(&"move_left"):
velocity.x -= 1
if velocity.length() > 0:
velocity = velocity.normalized() * speed
$AnimatedSprite2D.play()
else:
$AnimatedSprite2D.stop()
position += velocity * delta
position = position.clamp(Vector2.ZERO, screen_size)강한 토큰:
animatedsprite2d
is_action_pressed
move_left
move_right
normalized
clamp
screen_size
vector2
zero약한 토큰:
func
var
if
else
velocity
position
delta
x
0
1검색 입력은 계속 chunkText 그대로 유지한다. 검색 전에 Godot API signal을 필수로 추출해서 별도 query로 바꾸는 방식은 기본 설계의 핵심으로 두지 않는다. 필요하다면 나중에 보조 점수 정도로만 검토한다.
현재 /api/retrieve 방식
현재 프로젝트의 /api/retrieve는 BM25가 아니다.
흐름은 다음에 가깝다.
chunkText
-> plainto_tsquery('simple', chunkText)
-> search_tsv @@ query
-> ts_rank_cd(...)PostgreSQL의 ts_rank_cd는 full-text ranking 함수다. BM25처럼 term frequency, inverse document frequency, field length normalization을 조합하는 검색 엔진식 BM25 자체와는 다르게 봐야 한다.
plainto_tsquery(raw_chunk)는 입력 chunk에서 토큰을 뽑아 query를 만든다. 기준 chunk는 다음처럼 긴 query가 될 수 있다.
func & process & delta & var & velocity & vector2 & zero
& input & is_action_pressed & move_right & move_left
& length & normalized & speed & animatedsprite2d
& play & stop & position & clamp & screen_size이 방식은 한 row 안에 너무 많은 토큰을 요구할 수 있다.
공식문서 chunk가 다음처럼 나뉘어 있으면 문제가 생긴다.
chunk A:
Input.is_action_pressed
velocity.normalized
AnimatedSprite2D.play/stop
chunk B:
AnimatedSprite2D 설명
position.clamp
screen_size둘 다 관련 있지만, 하나의 row에 모든 토큰이 동시에 들어있지는 않을 수 있다.
원문 메모에서는 strict raw AND 성격의 검색이 다음처럼 실패할 수 있다고 본다.
strict raw AND hits: 0현재 방식은 PoC의 기준선으로는 볼 수 있지만, 최종 검색 전략으로 유지하기에는 약하다. 다음 단계에서는 현재 방식과 BM25를 분리해서 비교해야 한다.
모델 후보
voyage-code-3
현재 프로젝트에 가장 잘 맞는 embedding 후보로 언급됐다.
이유:
query가 자연어 질문이 아니라 GDScript code chunk다.
검색 대상 JSONL에도 code_blocks, API 이름, 문서 설명이 섞여 있다.장점:
- code retrieval에 강하다.
- 긴 chunk 처리에 유리하다.
- code -> docs 검색에 적합하다.
단점:
- 외부 API 의존이 있다.
- 비용이 든다.
- Godot 특화 모델은 아니다.
메모 기준 추천:
voyage-code-3 1024 floatOpenAI text-embedding-3-large
범용 고품질 embedding 후보.
장점:
- 범용 semantic retrieval에 강하다.
- 문서 설명 검색에 안정적이다.
- OpenAI ecosystem과 붙이기 쉽다.
단점:
- code retrieval 전용은 아니다.
- 기본 차원이 커서 저장/인덱스 비용이 커질 수 있다.
- GDScript chunk -> JSONL 검색에는 voyage-code-3보다 덜 직접적일 수 있다.
메모 기준 추천도:
2순위Gemini Embedding
범용/다국어 semantic retrieval 후보.
장점:
- 문서 설명형 retrieval에 좋다.
- 차원 축소 선택지가 있다.
- 다국어 문서 검색에 강점이 있을 수 있다.
단점:
- code retrieval 전용 선택지는 아니다.
- API 코드 정확성보다 의미 유사성에 가깝다.
- Godot migration exact 판단에는 단독 사용 위험이 있다.
Jina embeddings v4
복잡한 문서, multimodal, visually rich document retrieval에 강점이 있는 후보.
장점:
- 문서 검색 폭이 넓다.
- multimodal/복합 문서에 강하다.
- code adapter 계열도 검토 가능하다.
단점:
- 현재 프로젝트는 markdown/code 중심이다.
- 이미지/표 retrieval이 핵심이 아니다.
- 지금 단계에서는 과한 선택일 수 있다.
메모 기준 추천도:
지금 당장은 우선순위 낮음rerank-2.5
reranker 후보로 언급됐다.
역할:
BM25와 embedding이 가져온 후보를 raw chunk와 함께 다시 비교한다.
관련도 점수로 후보를 재정렬한다.이 프로젝트에서 기대하는 효과:
- 2D movement와 3D movement false positive를 낮춘다.
AnimatedSprite2D,Vector2,screen_size,position.clamp같은 직접 문맥을 더 잘 반영한다.- BM25와 embedding이 각각 가져온 후보를 최종 후보로 정리한다.
주의:
- reranker는 validator가 아니다.
- 직접근거 검증은 Qwen direct-evidence validator가 다시 해야 한다.
선택지 요약
| 대안 | 흐름 | 장점 | 위험 |
|---|---|---|---|
| A | PostgreSQL full-text 유지 | 이미 구현됨 | 긴 chunk에서 0건 가능, BM25 아님 |
| B | BM25 only | 투명함, 문자열/API에 강함 | 3D movement 같은 false positive |
| C | embedding only | 의미 검색 가능 | API/버전 정확도 약함 |
| D | BM25 + embedding | 현실적인 균형 | 점수 결합 튜닝 필요 |
| E | Qwen query profile | 하드코딩 감소, 의도 요약 가능 | hallucination, 비용, 검색 전 오염 |
| F | BM25 + embedding + reranker + validator | 품질 최우선 | 비용, latency, 단계 많음 |
현재 임시 판단
원문 메모의 결론은 다음에 가깝다.
입력은 chunkText 하나만 유지한다.
1차 검색은 BM25로 한다.
이유: 코드/API 문자열 검색에 투명하고 강하다.
2차 검색은 voyage-code-3 embedding으로 한다.
이유: query가 코드 chunk라서 code retrieval 모델이 맞다.
3차 정렬은 rerank-2.5로 한다.
이유: BM25와 embedding이 가져온 비슷한 후보 중 진짜 chunk와 맞는 JSONL을 위로 올리기 위해서다.
마지막 검증은 Qwen direct-evidence validator로 한다.
이유: JSONL 안에 chunk와 직접 맞는 문자열/패턴 근거가 없으면 버려야 하기 때문이다.한 줄 요약:
raw chunk 그대로 입력
-> BM25 + code embedding 병렬 후보 생성
-> reranker 재정렬
-> Qwen 직접근거 검증다음에 실제로 비교할 것
- 현재 PostgreSQL full-text 방식이 기준 chunk에서 몇 건을 반환하는지
- BM25가
first_2d_game을 실제로 상위에 올리는지 - BM25 only에서 3D movement false positive가 얼마나 섞이는지
- embedding only가 어떤 설명형 문서를 추가로 가져오는지
- BM25 + embedding union에서 중복과 점수를 어떻게 합칠지
- reranker가 2D/3D 후보를 제대로 재정렬하는지
- Qwen direct-evidence validator가 관련 없는 JSONL을 실제로
아니오로 버리는지