|
|
|
|
|
|
|
|
|
|
|
import time |
|
import uuid |
|
|
|
from fastapi import APIRouter, HTTPException |
|
from fastapi.responses import JSONResponse, StreamingResponse |
|
from src.models.requests import ResponseRequest |
|
from src.cores.sessions import get_or_create_session, session_store |
|
from src.services.streaming import event_generator |
|
from config import MODEL |
|
|
|
|
|
router = APIRouter() |
|
|
|
@router.post("/responses") |
|
async def responses(req: ResponseRequest): |
|
""" |
|
API endpoint to receive user input and return AI-generated responses. |
|
Supports both streaming and non-streaming modes to accommodate different client needs. |
|
|
|
Detailed Workflow: |
|
1. Determine which AI model to use, either from request or default configuration. |
|
2. Retrieve an existing session or create a new one based on session ID and model. |
|
3. Extract the AI client from the session data, ensuring it is available. |
|
4. If streaming is requested, return a streaming response that yields partial results as they arrive. |
|
5. For non-streaming requests, submit the entire user input to the AI client and collect the full response. |
|
6. Handle any errors during submission by returning appropriate HTTP error codes. |
|
7. Store the user input and AI response in the session history for future reference. |
|
8. Update the session's last access time to maintain session freshness. |
|
9. Format the AI response in a JSON structure compatible with OpenAI's chat completion format. |
|
10. Return the formatted JSON response along with the session ID for client reuse. |
|
|
|
Parameters: |
|
- req: ResponseRequest object containing user input, optional model, session ID, and streaming flag. |
|
|
|
Returns: |
|
- JSONResponse containing AI-generated text, metadata, and session information if non-streaming. |
|
- StreamingResponse yielding incremental AI output if streaming is enabled. |
|
|
|
Raises: |
|
- HTTPException with status 503 if AI client is unavailable. |
|
- HTTPException with status 500 if AI submission fails. |
|
""" |
|
|
|
model = req.model or MODEL |
|
|
|
|
|
session_id = get_or_create_session(req.session_id, model) |
|
|
|
|
|
last_update, session_data = session_store[session_id] |
|
|
|
|
|
user_input = req.input |
|
|
|
|
|
client = session_data["client"] |
|
|
|
|
|
if client is None: |
|
raise HTTPException(status_code=503, detail="AI client not available") |
|
|
|
|
|
if req.stream: |
|
|
|
return StreamingResponse(event_generator(user_input, model, session_id), media_type="text/event-stream") |
|
|
|
|
|
try: |
|
jarvis_response = client.submit(multi={"text": user_input}, api_name="/api") |
|
except Exception as e: |
|
|
|
raise HTTPException(status_code=500, detail=f"Failed to submit to AI: {str(e)}") |
|
|
|
|
|
buffer = "" |
|
|
|
for partial in jarvis_response: |
|
|
|
text = partial[0][0][1] |
|
|
|
buffer = text |
|
|
|
|
|
session_data["history"].append({"input": user_input, "response": buffer}) |
|
|
|
|
|
session_store[session_id] = (time.time(), session_data) |
|
|
|
|
|
response = { |
|
"id": f"chatcmpl-{uuid.uuid4().hex[:8]}", |
|
"object": "chat.completion", |
|
"created": int(time.time()), |
|
"model": model, |
|
"choices": [ |
|
{ |
|
"index": 0, |
|
"message": { |
|
"role": "assistant", |
|
"content": buffer |
|
}, |
|
"finish_reason": "stop" |
|
} |
|
], |
|
"session_id": session_id |
|
} |
|
|
|
|
|
return JSONResponse(response) |
|
|