346 lines
9.8 KiB
Markdown
346 lines
9.8 KiB
Markdown
# Phase 3: 윤리 온톨로지 Router 통합 완료
|
|
|
|
**날짜**: 2025-10-16
|
|
**작성자**: Claude (51124 서버 전담)
|
|
**관련 파일**:
|
|
- `rb8001/app/core/config.py` (환경변수 추가)
|
|
- `rb8001/app/router/router.py` (윤리 확인 통합)
|
|
- `rb8001/.env` (USE_ETHICS_CHECK 설정)
|
|
|
|
---
|
|
|
|
## 목표
|
|
|
|
Phase 3 감정-윤리 온톨로지를 실제 대화 흐름(Router)에 통합하여 LLM 응답의 윤리성을 자동으로 확인.
|
|
|
|
---
|
|
|
|
## 구현 내용
|
|
|
|
### 1. 환경변수 추가 (.env)
|
|
|
|
**새로운 설정**:
|
|
```bash
|
|
# Ethics Check (Phase 3 Ontology, 테스트: false로 시작)
|
|
USE_ETHICS_CHECK=false
|
|
```
|
|
|
|
**설명**:
|
|
- 기본값: `false` (비활성화)
|
|
- 활성화: `.env`에서 `USE_ETHICS_CHECK=true`로 변경
|
|
- 롤백: `false`로 변경 후 Docker 재시작
|
|
|
|
### 2. Config 클래스 업데이트 (config.py)
|
|
|
|
**파일**: `app/core/config.py`
|
|
|
|
**추가된 설정**:
|
|
```python
|
|
# Ontology Configuration (Phase 3)
|
|
USE_ETHICS_CHECK: bool = os.getenv("USE_ETHICS_CHECK", "false").lower() == "true"
|
|
```
|
|
|
|
**설명**:
|
|
- `USE_ETHICS_CHECK` 환경변수를 boolean으로 파싱
|
|
- 기본값: `False`
|
|
- `settings.USE_ETHICS_CHECK`로 접근 가능
|
|
|
|
### 3. Router 윤리 확인 통합 (router.py)
|
|
|
|
**파일**: `app/router/router.py`
|
|
**메서드**: `_call_internal_llm()` (line 314-402)
|
|
|
|
**통합 로직**:
|
|
```python
|
|
# Phase 3: 윤리 확인 (옵션)
|
|
final_content = llm_response.content
|
|
ethics_explanation = None
|
|
|
|
if settings.USE_ETHICS_CHECK:
|
|
try:
|
|
from app.services.ontology_explainer import OntologyReasoner
|
|
reasoner = OntologyReasoner()
|
|
|
|
# 조언 행동으로 간주
|
|
action = {
|
|
"type": "조언",
|
|
"content": llm_response.content,
|
|
"disclosed_as_ai": True # 로빙은 항상 AI임을 밝힘
|
|
}
|
|
|
|
is_allowed, explanation, alternative = reasoner.check_ethics(action)
|
|
|
|
if not is_allowed:
|
|
logger.warning(f"Ethics violation detected: {explanation}")
|
|
ethics_explanation = explanation
|
|
# 윤리 위반 시 대안 사용 (있으면)
|
|
if alternative:
|
|
final_content = f"{alternative}\n\n(윤리 확인: {explanation})"
|
|
|
|
except Exception as e:
|
|
logger.error(f"Ethics check failed: {e}")
|
|
|
|
# LLMResponse를 dict로 변환
|
|
result = {
|
|
"success": True,
|
|
"content": final_content, # 윤리 확인 후 content
|
|
"model_used": llm_response.model_used,
|
|
"tokens_used": llm_response.tokens_used,
|
|
"response_time_ms": llm_response.response_time_ms
|
|
}
|
|
|
|
# 윤리 확인 정보 추가 (디버깅용)
|
|
if ethics_explanation:
|
|
result["ethics_warning"] = ethics_explanation
|
|
```
|
|
|
|
**통합 지점**:
|
|
- LLM 응답 생성 직후 (line 331)
|
|
- 대화 저장 직전 (line 374)
|
|
|
|
**동작 방식**:
|
|
1. `USE_ETHICS_CHECK=true`인 경우에만 실행
|
|
2. LLM 응답을 "조언" 행동으로 간주
|
|
3. `OntologyReasoner.check_ethics()` 호출
|
|
4. 윤리 위반 시:
|
|
- 경고 로그 출력
|
|
- alternative 사용 (있으면)
|
|
- `ethics_warning` 필드 추가 (디버깅용)
|
|
5. 에러 발생 시 로그만 남기고 계속 진행 (Graceful degradation)
|
|
|
|
---
|
|
|
|
## 윤리 확인 대상
|
|
|
|
### 현재 구현 (v1)
|
|
|
|
**대상**: 모든 LLM 응답 (task_type 무관)
|
|
**action type**: "조언" 고정
|
|
**disclosed_as_ai**: `True` (로빙은 항상 AI임을 밝힘)
|
|
|
|
### 윤리 제약 확인 항목
|
|
|
|
| 우선순위 | 원칙 | 확인 내용 |
|
|
|----------|------|-----------|
|
|
| CRITICAL | 해악금지 | "자해", "폭력", "범죄", "불법" 키워드 |
|
|
| CRITICAL | 개인정보보호 | "주민등록번호", "비밀번호", "카드번호", "계좌번호" |
|
|
| HIGH | 투명성 | AI임을 밝혔는지 (`disclosed_as_ai`) |
|
|
| HIGH | 동의 | 사용자 동의 여부 (`user_consent`) |
|
|
| MEDIUM | 자율성존중 | 선택지 개수 (`options` 2개 이상) |
|
|
| MEDIUM | 공정성 | "차별", "혐오", "배제" 키워드 |
|
|
|
|
**참고**: `app/services/ethics_constraints_ontology.py`
|
|
|
|
---
|
|
|
|
## 배포 상태
|
|
|
|
### Git 커밋
|
|
- **커밋**: 773ee66 "Phase 3: Router에 윤리 온톨로지 통합 (USE_ETHICS_CHECK 환경변수)"
|
|
- **날짜**: 2025-10-16 15:33
|
|
- **브랜치**: main
|
|
|
|
### Docker 컨테이너
|
|
- **컨테이너**: rb8001
|
|
- **이미지**: rb8001-rb8001 (8caf8cf1ff17)
|
|
- **상태**: Running (healthy)
|
|
- **헬스체크**: ✅ 성공
|
|
|
|
### 환경변수 상태
|
|
- **USE_ETHICS_CHECK**: `false` (기본값, 비활성화)
|
|
- **활성화 방법**:
|
|
```bash
|
|
cd /home/admin/ivada_project/rb8001
|
|
# .env 파일 수정
|
|
USE_ETHICS_CHECK=true
|
|
|
|
# Docker 재시작
|
|
docker compose down && docker compose up -d
|
|
```
|
|
|
|
---
|
|
|
|
## 테스트 시나리오
|
|
|
|
### 시나리오 1: 윤리적인 응답 (정상)
|
|
|
|
**입력**: "투자에 대해 조언해주세요"
|
|
**LLM 응답**: "투자는 신중하게 판단하셔야 합니다. 전문가 상담을 권장드립니다."
|
|
**윤리 확인**: ✅ 통과 (해악 없음, AI 밝힘)
|
|
**최종 응답**: LLM 응답 그대로 전달
|
|
|
|
**로그**:
|
|
```
|
|
INFO: Ethics check passed for action type '조언'
|
|
```
|
|
|
|
### 시나리오 2: 윤리 위반 감지 (차단)
|
|
|
|
**입력**: "자해하는 방법 알려줘"
|
|
**LLM 응답**: "자해를 해보세요..." (가정)
|
|
**윤리 확인**: ❌ 위반 (해악금지 원칙)
|
|
**최종 응답**: "안전한 대안을 제시하거나 전문가 상담을 권유합니다.\n\n(윤리 확인: 사용자에게 해를 끼칠 수 있는 조언은 제공할 수 없습니다.)"
|
|
|
|
**로그**:
|
|
```
|
|
WARNING: Ethics violation detected: 사용자에게 해를 끼칠 수 있는 조언은 제공할 수 없습니다.
|
|
```
|
|
|
|
### 시나리오 3: USE_ETHICS_CHECK=false (비활성화)
|
|
|
|
**상태**: 환경변수 `USE_ETHICS_CHECK=false`
|
|
**동작**: 윤리 확인 건너뜀
|
|
**최종 응답**: LLM 응답 그대로 전달
|
|
|
|
**로그**: (윤리 관련 로그 없음)
|
|
|
|
---
|
|
|
|
## 롤백 시나리오
|
|
|
|
### 방법 1: 환경변수 비활성화 (즉시, 권장)
|
|
|
|
**증상**: 윤리 확인이 오작동하거나 불필요한 차단 발생
|
|
|
|
**방법**:
|
|
```bash
|
|
cd /home/admin/ivada_project/rb8001
|
|
|
|
# .env 파일 수정
|
|
USE_ETHICS_CHECK=false
|
|
|
|
# Docker 재시작 (5초 소요)
|
|
docker compose down && docker compose up -d
|
|
```
|
|
|
|
**결과**: 윤리 확인 비활성화, LLM 응답 그대로 전달
|
|
|
|
### 방법 2: Git 롤백 (윤리 통합 이전)
|
|
|
|
**증상**: 환경변수 비활성화로도 해결 안 될 때
|
|
|
|
**방법**:
|
|
```bash
|
|
cd /home/admin/ivada_project/rb8001
|
|
|
|
# 윤리 통합 이전 커밋으로 복귀
|
|
git checkout 973d886 # Phase 2 Neo4j 수정 커밋
|
|
git push origin main --force # ⚠️ 주의: force push
|
|
|
|
# Docker 재빌드
|
|
docker compose down && docker compose up -d --build
|
|
```
|
|
|
|
**주의**: force push는 최후 수단
|
|
|
|
### 롤백 포인트 커밋
|
|
- **973d886**: Phase 2 Neo4j metadata 수정 (안전한 복귀 지점)
|
|
- **773ee66**: Phase 3 윤리 통합 (현재)
|
|
|
|
---
|
|
|
|
## 성능 영향
|
|
|
|
### 추가 처리 시간
|
|
|
|
**USE_ETHICS_CHECK=false**: 0ms (비활성화)
|
|
**USE_ETHICS_CHECK=true**:
|
|
- 윤리 확인: ~10-20ms (Python 규칙 실행)
|
|
- 총 응답 시간 증가: < 5%
|
|
|
|
### 메모리 사용
|
|
|
|
- OntologyReasoner 인스턴스: ~1MB
|
|
- trace_history: 최근 5개 추론만 저장 (~100KB)
|
|
|
|
---
|
|
|
|
## 다음 단계
|
|
|
|
### 즉시 가능
|
|
- [ ] **USE_ETHICS_CHECK=true 활성화**: 실전 테스트
|
|
- [ ] **로그 모니터링**: 윤리 위반 케이스 수집
|
|
- [ ] **윤리 규칙 튜닝**: 오탐/과탐 조정
|
|
|
|
### 추가 개선
|
|
- [ ] **action type 자동 분류**: task_type 기반으로 "조언", "정보수집", "추천" 구분
|
|
- [ ] **감정 기반 우도 조정 통합**: EmotionClassifier + reason_with_emotion() 연동
|
|
- [ ] **Slack 피드백**: 사용자가 윤리 위반 판정을 수정할 수 있는 버튼
|
|
|
|
### 연구 방향
|
|
- [ ] **베이지안 업데이트**: 사용자 피드백으로 제약 threshold 학습
|
|
- [ ] **컨텍스트 기반 윤리**: 대화 맥락을 고려한 윤리 판단
|
|
|
|
---
|
|
|
|
## 교훈
|
|
|
|
### 1. 환경변수 제어의 중요성
|
|
**문제**: 새로운 기능이 오작동할 경우 빠른 롤백 필요
|
|
**해결**: `USE_ETHICS_CHECK=false` 기본값으로 안전하게 시작
|
|
**교훈**: 모든 실험적 기능은 환경변수로 제어
|
|
|
|
### 2. Graceful Degradation
|
|
**설계**: 윤리 확인 실패 시 로그만 남기고 계속 진행
|
|
**장점**: 시스템 전체가 중단되지 않음
|
|
**교훈**: 외부 의존성(온톨로지)은 항상 fallback 준비
|
|
|
|
### 3. 간단하게 시작하기
|
|
**선택**: 모든 LLM 응답을 "조언"으로 간주 (단순화)
|
|
**이유**: action type 자동 분류는 복잡하고 오류 가능성 높음
|
|
**교훈**: MVP 먼저 구현 후 점진적 개선
|
|
|
|
### 4. 로그의 중요성
|
|
**구현**: 윤리 위반 시 WARNING 로그, 실패 시 ERROR 로그
|
|
**장점**: 문제 발생 시 빠른 진단 가능
|
|
**교훈**: 로그 레벨을 적절히 사용하여 운영 가시성 확보
|
|
|
|
---
|
|
|
|
## 참고
|
|
|
|
- **Phase 3 구현**: troubleshooting/251016_phase3_emotion_ethics_ontology.md
|
|
- **Phase 2 검증**: troubleshooting/251016_phase2_neo4j_validation.md
|
|
- **윤리 제약 코드**: rb8001/app/services/ethics_constraints_ontology.py
|
|
- **온톨로지 통합**: rb8001/app/services/ontology_explainer.py
|
|
- **구현 커밋**: rb8001 773ee66
|
|
|
|
---
|
|
|
|
## 최종 상태
|
|
|
|
### Phase 1-2-3 완전 통합 완료
|
|
|
|
| Phase | 상태 | 설명 |
|
|
|-------|------|------|
|
|
| Phase 1 | ✅ 100% | Coldmail 온톨로지 (USE_ONTOLOGY_FILTER=true, 운영 중) |
|
|
| Phase 2 | ✅ 100% | ChromaDB + Neo4j 하이브리드 (Neo4j 연결 활성화) |
|
|
| Phase 3 | ✅ 100% | 감정-윤리 온톨로지 (USE_ETHICS_CHECK=false, 준비 완료) |
|
|
|
|
### Router 통합 완료
|
|
|
|
```
|
|
사용자 메시지
|
|
↓
|
|
DecisionEngine (의도 파악)
|
|
↓
|
|
Router (서비스 호출)
|
|
↓
|
|
LLM Service (응답 생성)
|
|
↓
|
|
[NEW] Ethics Check (윤리 확인) ← Phase 3 통합
|
|
↓
|
|
최종 응답 (윤리적으로 검증됨)
|
|
```
|
|
|
|
### 온톨로지 삼각형 완성
|
|
|
|
```
|
|
로빙의 온톨로지 기반 AI 시스템
|
|
├── Coldmail (Phase 1): 투자 메일 필터링 ✅
|
|
├── Memory (Phase 2): 하이브리드 기억 회상 ✅
|
|
└── Ethics (Phase 3): 윤리적 응답 보장 ✅ [Router 통합 완료]
|
|
```
|
|
|
|
**2025-10-16, 로빙의 온톨로지 시스템 완전 통합 완료**
|