| """ |
| DeepMed-AI — api/v1/endpoints/chat.py |
| Chat-related endpoints: /chat, /chat/stream, /clear, /new-chat — with rate limiting. |
| """ |
|
|
| import uuid |
|
|
| from fastapi import APIRouter, HTTPException, Request |
| from fastapi.responses import StreamingResponse |
| from slowapi import Limiter |
| from slowapi.util import get_remote_address |
|
|
| from app.schemas.chat import ChatRequest, ChatResponse |
| from app.services.chat_service import chat_service |
|
|
| router = APIRouter(tags=["Chat"]) |
| limiter = Limiter(key_func=get_remote_address) |
|
|
|
|
| def _get_session_id(request: Request) -> str: |
| """Get or create a session ID from X-Session-ID header or cookie session.""" |
| session_id = request.headers.get("X-Session-ID") |
| if session_id: |
| return session_id |
| if "session_id" not in request.session: |
| request.session["session_id"] = str(uuid.uuid4()) |
| return request.session["session_id"] |
|
|
|
|
| @router.post("/chat", response_model=ChatResponse) |
| @limiter.limit("15/minute") |
| async def chat_endpoint(request: Request, body: ChatRequest): |
| """Process a user message through the HybridRAG pipeline.""" |
| if not chat_service.workflow_app: |
| raise HTTPException(status_code=503, detail="AI system not initialized. Please wait.") |
| session_id = _get_session_id(request) |
| return await chat_service.process_message(session_id, body.message) |
|
|
|
|
| @router.post("/chat/stream") |
| @limiter.limit("15/minute") |
| async def chat_stream_endpoint(request: Request, body: ChatRequest): |
| """Stream AI response via Server-Sent Events (SSE).""" |
| if not chat_service.workflow_app: |
| raise HTTPException(status_code=503, detail="AI system not initialized. Please wait.") |
| session_id = _get_session_id(request) |
| return StreamingResponse( |
| chat_service.process_message_stream(session_id, body.message), |
| media_type="text/event-stream", |
| headers={ |
| "Cache-Control": "no-cache", |
| "Connection": "keep-alive", |
| "X-Accel-Buffering": "no", |
| }, |
| ) |
|
|
|
|
| @router.post("/clear") |
| async def clear_endpoint(req: Request): |
| """Clear the in-memory conversation state for the current session.""" |
| chat_service.clear_conversation(_get_session_id(req)) |
| return {"message": "Conversation cleared", "success": True} |
|
|
|
|
| @router.post("/new-chat") |
| async def new_chat_endpoint(req: Request): |
| """Create a new chat session with a fresh session ID.""" |
| new_id = str(uuid.uuid4()) |
| req.session["session_id"] = new_id |
| return {"message": "New chat created", "session_id": new_id, "success": True} |
|
|
|
|