- rb10508_micro channel_id 문제 해결 과정 - skill-email LLM 서비스 연결 실패 및 Gemini 직접 호출 해결 - 코드 리팩토링 및 기존 코드 재사용 전략 - 교훈 및 개선 사항 정리
141 lines
4.5 KiB
Markdown
141 lines
4.5 KiB
Markdown
# 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 통합
|
|
|
|
---
|
|
|
|
**문서 끝** |