Files
youlbot/docs/ROADMAP2.md
T
shinalok 06bcdb03ac Implement Phase 4~14: LangGraph Agent, RAG pipeline, Gradio Web UI, voice interface
- Upgrade LLM to Qwen3-14B-4bit with Thinking mode (MlxChatModel as LangChain BaseChatModel)
- Add LangGraph ReAct agent with tool calling loop (search_documents, web_search, get_current_date, remember/recall_user_info)
- Add RAG pipeline: BAAI/bge-m3 embeddings + Qdrant vector store + semantic chunking (SemanticSplitter via cosine similarity)
- Replace fixed-size RecursiveCharacterTextSplitter with meaning-based SemanticSplitter (numpy only, no extra deps)
- Add Gradio Web UI (app.py): chat, document ingestion, document management tabs
- Add multi-user support (user_id isolation in DB + per-user agent cache + dropdown selector)
- Add conversation history restore from MySQL on agent init (Phase 11)
- Add UserProfileRepository for persistent user profile (remember/recall tools)
- Add thread-local DB connections to fix pymysql thread-safety with LangGraph ToolNode
- Add Phase 14 voice interface: Whisper STT (microphone → text) + macOS TTS (say -v Yuna)
- Enforce search_documents-first policy in system prompt and tool descriptions
- Update ROADMAP2.md: Phase 14 완료, Phase 13 청킹 부분 완료

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 14:06:22 +09:00

9.3 KiB

율봇 개발 로드맵 2

현재 구현 상태 (Phase 111 + Phase 14 완료, 버그 13 수정 완료, 모델 업그레이드)

영역 현황
LLM Qwen3-14B-4bit (MLX, Apple Silicon)
Agent LangGraph ReAct + Tool Calling + Thinking 모드
RAG Qdrant + BAAI/bge-m3 임베딩
Tools search_documents, web_search, get_current_date, remember_user_info, recall_user_info (5개)
UI CLI + Gradio Web UI
Memory LangGraph MemorySaver (세션 내) + MySQL 대화 저장 + 장기 사용자 프로필
Tracing LangSmith 트레이싱
Streaming 비동기 토큰 스트리밍 + <think> 블록 파싱
History Compact 대화 20턴 초과 시 오래된 절반을 LLM으로 자동 요약 (CompactService)

버그 수정 현황

버그 1 — RAG 중복 수집 (수정 완료)

IngestionService._delete_by_source()를 구현해 같은 파일 경로로 저장된 기존 청크를 ingest() 시작 시 삭제한다.

버그 2 — LangGraph MemorySaver와 MySQL 이력 미연동 (수정 완료)

AgentService.__init__에서 MySQL에 저장된 최근 10턴을 _pending_history로 불러온 뒤, 첫 stream_response() 호출 시 LangGraph 초기 메시지로 주입한다.

버그 3 — 단일 사용자 전제 (수정 완료)

DB 스키마(td_conversations.user_id, td_user_profile.user_id)는 _migrate_schema로 자동 마이그레이션. AgentServiceuser_id 파라미터 추가, 모든 Repository 호출에 전파. Gradio에 사용자 선택 드롭다운(아록/근혜/도율/하율) 추가 및 사용자별 에이전트 캐시 구현.


Phase 9 — 문서 관리 (완료)

  • IngestionService._delete_by_source() — 파일 경로 기반 중복 청크 삭제
  • RetrieverService.list_documents() — Qdrant scroll로 고유 source 목록 반환
  • RetrieverService.delete_document(source) — source 기준 청크 전체 삭제
  • Gradio "문서 관리" 탭 — 목록 테이블 + 경로 입력 삭제 버튼 + 앱 로드 시 자동 새로고침

Phase 10 — 멀티유저 지원 (완료)

Bug 3 수정 및 Phase 9 작업과 함께 완전 구현됨.

  • DB 마이그레이션: mysql_service._migrate_schema()td_conversations, td_user_profile 양쪽에 user_id 컬럼 자동 추가
  • ConversationRepository: create_conversation(user_id) / get_latest_conversation_id(user_id) — user_id 기반 격리
  • AgentService: user_id 파라미터 추가, 모든 프로필·대화 조회에 전파
  • make_memory_tools(profile_repo, user_id): remember/recall 도구가 올바른 사용자 데이터만 접근
  • Gradio: 사용자 선택 드롭다운(아록/근혜/도율/하율, 기본값 아록) + _agent_cache 사전으로 사용자별 에이전트 분리

Phase 11 — 대화 이력 복원 (수정 완료)

버그 2와 함께 해결됨. AgentService 초기화 시 MySQL에서 최근 10턴을 _pending_history에 로드 → 첫 메시지와 함께 LangGraph에 주입.

# agent_service.py 초기화 (구현됨)
turns = conversation_repository.load_turns_after(self._conv_id, None, limit=10)
# → HumanMessage / AIMessage 변환 후 _pending_history에 저장

Phase 12 — 답변 피드백 & 품질 개선 ★★☆

배경: 에이전트가 잘못된 답변을 해도 피드백 루프가 없어 개선이 어려움.

구현 범위:

  • Gradio 채팅 메시지마다 👍 / 👎 버튼
  • td_feedback 테이블에 메시지·평점 저장
  • LangSmith의 run_id와 연결해 피드백을 트레이스에 기록 (langsmith.Client().create_feedback())
CREATE TABLE td_feedback (
    id INT AUTO_INCREMENT PRIMARY KEY,
    message TEXT,
    response TEXT,
    rating TINYINT,  -- 1: 좋음, -1: 나쁨
    langsmith_run_id VARCHAR(100),
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

난이도: 중간 | 임팩트: 중간 (장기 품질 향상)


Phase 13 — RAG 품질 향상 (Reranker + 청킹 개선) ★★☆ (부분 완료)

배경: 현재 고정 크기 청킹 + 벡터 유사도 검색만으로는 관련 없는 청크가 섞일 수 있음.

Semantic Chunker — 완료

  • _SemanticSplitter 클래스 직접 구현 (services/rag/ingestion_service.py)
  • langchain-experimental 사용 없이 numpy + 기존 BAAI/bge-m3 임베딩으로 구현
  • 인접 문장 간 코사인 유사도 계산 → 유사도 하위 5% 지점에서 청크 분리
  • config.py에서 rag_chunk_size / rag_chunk_overlap 제거 → semantic_breakpoint_threshold_type 추가

🔲 미완 — Reranker

  1. Reranker 추가cross-encoder/ms-marco-MiniLM-L-6-v2로 검색 결과 재순위
  2. top_k 조정 — 검색 후 rerank → 상위 3개만 LLM에 전달

기존 Qdrant 저장 문서는 재등록해야 새 청킹 방식이 적용됨.

난이도: 중간 | 임팩트: 중간 (답변 정확도 향상)


Phase 14 — 음성 인터페이스 (완료)

배경: 육아 중에는 손이 자유롭지 않아 타이핑이 어려움. 음성으로 질문하고 답변을 들을 수 있으면 핵심 사용 시나리오 커버.

구현 내용:

  • openai-whisper (small 모델) — 마이크 녹음 → 한국어 텍스트 변환, 지연 로딩
  • macOS say -v Yuna — 에이전트 응답을 음성으로 읽어줌 (aiff 파일 경유)
  • Gradio "대화" 탭 확장 — 마이크 녹음 + "음성→텍스트 변환" 버튼 + "음성으로 답변 읽기" 체크박스 + TTS 오디오 플레이어
  • LLM/Agent 레이어 변경 없음 — 순수 I/O 어댑터로 구현
# app.py — STT
def transcribe_audio(filepath: str) -> str:
    result = whisper.load_model("small").transcribe(filepath, language="ko")
    return result["text"].strip()

# app.py — TTS
def tts_speak(text: str, voice: str) -> str | None:
    subprocess.run(["say", "-v", voice, "-o", tmp.name, text], ...)

config.py 추가: whisper_model_size = "small", tts_voice = "Yuna"

난이도: 중간 | 임팩트: 높음 (핵심 사용 시나리오)


Phase 15 — 예방접종·건강검진 알림 스케줄러 ★★☆

배경: 아이 생년을 기억하고 있으므로, 예방접종 일정(BCG, DTaP 등)을 자동 계산해 알림을 줄 수 있음. 율봇의 차별화 포인트.

구현 방식:

  • td_user_profile에서 아이 생년 조회 → 예방접종 스케줄 계산 Tool
  • Gradio "건강 일정" 탭: 달력형 일정 표시
  • APScheduler로 당일 알림 (또는 Gradio 시작 시 오늘 일정 배너)
@tool
def get_vaccination_schedule(birth_year: int, birth_month: int) -> str:
    """아이 생년월을 기반으로 예방접종 일정을 계산합니다."""

난이도: 중간 | 임팩트: 높음 (육아 특화 차별화)


Phase 16 — 모델 선택 (Claude API / OpenAI 옵션) ★☆☆

배경: 로컬 MLX 모델은 Apple Silicon 전용. 원격 접속 시나리오나 더 높은 품질이 필요할 때 Claude API/OpenAI를 선택할 수 있으면 유연성 확보.

구현 방식: config.pymodel_provider 추가, container.py에서 provider별 chat_model 분기.

model_provider: str = "mlx"  # "mlx" | "claude" | "openai"

난이도: 중간 | 임팩트: 중간


Phase 17 — Docker 컨테이너화 ★☆☆

배경: 현재 로컬 전용. 가족이나 지인도 쓸 수 있도록 서버 배포 가능한 형태로 패키징.

구현 범위:

docker-compose.yml
├── youlbot (Gradio app)
├── qdrant
└── mysql

주의: MLX는 Apple Silicon 전용이라 서버 배포 시 Phase 16(모델 선택)이 선행되어야 함.

난이도: 높음 | 임팩트: 중간


Phase 18 — 멀티모달 이미지 이해 ★☆☆

배경: 이유식 사진 → 재료 분석, 금융 서류 사진 → 내용 해석 등.

제약: Qwen3-8B는 이미지 미지원 → mlx-community/Qwen2.5-VL-7B-Instruct-4bit 교체 필요.

난이도: 높음 | 임팩트: 높음 (장기 과제)


추천 진행 순서

단기 (1~2주)          중기 (1개월)          장기
────────────────     ──────────────────    ──────────────
Phase 14 (음성)   →  Phase 13 (RAG품질) →  Phase 17 (Docker)
Phase 15 (알림)      Phase 16 (모델선택)    Phase 18 (멀티모달)
Phase 12 (피드백)

우선순위 매트릭스

Phase 상태 난이도 임팩트 추천 순위
버그 1 RAG 중복 완료
버그 2 이력 미연동 완료
버그 3 단일 사용자 완료
Phase 9 문서 관리 완료
Phase 10 멀티유저 완료
Phase 11 이력 복원 완료
Phase 14 음성 인터페이스 완료
Phase 15 예방접종 알림 🔲 미완 중간 높음 2순위
Phase 12 피드백 🔲 미완 중간 중간 3순위
Phase 13 RAG 품질 (청킹 완료, Reranker 미완) 🔲 진행 중 중간 중간 4순위
Phase 16 모델 선택 🔲 미완 중간 중간 5순위
Phase 17 Docker 🔲 미완 높음 중간 6순위
Phase 18 멀티모달 🔲 미완 높음 높음 7순위