Skip to content

feat: HybridSearchEngine 구현 — Dense+Sparse 하이브리드 검색 (#154)#192

Merged
umyunsang merged 5 commits into
developfrom
feat/154-hybrid-search-engine
Mar 26, 2026
Merged

feat: HybridSearchEngine 구현 — Dense+Sparse 하이브리드 검색 (#154)#192
umyunsang merged 5 commits into
developfrom
feat/154-hybrid-search-engine

Conversation

@umyunsang
Copy link
Copy Markdown
Member

@umyunsang umyunsang commented Mar 25, 2026

Summary

  • HybridSearchEngine 핵심 모듈 (src/inference/hybrid_search.py): asyncio 기반 Dense(FAISS) + Sparse(BM25) 병렬 검색, Weighted RRF 융합 (k=60), 데이터 타입별 가중치 적용
  • 스키마 확장 (schemas.py): SearchRequestsearch_mode (dense/sparse/hybrid), SearchResponsesearch_time_ms, actual_search_mode 추가
  • API 통합 (api_server.py): /v1/search + /search 이중 경로, MultiIndexManager·BM25 초기화, 레거시 retriever 폴백
  • 파이프라인 통합 (pipeline.py): --mode full 시 BM25 자동 빌드, --mode bm25 단독 실행, IndexType 기반 파일명 통일
  • ADR-005 (docs/architecture/ADR-005-hybrid-search-architecture.md): 하이브리드 검색 아키텍처 결정 기록
  • 테스트: 단위 47개 + E2E 15개 + Okt 폴백 11개 + 통합 28개 = 101개 전체 통과 (hybrid_search.py 커버리지 91%)

코드 리뷰 반영사항 (2차)

@yuujjjj @siuJang 리뷰 반영 — Blocker 2건 + Critical 1건 + High 2건 + Medium 3건 수정 완료:

심각도 수정 내용 리뷰어 합의
Blocker build_index_from_jsonlinput 필드 fallback 추가 — civil_complaint_train.jsonl 빌드 실패 해결 3/3
Blocker BM25 파일명을 IndexType.value 기반 통일 (v2.pklcase.pkl) — 서버 로드 경로 불일치 해결 3/3
Critical 검색 결과 PII 마스킹 레이어 추가 — PIIMasker.mask_all() 적용, 개인정보보호법 준수 Security
High 양측 검색 동시 실패 시 RuntimeError 전파 — return_exceptions=True + 편측 graceful degradation Security
High 빌드→검색→RRF 전체 경로 통합 테스트 28개 추가 — 실제 BM25Indexer 사용 검증 Architect
Medium Hybrid→Dense 폴백 시 actual_search_mode 반환 — search() Tuple 시그니처 확장 3/3
Medium 타입별 content 추출 _extract_content_by_type() 분리 — LAW/MANUAL/NOTICE 본문 누락 해결 3/3
Medium /health에 BM25 인덱스 로딩 상태 + hybrid_search_enabled + pii_masking_enabled 노출 Security

변경 파일

파일 변경 내용
src/inference/bm25_indexer.py input 필드 fallback 추가
src/data_collection_preprocessing/pipeline.py IndexType 기반 BM25 빌드 + JSONL별 예외 격리
src/inference/hybrid_search.py 양측 실패 에러 전파 + actual_mode Tuple 반환
src/inference/api_server.py PII 마스킹 + 타입별 content 추출 + /health BM25 상태
src/inference/schemas.py actual_search_mode 필드 추가
tests/test_inference/test_hybrid_search_integration.py 통합 테스트 28개 신규
tests/test_inference/test_hybrid_search.py Tuple 시그니처 반영
tests/test_inference/test_hybrid_search_e2e.py Tuple 시그니처 반영

관련 이슈

Test plan

  • pytest tests/test_inference/test_hybrid_search.py — 단위 테스트 47개
  • pytest tests/test_inference/test_hybrid_search_e2e.py — E2E 통합 테스트 15개
  • pytest tests/test_inference/test_tokenizer_fallback.py — Okt 폴백 검증 11개
  • pytest tests/test_inference/test_hybrid_search_integration.py — 빌드→검색→RRF 통합 테스트 28개
  • 전체 101개 통과, 0 실패
  • search_mode별(dense/sparse/hybrid) 실제 서버 동작 확인
  • --mode bm25 파이프라인 단독 실행 확인

github-actions Bot and others added 4 commits March 25, 2026 09:09
2명 승인, CODEOWNERS 최종 승인, 리뷰 코멘트 해결 조건을 명시
- HybridSearchEngine 핵심 모듈 구현 (asyncio 기반 병렬 검색, Weighted RRF)
- SearchRequest/SearchResponse 스키마 확장 (search_mode, search_time_ms)
- /v1/search 엔드포인트 통합 및 레거시 /search 하위 호환 유지
- vLLMEngineManager에 MultiIndexManager, BM25 인덱스 초기화 추가
- pipeline.py에 BM25 빌드 단계 통합 (--mode full 자동, --mode bm25 단독)
- ADR-005 하이브리드 검색 아키텍처 결정 기록 작성
- 단위 테스트 47개, E2E 통합 테스트 15개, Okt 폴백 검증 11개 (총 73개)
@umyunsang umyunsang requested review from siuJang and yuujjjj March 25, 2026 11:56
@github-actions github-actions Bot added documentation Improvements or additions to documentation data preprocessing ai-model AI 모델 관련 backend 백엔드 관련 infra 인프라/배포 관련 enhancement New feature or request labels Mar 25, 2026
Copy link
Copy Markdown
Contributor

@yuujjjj yuujjjj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이번 PR에서 가장 큰 문제는 하이브리드 검색의 핵심 경로가 현재 저장소의 데이터/초기화 규약과 맞지 않아, 기능이 추가된 것처럼 보이지만 실제 운영 경로에서는 sparse 검색이 비활성화될 가능성이 높다는 점입니다.

🔴 Blocker: BM25 빌드가 현재 저장소의 표준 학습 포맷을 처리하지 못해 sparse 인덱스 생성이 깨집니다
관련 위치:

  • src/data_collection_preprocessing/pipeline.py:474
  • src/inference/bm25_indexer.py:205
  • src/inference/bm25_indexer.py:212
  • data/processed/civil_complaint_train.jsonl

build_bm25_indexes()*_train.jsonl 전체를 순회하는데, 현재 저장소에는 civil_complaint_train.jsonlv2_train.jsonl이 같이 있습니다. 그런데 BM25Indexer.build_index_from_jsonl()은 사실상 text 또는 complaint만 읽고 있어서, 실제 포맷이 input/outputcivil_complaint_train.jsonl은 빈 문서들로 처리됩니다. 이 경우 all-empty corpus 예외가 발생하고 함수 전체가 종료되어 BM25 빌드가 중간에 깨집니다.

Why:
현재 PR의 핵심 기능은 BM25 기반 sparse 검색 추가인데, 기본 데이터셋 조합에서 인덱스 생성이 실패하면 hybrid search는 운영 환경에서 성립하지 않습니다.

Suggestion:

  • v2_*civil_complaint_* 포맷을 모두 처리하도록 입력 필드 매핑을 명시해 주세요.
  • 파일 하나 실패가 전체 빌드 실패가 되지 않도록 JSONL 파일별 예외 처리를 분리하는 편이 안전합니다.

🔴 Blocker: BM25 산출물 이름 규약이 서버 로딩 규약과 달라, 빌드에 성공해도 hybrid가 실제로 활성화되지 않습니다
관련 위치:

  • src/data_collection_preprocessing/pipeline.py:476
  • src/data_collection_preprocessing/pipeline.py:479
  • src/inference/api_server.py:137
  • src/inference/hybrid_search.py:135

파이프라인은 BM25 파일을 v2.pkl, civil_complaint.pkl처럼 데이터셋 stem 기준으로 저장하지만, 서버는 case.pkl, law.pkl, manual.pkl, notice.pkl만 로드합니다. 이 상태에서는 BM25를 빌드해도 서버가 읽지 못하고, HybridSearchEngine은 곧바로 dense로 폴백합니다.

Why:
search_mode=hybrid가 설정되어도 실제로는 dense-only가 되어 기능이 묵살됩니다. 가장 위험한 점은 외부에서 실패가 드러나지 않는다는 점입니다.

Suggestion:

  • BM25 저장/로드 규약을 IndexType 기준으로 통일해 주세요.
  • 최소한 CASE 경로라도 case.pkl로 맞춰야 하고, 가능하면 pipeline 단계에서 타입별 산출물을 명시적으로 생성하는 구조가 더 안전합니다.

🟡 Suggestion: /v1/search 응답이 non-CASE 문서 본문을 잃어버리고, 내부 dense 폴백도 실제 mode로 보고하지 않습니다
관련 위치:

  • src/inference/api_server.py:448
  • src/inference/api_server.py:452
  • src/inference/api_server.py:466
  • src/inference/index_manager.py:33
  • docs/architecture/ADR-004-enhanced-rag-architecture.md:556

현재 contentextras.complaint_text + answer_text 조합만 우선 사용하고, 없으면 제목으로 대체합니다. 그런데 LAW/MANUAL/NOTICE는 타입별 추가 필드가 extras에 다르게 들어가므로, 이 경로에서는 본문이 아니라 제목만 반환될 가능성이 큽니다. 또 HybridSearchEngine이 BM25 미구축 상태에서 dense로 폴백해도 API 응답은 요청한 search_mode를 그대로 반환합니다.

Why:
확장 검색 스키마가 기대하는 본문/요약 전달이 깨지고, 실제 검색 방식에 대한 관측도 틀어져서 디버깅과 품질 평가가 어려워집니다.

Suggestion:

  • 타입별 content 추출 규칙을 별도 함수로 분리해 주세요.
  • 내부 폴백이 발생하면 실제 사용된 mode를 응답에 반영하는 편이 좋습니다.
  • 현재 추가된 E2E 테스트는 HybridSearchEngine을 mock한 CASE 형태 결과만 검증해서 이 회귀를 잡지 못하므로, 실제 초기화 경로와 non-CASE 문서 매핑까지 커버하는 테스트가 필요합니다.

로컬 환경에는 pytest가 설치되어 있지 않아 테스트는 직접 재실행하지 못했습니다. 위 리뷰는 PR diff와 현재 브랜치 기준 정적 분석 결과입니다.

Copy link
Copy Markdown
Contributor

@siuJang siuJang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #192 정밀분석 결과

대상: feat: HybridSearchEngine 구현 — Dense+Sparse 하이브리드 검색 (#154)


🔍 Code Reviewer 분석

1. 강점

1-1. RRF 구현이 정석적이다
_reciprocal_rank_fusion()에서 Cormack et al. (2009)의 표준 RRF 공식(1 / (k + rank))을 정확히 구현. rrf_k=60 기본값이 적절하고, IndexType별 가중치(RRFWeightConfig)로 튜닝 여지를 남겨둔 설계가 좋다.

1-2. BM25Indexer 보안 설계가 우수하다
Pickle의 위험성을 인지하고 HMAC-SHA256 서명/검증을 선택적으로 제공. 페이로드 버전 관리, 토크나이저 불일치 경고, 손상 파일 감지 등 방어가 다층적이다.

1-3. 병렬 검색 구조가 합리적이다
asyncio.gather로 dense/sparse를 동시 실행하고, 한쪽 실패가 전체를 중단시키지 않는 구조. run_in_executor로 blocking I/O를 비동기로 래핑한 점도 적절.

1-4. 테스트 커버리지가 충실하다
73개 테스트가 BM25 빌드/검색/직렬화/HMAC 보안/엣지케이스를 체계적으로 커버한다.

2. 약점 및 개선 권고사항

[Blocker] 2-1. civil_complaint_train.jsonl 데이터 형식 불일치 — BM25 빌드 실패

실제 civil_complaint_train.jsonl 필드: id, instruction, input, output, category, sourcetext 필드 없음.

build_index_from_jsonl()의 폴백 경로:

  1. "text" in itemFalse
  2. "complaint" in itemFalse
  3. _extract_complaint_from_template(item.get("text", "")) → 빈 문자열

→ 프로덕션 데이터로 BM25 인덱스를 빌드할 수 없음.

권고: input 필드 fallback 추가:

elif "input" in item:
    text = item["input"]

[Blocker] 2-2. 파이프라인 인덱스 파일명과 서버 로딩 경로 불일치

파이프라인 출력 서버 로딩 기대
v2.pkl, civil_complaint.pkl case.pkl, law.pkl, manual.pkl, notice.pkl

서버가 BM25 파일을 찾지 못해 하이브리드 검색이 항상 dense-only로 폴백된다.

권고: IndexType.value 기반 파일명으로 통일.

[Suggestion] 2-3. /v1/search content 추출이 CASE 타입에만 동작

complaint_text + answer_text 추출은 LAW/MANUAL/NOTICE에서 빈 content를 반환. 현재 CASE만 있으므로 당장 문제는 아니지만 API 계약상 불일관.

[Suggestion] 2-4. Hybrid→Dense 폴백 시 search_mode 미갱신

BM25 미준비 시 dense-only로 폴백하지만 응답의 search_mode가 여전히 "hybrid". 디버깅/모니터링에 혼란.

3. 프로젝트 적합성: 높음 (핵심 기능)

한국어 민원에서 "도로교통법 제12조", "강남구청 건설과" 같은 키워드 정확 매칭은 dense 검색만으로 한계가 있으며 BM25 보완이 실질적 검색 품질 향상을 가져온다.

4. 머지 가능 여부: 조건부 승인

구분 항목 심각도
필수 2-1: input 필드 fallback 추가 Blocker
필수 2-2: BM25 파일명 IndexType.value 기반 통일 Blocker
권장 2-3: content 추출 타입별 분리 Follow-up
권장 2-4: 폴백 시 actual_search_mode 반영 Follow-up

🛡️ Security Engineer 분석

1. 강점

S-1. RRF 기반 점수 퓨전은 점수 조작 공격 표면을 줄인다
원시 점수가 아닌 순위 기반 합산이므로 한쪽 리트리버의 점수 스케일을 왜곡해도 최종 결과에 미치는 영향이 제한적이다.

S-2. BM25 인덱스 무결성 검증 (HMAC-SHA256)
hmac.compare_digest() 사용으로 타이밍 공격도 방어.

S-3. 기존 보안 체계 일관 유지
API 키 인증, Rate Limiting(60/minute), 내부 예외 비노출 패턴이 /v1/search에도 동일 적용.

S-4. 입력 검증 스키마
SearchRequest에서 query(max 10000), top_k(max 100) Pydantic 검증 적용.

2. 약점 및 개선 권고사항

[Critical] C-1. 검색 결과를 통한 민원인 PII 유출 경로

검색 결과 메타데이터에 complaint(민원 원문), answer(답변 원문)이 그대로 포함된다. 민원 원문에는 이름, 주소, 전화번호 등 PII가 포함될 수 있다. pii_masking.py는 전처리 파이프라인에만 존재하며, 검색 시점 반환 메타데이터에는 마스킹 미적용.

권고: 검색 결과 반환 전 PII 마스킹 레이어 추가. 정부 시스템에서 개인정보 노출은 개인정보보호법 위반 리스크.

[High] H-1. BM25 파일명 불일치 — 사일런트 디그레이드

보안 관점에서: 운영자가 "hybrid" 검색이 활성화되었다고 인지하지만 실제로는 dense-only. WARNING 로그만 남기므로 모니터링 사각지대. BM25 키워드 정확 매칭 누락으로 부정확한 답변이 민원인에게 전달될 수 있다.

권고: /health에 BM25 로딩 상태 명시적 노출, 서버 시작 시 ERROR 레벨 로깅.

[High] H-2. 양측 검색 동시 실패 시 빈 결과 무음 반환

Dense/Sparse 모두 예외 시 빈 리스트를 반환하지만 호출자에게 오류 전파 없음. 사용자가 "검색 결과 없음"을 "해당 민원이 존재하지 않음"으로 오해할 수 있다.

권고: 양측 모두 실패 시 명시적 에러 반환.

[Medium] M-1. HMAC 검증이 선택적(opt-in)

BM25_INDEX_HMAC_KEY 미설정 시 HMAC 없이 pickle 역직렬화 수행. pickle은 임의 코드 실행(RCE) 직결.

권고: 운영 환경에서는 HMAC 필수화 권장.

[Medium] M-2. 메타데이터 매칭 키 (id, category, complaint[:40]) 충돌 가능

id가 None이거나 complaint 앞 40자가 동일한 유사 민원이 존재하면 RRF 점수가 잘못된 문서에 할당됨.

3. 프로젝트 적합성

  • 폐쇄망 적합성: 적합 — 외부 의존 없음, HMAC이 폐쇄망 무결성 검증에 적절
  • 보안 기준선: 부분 충족 — PII 보호 레이어 부재는 정부 시스템 기준 미충족

4. 머지 가능 여부: 조건부 승인

구분 항목
필수 C-1: 검색 결과 PII 마스킹 레이어 추가
필수 H-1: BM25 파일명 통일 + /health에 상태 노출
필수 H-2: 양측 검색 동시 실패 시 에러 전파
권장 M-1: 운영 환경 HMAC 필수화

🏗️ Backend Architect 분석

1. 강점

1-1. 아키텍처 설계의 학술적 기반이 탄탄함
RRF k=60은 원 논문의 표준 파라미터. IndexType별 가중치 차등화(CASE: dense 우위, LAW: sparse 우위)는 한국어 민원 도메인의 특성을 반영한 합리적 설계.

1-2. 비동기 병렬 실행이 적절하다
FAISS와 BM25 모두 CPU-bound이므로 run_in_executor가 적절한 선택.

1-3. 확장성 구조가 양호하다
np.argpartition O(N) top-k, MultiIndexManager의 IVFFlat 자동 전환(10만건 임계값)과 호환.

2. 약점 및 개선 권고사항

[CRITICAL] 2-1. 데이터 파이프라인 네이밍 불일치
파이프라인 출력(v2.pkl, civil_complaint.pkl)과 서버 로드 경로(case.pkl)가 일치하지 않아 BM25 인덱스 로드 불가.

[CRITICAL] 2-2. civil_complaint_train.jsonl 필드 불일치
input 필드에 실제 민원 내용이 있지만 코드가 이를 참조하지 않아 빈 코퍼스 빌드.

[HIGH] 2-3. RRF 퓨전 metadata lookup의 취약한 키 설계
(id, category, complaint[:40]) 3-tuple 키는 유일성 미보장. CivilComplaintRetriever.search()corpus_index를 반환하도록 확장하면 직접 매핑이 가능.

[HIGH] 2-4. E2E 테스트가 BM25를 mock하므로 실제 빌드-검색 경로 미검증
실제 JSONL 데이터 샘플(10건)로 build_index_from_jsonl → search → RRF 퓨전 전체 경로를 검증하는 통합 테스트 1건 이상 필요.

[MEDIUM] 2-5. Graceful fallback 시 search_mode 미갱신

[MEDIUM] 2-6. content 추출이 CASE 타입에만 동작
지원하지 않는 IndexType에 대해 명시적으로 501 Not Implemented 반환 권장.

3. 프로젝트 적합성

항목 평가
아키텍처 적합성 부분적 적합 — HybridSearchEngine이 서빙 레이어에 미연결
데이터 파이프라인 정합성 부적합 — 파일명 불일치 + 필드 불일치로 프로덕션 동작 불가
확장성 양호 — 619건~수만건 대응 가능 구조

4. 머지 가능 여부: 조건부 승인

구분 항목
필수 2-1: BM25 인덱스 파일명 IndexType.value 기반 통일
필수 2-2: build_index_from_jsonlinput 필드 탐색 추가
필수 2-4: 실제 JSONL 데이터로 빌드-검색 전체 경로 통합 테스트 추가
권장 2-3: corpus_index 직접 매핑으로 metadata lookup 개선
권장 2-5, 2-6: 폴백 모드 보고 + content 추출 분리

📊 종합 판정

분석 모드 판정 필수 수정 건수
Code Reviewer 조건부 승인 2건 (Blocker)
Security Engineer 조건부 승인 3건 (Critical 1 + High 2)
Backend Architect 조건부 승인 3건 (Critical 2 + High 1)

공통 필수 수정 사항 (중복 제거 후)

# 항목 합의
1 build_index_from_jsonlinput 필드 fallback 추가 3/3 일치
2 BM25 인덱스 파일명을 IndexType.value 기반으로 통일 3/3 일치
3 실제 JSONL 데이터로 빌드→검색→RRF 전체 경로 통합 테스트 추가 2/3 일치
4 검색 결과 PII 마스킹 레이어 추가 (정부 시스템 법적 요건) Security 단독
5 양측 검색 동시 실패 시 에러 전파 (빈 결과 무음 반환 방지) Security 단독

위 5건 해결 후 머지 승인 가능. 특히 #1, #2는 리뷰어 @yuujjjj 님의 지적과 정확히 일치하며, 실 데이터 검증 결과 확인됨.

Blocker 수정:
- bm25_indexer: build_index_from_jsonl에 input 필드 fallback 추가
- pipeline: BM25 파일명을 IndexType.value 기반으로 통일 (v2.pkl → case.pkl)

Critical/High 수정:
- api_server: 검색 결과 PII 마스킹 레이어 추가 (PIIMasker 재사용)
- hybrid_search: 양측 검색 동시 실패 시 RuntimeError 전파
- hybrid_search: search() 반환값에 actual_mode 포함 (Tuple 시그니처)

Medium 수정:
- api_server: 타입별 content 추출 함수 _extract_content_by_type() 분리
- api_server: /health에 BM25 인덱스 로딩 상태 노출
- schemas: SearchResponse에 actual_search_mode 필드 추가

테스트:
- 통합 테스트 28개 신규 추가 (test_hybrid_search_integration.py)
- 기존 테스트 시그니처 변경 반영 (73개 회귀 없음)
- 전체 101개 통과
@umyunsang umyunsang requested review from siuJang and yuujjjj March 26, 2026 05:18
@umyunsang umyunsang self-assigned this Mar 26, 2026
siuJang
siuJang previously approved these changes Mar 26, 2026
Copy link
Copy Markdown
Contributor

@siuJang siuJang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리뷰 반영 확인 완료 — 승인

이전 리뷰(REQUEST_CHANGES)에서 지적한 필수 수정 5건 모두 정상 반영 확인했습니다.

# 항목 판정
1 build_index_from_jsonlinput 필드 fallback text→complaint→input→template 순서 추가
2 BM25 파일명 IndexType.value 기반 통일 _JSONL_TO_INDEX_TYPE 매핑 → case.pkl 출력
3 빌드→검색→RRF 전체 경로 통합 테스트 ✅ 28개 신규 (실제 BM25 빌드+검색+RRF)
4 검색 결과 PII 마스킹 레이어 _mask_search_results() + /health 상태 노출
5 양측 실패 시 에러 전파 RuntimeError 전파 + actual_search_mode 반영

추가 확인

  • pipeline.pybm25_indexer.py 간 필드 탐색 순서 일치 확인
  • pipeline.py 파일명과 api_server.py 로딩 경로 정합성 확인
  • 테스트 101개 전체 통과 (회귀 없음)

수고하셨습니다 👍

@umyunsang umyunsang dismissed siuJang’s stale review March 26, 2026 05:46

The merge-base changed after approval.

Copy link
Copy Markdown
Contributor

@yuujjjj yuujjjj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

정밀분석 재확인 결과, 이전에 지적된 핵심 수정 사항은 최신 커밋 79caa50 기준으로 정상 반영된 것으로 확인했습니다.

확인 완료

  • BM25 input fallback 추가
  • BM25 산출물 파일명 IndexType.value 기준 통일 및 JSONL별 예외 격리
  • Hybrid 양측 실패 시 RuntimeError 전파
  • Hybrid -> Dense/Sparse 폴백 시 actual_search_mode 반영
  • 타입별 _extract_content_by_type() 분리로 non-CASE content 매핑 개선
  • 검색 결과 PII 마스킹 레이어 추가
  • /health에 BM25 로딩 상태, hybrid_search_enabled, pii_masking_enabled 노출
  • 실제 BM25 빌드/검색/RRF, content 추출, 양측 실패 전파를 보는 통합 테스트 28개 추가

코드 기준 근거

  • src/inference/bm25_indexer.py: text -> complaint -> input -> template fallback 확인
  • src/data_collection_preprocessing/pipeline.py: v2/civil_complaint -> case.pkl 매핑 및 파일별 예외 격리 확인
  • src/inference/hybrid_search.py: return_exceptions=True + 양측 실패 시 예외 전파 확인
  • src/inference/api_server.py: _extract_content_by_type(), _mask_search_results(), /health 상태 노출, actual_search_mode 반영 확인
  • src/inference/schemas.py: SearchResponse.actual_search_mode 필드 추가 확인

메모

  • 로컬 환경에는 pytest가 없어 테스트 재실행은 못 했습니다.
  • 다만 PR에 추가된 통합 테스트 정의 수(28개)와 코드 경로는 정적 분석으로 확인했습니다.
  • PII 마스킹 적용까지는 확인되지만, 법적 준수 여부 자체는 운영/정책 검토가 별도로 필요합니다.

이전 리뷰 기준으로는 머지를 막던 핵심 이슈들은 해소된 상태로 보입니다.

yuujjjj
yuujjjj previously approved these changes Mar 26, 2026
Copy link
Copy Markdown
Contributor

@yuujjjj yuujjjj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리뷰 반영 확인 완료 — 승인

이전 리뷰에서 지적된 핵심 수정 사항은 최신 커밋 79caa50 기준으로 정상 반영된 것으로 확인했습니다.

# 항목 판정
1 build_index_from_jsonlinput 필드 fallback 추가 text -> complaint -> input -> template 순서 확인
2 BM25 파일명 IndexType.value 기반 통일 v2/civil_complaint -> case.pkl 매핑 확인
3 빌드 -> 검색 -> RRF 전체 경로 통합 테스트 ✅ 통합 테스트 28개 추가 확인
4 검색 결과 PII 마스킹 레이어 _mask_search_results()PIIMasker 초기화 확인
5 양측 실패 시 에러 전파 return_exceptions=True + RuntimeError 전파 확인
6 Hybrid -> Dense/Sparse 폴백 시 실제 모드 반영 actual_search_mode 반환 확인
7 non-CASE 문서 content 추출 개선 _extract_content_by_type() 분리 확인
8 /health 상태 노출 보강 ✅ BM25 상태, hybrid_search_enabled, pii_masking_enabled 확인

추가 확인

  • pipeline.pybm25_indexer.py 간 필드 탐색 순서 정합성 확인
  • pipeline.py BM25 산출물 이름과 api_server.py 로딩 경로 정합성 확인
  • SearchResponse.actual_search_mode 스키마 반영 확인

메모

  • 로컬 환경에는 pytest가 없어 테스트 재실행은 못 했습니다.
  • 다만 추가된 통합 테스트 정의 수와 코드 경로는 정적 분석으로 확인했습니다.
  • PII 마스킹 적용은 확인했지만, 법적 준수 여부 자체는 운영/정책 검토가 별도로 필요합니다.

이전 리뷰 기준으로 머지를 막던 핵심 이슈들은 해소된 상태로 보입니다.

@umyunsang umyunsang dismissed yuujjjj’s stale review March 26, 2026 06:25

The merge-base changed after approval.

@yuujjjj yuujjjj dismissed their stale review March 26, 2026 06:38

The merge-base changed after approval. 이전 변경 요청 리뷰를 정리하고 최신 기준으로 새 승인 리뷰를 받을 수 있도록 dismiss합니다.

@yuujjjj yuujjjj requested a review from siuJang March 26, 2026 06:38
@umyunsang umyunsang merged commit ed04354 into develop Mar 26, 2026
4 checks passed
@umyunsang umyunsang deleted the feat/154-hybrid-search-engine branch March 26, 2026 06:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-model AI 모델 관련 backend 백엔드 관련 data documentation Improvements or additions to documentation enhancement New feature or request infra 인프라/배포 관련 preprocessing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants