Update app.py
Browse files
app.py
CHANGED
|
@@ -85,7 +85,7 @@ async def root():
|
|
| 85 |
|
| 86 |
@fastapi_app.get("/health")
|
| 87 |
async def health():
|
| 88 |
-
return {"status": "ok", "version": "4.
|
| 89 |
|
| 90 |
@fastapi_app.get("/v1/get_risk")
|
| 91 |
async def get_risk():
|
|
@@ -173,7 +173,24 @@ async def evaluate_incident(request: EvaluateRequest):
|
|
| 173 |
else:
|
| 174 |
action = RecommendedAction.ESCALATE
|
| 175 |
|
| 176 |
-
# 6. Build
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
healing_intent = HealingIntent(
|
| 178 |
action=action.value,
|
| 179 |
component=intent.service_name,
|
|
@@ -183,7 +200,7 @@ async def evaluate_incident(request: EvaluateRequest):
|
|
| 183 |
incident_id="", # Not used in this context
|
| 184 |
detected_at=datetime.now(timezone.utc).timestamp(),
|
| 185 |
risk_score=risk_score,
|
| 186 |
-
risk_factors=
|
| 187 |
cost_projection=cost_projection,
|
| 188 |
recommended_action=action,
|
| 189 |
similar_incidents=similar_incidents,
|
|
@@ -208,7 +225,7 @@ async def evaluate_incident(request: EvaluateRequest):
|
|
| 208 |
min(1.0, risk_score + 0.05),
|
| 209 |
]
|
| 210 |
if "risk_contributions" not in response_dict:
|
| 211 |
-
# Convert contributions to list format
|
| 212 |
response_dict["risk_contributions"] = [
|
| 213 |
{"factor": k, "contribution": v}
|
| 214 |
for k, v in contributions.items() if k not in ["weights", "conjugate_mean", "hmc_prediction"]
|
|
@@ -264,11 +281,27 @@ def get_risk_snapshot():
|
|
| 264 |
"risk_score": float(risk_value),
|
| 265 |
"outcome": None,
|
| 266 |
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 267 |
return {
|
| 268 |
"risk": float(risk_value),
|
| 269 |
"status": "critical" if risk_value > 0.8 else "normal",
|
| 270 |
"explanation": explanation,
|
| 271 |
-
"
|
| 272 |
"decision_id": decision_id,
|
| 273 |
"decision": decision,
|
| 274 |
"timestamp": datetime.now(timezone.utc).isoformat()
|
|
@@ -278,7 +311,7 @@ def get_risk_snapshot():
|
|
| 278 |
return {"error": str(e)}
|
| 279 |
|
| 280 |
def get_health_snapshot():
|
| 281 |
-
return {"status": "ok", "version": "4.
|
| 282 |
|
| 283 |
def get_memory_snapshot():
|
| 284 |
if memory.has_historical_data():
|
|
@@ -297,8 +330,10 @@ def record_outcome_ui(success: bool):
|
|
| 297 |
logger.exception("Outcome update failed")
|
| 298 |
return {"decision_id": last["decision_id"], "outcome": last["outcome"], "timestamp": datetime.now(timezone.utc).isoformat()}
|
| 299 |
|
| 300 |
-
with gr.Blocks(title="ARF v4 Demo") as demo:
|
| 301 |
-
gr.Markdown("# Agentic Reliability Framework v4
|
|
|
|
|
|
|
| 302 |
with gr.Row():
|
| 303 |
health_output = gr.JSON(label="Health")
|
| 304 |
risk_output = gr.JSON(label="Current Risk")
|
|
|
|
| 85 |
|
| 86 |
@fastapi_app.get("/health")
|
| 87 |
async def health():
|
| 88 |
+
return {"status": "ok", "version": "4.2.0"}
|
| 89 |
|
| 90 |
@fastapi_app.get("/v1/get_risk")
|
| 91 |
async def get_risk():
|
|
|
|
| 173 |
else:
|
| 174 |
action = RecommendedAction.ESCALATE
|
| 175 |
|
| 176 |
+
# 6. Build risk_factors from component contributions
|
| 177 |
+
risk_factors = {}
|
| 178 |
+
weights = contributions.get("weights", {})
|
| 179 |
+
if weights.get("conjugate", 0.0) > 0:
|
| 180 |
+
conj_risk = contributions.get("conjugate_mean", risk_score)
|
| 181 |
+
risk_factors["conjugate"] = weights["conjugate"] * conj_risk
|
| 182 |
+
if weights.get("hyper", 0.0) > 0:
|
| 183 |
+
hyper_risk = contributions.get("hyper_mean", risk_score)
|
| 184 |
+
risk_factors["hyperprior"] = weights["hyper"] * hyper_risk
|
| 185 |
+
if weights.get("hmc", 0.0) > 0:
|
| 186 |
+
hmc_risk = contributions.get("hmc_prediction", risk_score)
|
| 187 |
+
risk_factors["hmc"] = weights["hmc"] * hmc_risk
|
| 188 |
+
|
| 189 |
+
# Fallback if no factors added
|
| 190 |
+
if not risk_factors:
|
| 191 |
+
risk_factors["conjugate"] = risk_score
|
| 192 |
+
|
| 193 |
+
# 7. Build HealingIntent manually
|
| 194 |
healing_intent = HealingIntent(
|
| 195 |
action=action.value,
|
| 196 |
component=intent.service_name,
|
|
|
|
| 200 |
incident_id="", # Not used in this context
|
| 201 |
detected_at=datetime.now(timezone.utc).timestamp(),
|
| 202 |
risk_score=risk_score,
|
| 203 |
+
risk_factors=risk_factors,
|
| 204 |
cost_projection=cost_projection,
|
| 205 |
recommended_action=action,
|
| 206 |
similar_incidents=similar_incidents,
|
|
|
|
| 225 |
min(1.0, risk_score + 0.05),
|
| 226 |
]
|
| 227 |
if "risk_contributions" not in response_dict:
|
| 228 |
+
# Convert contributions to list format (keeping only factors)
|
| 229 |
response_dict["risk_contributions"] = [
|
| 230 |
{"factor": k, "contribution": v}
|
| 231 |
for k, v in contributions.items() if k not in ["weights", "conjugate_mean", "hmc_prediction"]
|
|
|
|
| 281 |
"risk_score": float(risk_value),
|
| 282 |
"outcome": None,
|
| 283 |
})
|
| 284 |
+
|
| 285 |
+
# Build risk_factors for UI
|
| 286 |
+
risk_factors = {}
|
| 287 |
+
weights = contributions.get("weights", {})
|
| 288 |
+
if weights.get("conjugate", 0.0) > 0:
|
| 289 |
+
conj_risk = contributions.get("conjugate_mean", risk_value)
|
| 290 |
+
risk_factors["conjugate"] = weights["conjugate"] * conj_risk
|
| 291 |
+
if weights.get("hyper", 0.0) > 0:
|
| 292 |
+
hyper_risk = contributions.get("hyper_mean", risk_value)
|
| 293 |
+
risk_factors["hyperprior"] = weights["hyper"] * hyper_risk
|
| 294 |
+
if weights.get("hmc", 0.0) > 0:
|
| 295 |
+
hmc_risk = contributions.get("hmc_prediction", risk_value)
|
| 296 |
+
risk_factors["hmc"] = weights["hmc"] * hmc_risk
|
| 297 |
+
if not risk_factors:
|
| 298 |
+
risk_factors["conjugate"] = risk_value
|
| 299 |
+
|
| 300 |
return {
|
| 301 |
"risk": float(risk_value),
|
| 302 |
"status": "critical" if risk_value > 0.8 else "normal",
|
| 303 |
"explanation": explanation,
|
| 304 |
+
"risk_factors": risk_factors,
|
| 305 |
"decision_id": decision_id,
|
| 306 |
"decision": decision,
|
| 307 |
"timestamp": datetime.now(timezone.utc).isoformat()
|
|
|
|
| 311 |
return {"error": str(e)}
|
| 312 |
|
| 313 |
def get_health_snapshot():
|
| 314 |
+
return {"status": "ok", "version": "4.2.0", "service": "ARF OSS API", "timestamp": datetime.now(timezone.utc).isoformat()}
|
| 315 |
|
| 316 |
def get_memory_snapshot():
|
| 317 |
if memory.has_historical_data():
|
|
|
|
| 330 |
logger.exception("Outcome update failed")
|
| 331 |
return {"decision_id": last["decision_id"], "outcome": last["outcome"], "timestamp": datetime.now(timezone.utc).isoformat()}
|
| 332 |
|
| 333 |
+
with gr.Blocks(title="ARF v4.2.0 Demo", theme=gr.themes.Soft()) as demo:
|
| 334 |
+
gr.Markdown("# Agentic Reliability Framework v4.2.0")
|
| 335 |
+
gr.Markdown("### Probabilistic Infrastructure Governance – [📚 API Docs](/api/docs) | [📦 GitHub](https://github.com/arf-foundation/agentic-reliability-framework) | [📅 Book a Call](https://calendly.com/petter2025us/30min)")
|
| 336 |
+
gr.Markdown("---")
|
| 337 |
with gr.Row():
|
| 338 |
health_output = gr.JSON(label="Health")
|
| 339 |
risk_output = gr.JSON(label="Current Risk")
|