Update ROADMAP: Phase 24 thinking UI + bug 6 TTS fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+50
-2
@@ -12,7 +12,8 @@
|
|||||||
| UI | CLI + Gradio Web UI + 음성 입력(STT)/출력(TTS) |
|
| UI | CLI + Gradio Web UI + 음성 입력(STT)/출력(TTS) |
|
||||||
| Memory | LangGraph MemorySaver (세션 내) + MySQL 대화 저장 + 장기 사용자 프로필 |
|
| Memory | LangGraph MemorySaver (세션 내) + MySQL 대화 저장 + 장기 사용자 프로필 |
|
||||||
| Tracing | LangSmith 트레이싱 |
|
| Tracing | LangSmith 트레이싱 |
|
||||||
| Streaming | 비동기 토큰 스트리밍 + `<think>` 블록 파싱 |
|
| Streaming | 비동기 토큰 스트리밍 + 타입별 이벤트 분리 (`__meta` / `__thinking` / `__status`) |
|
||||||
|
| 사고 과정 UI | 스트리밍 중 현재 줄 실시간 표시 → 완료 후 접기/펼치기 (`<details>`) |
|
||||||
| History Compact | 대화 20턴 초과 시 오래된 절반을 LLM으로 자동 요약 (`CompactService`) |
|
| History Compact | 대화 20턴 초과 시 오래된 절반을 LLM으로 자동 요약 (`CompactService`) |
|
||||||
| 나이 계산 | 시스템 프롬프트에 오늘 날짜 주입 + 한국 나이/만 나이 자동 계산 |
|
| 나이 계산 | 시스템 프롬프트에 오늘 날짜 주입 + 한국 나이/만 나이 자동 계산 |
|
||||||
|
|
||||||
@@ -32,6 +33,17 @@ DB 스키마(`td_conversations.user_id`, `td_user_profile.user_id`)는 `_migrate
|
|||||||
### ✅ 버그 4 — 나이 계산 오류 (수정 완료)
|
### ✅ 버그 4 — 나이 계산 오류 (수정 완료)
|
||||||
LLM이 훈련 데이터 기준 연도로 나이를 계산하는 문제. `AgentService.call_model()`에서 매 호출 시 시스템 프롬프트 앞에 `오늘 날짜: {date.today().isoformat()}`를 주입. 프로필에서 생년월일/생년 값을 파싱해 한국 나이(현재연도-출생연도+1)와 만 나이(생일 기준 정확 계산)를 자동 계산해 시스템 프롬프트에 포함.
|
LLM이 훈련 데이터 기준 연도로 나이를 계산하는 문제. `AgentService.call_model()`에서 매 호출 시 시스템 프롬프트 앞에 `오늘 날짜: {date.today().isoformat()}`를 주입. 프로필에서 생년월일/생년 값을 파싱해 한국 나이(현재연도-출생연도+1)와 만 나이(생일 기준 정확 계산)를 자동 계산해 시스템 프롬프트에 포함.
|
||||||
|
|
||||||
|
### ✅ 버그 6 — TTS가 진행 메시지까지 읽는 문제 (수정 완료)
|
||||||
|
|
||||||
|
`stream_response()`가 `[LangGraph → agent: ...]`, `문서 검색 중...` 등 진행 메시지와 실제 답변을 동일한 plain string으로 yield해 TTS가 전부 읽던 문제.
|
||||||
|
|
||||||
|
- `stream_response()` yield 타입 분리: 답변 → `plain str`, 진행/thinking/출처 → `{"__meta": str}` dict
|
||||||
|
- thinking 토큰은 별도 `{"__thinking": str}` key 사용
|
||||||
|
- `call_model` 시작 직후 `writer({"__start": True})` emit → `{"__status": label}` 변환으로 LLM 추론 전 즉각 피드백
|
||||||
|
- `api.py`: `json.dumps(token)` 이 dict/str 모두 처리하므로 변경 없음
|
||||||
|
- WebUI `respond()`: `tts_text` 누적 변수 분리, `__meta`·`__thinking` 토큰 제외 후 TTS 전달
|
||||||
|
- Telegram `bot.py`: `__meta`·`__thinking` 토큰 skip
|
||||||
|
|
||||||
### ✅ 버그 5 — 사고 과정(thinking) 체크박스 무효 (수정 완료)
|
### ✅ 버그 5 — 사고 과정(thinking) 체크박스 무효 (수정 완료)
|
||||||
ON/OFF와 무관하게 사고 과정이 표시되지 않던 버그.
|
ON/OFF와 무관하게 사고 과정이 표시되지 않던 버그.
|
||||||
- `call_model` 내부에서 `get_stream_writer()`로 thinking 토큰을 custom 이벤트로 emit → 답변 앞에 먼저 스트리밍
|
- `call_model` 내부에서 `get_stream_writer()`로 thinking 토큰을 custom 이벤트로 emit → 답변 앞에 먼저 스트리밍
|
||||||
@@ -347,6 +359,40 @@ cd youlbot-webui && python app.py
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## ✅ Phase 24 — 사고 과정 UI 분리 & 실시간 피드백 ★★☆
|
||||||
|
|
||||||
|
**배경**: 사고 과정(thinking)·진행 로그가 답변과 섞여 출력되고, 10초 동안 아무 피드백 없이 대기하는 UX 문제.
|
||||||
|
|
||||||
|
**구현 내용**:
|
||||||
|
|
||||||
|
**① 스트리밍 토큰 타입 분리 (`youlbot/services/agent/agent_service.py`)**
|
||||||
|
- 답변: `yield str` (기존 그대로)
|
||||||
|
- 진행 메시지(`[LangGraph → ...]`, `문서 검색 중...` 등): `yield {"__meta": str}`
|
||||||
|
- 사고 과정 내용: `yield {"__thinking": str}`
|
||||||
|
- LLM 추론 시작 즉시: `writer({"__start": True})` → `yield {"__status": label}` 으로 변환
|
||||||
|
|
||||||
|
**② 사고 과정 전용 박스 (`youlbot-webui/app.py`)**
|
||||||
|
|
||||||
|
| 단계 | 표시 방식 | 비고 |
|
||||||
|
|------|-----------|------|
|
||||||
|
| 전송 즉시 | `🤔 질문을 분석하고 있습니다...` | 단순 div, LLM 추론 전 즉각 표시 |
|
||||||
|
| 스트리밍 중 | `🤔 분석 중...` + 현재 줄 | plain `<div>`, 새 줄 도착 시 이전 줄 교체 |
|
||||||
|
| 진행 로그 | `🤔 분석 중...` + 로그 메시지 | `__meta` 토큰 전체를 표시 |
|
||||||
|
| 완료 | `💭 분석 완료 ▶` | `<details>` 로 전환, 클릭 시 전체 내용 펼침 |
|
||||||
|
|
||||||
|
- 스트리밍 중 `<details>` 미사용 → 내용 업데이트 시 닫힘 현상 없음
|
||||||
|
- TTS는 순수 답변 토큰만 읽음 (`__meta`·`__thinking` 제외)
|
||||||
|
- 챗봇에는 답변만 표시 (진행 메시지 숨김)
|
||||||
|
- `show_thinking` 체크박스 기본값 ON으로 변경
|
||||||
|
|
||||||
|
**③ 멀티클라이언트 대응**
|
||||||
|
- `youlbot-telegram/bot.py`: `__meta`·`__thinking` 토큰 skip → 순수 답변만 스트리밍
|
||||||
|
- `asyncio.get_event_loop().run_until_complete()` → `asyncio.run()` 전체 교체 (AnyIO 워커 스레드 호환)
|
||||||
|
|
||||||
|
**난이도**: 중간 | **임팩트**: 높음 (UX 대폭 개선)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Phase 20 — RAG 품질 자동 평가 (RAGAS) ★☆☆
|
## Phase 20 — RAG 품질 자동 평가 (RAGAS) ★☆☆
|
||||||
|
|
||||||
**배경**: 청킹 전략·검색 파라미터·Reranker 변경 시 답변 품질이 실제로 나아졌는지 수치로 확인할 방법이 없다.
|
**배경**: 청킹 전략·검색 파라미터·Reranker 변경 시 답변 품질이 실제로 나아졌는지 수치로 확인할 방법이 없다.
|
||||||
@@ -420,6 +466,7 @@ Phase 20 RAGAS 평가 → Phase 15 (모델선택) → Phase 16 (Docke
|
|||||||
| 버그 3 단일 사용자 | ✅ 완료 | — | — | — |
|
| 버그 3 단일 사용자 | ✅ 완료 | — | — | — |
|
||||||
| 버그 4 나이 계산 오류 | ✅ 완료 | — | — | — |
|
| 버그 4 나이 계산 오류 | ✅ 완료 | — | — | — |
|
||||||
| 버그 5 thinking 체크박스 무효 | ✅ 완료 | — | — | — |
|
| 버그 5 thinking 체크박스 무효 | ✅ 완료 | — | — | — |
|
||||||
|
| 버그 6 TTS 메타 토큰 혼재 | ✅ 완료 | — | — | — |
|
||||||
| Phase 4 Web UI | ✅ 완료 | — | — | — |
|
| Phase 4 Web UI | ✅ 완료 | — | — | — |
|
||||||
| Phase 5 장기 사용자 메모리 | ✅ 완료 | — | — | — |
|
| Phase 5 장기 사용자 메모리 | ✅ 완료 | — | — | — |
|
||||||
| Phase 6 웹 검색 | ✅ 완료 | — | — | — |
|
| Phase 6 웹 검색 | ✅ 완료 | — | — | — |
|
||||||
@@ -436,7 +483,8 @@ Phase 20 RAGAS 평가 → Phase 15 (모델선택) → Phase 16 (Docke
|
|||||||
| Phase 21 Telegram Bot | ✅ 완료 | — | — | — |
|
| Phase 21 Telegram Bot | ✅ 완료 | — | — | — |
|
||||||
| Phase 22 REST API | ✅ 완료 | — | — | — |
|
| Phase 22 REST API | ✅ 완료 | — | — | — |
|
||||||
| Phase 23 WebUI 분리 | ✅ 완료 | — | — | — |
|
| Phase 23 WebUI 분리 | ✅ 완료 | — | — | — |
|
||||||
| Phase 20 RAGAS 평가 | 🔲 신규 | 중간 | 중간 | 3순위 |
|
| Phase 24 사고 과정 UI 분리 | ✅ 완료 | — | — | — |
|
||||||
|
| Phase 20 RAGAS 평가 | 🔲 신규 | 중간 | 중간 | 1순위 |
|
||||||
| Phase 15 모델 선택 | 🔲 미완 | 중간 | 중간 | 4순위 |
|
| Phase 15 모델 선택 | 🔲 미완 | 중간 | 중간 | 4순위 |
|
||||||
| Phase 16 Docker | 🔲 미완 | 높음 | 중간 | 5순위 |
|
| Phase 16 Docker | 🔲 미완 | 높음 | 중간 | 5순위 |
|
||||||
| Phase 17 멀티모달 | 🔲 미완 | 높음 | 높음 | 6순위 |
|
| Phase 17 멀티모달 | 🔲 미완 | 높음 | 높음 | 6순위 |
|
||||||
|
|||||||
Reference in New Issue
Block a user