Phase 25: RAG sources in collapsible box + Korean thinking enforcement
- agent_service: yield {"__sources": [...]} token instead of __meta for sources
- agent_service: inject Korean-only rule at top of system message before date
- config.py: strengthen Korean thinking instruction in system prompt
- ROADMAP: add Phase 25 entry
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -59,7 +59,7 @@ class Config(BaseSettings):
|
||||
whisper_model_size: str = "small"
|
||||
tts_voice: str = "Yuna" # macOS say 명령어 한국어 음성
|
||||
|
||||
system_prompt: str = """모든 응답과 내부 사고 과정을 반드시 한국어로 작성하세요.
|
||||
system_prompt: str = """모든 사고 과정(thinking)과 답변은 반드시 한국어로만 작성하세요. 영어 사용 절대 금지.
|
||||
|
||||
당신의 이름은 '율봇'입니다. 친절하고 따뜻한 한국어 상담 도우미입니다.
|
||||
육아와 금융 두 분야를 전문으로 합니다.
|
||||
|
||||
@@ -393,6 +393,22 @@ cd youlbot-webui && python app.py
|
||||
|
||||
---
|
||||
|
||||
## ✅ Phase 25 — RAG 출처 전용 접기/펼치기 박스
|
||||
|
||||
**배경**: RAG 검색 출처가 사고 과정(thinking)과 같은 `__meta` 토큰으로 섞여 "💭 분석 완료" 박스 안에 표시되던 문제.
|
||||
|
||||
**구현 내용**:
|
||||
- `agent_service.py`: 출처를 `{"__meta": "..."}` 개별 토큰 대신 `{"__sources": [{filename, page}, ...]}` 단일 토큰으로 yield
|
||||
- `youlbot-webui/app.py`:
|
||||
- `_sources_html()` 헬퍼 추가 — `<details>` 기반 접기/펼치기
|
||||
- chatbot 바로 아래 `source_box = gr.HTML()` 컴포넌트 추가
|
||||
- `respond()`에서 `__sources` 토큰 처리 → 답변 완료 후 "📄 출처 (N개)" 박스 표시
|
||||
- `youlbot-telegram/bot.py`: `__sources` 토큰 skip 처리 추가
|
||||
|
||||
**난이도**: 하 | **임팩트**: 중간 (UX 개선 — 출처와 사고 과정 분리)
|
||||
|
||||
---
|
||||
|
||||
## Phase 20 — RAG 품질 자동 평가 (RAGAS) ★☆☆
|
||||
|
||||
**배경**: 청킹 전략·검색 파라미터·Reranker 변경 시 답변 품질이 실제로 나아졌는지 수치로 확인할 방법이 없다.
|
||||
@@ -484,6 +500,7 @@ Phase 20 RAGAS 평가 → Phase 15 (모델선택) → Phase 16 (Docke
|
||||
| Phase 22 REST API | ✅ 완료 | — | — | — |
|
||||
| Phase 23 WebUI 분리 | ✅ 완료 | — | — | — |
|
||||
| Phase 24 사고 과정 UI 분리 | ✅ 완료 | — | — | — |
|
||||
| Phase 25 RAG 출처 전용 박스 | ✅ 완료 | — | — | — |
|
||||
| Phase 20 RAGAS 평가 | 🔲 신규 | 중간 | 중간 | 1순위 |
|
||||
| Phase 15 모델 선택 | 🔲 미완 | 중간 | 중간 | 4순위 |
|
||||
| Phase 16 Docker | 🔲 미완 | 높음 | 중간 | 5순위 |
|
||||
|
||||
@@ -79,7 +79,12 @@ class AgentService:
|
||||
|
||||
async def call_model(state: MessagesState, config: RunnableConfig) -> dict:
|
||||
from datetime import date
|
||||
system_content = f"오늘 날짜: {date.today().isoformat()}\n\n" + self._system_prompt
|
||||
system_content = (
|
||||
"【언어 규칙】모든 사고 과정(thinking)과 답변을 반드시 한국어로 작성하세요. "
|
||||
"영어 사용 금지. Think in Korean only.\n\n"
|
||||
f"오늘 날짜: {date.today().isoformat()}\n\n"
|
||||
+ self._system_prompt
|
||||
)
|
||||
if self._profile_repo:
|
||||
profile = self._profile_repo.get_all(self._user_id)
|
||||
if profile:
|
||||
@@ -367,11 +372,13 @@ class AgentService:
|
||||
print(f"[Agent] 대화 저장 실패: {e}")
|
||||
|
||||
if self._rag_show_sources and self._source_buffer:
|
||||
yield {"__meta": "\n\n[참고 문서]\n"}
|
||||
sources = []
|
||||
for src in self._source_buffer:
|
||||
filename = os.path.basename(src["source"])
|
||||
page = f" {src['page']}페이지" if "page" in src else ""
|
||||
yield {"__meta": f"- {filename}{page}\n"}
|
||||
entry = {"filename": os.path.basename(src["source"])}
|
||||
if "page" in src:
|
||||
entry["page"] = src["page"]
|
||||
sources.append(entry)
|
||||
yield {"__sources": sources}
|
||||
|
||||
def reset(self) -> None:
|
||||
"""새 thread_id로 대화 히스토리를 초기화한다."""
|
||||
|
||||
Reference in New Issue
Block a user