Skip to content

feat(S15P11A705): 검색 결과 LLM 관련도 재판정 4번째 신호 추가 - #209

Merged
colosair merged 2 commits into
devfrom
S15P11A705-relevance-judge
Aug 7, 2026
Merged

feat(S15P11A705): 검색 결과 LLM 관련도 재판정 4번째 신호 추가#209
colosair merged 2 commits into
devfrom
S15P11A705-relevance-judge

Conversation

@colosair

@colosair colosair commented Aug 7, 2026

Copy link
Copy Markdown
Member

요약

배포 직후 사용자가 발견한 검색 순위 오류를 교정하는 4번째 검색 신호(LLM 관련도 재판정)다. back이 3신호 병합까지 끝난 최종 후보(본문 포함)를 ai의 신규 엔드포인트에 보내 판정받고, 결과로 무관한 항목을 걸러내고 재정렬한다. 이 PR은 dev로 머지되며 배포를 유발한다 — 단 기능은 기본 꺼짐이라 배포 자체가 검색 동작을 바꾸지 않는다.

Jira

미발급. 사용자가 실배포 버그를 직접 지시해 시작한 작업이다.

변경 사항

  • AiRelevanceJudgeClient(domain/ai/client) 신설 — AiSearchClient를 본떴지만 실패 정책은 반대. 보조 신호라 실패를 흡수하지 않고 그대로 던진다 — 흡수는 호출부(RecordSearchService) 책임
  • RecordSearchService.judgeRelevance() 추가 — matchedContexts 빌드 직후, keyword 조회 직전에 삽입(3신호 병합까지 끝난 진짜 최종 후보가 모이는 유일한 지점). mergeLexicalMatches()(BI-43)와 같은 강등 패턴: 플래그 꺼짐·후보 없음·호출 실패는 모두 원본 순서로 되돌아간다. NOT_RELEVANT 제거, 나머지는 (등급 desc, 원 순서) 안정 정렬. 판정 누락 항목은 RELEVANT와 동급 취급. 전부 무관이면 빈 결과를 그대로 신뢰
  • RelevanceJudgeProperties(pinlog.search.relevance-judge.enabled, 기본 false) 신설
  • AiPropertiesjudge 타임아웃 필드 추가(connect 1s / read 10s — 후보 최대 10건의 본문을 한 번의 LLM 호출로 판정하는 동기 경로라 search(5s)보다 길게 잡음), AiIntegrationConfigaiJudgeRestClient Bean 추가
  • FastApiSearchStub 확장 — /internal/v1/search/judge를 같은 대역·같은 포트에서 함께 받도록(두 클라이언트가 같은 pinlog.ai.base-url을 보므로)
  • docs/backend/implements/BI-44, docs/backend/worklog/2026-08-07-search-relevance-judge.md 추가

설계 결정

back이 직접 LLM을 호출하는 대안(안 A)은 배제했다 — back에는 LLM 호출 인프라가 전무해 벤더 체인·구조화 출력 파싱·재시도 정책을 전부 새로 만들어야 하지만, ai에는 이미 그 인프라가 있다. 상세 근거는 Team-PinLog/docs PR #56.

테스트 / 검증

  • RelevanceJudgeSearchApiTests 4건(켠 컨텍스트) — 사용자 보고 실사례와 같은 모양의 순위 역전 교정, NOT_RELEVANT 제거, 전부 무관 시 빈 결과, 판정 실패 시 강등
  • RecordSearchApiTests에 꺼짐 계약 1건 추가(기본값 컨텍스트)
  • ./gradlew clean check --no-daemon 통과
  • 사용자가 보고한 정확한 사례(개인 배포 데이터, 피치플레이헬스 vs MH토탈휘트니스)는 시딩 데이터에 없어 로컬 재현 불가 → 같은 실패 모양의 테스트 픽스처로 대체 검증

리뷰 포인트

  1. judgeRelevance() 삽입 위치 — keyword 조회 직전으로 옮기면서 verifiedRecordIds를 판정 후 필터된 matches 기준으로 좁혔다(기존은 verified.keySet() 전체 기준). 판정으로 제외된 레코드의 keyword를 불필요하게 조회하지 않는 최적화지만, 동작 자체가 바뀐 것은 아닌지 확인 부탁

미결 / 후속

  • 기본 꺼짐 — 켜는 결정은 별도.
  • 시연 DB·스냅샷 DB 반영은 이번 범위 밖.

colosair and others added 2 commits August 7, 2026 19:08
배포 후 사용자가 발견한 검색 순위 오류(문장형 질의에 포함된 고유명사가
재작성·문자열 검색·키워드 재정렬 세 신호 모두의 사각지대에 걸려 관련
기록이 무관한 기록보다 낮은 순위로 나온 사례)를 교정한다. back이 3신호
병합까지 끝난 최종 후보(본문 포함)를 ai의 신규 엔드포인트에 보내
LLM 관련도 4단계로 재판정받고, 결과로 무관한 항목을 걸러내고 재정렬한다.

- AiRelevanceJudgeClient — AiSearchClient를 본떴지만 실패 정책은 반대,
  보조 신호라 실패를 삼키지 않고 그대로 던진다
- RecordSearchService.judgeRelevance() — mergeLexicalMatches()와 같은
  강등 패턴(플래그 → 게이트 → try/catch 흡수), 실패 시 판정 이전
  순서로 되돌아간다
- RelevanceJudgeProperties(pinlog.search.relevance-judge.enabled,
  기본 false) · AiProperties.judge 타임아웃 · aiJudgeRestClient Bean
- RelevanceJudgeSearchApiTests(켠 컨텍스트 4건) +
  RecordSearchApiTests 꺼짐 계약 1건, FastApiSearchStub이
  /internal/v1/search/judge도 함께 받도록 확장

기본 꺼짐 — 켜기 전까지 기존 검색 동작에 영향 없음.
./gradlew clean check --no-daemon 통과.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@colosair
colosair merged commit 5bbd1f4 into dev Aug 7, 2026
2 checks passed
@colosair
colosair deleted the S15P11A705-relevance-judge branch August 7, 2026 17:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant