Spaces:
Sleeping
Sleeping
| """ | |
| FlashTriage — entry point. | |
| Run: | |
| cp .env.example .env # add your CEREBRAS_API_KEY | |
| pip install -r requirements.txt | |
| uvicorn backend.main:app --reload --port 8000 | |
| Then open http://localhost:8000 | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import os | |
| from pathlib import Path | |
| import httpx | |
| from dotenv import load_dotenv | |
| from fastapi import FastAPI, Request | |
| from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse | |
| from .agents import Swarm | |
| from .cerebras_client import CerebrasClient, MockClient | |
| from .models import normalize | |
| load_dotenv(Path(__file__).resolve().parent.parent / ".env") | |
| ROOT = Path(__file__).resolve().parent.parent | |
| app = FastAPI(title="FlashTriage") | |
| def _cerebras(): | |
| key = os.getenv("CEREBRAS_API_KEY", "").strip() | |
| if os.getenv("USE_MOCK", "0") == "1" or not key: | |
| return MockClient(provider="cerebras"), "cerebras (mock)" | |
| return CerebrasClient( | |
| api_key=key, | |
| base_url=os.getenv("CEREBRAS_BASE_URL", "https://api.cerebras.ai/v1"), | |
| model=os.getenv("CEREBRAS_MODEL", "gemma-4-31b"), | |
| provider="cerebras", | |
| ), os.getenv("CEREBRAS_MODEL", "gemma-4-31b") | |
| def _baseline(): | |
| """Real second provider if configured; else None (caller falls back to sequential). | |
| Point this at Ollama on your RTX 5090 for a real local-GPU-vs-Cerebras race: | |
| BASELINE_BASE_URL=http://localhost:11434/api BASELINE_API_KEY=ollama BASELINE_MODEL=gemma5090:latest | |
| """ | |
| url = os.getenv("BASELINE_BASE_URL", "").strip() | |
| key = os.getenv("BASELINE_API_KEY", "").strip() | |
| model = os.getenv("BASELINE_MODEL", "").strip() | |
| if url and model: | |
| label = os.getenv("BASELINE_LABEL", "").strip() or model | |
| return CerebrasClient(api_key=key or "none", base_url=url, model=model, | |
| provider="baseline", profile="ollama_native"), label | |
| return None, None | |
| def _swarm(client): | |
| return Swarm( | |
| client, | |
| max_concurrency=int(os.getenv("MAX_CONCURRENCY", "10")), | |
| remediate_min_cvss=float(os.getenv("REMEDIATE_MIN_CVSS", "7.0")), | |
| ) | |
| def _sse(obj: dict) -> str: | |
| return f"data: {json.dumps(obj)}\n\n" | |
| def index(): | |
| return (ROOT / "frontend" / "index.html").read_text(encoding="utf-8") | |
| def sample(): | |
| return JSONResponse(json.loads((ROOT / "samples" / "sample_findings.json").read_text())) | |
| async def triage(req: Request): | |
| """ | |
| Body: { "payload": <scanner output: SARIF|JSON|text|list>, | |
| "lane": "cerebras" | "baseline", | |
| "limit": int } | |
| Streams SSE: meta -> finding* -> rollup -> summary | |
| """ | |
| body = await req.json() | |
| findings = normalize(body.get("payload")) | |
| limit = int(body.get("limit") or 0) | |
| if limit > 0: | |
| findings = findings[:limit] | |
| lane = body.get("lane", "cerebras") | |
| if lane == "baseline": | |
| bclient, blabel = _baseline() | |
| if bclient is not None: # real second provider, sequential | |
| client, model_label, parallel = bclient, blabel, False | |
| else: # honest fallback: same model, sequential | |
| client, model_label, parallel = _cerebras()[0], _cerebras()[1] + " (sequential)", False | |
| else: | |
| client, model_label = _cerebras() | |
| parallel = True | |
| swarm = _swarm(client) | |
| async def gen(): | |
| yield _sse({"type": "meta", "data": { | |
| "lane": lane, "model": model_label, | |
| "parallel": parallel, "count": len(findings)}}) | |
| async for ev in swarm.run_batch(findings, parallel=parallel): | |
| yield _sse(ev) | |
| return StreamingResponse(gen(), media_type="text/event-stream", | |
| headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"}) | |
| async def deepdive(req: Request): | |
| """ | |
| Body: { "context": str, "image_base64": str (no data: prefix), "media_type": str } | |
| Multimodal root-cause analysis on a single finding's screenshot. | |
| """ | |
| body = await req.json() | |
| client, model_label = _cerebras() | |
| swarm = _swarm(client) | |
| async with httpx.AsyncClient() as http: | |
| out = await swarm.vision_rca( | |
| http, | |
| context=body.get("context", "Analyze this security finding."), | |
| image_b64=body.get("image_base64", ""), | |
| media_type=body.get("media_type", "image/png"), | |
| ) | |
| return JSONResponse({"model": model_label, "rca": out["rca"], | |
| "ttft_ms": out["timing"].ttft_ms, | |
| "wall_ms": out["timing"].wall_ms}) | |