From 56194e82bbf822035242e1e1d253851318d7bbe8 Mon Sep 17 00:00:00 2001 From: Claude-51124 Date: Thu, 23 Oct 2025 16:49:29 +0900 Subject: [PATCH] =?UTF-8?q?docs(intent):=20=EC=9D=98=EB=8F=84=20=EB=9F=B0?= =?UTF-8?q?=ED=83=80=EC=9E=84=20=ED=95=98=EC=9D=B4=EB=B8=8C=EB=A6=AC?= =?UTF-8?q?=EB=93=9C=20=EC=84=A4=EA=B3=84(=EC=9E=84=EB=B2=A0=EB=94=A9+?= =?UTF-8?q?=EB=B2=A0=EC=9D=B4=EC=A7=80=EC=95=88+=EB=8F=99=EC=A0=81?= =?UTF-8?q?=ED=95=99=EC=8A=B5+LLM=20=EC=9E=AC=EB=B6=84=EC=84=9D+A/B)=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(251023)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...드_임베딩_베이지안_동적학습.md | 80 +++++++++++++++++ ...mini_single_model_and_ethics_visibility.md | 86 +++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 plans/251023_happybell80_의도_런타임_하이브리드_임베딩_베이지안_동적학습.md create mode 100644 troubleshooting/251021_admin_gemini_single_model_and_ethics_visibility.md diff --git a/plans/251023_happybell80_의도_런타임_하이브리드_임베딩_베이지안_동적학습.md b/plans/251023_happybell80_의도_런타임_하이브리드_임베딩_베이지안_동적학습.md new file mode 100644 index 0000000..9ad05ab --- /dev/null +++ b/plans/251023_happybell80_의도_런타임_하이브리드_임베딩_베이지안_동적학습.md @@ -0,0 +1,80 @@ +# 의도 런타임(하이브리드) 설계: 임베딩 + 베이지안 + 동적학습 + LLM 재분석 + A/B/밴딧 + +작성일: 2025-10-23 +작성자: happybell80 +대상 서비스: rb8001 (51124) + +--- + +## 1) 개요 +- 목표: 룰/키워드 중심 의도 파악의 한계를 넘어, 의미 기반·불확실성 관리·지속 학습을 갖춘 “의도 런타임”으로 전환. +- 접근: FastPath(규칙/NB) + 임베딩 Top‑K 후보축소 + LLM JSON 재분석 + Beta(α,β) 기반 동적 임계치/경로 최적화. +- 기대: Unknown↓, 잘못된 실행<1%, LLM 호출≤30% 유지, 지연 관리(중앙값 < 800ms). + +## 2) 아키텍처(Phase 1) +- FastPath: 기존 `DecisionEngine`(정규식 + Naive Bayes). conf≥0.9 시 즉시 결정. +- 임베딩 후보축소: intent 설명/예시 벡터와 코사인 유사도 Top‑K + 마진 기반 신뢰도. +- LLM 재분석: Top‑K만 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)·마진(top1–top2) 합성 → 캘리브레이션으로 정규화. + +## 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 재분석 가드레일 +- 입력: Top‑K 후보명/설명 + 최근 컨텍스트 최소화 주입. +- 출력: 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 게이트/Top‑K 축소로 절감. +- 과신/오실행: 캘리브레이션+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 → 임베딩 Top‑K → LLM JSON 재분석(+clarify) + 신뢰도 캘리브레이션. +- 동적 학습/최적화: 로그 기반 프로토타입·동의어 갱신, Beta(α,β)+Thompson Sampling·A/B/밴딧으로 임계치·경로 자동 튜닝. +- rb8001 IntentGraph 스캐폴드 위 단계적 적용 가능, Unknown↓·오실행<1%·LLM 호출≤30% 목표. + diff --git a/troubleshooting/251021_admin_gemini_single_model_and_ethics_visibility.md b/troubleshooting/251021_admin_gemini_single_model_and_ethics_visibility.md new file mode 100644 index 0000000..cc5cf90 --- /dev/null +++ b/troubleshooting/251021_admin_gemini_single_model_and_ethics_visibility.md @@ -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` 준수