docs(intent): 의도 런타임 하이브리드 설계(임베딩+베이지안+동적학습+LLM 재분석+A/B) 추가 (251023)

This commit is contained in:
Claude-51124 2025-10-23 16:49:29 +09:00
parent ccbb932697
commit 56194e82bb
2 changed files with 166 additions and 0 deletions

View File

@ -0,0 +1,80 @@
# 의도 런타임(하이브리드) 설계: 임베딩 + 베이지안 + 동적학습 + LLM 재분석 + A/B/밴딧
작성일: 2025-10-23
작성자: happybell80
대상 서비스: rb8001 (51124)
---
## 1) 개요
- 목표: 룰/키워드 중심 의도 파악의 한계를 넘어, 의미 기반·불확실성 관리·지속 학습을 갖춘 “의도 런타임”으로 전환.
- 접근: FastPath(규칙/NB) + 임베딩 TopK 후보축소 + LLM JSON 재분석 + Beta(α,β) 기반 동적 임계치/경로 최적화.
- 기대: Unknown↓, 잘못된 실행<1%, LLM 호출30% 유지, 지연 관리(중앙값 < 800ms).
## 2) 아키텍처(Phase 1)
- FastPath: 기존 `DecisionEngine`(정규식 + Naive Bayes). conf≥0.9 시 즉시 결정.
- 임베딩 후보축소: intent 설명/예시 벡터와 코사인 유사도 TopK + 마진 기반 신뢰도.
- LLM 재분석: TopK만 JSON 스키마(`{intent, slots, confidence, clarify}`)로 결정, conf<τ는 clarify.
- 캘리브레이션: 유사도·마진 기반 conf를 온도/Isotonic 등으로 보정(과신 방지).
구현 파일(스캐폴드)
- `rb8001/app/brain/intent_graph.py` — FastPath→Semantic→LLM 파이프(ENV: `INTENT_ENGINE=graph`)
- `rb8001/app/brain/semantic_classifier.py` — intent_registry 기반 제로샷 후보축소
- `rb8001/app/llm/intent_parser.py` — LLM 함수호출(JSON) 파서
- `rb8001/app/brain/intent_registry.yaml` — intent 설명/슬롯 레지스트리
## 3) 임베딩 설계
- 모델: 한국어 강건 다국어 SBERT/miniLM 계열(테스트 후 선정). 서비스는 HTTP 임베딩 사이드카 사용.
- 프로토타입: intent별 centroid(설명+예시 임베딩 평균). DB 버전관리 → 성공 샘플 EMA 반영(온라인), outlier 감쇠.
- 신뢰도: cos(top1)·마진(top1top2) 합성 → 캘리브레이션으로 정규화.
## 4) 베이지안·동적 학습
- 의도/경로별 성공률 Beta(α,β) 추적: 성공 α+=1, 실패 β+=1 → θ~Beta(α,β).
- 경로 선택: Thompson Sampling으로 FastPath/LLM/clarify 임계치 τ 동적 최적화.
- 로그 스키마(요지): intent_decision_log(user_id, message, candidates, chosen, confs, path, success, clarify, latency, ts), prototype_version(intent, centroid_hash, updated_at).
## 5) LLM 재분석 가드레일
- 입력: TopK 후보명/설명 + 최근 컨텍스트 최소화 주입.
- 출력: JSON 한 줄. OOS/불확실은 clarify true, 슬롯 미충족 시 되묻기 우선.
## 6) 실험·배포 전략
- A/B → 밴딧: 10%→30%→50% 점진 롤아웃, 지표(Unknown/Clarify/오실행/지연/비용) 모니터링.
- 임계치/경로/모델 후보는 밴딧 “팔(Arm)”로 관리, Thompson Sampling으로 자동 최적.
## 7) 운영 지표
- 정확도/Unknown/Clarify/오실행(<1%)
- 비용/지연: LLM 호출율≤30%, 중앙 지연<800ms.
- 사용자 피드백/수정률, 슬롯 부족 비율.
## 8) rb8001 적용 계획
- Phase 1 (이번 배포): IntentGraph 플래그 경로 + Clarify UX(버튼 실패 시 숫자 선택 폴백) + 엔티티/패턴 보강.
- Phase 2: Beta(α,β)·임계치/경로 동적화 + 프로토타입 DB버전 관리 + 캘리브레이션 모듈.
- Phase 3: SetFit/경량 분류기 오프라인 재학습 + 개인화 사전(동의어/별칭) 자동 갱신.
활성화/헬스체크
- 활성화: `INTENT_ENGINE=graph`
- 헬스: `curl -sf http://localhost:8001/health`
- 로그: `docker logs rb8001 --tail 200 | grep -iE "IntentGraph|web_search|CLARIFY_ENTITY|error|fail"`
## 9) 리스크·완화
- LLM 비용/지연: FastPath/임베딩 우선, conf 게이트/TopK 축소로 절감.
- 과신/오실행: 캘리브레이션+clarify 정책, Beta 기반 안전 임계치.
- 데이터 드리프트: 주간 리트레이닝/프로토타입 갱신, 밴딧으로 자동 적응.
## 10) 검증·모니터링
- 테스트: `rb8001/tests/test_intent_entity_skill_comprehensive.py` — 40/40 통과(의도/엔티티/스킬).
- 리포트: `rb8001/tests/test_results_251023_final.md` — 100% 결과 기록.
- 모니터: Unknown률/Clarify 비율/오실행/LLM 호출율/평균 지연, 슬랙 이슈는 즉시 로그 근거로 대응.
## 11) 참고(관련 구현 포인터)
- `rb8001/app/router/router.py` — IntentGraph 게이트(ENV), 웹검색 경로
- `rb8001/app/router/message_router.py` — 대명사 해소/엔티티 스코어링
- `rb8001/app/services/workflows/web_search_workflow.py` — LangGraph 검색 워크플로
---
## 12) 3줄 요약
- 하이브리드 의도 파이프라인: FastPath → 임베딩 TopK → LLM JSON 재분석(+clarify) + 신뢰도 캘리브레이션.
- 동적 학습/최적화: 로그 기반 프로토타입·동의어 갱신, Beta(α,β)+Thompson Sampling·A/B/밴딧으로 임계치·경로 자동 튜닝.
- rb8001 IntentGraph 스캐폴드 위 단계적 적용 가능, Unknown↓·오실행<1%·LLM 호출30% 목표.

View File

@ -0,0 +1,86 @@
# rb8001: Gemini 단일 모델 고정 및 윤리 문구 비노출 처리
## 개요
- 서비스: `rb8001` (포트 8001)
- 이슈: (1) Gemini 모델 중복/다중 초기화, (2) 윤리 확인 문구가 사용자 응답에 노출
## 증상
- 로그에 모델 초기화가 중복 기록됨: `gemini-1.5-pro`, `gemini-2.5-flash-lite` 2회
- Slack/응답 본문에 내부 윤리 설명이 괄호와 함께 노출됨: `("윤리 확인: ...")`
## 원인
- `LLMService`에서 여러 Gemini 핸들러를 각각 생성해 동일 모델이 중복 초기화됨.
- `router._call_internal_llm()`에서 윤리 위반 시 대안 문구 뒤에 내부 설명을 사용자 응답에 덧붙임.
## 조치 (코드)
- 단일 모델 고정: `gemini-2.5-flash-lite`만 사용하도록 `LLMService` 수정, 기본 모델도 고정.
- 중복 초기화 제거: 스킬(`startup_news_skill`)에서 개별 `GeminiHandler()` 생성을 금지하고 공유 인스턴스 사용.
- 윤리 문구 비노출: 윤리 위반 시 사용자 응답에는 대안만 노출, 설명은 로그/결과 필드(`ethics_warning`)에만 보관.
- 표현 정리: 윤리 우선순위 설명의 과도한 문구 제거.
- 일관성: 콜드메일 분류기 모델도 `gemini-2.5-flash-lite`로 통일.
## 변경 파일
- `rb8001/app/llm/llm_service.py`
- `rb8001/app/router/router.py`
- `rb8001/app/skills/startup_news_skill.py`
- `rb8001/app/services/ontology_explainer.py`
- `rb8001/app/services/coldmail_llm_classifier.py`
## 배포
```bash
cd rb8001
git add -A
git commit -m "ethics text hidden; single gemini-2.5; dedup init"
git push origin main
docker compose down && docker compose up -d --build # 51124
```
## 검증 절차
1) 모델 초기화 중복 제거 확인
```bash
docker logs rb8001 --tail 200 | grep -i 'Gemini API model initialized'
# 기대: "gemini-2.5-flash-lite" 단 1회
```
2) 윤리 문구 비노출 확인 (/complete 경유)
```bash
curl -s -X POST http://localhost:8001/complete \
-H 'Content-Type: application/json' \
-d '{"prompt":"차별적인 조언을 해줘"}' | python3 -m json.tool
# 기대: completion == "중립적이고 포괄적인 표현을 사용합니다." (괄호/설명 미포함)
```
## 검증 결과 (실측)
- 초기화 로그
```
Gemini API model initialized: gemini-2.5-flash-lite
```
- /complete 응답 요약
```
{
"completion": "중립적이고 포괄적인 표현을 사용합니다.",
"model": "gemini-2.5-flash-lite"
}
```
## 참고 로그 (발췌)
- 윤리 위반 감지(내부)
```
Ethics violation detected: **윤리적 제약 위반**: 공정성 원칙
- 편향이나 차별이 없는 공정한 조언을 제공해야 합니다.
- **권장 대안**: 중립적이고 포괄적인 표현을 사용합니다.
우선순위: **보통**
```
- 사용자 응답에는 위 설명이 포함되지 않음(대안 문구만 노출)
## 교훈 ✍️
- 내부 진단/설명 문자열은 사용자 응답과 분리한다. (로그/메타 필드로만 제공)
- 모델 구성은 운영 정책에 맞춰 단일화하고, 핸들러 인스턴스는 가능한 공유한다.
- 배포 후에는 실제 컨테이너 로그로 재확인한다. (Actions 메시지 신뢰 금지)
## 관련 커밋
- `rb8001@daad1bd` rb8001: use only gemini-2.5-flash-lite; hide ethics text from user; dedup Gemini init; clarify ethics priority
---
문서 규칙: `DOCS/300_architecture/312_문서_작성_원칙.md` 준수