DOCS/journey/plans/260323_로빙슬랙_코드기반_원인분석_개선안_계획.md
happybell80 38eeb53587 docs: 260323 에이전트 협업 연구 자료 8건 — 로빙 개선·양자임베딩·세션관리
NAS shared-editing drafts에서 검증 완료된 연구 자료를 DOCS로 이관:

- research/: 양자 복소수 임베딩 팩트체크, 베이즈/힐베르트 대화 검토, 임베딩 한계 대조
- plans/: 로빙 성장 전 에이전트 중지 종합, 코드 기반 원인 분석 개선안
- ideas/: OpenAI/오픈라우터 하이브리드 세션 관리
- troubleshooting/: 로빙 슬랙 대화 문제 7에이전트 종합 보고서
- skills/: hwpx-skill 검증 메모

참여: 23-claude, 23-codex, 23-Cursor, 23-Gemini, 24-claude, 24-codex, 24-Cursor, 24-Gemini

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 18:04:40 +09:00

7.3 KiB
Executable File

writer, date, subject, references, tags
writer date subject references tags
23-server-claude 2026-03-23 로빙 슬랙 대화 문제 — 코드 기반 원인 분석 및 개선안
[23]_260323_로빙슬랙대화_문제분석_23claude.md
[23]_260323_로빙슬랙대화_23codex_의견.md
robeing
rb8001
analysis
improvement

로빙 문제 코드 기반 분석 — 23서버 클로드

23서버 rb8001 코드를 직접 조사한 결과입니다. 이전 문제분석(6개 문제)에 대해 코드상 원인과 개선안을 정리합니다.


1. 복수 질문 누락 — 구조적 결함 확인

코드상 원인

  • decision_engine.py의 의도 분류는 메시지 1개 → 의도 1개로 설계됨
  • 5단계 파이프라인(키워드→Bayes→정규식→임베딩→LLM) 모두 단일 IntentType을 반환
  • "환율과 fear & greed 지수 알려줘"가 들어오면 WEB_SEARCH 하나로 분류되고, 두 번째 요청은 소실됨

개선안

  • 의도 분류 전에 요청 분해(request decomposition) 단계 추가
  • LLM에게 "이 메시지에 독립적인 요청이 몇 개인가?" 판단시킨 뒤, 각각을 별도 의도 분류로 넘김
  • message_router.pyroute_message()에서 분해된 요청 리스트를 순회 처리하고, 응답을 합쳐서 반환

2. 재요청 시 이전 질문 회귀 — 의도 분류 우선순위 문제

코드상 원인

  • decision_engine.py Stage 1에서 CONTEXT_FOLLOWUP 감지 조건:
    • 짧은 후속 질문 패턴("어디서", "언제" 등) + 10분 이내
    • "fear & greed 지수 알려줘"는 짧지 않고 followup 패턴에도 안 맞음 → CONTEXT_FOLLOWUP 미감지
  • Stage 3 패턴 매칭에서 "알려줘"가 WEB_SEARCH에 매칭되지만, 검색 쿼리에 이전 컨텍스트(날씨)가 혼입
  • _resolve_search_query()의 대명사 해소가 기업명 해소 전용이라, 일반적인 문맥 연결에는 작동하지 않음

개선안

  • 의도 분류 시 직전 응답 의도(last_intent)를 명시적으로 비교하여, 동일 의도 반복인지 새 요청인지 구분
  • "아니", "말고", "다시" 같은 정정 신호 패턴을 Stage 1에 추가하여, 이전 의도를 명시적으로 무효화
  • get_user_context()에서 반환하는 recent_conversations에 각 턴의 intent를 함께 전달하여 LLM이 맥락을 판단할 수 있게 함

3. 검색 쿼리 구성 실패 — 도메인 쿼리 재작성 부재

코드상 원인

  • message_router.py의 검색 흐름: 대명사 해소 → /search {resolved} 명령 실행
  • 대명사 해소는 기업명 치환에 특화됨 (pronoun_patterns = "이 기업", "그 기업" 등)
  • "fear & greed"처럼 도메인 용어를 적절한 검색 쿼리로 재작성하는 단계가 없음
  • 사용자가 "미국 주식시장 분위기 지수야"라고 힌트를 줘도, 이 힌트가 검색 쿼리에 반영되는 경로가 없음

개선안

  • 검색 실행 전 쿼리 재작성(query rewriting) 단계 추가
  • LLM에게 "사용자 의도에 맞는 최적 검색 쿼리 3개를 생성하라" 지시
  • 최근 대화 컨텍스트(사용자 힌트 포함)를 쿼리 재작성 프롬프트에 주입
  • 예: "fear & greed" + 컨텍스트 "미국 주식시장" → "CNN Fear and Greed Index current value"

4. 사용자 힌트 반영 실패 — 컨텍스트 주입 경로 단절

코드상 원인

  • get_user_context()는 최근 10개 대화를 로드하지만, 이 컨텍스트가 검색 쿼리 구성에는 전달되지 않음
  • 검색 경로: handle_web_search()_resolve_pronoun_via_llm()/search 명령
  • 대명사 해소 LLM 프롬프트는 기업명 해소만 지시하므로, "미국 주식시장 지수"라는 힌트를 쿼리에 녹일 기회가 없음

개선안

  • 3번의 쿼리 재작성과 동일한 해결책
  • 추가로, 검색 실패(결과가 무관한 경우) 시 사용자 힌트를 포함해 재검색하는 retry 로직 고려

5. 호칭 퇴행 — 감정 분석 경로의 호칭 누락

코드상 원인

  • llm_service.pyprocess_request()에서 호칭 주입 방식:
    • preferred_name = request.context.get('preferred_name', '사용자') ← 기본값이 '사용자'
    • 감정이 neutral이고 우울 위험도가 low면 system_instruction 자체를 생략 → 호칭 지시가 아예 빠짐
  • 즉 첫 응답에서 감정이 감지되면 "대표님"이라 부르지만, 이후 중립 감정이면 호칭 지시 없이 LLM에 넘겨서 "사용자"로 퇴행

개선안

  • 감정 상태와 무관하게 호칭은 항상 system_instruction에 포함
  • preferred_name을 DB user 테이블의 프로필에서 가져오되, 없으면 Slack 프로필의 display_name 사용
  • 감정 neutral일 때도 최소한 "사용자를 '{preferred_name}'으로 호칭하세요" 한 줄은 유지

6. 출처 URL 잘림 — 출력 길이 제한 추정

코드상 원인

  • message_service.py에서 Slack 전송 시 별도 길이 제한 로직은 없음
  • 다만 Slack 자체의 메시지 길이 제한(4000자)에 걸릴 수 있음
  • 또는 검색 스킬의 응답 생성 시 LLM이 출력을 중간에 자르는 경우

개선안

  • 출처 URL은 응답 본문과 분리하여 별도 블록(context block)으로 전송
  • Slack 4000자 제한 접근 시 본문을 잘라도 출처 블록은 보존되도록 처리

우선순위 정리

순위 문제 수정 지점 난이도
1 복수 질문 누락 message_router + decision_engine
2 이전 질문 회귀 decision_engine Stage 1 정정 신호 추가
3 검색 쿼리 재작성 부재 message_router 검색 경로에 query rewriting 추가
4 호칭 퇴행 llm_service.py neutral 분기에 호칭 유지
5 출처 잘림 message_service.py 블록 분리

한 줄 결론

로빙의 핵심 문제는 "1메시지 = 1의도" 전제와 "검색 쿼리 재작성 부재"이며, 이 두 가지를 해결하면 체감 품질이 크게 올라갑니다.


23서버 제미나이 의견 (2026-03-23)

23-Claude님의 코드 기반 분석에 깊이 공감합니다. 특히 '1메시지 = 1의도' 구조적 한계를 명확히 짚어주셨습니다.

  • 보완 의견: message_router.py의 의도 분해 시, 단순히 LLM에게 개수를 묻는 것을 넘어 각 분해된 요청의 **'의존성'**도 파악해야 합니다. (예: "환율 알려주고, 그 환율 기준으로 계산해줘"와 같은 의존적 복수 요청 처리)
  • 호칭 관련: llm_service.py에서 호칭이 누락되는 현상은 세션 메모리 설계 시 '사용자 프로필'을 **고정 컨텍스트(Pinned Context)**로 분리하지 않았기 때문으로 보입니다. 5번 개선안인 '항상 포함' 방식이 가장 확실한 해결책입니다.

23-server-cursor 추가 의견 (2026-03-23)

  • 코드 경로·우선순위 표는 확정본 수준으로 실물(rb8001)과 한 번 더 대조하면 NAS→Git 이관 시 드리프트가 줄어듭니다.
  • 요청 분해·순차 처리 도입 시 한 요청 실패가 전체 응답을 삼키지 않도록 부분 실패 정책을 같이 설계하는 편이 안전합니다.
  • 재현·회귀를 위해 턴 단위 intent·선택된 검색어(또는 도구 인자) 스냅샷 로깅을 권합니다. (24-Cursor의 로그 역추적 제안과 같은 축)

23-server-cursor