Update app.py
Browse files
app.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
# app.py – ARF v4 API with Gradio frontend (
|
| 2 |
import logging
|
| 3 |
import uuid
|
| 4 |
from datetime import datetime, timezone
|
|
@@ -18,10 +18,10 @@ logging.basicConfig(level=logging.INFO)
|
|
| 18 |
logger = logging.getLogger(__name__)
|
| 19 |
|
| 20 |
# ========================= FASTAPI APP =========================
|
| 21 |
-
|
| 22 |
|
| 23 |
# Enable CORS for your frontend
|
| 24 |
-
|
| 25 |
CORSMiddleware,
|
| 26 |
allow_origins=["https://arf-frontend-sandy.vercel.app"],
|
| 27 |
allow_methods=["*"],
|
|
@@ -58,17 +58,16 @@ class _DemoIntent:
|
|
| 58 |
service_name = "demo"
|
| 59 |
|
| 60 |
# ========================= API ENDPOINTS =========================
|
| 61 |
-
|
| 62 |
-
@app.get("/")
|
| 63 |
async def root():
|
| 64 |
"""Root endpoint – returns a welcome message."""
|
| 65 |
return {"message": "ARF v4 API. See /docs for documentation."}
|
| 66 |
|
| 67 |
-
@
|
| 68 |
async def health():
|
| 69 |
return {"status": "ok", "version": "4.0.0"}
|
| 70 |
|
| 71 |
-
@
|
| 72 |
async def get_risk():
|
| 73 |
"""Return the current demo risk."""
|
| 74 |
intent = _DemoIntent()
|
|
@@ -88,7 +87,7 @@ async def get_risk():
|
|
| 88 |
"decision_id": decision_id,
|
| 89 |
"timestamp": datetime.now(timezone.utc).isoformat(),
|
| 90 |
"risk_score": float(risk_value),
|
| 91 |
-
"outcome": None,
|
| 92 |
})
|
| 93 |
|
| 94 |
return {
|
|
@@ -101,17 +100,18 @@ async def get_risk():
|
|
| 101 |
"timestamp": datetime.now(timezone.utc).isoformat()
|
| 102 |
}
|
| 103 |
|
| 104 |
-
@
|
| 105 |
async def get_history():
|
| 106 |
"""Return the last 10 decisions."""
|
| 107 |
return decision_history[-10:]
|
| 108 |
|
| 109 |
-
@
|
| 110 |
async def evaluate_incident(request: EvaluateRequest):
|
| 111 |
"""
|
| 112 |
Evaluate an incident and return a risk score with explainability.
|
| 113 |
This is a placeholder – replace with actual call to your risk engine.
|
| 114 |
"""
|
|
|
|
| 115 |
return EvaluateResponse(
|
| 116 |
risk_score=0.23,
|
| 117 |
base_risk=0.15,
|
|
@@ -121,12 +121,13 @@ async def evaluate_incident(request: EvaluateRequest):
|
|
| 121 |
confidence=0.9
|
| 122 |
)
|
| 123 |
|
| 124 |
-
@
|
| 125 |
async def record_outcome(decision_id: str, success: bool):
|
| 126 |
"""Record the outcome of a decision (success/failure)."""
|
| 127 |
for dec in decision_history:
|
| 128 |
if dec["decision_id"] == decision_id:
|
| 129 |
dec["outcome"] = "success" if success else "failure"
|
|
|
|
| 130 |
intent = _DemoIntent()
|
| 131 |
try:
|
| 132 |
risk_engine.update_outcome(intent, success)
|
|
@@ -135,8 +136,9 @@ async def record_outcome(decision_id: str, success: bool):
|
|
| 135 |
return {"status": "ok", "decision_id": decision_id, "outcome": dec["outcome"]}
|
| 136 |
return {"error": "decision not found"}
|
| 137 |
|
| 138 |
-
# ========================= GRADIO UI (
|
| 139 |
-
#
|
|
|
|
| 140 |
|
| 141 |
def get_risk_snapshot():
|
| 142 |
try:
|
|
@@ -215,5 +217,8 @@ with gr.Blocks(title="ARF v4 Demo") as demo:
|
|
| 215 |
memory_btn.click(fn=get_memory_snapshot, outputs=memory_output)
|
| 216 |
history_btn.click(fn=lambda: decision_history[-10:], outputs=decision_output)
|
| 217 |
|
| 218 |
-
# Mount
|
| 219 |
-
app = gr.mount_gradio_app(
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# app.py – ARF v4 API with Gradio frontend (FastAPI mounted under /api)
|
| 2 |
import logging
|
| 3 |
import uuid
|
| 4 |
from datetime import datetime, timezone
|
|
|
|
| 18 |
logger = logging.getLogger(__name__)
|
| 19 |
|
| 20 |
# ========================= FASTAPI APP =========================
|
| 21 |
+
fastapi_app = FastAPI(title="ARF v4 API")
|
| 22 |
|
| 23 |
# Enable CORS for your frontend
|
| 24 |
+
fastapi_app.add_middleware(
|
| 25 |
CORSMiddleware,
|
| 26 |
allow_origins=["https://arf-frontend-sandy.vercel.app"],
|
| 27 |
allow_methods=["*"],
|
|
|
|
| 58 |
service_name = "demo"
|
| 59 |
|
| 60 |
# ========================= API ENDPOINTS =========================
|
| 61 |
+
@fastapi_app.get("/")
|
|
|
|
| 62 |
async def root():
|
| 63 |
"""Root endpoint – returns a welcome message."""
|
| 64 |
return {"message": "ARF v4 API. See /docs for documentation."}
|
| 65 |
|
| 66 |
+
@fastapi_app.get("/health")
|
| 67 |
async def health():
|
| 68 |
return {"status": "ok", "version": "4.0.0"}
|
| 69 |
|
| 70 |
+
@fastapi_app.get("/v1/get_risk")
|
| 71 |
async def get_risk():
|
| 72 |
"""Return the current demo risk."""
|
| 73 |
intent = _DemoIntent()
|
|
|
|
| 87 |
"decision_id": decision_id,
|
| 88 |
"timestamp": datetime.now(timezone.utc).isoformat(),
|
| 89 |
"risk_score": float(risk_value),
|
| 90 |
+
"outcome": None, # will be filled when feedback is given
|
| 91 |
})
|
| 92 |
|
| 93 |
return {
|
|
|
|
| 100 |
"timestamp": datetime.now(timezone.utc).isoformat()
|
| 101 |
}
|
| 102 |
|
| 103 |
+
@fastapi_app.get("/v1/history")
|
| 104 |
async def get_history():
|
| 105 |
"""Return the last 10 decisions."""
|
| 106 |
return decision_history[-10:]
|
| 107 |
|
| 108 |
+
@fastapi_app.post("/v1/incidents/evaluate", response_model=EvaluateResponse)
|
| 109 |
async def evaluate_incident(request: EvaluateRequest):
|
| 110 |
"""
|
| 111 |
Evaluate an incident and return a risk score with explainability.
|
| 112 |
This is a placeholder – replace with actual call to your risk engine.
|
| 113 |
"""
|
| 114 |
+
# For now, return a dummy response
|
| 115 |
return EvaluateResponse(
|
| 116 |
risk_score=0.23,
|
| 117 |
base_risk=0.15,
|
|
|
|
| 121 |
confidence=0.9
|
| 122 |
)
|
| 123 |
|
| 124 |
+
@fastapi_app.post("/v1/feedback")
|
| 125 |
async def record_outcome(decision_id: str, success: bool):
|
| 126 |
"""Record the outcome of a decision (success/failure)."""
|
| 127 |
for dec in decision_history:
|
| 128 |
if dec["decision_id"] == decision_id:
|
| 129 |
dec["outcome"] = "success" if success else "failure"
|
| 130 |
+
# Update the risk engine (optional)
|
| 131 |
intent = _DemoIntent()
|
| 132 |
try:
|
| 133 |
risk_engine.update_outcome(intent, success)
|
|
|
|
| 136 |
return {"status": "ok", "decision_id": decision_id, "outcome": dec["outcome"]}
|
| 137 |
return {"error": "decision not found"}
|
| 138 |
|
| 139 |
+
# ========================= GRADIO UI (Main App) =========================
|
| 140 |
+
# Gradio interface will be served at the root path ("/").
|
| 141 |
+
# The FastAPI app is mounted under the "/api" subpath.
|
| 142 |
|
| 143 |
def get_risk_snapshot():
|
| 144 |
try:
|
|
|
|
| 217 |
memory_btn.click(fn=get_memory_snapshot, outputs=memory_output)
|
| 218 |
history_btn.click(fn=lambda: decision_history[-10:], outputs=decision_output)
|
| 219 |
|
| 220 |
+
# ========================= Mount FastAPI under /api =========================
|
| 221 |
+
app = gr.mount_gradio_app(demo, fastapi_app, path="/api")
|
| 222 |
+
|
| 223 |
+
# Note: No manual server start. Hugging Face will serve this `app` (which is a Gradio app)
|
| 224 |
+
# and the FastAPI endpoints will be available under /api.
|