feat: NanoClaude Phase 2 — EXAONE→Gemma 파이프라인, 큐, 상태 API
- ModelAdapter: 범용 OpenAI-compat 어댑터 (stream/complete/health)
- BackendRegistry: rewriter(EXAONE) + reasoner(Gemma4) 헬스체크 루프
- 2단계 파이프라인: EXAONE rewrite → Gemma reasoning (SSE rewrite 이벤트 노출)
- Fallback: 맥미니 다운 시 EXAONE 단독 모드, stream 중간 실패 시 자동 전환
- Cancel-safe: rewrite 전/후, streaming loop 내, fallback 경로 모두 체크
- Rewrite heartbeat: complete_chat 대기 중 2초 간격 processing 이벤트
- JobQueue: Semaphore(3) 기반 동시성 제한, 정확한 queue position
- GET /chat/{job_id}/status, GET /queue/stats 엔드포인트
- DB: rewrite_model, reasoning_model, rewritten_message 컬럼 추가
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
"""NanoClaude — 비동기 job 기반 AI Gateway."""
|
||||
"""NanoClaude — 비동기 job 기반 AI Gateway (Phase 2: EXAONE → Gemma 파이프라인)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -12,22 +12,29 @@ from fastapi.responses import JSONResponse
|
||||
from config import settings
|
||||
from db.database import init_db
|
||||
from routers import chat
|
||||
from services.backend_registry import backend_registry
|
||||
from services.job_queue import init_queue, job_queue
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s %(levelname)s %(name)s — %(message)s",
|
||||
)
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
await init_db()
|
||||
backend_registry.init_from_settings(settings)
|
||||
backend_registry.start_health_loop(settings.health_check_interval)
|
||||
init_queue(settings.max_concurrent_jobs)
|
||||
yield
|
||||
backend_registry.stop_health_loop()
|
||||
|
||||
|
||||
app = FastAPI(
|
||||
title="NanoClaude",
|
||||
version="0.1.0",
|
||||
description="비동기 job 기반 AI Gateway — Phase 1",
|
||||
version="0.2.0",
|
||||
description="비동기 job 기반 AI Gateway — Phase 2 (EXAONE → Gemma 파이프라인)",
|
||||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
@@ -54,9 +61,14 @@ app.include_router(chat.router)
|
||||
|
||||
@app.get("/")
|
||||
async def root():
|
||||
return {"service": "NanoClaude", "version": "0.1.0", "phase": 1}
|
||||
return {"service": "NanoClaude", "version": "0.2.0", "phase": 2}
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
async def health():
|
||||
return {"status": "ok"}
|
||||
from services.job_queue import job_queue
|
||||
return {
|
||||
"status": "ok",
|
||||
"backends": backend_registry.health_summary(),
|
||||
"queue": job_queue.stats if job_queue else {},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user