청크와 chunk_id

문서를 검색 가능한 조각으로 자른 것.

왜 자르나

RFP 한 건이 수백 페이지다. 통째로 벡터 하나에 넣으면 뜻이 뭉개지고, LLM에 통째로 넘길 수도 없다. 그래서 의미 단위로 자른다.

우리는 임베딩 모델 제한에 맞춰 512토큰 기준으로 자른다.

chunk_id — 위치 기반이라는 함정

doc_id::순번        예) 봉화군_재난통합관리시스템 고도화::0013

순번이 위치다. 그래서 다시 인덱싱하면 같은 id에 다른 본문이 들어갈 수 있다.

🔴 실제로 겪은 사고

골든셋 정답을 chunk_id로 저장해뒀는데, 다른 인덱스로 실험을 돌렸다.

인덱스id 매칭본문 일치
구버전56/56 (100%)0/56 (0%)
정본56/56 (100%)56/56 (100%)

id는 100% 맞아서 에러 없이 돌아간다. 본문만 전부 다르다. 아무 경고 없이 완전히 틀린 결과가 나온다. 가장 위험한 실패 모드.

대응: 실험할 때 인덱스 경로를 항상 명시하고, 정답 청크의 본문까지 대조한다.

표 청크

우리 코퍼스는 63.3%가 표 청크다. RFP의 핵심 정보(배점표·요구사항·장비 규격)가 거의 다 표 안에 있기 때문.

표 청크는 Dense 검색에 불리하다 — 셀 수십 개가 벡터 하나로 뭉개져 핵심 토큰의 신호가 희석된다. BM25가 이걸 보완할 후보였던 이유.

관련

골든셋 · 임베딩 · Dense 검색