| from dotenv import load_dotenv |
| load_dotenv() |
|
|
| import json |
|
|
| from fastapi import FastAPI |
| from fastapi.middleware.cors import CORSMiddleware |
| from fastapi.responses import StreamingResponse |
| from pydantic import BaseModel |
|
|
| from app.graph.build import build_graph |
|
|
| app = FastAPI(title="VeriScite", version="0.1.0") |
|
|
| app.add_middleware( |
| CORSMiddleware, |
| allow_origins=["*"], |
| allow_methods=["*"], |
| allow_headers=["*"], |
| ) |
|
|
| graph = build_graph() |
|
|
|
|
| class AuditRequest(BaseModel): |
| text: str |
|
|
|
|
| @app.get("/health") |
| async def health(): |
| return {"status": "ok"} |
|
|
|
|
| @app.post("/audit") |
| async def audit(req: AuditRequest): |
| initial_state = { |
| "source_text": req.text, |
| "claims": [], |
| "audits": [], |
| "current_index": 0, |
| "report": None, |
| } |
| final_state = await graph.ainvoke(initial_state) |
| return final_state["report"] |
|
|
|
|
| @app.post("/audit/stream") |
| async def audit_stream(req: AuditRequest): |
| """Server-Sent Events version of /audit — emits a live event after each |
| graph node (and after each individual tool call inside the escalate |
| agent loop) completes, rather than only returning at the very end. |
| Powers the frontend's live agent-workflow visualization. |
| |
| Event shapes: |
| {"type": "progress", ...node-specific fields, see nodes.py _writer() calls} |
| {"type": "final", "report": {...}} -- sent once, at the end |
| """ |
| initial_state = { |
| "source_text": req.text, |
| "claims": [], |
| "audits": [], |
| "current_index": 0, |
| "report": None, |
| } |
|
|
| async def event_generator(): |
| async for mode, chunk in graph.astream(initial_state, stream_mode=["custom", "values"]): |
| if mode == "custom": |
| yield f"data: {json.dumps({'type': 'progress', **chunk})}\n\n" |
| elif mode == "values" and chunk.get("report") is not None: |
| yield f"data: {json.dumps({'type': 'final', 'report': chunk['report']})}\n\n" |
|
|
| return StreamingResponse(event_generator(), media_type="text/event-stream") |
|
|