docs: skill-email Gemini 통합 트러블슈팅 문서 추가

- rb10508_micro channel_id 문제 해결 과정
- skill-email LLM 서비스 연결 실패 및 Gemini 직접 호출 해결
- 코드 리팩토링 및 기존 코드 재사용 전략
- 교훈 및 개선 사항 정리
This commit is contained in:
happybell80 2025-08-20 00:29:38 +09:00
parent 80613a02bf
commit 748cba43b5

View File

@ -0,0 +1,141 @@
# skill-email Gemini API 통합 및 rb10508_micro 연동 문제 해결
## 작성일: 2025-08-19
## 작성자: happybell80
## 관련 서비스: rb10508_micro, skill-email
---
## 오후 6시 14분
### rb10508_micro channel_id 속성 누락 문제
#### 문제 상황
- rb10508_micro에서 skill-email 호출 시 `'ThinkInput' object has no attribute 'channel_id'` 에러 발생
- /api/message 엔드포인트에서 channel_id가 전달되지 않음
#### 해결 과정
1. ThinkInput NamedTuple에 `channel_id: Optional[str] = None` 속성 추가
2. extract_message 함수에서 channel_id 추출 로직 추가
3. MessageRequest Pydantic 모델에 channel_id 필드 추가
4. /api/message와 /api/think 엔드포인트에서 channel_id 전달
#### 결과
- channel_id 에러 해결
- skill-email 호출 시 필요한 모든 파라미터 전달 성공
---
## 오후 8시 30분
### skill-email LLM 서비스 연결 실패 문제
#### 문제 상황
- skill-email이 `http://localhost:8003` LLM 서비스 호출 시 "All connection attempts failed" 에러
- 8003 포트에 실제 서비스가 존재하지 않음
- 이메일 정보 추출 실패 (to, subject, body 모두 null)
#### 원인 분석
- conversation_handler.py의 `_extract_email_info` 함수가 존재하지 않는 8003 서비스에 의존
- 원래 중앙 LLM 프록시 서비스를 가정한 설계였으나 실제로 구현되지 않음
#### 해결 과정
##### 1차 시도: Gemini 폴백 추가
```python
except Exception as e:
# 8003 실패시 Gemini 직접 호출
genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
response = genai.GenerativeModel('gemini-2.5-flash-lite').generate_content(prompt)
```
- 문제: except 블록이 실행되지 않음 (httpx가 예외를 발생시키지 않음)
##### 2차 시도: 디버깅 로그 추가
- GEMINI_API_KEY 존재 여부 확인 로깅
- 예외 타입 및 상세 정보 로깅
- 발견: Gemini 폴백 코드가 아예 실행되지 않음
##### 최종 해결: 8003 스킵하고 Gemini 직접 호출
```python
use_gemini_direct = True # 8003 서비스가 없으므로 True
if use_gemini_direct:
# Gemini 직접 호출
api_key = os.getenv("GEMINI_API_KEY")
genai.configure(api_key=api_key)
gemini_response = genai.GenerativeModel('gemini-2.5-flash-lite').generate_content(prompt)
# 8003 응답 형식으로 맞춤
result = {"content": gemini_response.text}
response_status = 200
else:
# 8003 서비스 호출 (나중에 복원 가능)
response = await self.http_client.post(...)
```
#### 추가 작업
1. requirements.txt에 `google-generativeai>=0.3.0` 추가
2. docker-compose.yml에 환경변수 추가:
- DATABASE_URL
- POSTGRES_CONNECTION_STRING
- GEMINI_API_KEY
---
## 오후 11시 45분
### 코드 리팩토링 - 기존 코드 최대한 재사용
#### 개선 내용
- 8003 서비스 코드 완전 보존 (주석 처리 없이 조건부 실행)
- JSON 추출 로직 100% 재사용
- 응답을 8003 형식(`{"content": "..."}`)으로 통일
- `use_gemini_direct` 플래그로 쉽게 전환 가능
#### 장점
- 8003 서비스가 나중에 생기면 플래그만 False로 변경
- 코드 중복 제거
- 기존 로직 그대로 유지
---
## 최종 테스트 결과
### 성공한 부분
1. Gemini API 정상 호출
2. 이메일 정보 부분 추출 성공 (subject 인식)
3. 대화형 처리 작동 (누락된 필드 이어받기)
### 개선 필요 사항 (추후 작업)
1. 이메일 주소 인식 정확도 개선
2. "종태님" 같은 한국어 이름 → 이메일 매핑
3. 대화형 응답 메시지 다양화
---
## 교훈
### 1. 외부 의존성 최소화
- 존재하지 않는 서비스(8003)에 의존하는 설계는 위험
- 폴백 메커니즘을 처음부터 고려해야 함
### 2. 기존 코드 재사용의 중요성
- 처음엔 Gemini 폴백을 별도로 구현하려 했으나, 기존 JSON 추출 로직을 재사용하는 것이 훨씬 깔끔
- 응답 형식을 통일하면 하나의 처리 로직으로 여러 소스 처리 가능
### 3. 디버깅 로그의 중요성
- 문제 원인 파악을 위해 단계별 로깅 필수
- 특히 API 키 존재 여부, 응답 내용 등 핵심 정보 로깅
### 4. 점진적 개선 전략
- 완벽한 이메일 정보 추출보다 먼저 기본 동작 확보
- 정확도 개선은 나중에 고도화 단계에서 진행
---
## 관련 커밋
- rb10508_micro: `18f06c7` - channel_id 속성 누락 문제 해결
- skill-email: `75efb4f` - 기존 코드 최대한 재사용하며 Gemini 통합
---
**문서 끝**