File size: 4,887 Bytes
5c244a3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
"""
Chat API Endpoint - AI Orchestrator
"""
from fastapi import APIRouter, HTTPException, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from uuid import UUID, uuid4
from src.api.models import ChatCommandRequest, ChatCommandResponse
from src.models import Task
from src.services import IntentDetector, SkillDispatcher, EventPublisher
from src.utils.database import get_db_session
from src.utils.logging import get_logger
logger = get_logger(__name__)
router = APIRouter(prefix="/chat", tags=["chat"])
intent_detector = IntentDetector()
skill_dispatcher = SkillDispatcher()
event_publisher = EventPublisher()
@router.post("/command", response_model=ChatCommandResponse)
async def chat_command(
request: ChatCommandRequest,
db_session: AsyncSession = Depends(get_db_session),
):
"""Process chat command via AI orchestrator"""
correlation_id = str(uuid4())
# Detect intent
intent_result = intent_detector.detect(request.user_input)
if intent_result["requires_clarification"]:
return ChatCommandResponse(
response=f"I need more info: {', '.join(intent_result['missing_fields'])}",
intent_detected=intent_result["intent"],
skill_agent_used=intent_result["agent"] or "none",
confidence_score=intent_result["confidence"],
requires_clarification=True,
)
# Build context
context = {
"user_id": "default-user-id",
"db_session": db_session,
"correlation_id": correlation_id,
}
# Dispatch to skill agent
await skill_dispatcher.dispatch(
agent_name=intent_result["agent"],
intent_data=intent_result["data"],
context=context,
)
# Execute operation
try:
if intent_result["intent"] == "create":
result = await _create_task(intent_result["data"], context, correlation_id)
elif intent_result["intent"] == "complete":
result = await _complete_task(intent_result["data"], context, correlation_id)
elif intent_result["intent"] == "list":
result = await _list_tasks(intent_result["data"], context)
else:
result = {"response": "Could you please rephrase that?"}
return ChatCommandResponse(
response=result["response"],
intent_detected=intent_result["intent"],
skill_agent_used=intent_result["agent"],
confidence_score=intent_result["confidence"],
requires_clarification=False,
data=result.get("data"),
)
except Exception as e:
logger.error("chat_command_failed", error=str(e))
raise HTTPException(status_code=500, detail=str(e))
async def _create_task(data: dict, context: dict, correlation_id: str) -> dict:
"""Create a new task"""
db_session = context["db_session"]
task = Task(
user_id=UUID(context["user_id"]),
title=data["title"],
priority=data.get("priority", "medium"),
tags=data.get("tags", []),
status="active",
)
db_session.add(task)
await db_session.commit()
await db_session.refresh(task)
# Publish event
await event_publisher.publish_task_created(
task_id=str(task.id),
user_id=context["user_id"],
task_data=task.to_dict(),
correlation_id=correlation_id,
)
return {
"response": f"I've created '{task.title}' with {task.priority} priority.",
"data": {"task_id": str(task.id)},
}
async def _complete_task(data: dict, context: dict, correlation_id: str) -> dict:
"""Mark a task as complete"""
db_session = context["db_session"]
result = await db_session.execute(select(Task).where(Task.id == UUID(data["task_id"])))
task = result.scalar_one_or_none()
if not task:
return {"response": "Task not found."}
task.status = "completed"
await db_session.commit()
await event_publisher.publish_task_completed(
task_id=str(task.id),
user_id=context["user_id"],
correlation_id=correlation_id,
)
return {"response": f"Marked '{task.title}' as complete!", "data": {"task_id": str(task.id)}}
async def _list_tasks(data: dict, context: dict) -> dict:
"""List user's tasks"""
db_session = context["db_session"]
query = select(Task).where(Task.user_id == UUID(context["user_id"]))
filters = data.get("filters", {})
if "status" in filters:
query = query.where(Task.status == filters["status"])
result = await db_session.execute(query)
tasks = result.scalars().all()
if not tasks:
return {"response": "No tasks found.", "data": {"tasks": []}}
task_list = "\n".join([f"- {t.title} ({t.status})" for t in tasks[:10]])
return {"response": f"Your tasks:\n{task_list}", "data": {"tasks": [t.to_dict() for t in tasks]}}
|