|
|
""" |
|
|
Agent API Endpoints |
|
|
New FastAPI router for Agent-based interactions |
|
|
""" |
|
|
from fastapi import APIRouter, HTTPException, UploadFile, File, Form |
|
|
from pydantic import BaseModel |
|
|
from typing import Optional, List, Dict, Any |
|
|
import tempfile |
|
|
import os |
|
|
import logging |
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
router = APIRouter(prefix="/api/agent", tags=["agent"]) |
|
|
|
|
|
|
|
|
class AgentChatRequest(BaseModel): |
|
|
"""Request model for agent chat""" |
|
|
session_id: str |
|
|
message: str |
|
|
file_path: Optional[str] = None |
|
|
boundary_coords: Optional[List[List[float]]] = None |
|
|
|
|
|
|
|
|
class AgentChatResponse(BaseModel): |
|
|
"""Response model for agent chat""" |
|
|
status: str |
|
|
response: str |
|
|
tool_calls: List[Dict[str, Any]] = [] |
|
|
session_id: str |
|
|
|
|
|
|
|
|
@router.post("/chat", response_model=AgentChatResponse) |
|
|
async def agent_chat(request: AgentChatRequest): |
|
|
""" |
|
|
Chat with the REMB Agent |
|
|
|
|
|
The agent can: |
|
|
- Read and parse DXF files |
|
|
- Generate optimized layouts |
|
|
- Check regulatory compliance |
|
|
- Export results to DXF |
|
|
- Self-correct on errors |
|
|
""" |
|
|
try: |
|
|
from src.agent import get_agent |
|
|
|
|
|
agent = get_agent() |
|
|
result = agent.invoke( |
|
|
user_input=request.message, |
|
|
session_id=request.session_id, |
|
|
file_path=request.file_path, |
|
|
boundary_coords=request.boundary_coords |
|
|
) |
|
|
|
|
|
return AgentChatResponse(**result) |
|
|
|
|
|
except ValueError as e: |
|
|
raise HTTPException(400, str(e)) |
|
|
except Exception as e: |
|
|
logger.error(f"Agent chat error: {e}") |
|
|
raise HTTPException(500, f"Agent error: {str(e)}") |
|
|
|
|
|
|
|
|
@router.post("/process-file") |
|
|
async def agent_process_file( |
|
|
file: UploadFile = File(...), |
|
|
message: str = Form(default="Analyze this site and suggest optimal layouts"), |
|
|
session_id: str = Form(default="default") |
|
|
): |
|
|
""" |
|
|
Upload a CAD file and process with the agent |
|
|
|
|
|
The agent will: |
|
|
1. Parse the file |
|
|
2. Analyze the site |
|
|
3. Generate layout options |
|
|
4. Check compliance |
|
|
5. Return comprehensive results |
|
|
""" |
|
|
if not file.filename: |
|
|
raise HTTPException(400, "No file provided") |
|
|
|
|
|
|
|
|
try: |
|
|
content = await file.read() |
|
|
suffix = ".dwg" if file.filename.lower().endswith(".dwg") else ".dxf" |
|
|
|
|
|
with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as tmp: |
|
|
tmp.write(content) |
|
|
tmp_path = tmp.name |
|
|
|
|
|
|
|
|
from src.agent import get_agent |
|
|
|
|
|
agent = get_agent() |
|
|
result = agent.invoke( |
|
|
user_input=f"[File uploaded: {file.filename}]\n{message}", |
|
|
session_id=session_id, |
|
|
file_path=tmp_path |
|
|
) |
|
|
|
|
|
|
|
|
try: |
|
|
os.unlink(tmp_path) |
|
|
except: |
|
|
pass |
|
|
|
|
|
return { |
|
|
"status": result.get("status"), |
|
|
"response": result.get("response"), |
|
|
"tool_calls": result.get("tool_calls", []), |
|
|
"session_id": session_id, |
|
|
"file_processed": file.filename |
|
|
} |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"File processing error: {e}") |
|
|
raise HTTPException(500, f"Processing error: {str(e)}") |
|
|
|
|
|
|
|
|
@router.get("/health") |
|
|
async def agent_health(): |
|
|
"""Check agent status""" |
|
|
try: |
|
|
from src.agent import get_agent |
|
|
from src.tools import all_tools |
|
|
|
|
|
agent = get_agent() |
|
|
|
|
|
return { |
|
|
"status": "healthy", |
|
|
"agent_type": "ReAct", |
|
|
"model": agent.model_name, |
|
|
"tools_available": len(all_tools), |
|
|
"tool_names": [t.name for t in all_tools] |
|
|
} |
|
|
except Exception as e: |
|
|
return { |
|
|
"status": "error", |
|
|
"message": str(e) |
|
|
} |
|
|
|