GPU 서버 중앙 AI 라우팅 서비스 초기 구현: - OpenAI 호환 API (/v1/chat/completions, /v1/models, /v1/embeddings) - 모델 레지스트리 + 백엔드 헬스체크 (30초 루프) - Ollama SSE 프록시 (NDJSON → OpenAI SSE 변환) - JWT 인증 이중 경로 (httpOnly 쿠키 + Bearer 토큰) - owner/guest 역할 분리, 로그인 rate limiting - 백엔드별 rate limiting (NanoClaude 대비) - SQLite 스키마 사전 정의 (aiosqlite + WAL) - Docker Compose + Caddy 리버스 프록시 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
51 lines
1.4 KiB
Python
51 lines
1.4 KiB
Python
import aiosqlite
|
|
|
|
from config import settings
|
|
|
|
SCHEMA = """
|
|
CREATE TABLE IF NOT EXISTS chat_sessions (
|
|
id TEXT PRIMARY KEY,
|
|
title TEXT,
|
|
model TEXT NOT NULL,
|
|
role TEXT NOT NULL DEFAULT 'guest',
|
|
created_at REAL NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS chat_messages (
|
|
id TEXT PRIMARY KEY,
|
|
session_id TEXT NOT NULL REFERENCES chat_sessions(id),
|
|
role TEXT NOT NULL,
|
|
content TEXT NOT NULL,
|
|
created_at REAL NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS usage_logs (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
backend_id TEXT NOT NULL,
|
|
model TEXT NOT NULL,
|
|
prompt_tokens INTEGER DEFAULT 0,
|
|
completion_tokens INTEGER DEFAULT 0,
|
|
latency_ms REAL DEFAULT 0,
|
|
user_role TEXT NOT NULL DEFAULT 'guest',
|
|
created_at REAL NOT NULL
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_messages_session ON chat_messages(session_id);
|
|
CREATE INDEX IF NOT EXISTS idx_usage_created ON usage_logs(created_at);
|
|
"""
|
|
|
|
|
|
async def init_db():
|
|
"""Initialize SQLite database with WAL mode and schema."""
|
|
async with aiosqlite.connect(settings.db_path) as db:
|
|
await db.execute("PRAGMA journal_mode=WAL")
|
|
await db.executescript(SCHEMA)
|
|
await db.commit()
|
|
|
|
|
|
async def get_db() -> aiosqlite.Connection:
|
|
"""Get a database connection."""
|
|
db = await aiosqlite.connect(settings.db_path)
|
|
await db.execute("PRAGMA journal_mode=WAL")
|
|
return db
|