Implement Phase 22: REST API (FastAPI + SSE streaming)

- api.py: FastAPI 앱 신규 생성
  - GET /health, POST /chat (SSE), POST /reset, POST /ingest, GET/DELETE /documents
  - SSE 포맷: data: <JSON 토큰>\n\n / data: [DONE]\n\n
  - Bearer Token 인증 (API_TOKEN 미설정 시 개발 모드)
  - user_id 파라미터로 멀티유저 지원 (기존 AgentService·DB 구조 재사용)
- config.py: api_token 필드 추가
- app.py: _get_agent에 query_rewrite_enabled 누락 수정
- requirements.txt: fastapi, uvicorn[standard], python-multipart 추가
- ROADMAP: Phase 22 , Telegram Bot 클라이언트 예시 추가

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
sal
2026-05-29 20:11:49 +09:00
parent 432cc9565c
commit 2e9e8a33fe
6 changed files with 176 additions and 33 deletions
+37 -33
View File
@@ -249,40 +249,44 @@ telegram_bot.py
---
## Phase 22 — REST API (FastAPI) ★★☆
## Phase 22 — REST API (FastAPI) ★★☆
**배경**: 다른 Python 스크립트나 원격 서버에서 율봇을 호출하려면 HTTP API가 필요하다.
Phase 21 Telegram Bot을 원격 서버에서 실행하거나, 다른 앱에 율봇을 임베딩할 때도 활용 가능.
**구현 방식**: FastAPI + SSE(Server-Sent Events) 스트리밍.
```
api.py (uvicorn api:app)
├── POST /chat — SSE 스트리밍 응답
├── POST /ingest — 파일 수집
├── GET /documents — 등록 문서 목록
└── DELETE /documents/{source} — 문서 삭제
```
**클라이언트 예시**:
```python
import httpx
with httpx.Client() as client:
with client.stream("POST", "http://localhost:8000/chat",
json={"message": "아이 발달 단계가 궁금해요"},
headers={"Authorization": "Bearer YOUR_TOKEN"}) as r:
for line in r.iter_lines():
if line.startswith("data: "):
print(line[6:], end="", flush=True)
```
Telegram Bot을 별도 프로젝트로 분리해 이 API를 호출하는 구조로 사용 가능.
**구현 내용**:
- `api.py` — FastAPI 앱, `uvicorn api:app --host 0.0.0.0 --port 8000`으로 실행
- Bearer Token 인증 (`.env` `API_TOKEN`)
- `user_id` 헤더/파라미터로 멀티유저 지원
- SSE(`text/event-stream`)로 토큰 단위 스트리밍
- Gradio(`app.py`)와 동일한 `Container` 공유 가능
- SSE(`text/event-stream`) 스트리밍: 각 라인 `data: <JSON 토큰>\n\n`, 종료 `data: [DONE]\n\n`
- Bearer Token 인증 (`.env` `API_TOKEN` 설정; 빈 값이면 개발 모드 무인증)
- `user_id` 파라미터로 멀티유저 지원 (기존 DB·메모리 구조 그대로 재사용)
| 엔드포인트 | 설명 |
|-----------|------|
| `GET /health` | 헬스체크 |
| `POST /chat` | SSE 스트리밍 대화 (`message`, `user_id`, `show_thinking`) |
| `POST /reset` | 대화 이력 초기화 (`user_id`) |
| `POST /ingest` | PDF/TXT 파일 업로드 → 벡터DB 수집 |
| `GET /documents` | 등록 문서 목록 |
| `DELETE /documents/{source}` | 문서 삭제 |
**클라이언트 예시 (별도 Telegram 봇 프로젝트)**:
```python
import httpx, json
API_URL = "http://192.168.10.x:8000"
HEADERS = {"Authorization": "Bearer YOUR_TOKEN"}
async def ask_youlbot(message: str, user_id: str) -> str:
full = ""
async with httpx.AsyncClient(timeout=120) as client:
async with client.stream("POST", f"{API_URL}/chat",
json={"message": message, "user_id": user_id},
headers=HEADERS) as r:
async for line in r.aiter_lines():
if line.startswith("data: ") and line != "data: [DONE]":
full += json.loads(line[6:])
return full
```
**난이도**: 중간 | **임팩트**: 높음 (확장성·외부 연동)
@@ -348,8 +352,8 @@ docker-compose.yml
```
단기 (1~2주) 중기 (1개월) 장기
──────────────────────── ────────────────────── ──────────────────
Phase 21 Telegram Bot → Phase 22 REST API → Phase 16 (Docker)
Phase 20 RAGAS 평가 → Phase 15 (모델선택) → Phase 17 (멀티모달)
Phase 21 Telegram Bot → Phase 20 RAGAS 평가 → Phase 16 (Docker)
→ Phase 15 (모델선택) → Phase 17 (멀티모달)
```
### 우선순위 매트릭스
@@ -374,8 +378,8 @@ Phase 20 RAGAS 평가 → Phase 15 (모델선택) → Phase 17 (멀
| Phase 13-B Reranker | ✅ 완료 | — | — | — |
| Phase 18 Hybrid Search | ✅ 완료 | — | — | — |
| Phase 19 Query Rewriting | ✅ 완료 | — | — | — |
| Phase 21 Telegram Bot | 🔲 신규 | 중간 | 높음 | ⭐ 1순위 |
| Phase 22 REST API | 🔲 신규 | 중간 | 높음 | ⭐ 2순위 |
| Phase 21 Telegram Bot | 🔲 신규 | 중간 | 높음 | ⭐ 1순위 (REST API 활용) |
| Phase 22 REST API | ✅ 완료 | | | |
| Phase 20 RAGAS 평가 | 🔲 신규 | 중간 | 중간 | 3순위 |
| Phase 15 모델 선택 | 🔲 미완 | 중간 | 중간 | 4순위 |
| Phase 16 Docker | 🔲 미완 | 높음 | 중간 | 5순위 |