petter2025 commited on
Commit
0f5f4d1
·
verified ·
1 Parent(s): 14cc3c4

Update hf_demo.py

Browse files
Files changed (1) hide show
  1. hf_demo.py +127 -160
hf_demo.py CHANGED
@@ -1,10 +1,12 @@
1
- # hf_demo.py – ARF v4 dashboard for Hugging Face Spaces
2
  import logging
3
  import uuid
4
  from datetime import datetime, timezone
 
5
 
6
- from fastapi import FastAPI, HTTPException
7
  from fastapi.middleware.cors import CORSMiddleware
 
8
  import gradio as gr
9
 
10
  # ARF v4 imports
@@ -15,9 +17,10 @@ from agentic_reliability_framework.runtime.memory.constants import MemoryConstan
15
  logging.basicConfig(level=logging.INFO)
16
  logger = logging.getLogger(__name__)
17
 
18
- app = FastAPI(title="ARF v4 API with Memory")
 
19
 
20
- # Enable CORS
21
  app.add_middleware(
22
  CORSMiddleware,
23
  allow_origins=["https://arf-frontend-sandy.vercel.app"],
@@ -25,62 +28,55 @@ app.add_middleware(
25
  allow_headers=["*"],
26
  )
27
 
28
- # ---------------------------------------------------------------------------
29
- # Initialize ARF components
30
- # ---------------------------------------------------------------------------
31
-
32
  risk_engine = RiskEngine()
33
-
34
  faiss_index = create_faiss_index(dim=MemoryConstants.VECTOR_DIM)
35
  memory = RAGGraphMemory(faiss_index)
36
 
37
- # ---------------------------------------------------------------------------
38
- # Decision Memory (NEW)
39
- # ---------------------------------------------------------------------------
40
-
41
  decision_history = []
42
- risk_history = []
43
 
44
- # ---------------------------------------------------------------------------
45
- # API Endpoints
46
- # ---------------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
  @app.get("/")
49
  async def root():
50
- return {
51
- "service": "ARF OSS API",
52
- "version": "4.0.0",
53
- "status": "operational",
54
- "memory_stats": memory.get_graph_stats() if memory.has_historical_data() else "empty",
55
- }
56
 
57
  @app.get("/health")
58
  async def health():
59
  return {"status": "ok", "version": "4.0.0"}
60
 
61
- # ---------------------------------------------------------------------------
62
- # Demo Intent Object
63
- # ---------------------------------------------------------------------------
64
-
65
- class _DemoIntent:
66
- environment = "dev"
67
- deployment_target = "dev"
68
- service_name = "demo"
69
-
70
- # ---------------------------------------------------------------------------
71
- # Risk Calculation
72
- # ---------------------------------------------------------------------------
73
-
74
- def _calculate_demo_risk():
75
-
76
  intent = _DemoIntent()
77
-
78
  risk_value, explanation, contributions = risk_engine.calculate_risk(
79
  intent=intent,
80
  cost_estimate=None,
81
  policy_violations=[],
82
  )
83
-
84
  decision = "approve"
85
  if risk_value > 0.8:
86
  decision = "deny"
@@ -88,167 +84,138 @@ def _calculate_demo_risk():
88
  decision = "escalate"
89
 
90
  decision_id = str(uuid.uuid4())
91
-
92
- decision_record = {
93
- "id": decision_id,
94
  "timestamp": datetime.now(timezone.utc).isoformat(),
95
- "risk": float(risk_value),
96
- "decision": decision
97
- }
98
-
99
- decision_history.append(decision_record)
100
-
101
- risk_history.append(
102
- {
103
- "timestamp": decision_record["timestamp"],
104
- "risk": float(risk_value)
105
- }
106
- )
107
 
108
  return {
109
- "risk": float(risk_value),
110
  "status": "critical" if risk_value > 0.8 else "normal",
111
  "explanation": explanation,
112
  "contributions": contributions,
113
  "decision_id": decision_id,
114
- "decision": decision
 
115
  }
116
 
117
- # ---------------------------------------------------------------------------
118
- # Outcome Feedback
119
- # ---------------------------------------------------------------------------
120
-
121
- def record_outcome(success: bool):
122
-
123
- if not decision_history:
124
- return {"error": "no decisions yet"}
125
-
126
- last_decision = decision_history[-1]
127
-
128
- intent = _DemoIntent()
129
-
130
- try:
131
- risk_engine.update_outcome(intent, success)
132
- except Exception as e:
133
- logger.exception("Outcome update failed")
134
-
135
- last_decision["outcome"] = "success" if success else "failure"
136
 
137
- return {
138
- "decision_id": last_decision["id"],
139
- "outcome": last_decision["outcome"],
140
- "timestamp": datetime.now(timezone.utc).isoformat()
141
- }
 
 
 
 
 
 
 
 
 
 
142
 
143
- # ---------------------------------------------------------------------------
144
- # Snapshot functions
145
- # ---------------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
  def get_risk_snapshot():
148
-
149
  try:
150
- snapshot = _calculate_demo_risk()
151
-
152
- snapshot["timestamp"] = datetime.now(timezone.utc).isoformat()
153
-
154
- return snapshot
155
-
156
- except Exception as e:
157
-
158
- logger.exception("Failed to compute risk snapshot")
159
-
160
- return {
161
- "status": "error",
162
- "error": str(e),
 
163
  "timestamp": datetime.now(timezone.utc).isoformat(),
 
 
 
 
 
 
 
 
 
 
 
164
  }
 
 
 
165
 
166
  def get_health_snapshot():
167
-
168
- return {
169
- "status": "ok",
170
- "version": "4.0.0",
171
- "service": "ARF OSS API",
172
- "timestamp": datetime.now(timezone.utc).isoformat(),
173
- }
174
 
175
  def get_memory_snapshot():
 
 
 
176
 
 
 
 
 
 
 
177
  try:
178
-
179
- if memory.has_historical_data():
180
-
181
- stats = memory.get_graph_stats()
182
-
183
- return {
184
- "status": "ok",
185
- "memory_stats": stats,
186
- "timestamp": datetime.now(timezone.utc).isoformat(),
187
- }
188
-
189
- return {
190
- "status": "empty",
191
- "memory_stats": "No historical memory yet.",
192
- "timestamp": datetime.now(timezone.utc).isoformat(),
193
- }
194
-
195
  except Exception as e:
196
-
197
- logger.exception("Failed to compute memory snapshot")
198
-
199
- return {
200
- "status": "error",
201
- "error": str(e),
202
- "timestamp": datetime.now(timezone.utc).isoformat(),
203
- }
204
-
205
- def get_decision_history():
206
- return decision_history[-10:]
207
-
208
- # ---------------------------------------------------------------------------
209
- # Gradio Dashboard
210
- # ---------------------------------------------------------------------------
211
 
212
  with gr.Blocks(title="ARF v4 Demo") as demo:
213
-
214
- gr.Markdown("# Agentic Reliability Framework v4")
215
- gr.Markdown("### Probabilistic Infrastructure Governance")
216
-
217
  with gr.Row():
218
  health_output = gr.JSON(label="Health")
219
  risk_output = gr.JSON(label="Current Risk")
220
-
221
  with gr.Row():
222
  memory_output = gr.JSON(label="Memory Stats")
223
-
224
  with gr.Row():
225
  decision_output = gr.JSON(label="Recent Decisions")
226
-
227
  with gr.Row():
228
  refresh_btn = gr.Button("Evaluate Intent")
229
  success_btn = gr.Button("Action Succeeded")
230
  fail_btn = gr.Button("Action Failed")
231
-
232
  refresh_btn.click(fn=get_risk_snapshot, outputs=risk_output)
233
- success_btn.click(fn=lambda: record_outcome(True), outputs=decision_output)
234
- fail_btn.click(fn=lambda: record_outcome(False), outputs=decision_output)
235
-
236
  with gr.Row():
237
  health_btn = gr.Button("Refresh Health")
238
  memory_btn = gr.Button("Refresh Memory")
239
  history_btn = gr.Button("Show Decision History")
240
-
241
  health_btn.click(fn=get_health_snapshot, outputs=health_output)
242
  memory_btn.click(fn=get_memory_snapshot, outputs=memory_output)
243
- history_btn.click(fn=get_decision_history, outputs=decision_output)
244
-
245
- demo.load(fn=get_health_snapshot, outputs=health_output)
246
- demo.load(fn=get_risk_snapshot, outputs=risk_output)
247
- demo.load(fn=get_memory_snapshot, outputs=memory_output)
248
-
249
- # ---------------------------------------------------------------------------
250
- # Entry point
251
- # ---------------------------------------------------------------------------
252
 
253
- if __name__ == "__main__":
254
- demo.launch(server_name="0.0.0.0")
 
1
+ # hf_demo.py – ARF v4 API with Gradio frontend (optional)
2
  import logging
3
  import uuid
4
  from datetime import datetime, timezone
5
+ from typing import Dict, Any, Optional
6
 
7
+ from fastapi import FastAPI
8
  from fastapi.middleware.cors import CORSMiddleware
9
+ from pydantic import BaseModel
10
  import gradio as gr
11
 
12
  # ARF v4 imports
 
17
  logging.basicConfig(level=logging.INFO)
18
  logger = logging.getLogger(__name__)
19
 
20
+ # ========================= FASTAPI APP =========================
21
+ app = FastAPI(title="ARF v4 API")
22
 
23
+ # Enable CORS for your frontend
24
  app.add_middleware(
25
  CORSMiddleware,
26
  allow_origins=["https://arf-frontend-sandy.vercel.app"],
 
28
  allow_headers=["*"],
29
  )
30
 
31
+ # ========================= ARF COMPONENTS =========================
 
 
 
32
  risk_engine = RiskEngine()
 
33
  faiss_index = create_faiss_index(dim=MemoryConstants.VECTOR_DIM)
34
  memory = RAGGraphMemory(faiss_index)
35
 
36
+ # In‑memory storage for demo purposes (replace with a real DB later)
 
 
 
37
  decision_history = []
 
38
 
39
+ # ========================= PYDANTIC MODELS =========================
40
+ class EvaluateRequest(BaseModel):
41
+ service_name: str
42
+ event_type: str
43
+ severity: str
44
+ metrics: Dict[str, float] = {}
45
+
46
+ class EvaluateResponse(BaseModel):
47
+ risk_score: float
48
+ base_risk: float
49
+ memory_risk: Optional[float] = None
50
+ weight: float
51
+ similar_events: list = []
52
+ confidence: float
53
+
54
+ # ========================= HELPER: Demo Intent =========================
55
+ class _DemoIntent:
56
+ environment = "dev"
57
+ deployment_target = "dev"
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
  @app.get("/health")
68
  async def health():
69
  return {"status": "ok", "version": "4.0.0"}
70
 
71
+ @app.get("/api/v1/get_risk")
72
+ async def get_risk():
73
+ """Return the current demo risk."""
 
 
 
 
 
 
 
 
 
 
 
 
74
  intent = _DemoIntent()
 
75
  risk_value, explanation, contributions = risk_engine.calculate_risk(
76
  intent=intent,
77
  cost_estimate=None,
78
  policy_violations=[],
79
  )
 
80
  decision = "approve"
81
  if risk_value > 0.8:
82
  decision = "deny"
 
84
  decision = "escalate"
85
 
86
  decision_id = str(uuid.uuid4())
87
+ decision_history.append({
88
+ "decision_id": decision_id,
 
89
  "timestamp": datetime.now(timezone.utc).isoformat(),
90
+ "risk_score": float(risk_value),
91
+ "outcome": None, # will be filled when feedback is given
92
+ })
 
 
 
 
 
 
 
 
 
93
 
94
  return {
95
+ "system_risk": float(risk_value),
96
  "status": "critical" if risk_value > 0.8 else "normal",
97
  "explanation": explanation,
98
  "contributions": contributions,
99
  "decision_id": decision_id,
100
+ "decision": decision,
101
+ "timestamp": datetime.now(timezone.utc).isoformat()
102
  }
103
 
104
+ @app.get("/api/v1/history")
105
+ async def get_history():
106
+ """Return the last 10 decisions."""
107
+ return decision_history[-10:]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
+ @app.post("/api/v1/incidents/evaluate", response_model=EvaluateResponse)
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
+ # For now, return a dummy response
116
+ return EvaluateResponse(
117
+ risk_score=0.23,
118
+ base_risk=0.15,
119
+ memory_risk=0.3,
120
+ weight=0.5,
121
+ similar_events=[],
122
+ confidence=0.9
123
+ )
124
 
125
+ @app.post("/api/v1/feedback")
126
+ async def record_outcome(decision_id: str, success: bool):
127
+ """Record the outcome of a decision (success/failure)."""
128
+ for dec in decision_history:
129
+ if dec["decision_id"] == decision_id:
130
+ dec["outcome"] = "success" if success else "failure"
131
+ # Update the risk engine (optional)
132
+ intent = _DemoIntent()
133
+ try:
134
+ risk_engine.update_outcome(intent, success)
135
+ except Exception as e:
136
+ logger.exception("Outcome update failed")
137
+ return {"status": "ok", "decision_id": decision_id, "outcome": dec["outcome"]}
138
+ return {"error": "decision not found"}
139
+
140
+ # ========================= GRADIO UI (Optional) =========================
141
+ # This mounts the Gradio interface at the root path ("/").
142
 
143
  def get_risk_snapshot():
 
144
  try:
145
+ intent = _DemoIntent()
146
+ risk_value, explanation, contributions = risk_engine.calculate_risk(
147
+ intent=intent,
148
+ cost_estimate=None,
149
+ policy_violations=[],
150
+ )
151
+ decision = "approve"
152
+ if risk_value > 0.8:
153
+ decision = "deny"
154
+ elif risk_value > 0.2:
155
+ decision = "escalate"
156
+ decision_id = str(uuid.uuid4())
157
+ decision_history.append({
158
+ "decision_id": decision_id,
159
  "timestamp": datetime.now(timezone.utc).isoformat(),
160
+ "risk_score": float(risk_value),
161
+ "outcome": None,
162
+ })
163
+ return {
164
+ "risk": float(risk_value),
165
+ "status": "critical" if risk_value > 0.8 else "normal",
166
+ "explanation": explanation,
167
+ "contributions": contributions,
168
+ "decision_id": decision_id,
169
+ "decision": decision,
170
+ "timestamp": datetime.now(timezone.utc).isoformat()
171
  }
172
+ except Exception as e:
173
+ logger.exception("Failed to compute risk snapshot")
174
+ return {"error": str(e)}
175
 
176
  def get_health_snapshot():
177
+ return {"status": "ok", "version": "4.0.0", "service": "ARF OSS API", "timestamp": datetime.now(timezone.utc).isoformat()}
 
 
 
 
 
 
178
 
179
  def get_memory_snapshot():
180
+ if memory.has_historical_data():
181
+ return {"status": "ok", "memory_stats": memory.get_graph_stats(), "timestamp": datetime.now(timezone.utc).isoformat()}
182
+ return {"status": "empty", "memory_stats": "No historical memory yet.", "timestamp": datetime.now(timezone.utc).isoformat()}
183
 
184
+ def record_outcome_ui(success: bool):
185
+ if not decision_history:
186
+ return {"error": "no decisions yet"}
187
+ last = decision_history[-1]
188
+ last["outcome"] = "success" if success else "failure"
189
+ intent = _DemoIntent()
190
  try:
191
+ risk_engine.update_outcome(intent, success)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  except Exception as e:
193
+ logger.exception("Outcome update failed")
194
+ return {"decision_id": last["decision_id"], "outcome": last["outcome"], "timestamp": datetime.now(timezone.utc).isoformat()}
 
 
 
 
 
 
 
 
 
 
 
 
 
195
 
196
  with gr.Blocks(title="ARF v4 Demo") as demo:
197
+ gr.Markdown("# Agentic Reliability Framework v4\n### Probabilistic Infrastructure Governance")
 
 
 
198
  with gr.Row():
199
  health_output = gr.JSON(label="Health")
200
  risk_output = gr.JSON(label="Current Risk")
 
201
  with gr.Row():
202
  memory_output = gr.JSON(label="Memory Stats")
 
203
  with gr.Row():
204
  decision_output = gr.JSON(label="Recent Decisions")
 
205
  with gr.Row():
206
  refresh_btn = gr.Button("Evaluate Intent")
207
  success_btn = gr.Button("Action Succeeded")
208
  fail_btn = gr.Button("Action Failed")
 
209
  refresh_btn.click(fn=get_risk_snapshot, outputs=risk_output)
210
+ success_btn.click(fn=lambda: record_outcome_ui(True), outputs=decision_output)
211
+ fail_btn.click(fn=lambda: record_outcome_ui(False), outputs=decision_output)
 
212
  with gr.Row():
213
  health_btn = gr.Button("Refresh Health")
214
  memory_btn = gr.Button("Refresh Memory")
215
  history_btn = gr.Button("Show Decision History")
 
216
  health_btn.click(fn=get_health_snapshot, outputs=health_output)
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 Gradio app at the root path
221
+ app = gr.mount_gradio_app(app, demo, path="/")