49 lines
1.6 KiB
Python
49 lines
1.6 KiB
Python
"""FluentGerman.ai — Chat router with SSE streaming."""
|
|
|
|
import json
|
|
import logging
|
|
|
|
from fastapi import APIRouter, Depends
|
|
from fastapi.responses import StreamingResponse
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.auth import get_current_user
|
|
from app.database import get_db
|
|
from app.models import User
|
|
from app.schemas import ChatRequest
|
|
from app.services.instruction_service import get_system_prompt
|
|
from app.services.llm_service import chat_stream
|
|
|
|
logger = logging.getLogger("fluentgerman.chat")
|
|
|
|
router = APIRouter(prefix="/api/chat", tags=["chat"])
|
|
|
|
|
|
@router.post("/")
|
|
async def chat(
|
|
body: ChatRequest,
|
|
user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
"""Send a message and receive a streamed SSE response."""
|
|
logger.info("Chat request from user=%s message_len=%d history=%d",
|
|
user.username, len(body.message), len(body.history))
|
|
|
|
system_prompt = await get_system_prompt(db, user.id)
|
|
|
|
messages = [{"role": "system", "content": system_prompt}]
|
|
for msg in body.history:
|
|
messages.append({"role": msg.role, "content": msg.content})
|
|
messages.append({"role": "user", "content": body.message})
|
|
|
|
async def event_generator():
|
|
try:
|
|
async for token in chat_stream(messages):
|
|
yield f"data: {json.dumps({'token': token})}\n\n"
|
|
yield "data: [DONE]\n\n"
|
|
except Exception as e:
|
|
logger.error("LLM streaming error: %s", e, exc_info=True)
|
|
yield f"data: {json.dumps({'error': str(e)})}\n\n"
|
|
|
|
return StreamingResponse(event_generator(), media_type="text/event-stream")
|