Repository navigation
[Feat] 하이브리드 검색 도입: 벡터 유사도에 희귀 단어 가중 키워드 점수 결합 #456
Copy link
Copy link
Closed
Labels
✨ Feature기능 개발기능 개발
Description
📌 Description
배경
멘토링에서 "벡터 검색에 키워드 검색을 함께 쓰는 하이브리드 방식"을 고려해 보라는 개선안이 나왔습니다.
현재 검색은 벡터(코사인 유사도) 하나로만 순위를 매기고 거릅니다.
벡터 거리순 후보 (topK × 4) → 유사도 0.30 미만 제거 → 문서당 2개 상한 → 상위 topK
(VectorSearchQueryService.selectCandidates, VectorSearchRepository.findTopK)
RAG는 이 결과 중 상위 3개 청크만 프롬프트에 넣기 때문에, 정답 청크가 4위 이하로 밀리면 LLM이 정답을 보지 못합니다.
현재 상태 측정 (구현 전 기준선)
로컬 DB에 같은 5개 문서(청크 83개)를 올리고 질문 42개(정답 있음 34, 문서에 없음 8)로 벡터 단독을 측정했습니다.
화면(공유 DB)에서 7개 질문을 실행한 결과와 순위·점수가 같아 로컬 측정을 대리 테스트로 썼습니다.
| 최소 유사도 기준 | 정답이 1위 | 정답이 3위 안 | MRR@10 | 식별자 질문 1위 | 문서에 없는 질문 → 결과 없음 |
|---|---|---|---|---|---|
| 0.30 (현재) | 0.765 | 0.941 | 0.847 | 0.714 | 0 / 8 |
| 0.45 | 0.765 | 0.941 | 0.843 | 0.714 | 3 / 8 |
| 0.50 | 0.706 | 0.882 | 0.784 | 0.571 | 6 / 8 |
| 0.55 | 0.588 | 0.735 | 0.652 | 0.357 | 8 / 8 |
문제
- 짧은 용어·약어 질문에 약함:
OM은 뭐야?의 정답 청크가 7위로 밀려 LLM이 "관련 문서를 찾지 못했습니다"라고 답함. 글자가 그대로 들어 있다는 정보를 순위에 쓰지 않음 - 기준값만으로는 해결 불가: 기준값을 올리면 문서에 없는 질문은 걸러지지만 식별자 질문의 1위 비율이 0.714에서 0.357로 떨어짐. 점수 하나로는 두 문제를 동시에 풀 수 없음
- 문서에 없는 질문에도 항상 5건이 반환됨 (AI가 이미 거절하므로 사용자에게 보이는 답변 영향은 작음)
반대로 바꿔 말한 질문은 현재도 잘 동작하므로 이 성능은 유지해야 합니다.
목표
기존 벡터 갈래는 그대로 두고, 질문 단어 일치를 작은 가산점으로 더해 벡터가 놓친 청크를 끌어올립니다.
설계 결정 (최종)
초기 계획은
pg_trgm키워드 갈래 + RRF 결합이었으나, 처음 보는 질문(세트 2, 38개)에서 1위 정답이 28개에서 24개로 줄어 폐기했습니다.
RRF는 순위만 봐서 벡터 1위 정답을 밀어내고, 문장 전체 비교는 질문 말투까지 점수화했기 때문입니다.
- 점수 결합:
순위 점수 = 벡터 유사도 + 0.1 × 단어 커버리지. 벡터가 순위를 주도하고 단어 일치는 최대 0.1점 보조 - 단어 커버리지: 질문에서 핵심 단어만 뽑고(조사·질문 말투 제거, 중복 제거), 단어마다 IDF 배점
ln((N+1)/(n+0.5))(N=읽을 수 있는 색인 완료 문서의 청크 수, n=그 단어가 든 청크 수)을 준 뒤청크가 가진 단어의 배점 합 ÷ 질문 단어 전체의 배점 합으로 계산 - 관련도 판정:
벡터 유사도 ≥ 0.45또는커버리지 ≥ 0.50일 때만 결과로 인정 - 단어 일치 방식: 정규식(
~*) +pg_trgmGIN 인덱스.tsvector('simple')는 "고구려는", "@MessageMapping으로"처럼 조사가 붙은 토큰을 한 단어로 봐서 제외. 영문·숫자 단어는 단어 경계로 일치 - 문서당 상한은 점수 결합 후에 적용
- 롤백 스위치:
search.hybrid.enabled(기본 켜짐). 끄면 기존 벡터 단독 검색 - 검증 방식: 질문 세트 3개를 겹치지 않게 나누고, 마지막 세트는 설계와 판정 기준 4개를 결과를 보기 전에 파일로 고정한 뒤 처음 사용
범위
document_chunks.chunk_text에pg_trgmGIN 인덱스 추가 (Flyway V46)- 단어 조회 쿼리 추가: 벡터 쿼리와 동일한 권한·상태 조건(
permittedIds,INDEXED,current_version_id, 삭제 제외, 활성 임베딩, 같은 모델) - 질문 단어 추출, IDF 배점, 점수 결합, 관련도 판정, 결합 후 문서당 상한
- 판정 기준값·가산점 가중치를 설정값으로 분리 (
search.hybrid.*) - 전후 비교용 질문 세트와 측정 도구
범위 밖
- 청킹 방식 변경 (문장·문단 경계, 작은 구간 병합, PDF 제목 인식)
- 리랭커, 형태소 분석기 도입
- 기존 문서 재임베딩 (임베딩은 바뀌지 않으므로 필요 없음)
- 메타데이터 필터(JSONB) 기반 검색
- 프런트엔드 표시 변경
- 큰 코퍼스(수만 청크)에서의 정확도·응답 시간 측정, 갈래별 점수 로그 (후속)
✅ To-do
- 운영 대상 OpenSQL에서
pg_trgm사용 가능 여부 확인 (1.6, trusted, 미설치) - 로컬 DB에 같은 5개 문서를 올려 공유 DB 화면 결과와 동일한지 확인
- 라벨된 질문 세트 3개 작성 (식별자, 바꿔 말함, 한영 혼합, 문서에 없음)
- 구현 전 기준선 측정 (벡터 단독, 기준값 0.30~0.55)
- Flyway:
pg_trgm확장과chunk_textGIN 인덱스 (V46) - 단어 조회 Repository 쿼리 (벡터와 동일한 권한·상태 조건)
- 질문 단어 추출, IDF 배점, 점수 결합과 결합 후 문서당 상한 Service 구현
- 관련도 판정과 설정값 분리, 롤백 스위치
- 권한 누수 방지 테스트 (접근 불가·삭제·비INDEXED·이전 버전·비활성 임베딩·다른 모델)
- 단위 테스트, Repository 통합 테스트
- 동일 질문 세트로 전후 재측정, 실제 AI 답변 12개 비교
- 설계 문서
docs/design/kangcheolung-#456-hybrid-search.md작성 - 큰 코퍼스(청크 수만 개)에서 응답 시간 전후 비교 (DB 조회가 요청마다 2번 늘어남)
- 공유 DB에
pg_trgm확장 선설치 (머지 후, 새 코드로 공유 DB에 백엔드를 띄우기 전) - 화면에서 동일 질문으로 최종 확인
✅ 완료 기준
- 질문 111개에서 정답이 1위인 질문이 벡터 단독보다 늘어난다 (82개에서 92개)
- 사전에 고정한 기준으로 처음 보는 질문(세트 3, 39개)에서도 개선된다 (1위 28개에서 32개, 좋아진 8 / 나빠진 0)
- 바꿔 말한 질문의 정확도가 벡터 단독 대비 떨어지지 않는다 (세트 3 기준: 1위 8 ≥ 7, 3위 안 9 ≥ 8)
- 권한 없는 문서가 단어 조회 경로로 나오지 않는다
구현 PR: #482
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
✨ Feature기능 개발기능 개발
Activity
kangcheolung commentedon Oct 9, 2026
Branch feature/456 created!
feat: #456 chunk_text pg_trgm 확장과 GIN 인덱스 추가
feat: #456 단어 문서 빈도와 가중 커버리지 조회 쿼리 추가
feat: #456 하이브리드 검색 설정과 기본값 추가
feat: #456 질문 단어 추출과 하이브리드 검색 서비스 추가
feat: #456 SearchFacade가 설정에 따라 하이브리드 검색을 사용
test: #456 단어 갈래 Repository 통합 테스트 추가
test: #456 단어 추출·하이브리드 서비스·설정 단위 테스트 추가
test: #456 SearchFacade 하이브리드 분기와 트랜잭션 경계 테스트 갱신
test: #456 검색 품질 측정 질문 세트와 스크립트, 실측 결과 증빙 추가
docs: #456 하이브리드 검색 설계 문서
fix: #456 마이그레이션 버전을 develop의 V45 이후인 V46으로 변경
test: #456 단어 갈래 통합 테스트 주석의 마이그레이션 버전 정정
docs: #456 설계 문서의 마이그레이션 버전을 V46으로 정정
docs: #456 하이브리드 검색 테스트 결과 문서
fix: #456 질문 단어 중복 제거
test: #456 단어 중복 제거 테스트 갱신
docs: #456 측정 판정 방식과 재현 방법 문구 정정
[-][Feat] 하이브리드 검색 도입: pg_trgm 키워드 갈래 + RRF 결합과 관련도 판정 개선[/-][+][Feat] 하이브리드 검색 도입: 벡터 유사도에 희귀 단어 가중 키워드 점수 결합[/+]