from fastapi import APIRouter, HTTPException, Depends import httpx import json from ..config import settings from ..models import SummarizeRequest, SummarizeResponse, ActionItemCreate, TokenPayload from .auth import get_current_user router = APIRouter() @router.post("/ai/summarize", response_model=SummarizeResponse) async def summarize_transcript( request: SummarizeRequest, current_user: TokenPayload = Depends(get_current_user) ): """ Send transcript to Dify for AI summarization. Returns structured conclusions and action items. """ if not settings.DIFY_API_KEY: raise HTTPException(status_code=503, detail="Dify API not configured") async with httpx.AsyncClient() as client: try: response = await client.post( f"{settings.DIFY_API_URL}/chat-messages", headers={ "Authorization": f"Bearer {settings.DIFY_API_KEY}", "Content-Type": "application/json", }, json={ "inputs": {}, "query": request.transcript, "response_mode": "blocking", "user": current_user.email, }, timeout=120.0, # Long timeout for LLM processing ) if response.status_code != 200: raise HTTPException( status_code=response.status_code, detail=f"Dify API error: {response.text}", ) data = response.json() answer = data.get("answer", "") # Try to parse structured JSON from Dify response parsed = parse_dify_response(answer) return SummarizeResponse( conclusions=parsed["conclusions"], action_items=[ ActionItemCreate( content=item.get("content", ""), owner=item.get("owner", ""), due_date=item.get("due_date"), ) for item in parsed["action_items"] ], ) except httpx.TimeoutException: raise HTTPException( status_code=504, detail="Dify API timeout - transcript may be too long" ) except httpx.RequestError as e: raise HTTPException(status_code=503, detail=f"Dify API unavailable: {str(e)}") def parse_dify_response(answer: str) -> dict: """ Parse Dify response to extract conclusions and action items. Attempts JSON parsing first, then falls back to text parsing. """ # Try to find JSON in the response try: # Look for JSON block if "```json" in answer: json_start = answer.index("```json") + 7 json_end = answer.index("```", json_start) json_str = answer[json_start:json_end].strip() elif "{" in answer and "}" in answer: # Try to find JSON object json_start = answer.index("{") json_end = answer.rindex("}") + 1 json_str = answer[json_start:json_end] else: raise ValueError("No JSON found") data = json.loads(json_str) return { "conclusions": data.get("conclusions", []), "action_items": data.get("action_items", []), } except (ValueError, json.JSONDecodeError): # Fallback: return raw answer as single conclusion return { "conclusions": [answer] if answer else [], "action_items": [], }