ZARAI / backend /app /api /chat.py
Srajal2579
Deploy JARVIS
3e646d9
Raw History Blame Contribute Delete
4.7 kB
"""
JARVIS β€” Chat API Route
POST /api/chat/message β€” send a message, get AI response
GET /api/chat/history β€” retrieve session history
"""
import uuid
from typing import Optional, List
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel, Field
from loguru import logger
from app.db.database import (
AsyncSession, get_db,
create_session, get_session, get_messages, add_message,
)
from app.agents.react_agent import ReActAgent
from app.core.config import settings
router = APIRouter()
# ─────────────────────────────────────────────
# Request / Response schemas
# ─────────────────────────────────────────────
class ChatRequest(BaseModel):
message: str = Field(..., min_length=1, max_length=4096)
session_id: Optional[str] = None
image_caption: Optional[str] = None # pre-analyzed image context
stream: bool = False
class Config:
json_schema_extra = {
"example": {
"message": "What is the capital of France?",
"session_id": "abc-123",
}
}
class AgentStepOut(BaseModel):
step_type: str
content: str
tool_name: Optional[str] = None
class ChatResponse(BaseModel):
response: str
session_id: str
message_id: int
steps: List[AgentStepOut] = []
used_tools: List[str] = []
memory_hits: int = 0
iterations: int = 1
# ─────────────────────────────────────────────
# Routes
# ─────────────────────────────────────────────
@router.post("/message", response_model=ChatResponse)
async def chat_message(
request: ChatRequest,
db: AsyncSession = Depends(get_db),
):
"""
Send a message to JARVIS and get an AI response.
Creates a new session if session_id not provided.
"""
# Ensure session exists
session_id = request.session_id or str(uuid.uuid4())
session = await get_session(db, session_id)
if not session:
title = request.message[:50] + ("..." if len(request.message) > 50 else "")
await create_session(db, session_id, title=title)
# Load conversation history (last 20 messages)
messages = await get_messages(db, session_id, limit=20)
history = [
{"role": msg.role, "content": msg.content}
for msg in messages
]
# Save user message to DB
user_msg = await add_message(
db, session_id,
role="user",
content=request.message,
modality="text",
)
# Run ReAct agent
try:
agent = ReActAgent()
result = agent.run(
user_message=request.message,
conversation_history=history,
session_id=session_id,
image_caption=request.image_caption,
)
except Exception as e:
logger.error(f"Agent error: {e}")
raise HTTPException(status_code=500, detail=f"Agent error: {str(e)}")
# Save assistant response to DB
asst_msg = await add_message(
db, session_id,
role="assistant",
content=result.final_response,
modality="text",
)
return ChatResponse(
response=result.final_response,
session_id=session_id,
message_id=asst_msg.id,
steps=[
AgentStepOut(
step_type=s.step_type.value,
content=s.content,
tool_name=s.tool_name,
)
for s in result.steps
],
used_tools=result.used_tools,
memory_hits=result.memory_hits,
iterations=result.iterations,
)
@router.get("/history/{session_id}")
async def get_history(
session_id: str,
limit: int = 50,
db: AsyncSession = Depends(get_db),
):
"""Retrieve conversation history for a session."""
session = await get_session(db, session_id)
if not session:
raise HTTPException(status_code=404, detail="Session not found")
messages = await get_messages(db, session_id, limit=limit)
return {
"session_id": session_id,
"title": session.title,
"messages": [
{
"id": msg.id,
"role": msg.role,
"content": msg.content,
"modality": msg.modality,
"created_at": msg.created_at.isoformat(),
}
for msg in messages
],
}