Commit Graph

2 Commits

Author SHA1 Message Date
f7485aab32 매칭을 속성별 다중 질의 + 가중 RRF + 사실 기반 필터로 재구성
프로필을 통짜로 한 벡터에 넣으면 속성이 희석된다.
실측: 통짜는 점수 폭 0.0076, 속성별로 쪼개면 0.0624 (8배).

- src/serving/match.rules.ts — 레인 빌더, 권역 판정, 수용 인원/시설 필터,
  시설 통제 어휘 정규화
- src/serving/match.service.ts — 레인별 검색 → 가중 RRF 융합 → 필터 →
  레인별 그룹(byLane) 출력. 근거(어느 레인 몇 위)를 함께 반환
- POST /v1/match 에 mode=fusion(기본) / single(기존 통짜, 비교용)
- 데모 페이지: 모드 토글, 레인 카드, 융합/레인별/배제됨 탭

레인 설계에서 실측으로 고친 것
- 브랜드 레인 제거 — 상호는 사전에 없어 generic '군산 펜션 ~예약'만 끌어왔다
- 권역/인근 레인 병합 — '신흥동' 토큰이 겹쳐 위치 키워드가 상위를 쓸어갔다
- RRF 상수 60 → 20 — 60은 1위/40위 기여도 차이가 1.6배뿐이라 generic이 유리했다

사실 기반 필터는 벡터가 못 거르는 모순을 배제한다.
스테이머뭄(최대 4인, 원도심) 기준 61건 배제.
미확인 시설은 배제하지 않고 '보류'로 표시한다 — 없음이 아니라 모름이므로.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-09 16:00:00 +09:00
edde23f15e 고정 데이터셋 1,000건 적재 + 로컬 임베딩 + 매칭 콘솔
정책 변경: 주기 수집 없이 고정 데이터셋을 1회 적재한다.

- data/gunsan-pension-keywords.json — "군산 펜션" 키워드·태그 1,000건
  실제 군산 지명·관광지·숙박 시설 어휘 × 로컬 검색 패턴으로 작성
- 임베딩을 LlmProvider 에서 EmbeddingProvider 로 분리
  (mock | local:multilingual-e5-small | openai), e5 의 query/passage 비대칭 반영
- vector(1536) → vector(384) 마이그레이션, keyword 에 source/kind/category 추가
- scripts/ingest-dataset.ts — 어휘 중복만 자동 병합, 벡터 근접쌍은 검토 목록만 출력
- POST /v1/match — 업체명(띄어쓰기 무관) 또는 문장 → 사전에서 매칭
  업체는 프로필 전체를 질의문으로 조립해 임베딩
- GET /demo — 매칭 콘솔 (public/demo.html)

실측으로 코사인 자동 병합 임계값을 0.92 → 0.99 로 정정.
짧은 한글 키워드는 같은 도메인이면 0.93+ 가 기본이라 0.92 는 오병합을 부른다.

적재 결과: 1,000건 → 어휘 중복 27 병합, 금칙어 2 차단 → 971건.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-09 15:11:45 +09:00