From a0ead913f335c795e023b3d1ca71fb8578b98b30 Mon Sep 17 00:00:00 2001 From: happybell80 Date: Sun, 31 Aug 2025 21:35:47 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20rb8001=20=EB=8C=80=ED=99=94=20=EC=BB=A8?= =?UTF-8?q?=ED=85=8D=EC=8A=A4=ED=8A=B8=20=EB=B0=8F=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EC=BB=A8=EB=94=94=EC=85=98=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0=20=EB=AC=B8=EC=84=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...50831_rb8001_context_race_condition_fix.md | 242 ++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 troubleshooting/250831_rb8001_context_race_condition_fix.md diff --git a/troubleshooting/250831_rb8001_context_race_condition_fix.md b/troubleshooting/250831_rb8001_context_race_condition_fix.md new file mode 100644 index 0000000..e354b93 --- /dev/null +++ b/troubleshooting/250831_rb8001_context_race_condition_fix.md @@ -0,0 +1,242 @@ +# rb8001 대화 컨텍스트 및 레이스 컨디션 문제 해결 + +## 날짜: 2025-08-31 +## 작성자: happybell80 & Claude +## 관련 서비스: rb8001, auth-server, robeing-gateway +## 상태: ✅ 해결 완료 + +--- + +## 1. 문제 상황 요약 + +### 1.1 주요 증상들 +- "아들은 초등학교 2학년"이라고 알려줬는데 나중에 물어보면 모름 +- "오늘 날씨 어때?" → "그래 알려줘" 연속 대화 시 맥락 단절 +- 반말 사용 문제 ("~라고 하셨어요" 대신 "~했어") +- Gmail 처리가 모든 메시지를 가로채는 문제 +- Slack에서만 대화 맥락 단절 (Frontend는 정상) + +### 1.2 근본 원인들 +1. **제한된 컨텍스트 범위**: 최근 10개 대화만 조회, LLM은 5개만 사용 +2. **레이스 컨디션**: Slack 비동기 처리로 첫 응답 저장 전 두 번째 요청 처리 +3. **UUID 불일치**: Slack ID로 캐시 저장, UUID로 조회 시도 +4. **과도한 이메일 키워드**: "내용", "제목" 같은 일반 단어도 트리거 + +--- + +## 2. 해결 과정 + +### 2.1 존댓말 사용 명시 +**파일**: `app/llm/gemini_handler.py` +```python +# 시스템 프롬프트에 추가 +응답 스타일: +- 간결하고 친근하게 +- 구체적이고 실용적으로 +- 한국어로 자연스럽게 +- 항상 정중한 존댓말 사용 # 추가 + +# 예시도 수정 +좋은 답변: "김종태님, 아드님은 초등학교 2학년이시고 딸은 없으신 것으로 알고 있습니다." +``` + +### 2.2 이메일 스킬 오작동 수정 +**파일**: `app/skills/email_integration.py` +```python +# "제목", "내용" 키워드 제거 - 너무 일반적 +if any(word in message_lower for word in ["보내", "전송", "발송", "send"]) or has_email_address: +``` + +**파일**: `app/router/router.py` +```python +# 이메일 키워드가 있을 때만 Gmail 처리 +email_keywords = ["이메일", "메일", "email", "mail", "보내", "전송", "발송", "@"] +has_email_intent = any(keyword in message_lower for keyword in email_keywords) + +if has_email_intent: + email_result = await email_integration.process_email_request(...) +``` + +### 2.3 auth-server UUID 지원 추가 +**파일**: `auth-server/app/api/slack_router.py` +```python +@router.get("/api/slack/mapping/{identifier}") +async def get_user_mapping(identifier: str, db: Session = Depends(get_db)): + # UUID 패턴 체크 (36자, 하이픈 4개) + is_uuid = len(identifier) == 36 and identifier.count('-') == 4 + + if is_uuid: + # UUID로 직접 조회 + query = text(""" + SELECT u.id as user_id, u.username, u.email, wm.robeing_id + FROM users u + LEFT JOIN workspace_members wm ON u.id = wm.user_id + WHERE u.id = :user_id + """) + result = db.execute(query, {"user_id": identifier}).first() +``` + +### 2.4 대화 컨텍스트 대폭 확대 +**변경 전**: +- PostgreSQL: 10개 조회 +- Gemini: 5개만 사용 +- ChromaDB: 3개 검색 + +**변경 후**: +```python +# app/router/router.py +recent_conversations = await get_recent_conversations(user_id, limit=300) # 300개 조회 + +# app/llm/gemini_handler.py +for conv in recent_conversations[:100]: # 100개 사용 + ... +memories = await memory_manager.search_memories(query=message, n_results=50) # 50개 검색 +``` + +### 2.5 직전 대화 우선 배치 +**파일**: `app/llm/gemini_handler.py` +```python +# 직전 3개 대화를 프롬프트 최상단에 배치 +last_3_context = "" +if context and context.get('recent_conversations'): + last_3 = context['recent_conversations'][:3] # 가장 최근 3개 + if last_3: + last_3_context = "\n[직전 대화 - 반드시 이 맥락에서 답변하세요]\n" + for conv in last_3: + if conv.get('message') and conv.get('response'): + last_3_context += f"사용자: {conv['message'][:200]}\n" + last_3_context += f"로빙: {conv['response'][:200]}\n\n" + last_3_context += "---위 대화의 직접적인 연속입니다---\n" + +# 프롬프트 구성: 직전 대화 최우선 +full_prompt = f"{self._get_system_prompt()}\n{last_3_context}\n[현재 질문]\n사용자: {message}\n\n{recent_context}{memory_context}" +``` + +### 2.6 Slack 레이스 컨디션 해결 +**문제**: Slack ID로 캐시 저장 → UUID로 조회 시도 → 캐시 미스 + +**해결**: UUID 변환 후 캐시 저장 +```python +# app/router/router.py +async def route_message(self, message: str, user_id: str, ...): + # UUID 변환을 먼저! + if channel in ["slack", ...] and user_id.startswith("U"): + # Slack ID → UUID 변환 + user_id = str(result.user_id) + + # UUID로 캐시 저장 + self.processing_cache[user_id] = { + 'message': message, + 'timestamp': datetime.now() + } + + # 조회 시 캐시 확인 + if user_id in self.processing_cache: + cached = self.processing_cache[user_id] + if datetime.now() - cached['timestamp'] < timedelta(minutes=5): + recent_conversations.insert(0, { + 'message': cached['message'], + 'response': cached.get('response', '처리 중...'), + 'timestamp': cached['timestamp'].isoformat() + }) +``` + +### 2.7 Gateway 기본값 변경 +**파일**: `robeing-gateway/app/database.py` +```python +# spaceboum 등 workspace_members 없는 사용자를 위해 +DEFAULT_ROBEING_PORT = int(os.getenv('DEFAULT_ROBEING_PORT', '8001')) # 10508 → 8001 +DEFAULT_ROBEING_ID = os.getenv('DEFAULT_ROBEING_ID', 'rb8001') # rb10508_test → rb8001 +``` + +--- + +## 3. 테스트 결과 + +### 3.1 Frontend 테스트 ✅ +``` +Q: "오늘 날씨 어때?" +A: "서울 날씨는 맑고 최고 25도..." + +Q: "그래 구체적으로 알려줘" +A: "서울 날씨는 맑고 최고 25도..." (맥락 유지!) +``` + +### 3.2 Slack 테스트 +**4초 간격 (빠른 입력)**: ❌ 맥락 단절 +- 첫 응답 저장 전 두 번째 처리 시작 + +**8초 간격 (충분한 시간)**: ✅ 정상 작동 +``` +Q: "내 아들은 몇 살이야?" +Q: "초등학교 몇 학년이야?" +A: "김종태님, 아드님은 초등학교 2학년입니다." +``` + +### 3.3 캐시 작동 확인 +``` +✅ Cache saved for UUID: 1e16e9d5-... +✅ Added processing cache for user +✅ Last 3 conversations loaded: 3 items +``` + +--- + +## 4. 최종 수정 사항 요약 + +| 커밋 | 내용 | 영향 | +|------|------|------| +| f2a7cec | Gemini 시스템 프롬프트 존댓말 명시 | 반말 문제 해결 | +| 63f5d60 | 이메일 과도한 키워드 제거 | 일반 대화 정상 처리 | +| c44de53 | auth-server UUID 지원 추가 | Gmail 토큰 조회 개선 | +| e1ad875 | 컨텍스트 200→300개 확대 | 오래된 대화 참조 가능 | +| 68c2f20 | 직전 대화 맥락 강조 | "그래", "응" 연속성 개선 | +| 4083a91 | UUID 중심 캐시 | 레이스 컨디션 부분 해결 | + +--- + +## 5. 교훈 + +### 5.1 문제 진단의 중요성 +- **증상과 원인 구분**: "대화 맥락 단절"의 원인이 여러 개 +- **단계별 해결**: 한 번에 모든 문제 해결 시도 X +- **로그 활용**: DEBUG 로그로 실제 데이터 흐름 파악 + +### 5.2 시스템 설계 원칙 +- **UUID 중심**: 내부는 모두 UUID로 통일 +- **충분한 컨텍스트**: 10개 → 300개로 확대 +- **명시적 지시**: "존댓말 사용" 같은 명확한 규칙 + +### 5.3 Frontend vs Slack 차이 +- **동기 vs 비동기**: Frontend는 응답 대기, Slack은 연속 입력 +- **레이스 컨디션**: 비동기 환경에서만 발생 +- **캐시 필요성**: 처리 중인 대화 임시 저장 + +--- + +## 6. 향후 개선 사항 + +### 즉시 가능 +- [x] 존댓말 사용 +- [x] 이메일 키워드 정리 +- [x] 컨텍스트 확대 +- [x] UUID 중심 캐시 + +### 추가 개선 필요 +- [ ] 처리 완료 대기 큐 시스템 +- [ ] ChromaDB 벡터 유사도 개선 +- [ ] 중요 정보 별도 테이블 (user_facts) + +--- + +## 7. 관련 문서 +- [PostgreSQL 컨텍스트 통합](./250831_rb8001_postgresql_context_integration.md) +- [다중 이슈 트러블슈팅](./250831_rb8001_multiple_issues.md) +- [UUID 통합 계획](./250828_UUID_통합_및_사용자_격리_계획.md) + +--- + +**상태**: ✅ 실사용 가능 수준 도달 +- 8초 이상 간격: 완벽 작동 +- 4초 이내: 부분적 맥락 단절 (허용 가능) +- 일반 사용 시나리오에서 충분히 안정적 \ No newline at end of file