Spaces:
Paused
Paused
Download sensorflow/retro/api.py from whassan/SensorflowStudio: direct link, hf CLI and curl.
- Browser
- Download file 5.06 kB
-
https://huggingface.co/spaces/whassan/SensorflowStudio/resolve/main/sensorflow/retro/api.py
- Command line
-
hf download hf://spaces/whassan/SensorflowStudio/sensorflow/retro/api.py
-
curl -L -o api.py https://huggingface.co/spaces/whassan/SensorflowStudio/resolve/main/sensorflow/retro/api.py
5.06 kB
| """FastAPI router for the Agentic Retrospective Safety Analyzer. | |
| Mounted at /api/retro by app_backend.py. Artifacts persist under runs/retro/. | |
| """ | |
| from __future__ import annotations | |
| import json | |
| from pathlib import Path | |
| from typing import Any, Dict, Optional | |
| from fastapi import APIRouter, Body, HTTPException, Query | |
| from sensorflow.retro import store | |
| from sensorflow.retro.agent.orchestrator import analyze | |
| from sensorflow.retro.inference.client import all_backend_statuses | |
| from sensorflow.retro.inference.compat import check_vllm_compatibility, format_report | |
| from sensorflow.retro.inference.env_detect import detect_environment | |
| from sensorflow.retro.rag.evalharness import run_retrieval_eval | |
| from sensorflow.retro.rag.retriever import get_index | |
| from sensorflow.retro.tools.builtin import FIXTURES_DIR, build_registry | |
| router = APIRouter(prefix="/api/retro", tags=["retro"]) | |
| def env_report(): | |
| env = detect_environment() | |
| return {"status": "ok", "environment": env.model_dump()} | |
| def compat_report(model_name: str = "meta-llama/Llama-3.1-8B-Instruct", | |
| quantization: str = "none"): | |
| env = detect_environment(probe_ollama=False) | |
| report = check_vllm_compatibility(env, model_name=model_name, | |
| quantization=quantization) | |
| return {"status": "ok", "report": report.model_dump(), | |
| "formatted": format_report(report)} | |
| def backends_status(): | |
| return {"status": "ok", | |
| "backends": [s.model_dump() for s in all_backend_statuses()]} | |
| def rag_search(q: str = Query(min_length=3), k: int = Query(4, ge=1, le=10)): | |
| index = get_index() | |
| hits = index.search(q, k=k) | |
| return {"status": "ok", "store_backend": index.backend_name, | |
| "hits": [h.model_dump() for h in hits]} | |
| def rag_eval(k: int = Query(4, ge=1, le=10)): | |
| return {"status": "ok", "report": run_retrieval_eval(k=k).model_dump()} | |
| def list_fixtures(): | |
| out = [] | |
| for p in sorted(Path(FIXTURES_DIR).glob("*.json")): | |
| try: | |
| data = json.loads(p.read_text()) | |
| out.append({ | |
| "fixture_id": p.stem, | |
| "evaluation_id": data.get("evaluation_id"), | |
| "description": (data.get("scenario") or {}).get("description", ""), | |
| "weather": (data.get("scenario") or {}).get("weather"), | |
| }) | |
| except (json.JSONDecodeError, OSError): | |
| continue | |
| return {"status": "ok", "fixtures": out} | |
| def analyze_failure(fixture_id: Optional[str] = None, | |
| backend: str = Query("mock", pattern="^(mock|ollama|vllm)$"), | |
| log: Optional[Dict[str, Any]] = Body(None)): | |
| """Analyze a fixture by id, or an uploaded JSON eval log in the body.""" | |
| if not fixture_id and not log: | |
| raise HTTPException(status_code=400, | |
| detail="provide ?fixture_id= or a JSON log body") | |
| try: | |
| if fixture_id: | |
| scorecard = analyze(fixture_id=fixture_id, backend=backend) | |
| else: | |
| eval_id = log.get("evaluation_id", "uploaded") | |
| safe = "".join(c for c in eval_id if c.isalnum() or c in "-_")[:64] | |
| upload_path = store.uploads_dir() / f"{safe or 'uploaded'}.json" | |
| upload_path.write_text(json.dumps(log, indent=2)) | |
| scorecard = analyze(path=str(upload_path), backend=backend) | |
| except FileNotFoundError as exc: | |
| raise HTTPException(status_code=404, detail=str(exc)) | |
| except RuntimeError as exc: # backend unavailable | |
| raise HTTPException(status_code=503, detail=str(exc)) | |
| return {"status": "ok", | |
| "scorecard": json.loads(scorecard.model_dump_json()), | |
| "markdown": scorecard.render_markdown()} | |
| def list_analyses(): | |
| return {"status": "ok", "analyses": store.list_analyses()} | |
| def get_analysis(evaluation_id: str): | |
| data = store.load_analysis(evaluation_id) | |
| if data is None: | |
| raise HTTPException(status_code=404, | |
| detail=f"no analysis for {evaluation_id}") | |
| return {"status": "ok", **data} | |
| def get_audit(evaluation_id: str): | |
| data = store.load_analysis(evaluation_id) | |
| if data is None: | |
| raise HTTPException(status_code=404, | |
| detail=f"no analysis for {evaluation_id}") | |
| audit_id = data.get("audit_analysis_id", evaluation_id) | |
| return {"status": "ok", "audit_analysis_id": audit_id, | |
| "records": store.read_audit(audit_id)} | |
| def tool_registry_listing(): | |
| reg = build_registry(persist_audit=False) | |
| return {"status": "ok", | |
| "tools": [s.model_dump() for s in reg.specs()], | |
| "note": "write tools require policy_authorization=true per call; " | |
| "all calls are audited"} | |