petter2025 commited on
Commit
6c7e606
·
verified ·
1 Parent(s): 5d40d5d

Rename hf_demo.py to app.py

Browse files
Files changed (2) hide show
  1. app.py +304 -0
  2. hf_demo.py +0 -1249
app.py ADDED
@@ -0,0 +1,304 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Enterprise-Grade FastAPI Backend for ARF OSS Demo
3
+ Uses real ARF components, no simulation
4
+ """
5
+ from fastapi import FastAPI, HTTPException, Depends
6
+ from fastapi.middleware.cors import CORSMiddleware
7
+ from pydantic import BaseModel, Field
8
+ from typing import Optional, List, Dict, Any
9
+ import uuid
10
+ from datetime import datetime
11
+ import logging
12
+
13
+ # Real ARF OSS imports
14
+ from agentic_reliability_framework.engine import (
15
+ v3_reliability,
16
+ healing_policies,
17
+ mcp_client,
18
+ business
19
+ )
20
+ from agentic_reliability_framework.memory import rag_graph
21
+
22
+ from arf_orchestrator import ARFOrchestrator
23
+ from memory_store import ARFMemoryStore
24
+
25
+ # Configure logging
26
+ logging.basicConfig(level=logging.INFO)
27
+ logger = logging.getLogger(__name__)
28
+
29
+ # Initialize FastAPI
30
+ app = FastAPI(
31
+ title="ARF OSS Real Engine",
32
+ version="3.3.9",
33
+ description="Real ARF OSS backend - Bayesian risk, RAG memory, MCP client"
34
+ )
35
+
36
+ # CORS for Replit UI
37
+ app.add_middleware(
38
+ CORSMiddleware,
39
+ allow_origins=["*"], # Replit domains will be added
40
+ allow_credentials=True,
41
+ allow_methods=["*"],
42
+ allow_headers=["*"],
43
+ )
44
+
45
+ # ============== PYDANTIC MODELS ==============
46
+ # Match Replit UI exactly
47
+
48
+ class ActionRequest(BaseModel):
49
+ """Matches Replit UI's action structure"""
50
+ id: Optional[int] = None
51
+ incidentId: Optional[int] = None
52
+ description: str = Field(..., description="Human-readable description")
53
+ proposedAction: str = Field(..., description="Actual command")
54
+ confidenceScore: float = Field(..., ge=0.0, le=1.0)
55
+ riskLevel: str = Field(..., regex="^(LOW|MEDIUM|HIGH|CRITICAL)$")
56
+ requiredLevel: Optional[str] = None
57
+ requiresHuman: bool = False
58
+ rollbackFeasible: bool = True
59
+ metadata: Optional[Dict[str, Any]] = None
60
+
61
+ class ConfigUpdateRequest(BaseModel):
62
+ confidenceThreshold: Optional[float] = Field(None, ge=0.5, le=1.0)
63
+ maxAutonomousRisk: Optional[str] = Field(None, regex="^(LOW|MEDIUM|HIGH|CRITICAL)$")
64
+ riskScoreThresholds: Optional[Dict[str, float]] = None
65
+
66
+ class GateResult(BaseModel):
67
+ """Matches Replit UI's gate display"""
68
+ gate: str
69
+ reason: str
70
+ passed: bool
71
+ threshold: Optional[float] = None
72
+ actual: Optional[float] = None
73
+ metadata: Optional[Dict[str, Any]] = None
74
+
75
+ class EvaluationResponse(BaseModel):
76
+ """Matches Replit UI's expected response"""
77
+ allowed: bool
78
+ requiredLevel: str
79
+ gatesTriggered: List[GateResult]
80
+ shouldEscalate: bool
81
+ escalationReason: Optional[str] = None
82
+ executionLadder: Optional[Dict[str, Any]] = None
83
+
84
+ # ============== INITIALIZE REAL ARF ==============
85
+ arf = ARFOrchestrator()
86
+ memory = ARFMemoryStore() # Light persistence with RAG
87
+
88
+ # ============== API ENDPOINTS ==============
89
+
90
+ @app.get("/api/v1/config")
91
+ async def get_config():
92
+ """Get current ARF configuration - real OSS config"""
93
+ return {
94
+ "confidenceThreshold": arf.policy_engine.config.confidence_threshold,
95
+ "maxAutonomousRisk": arf.policy_engine.config.max_autonomous_risk,
96
+ "riskScoreThresholds": arf.policy_engine.config.risk_thresholds
97
+ }
98
+
99
+ @app.post("/api/v1/config")
100
+ async def update_config(config: ConfigUpdateRequest):
101
+ """Update ARF configuration - live updates"""
102
+ try:
103
+ if config.confidenceThreshold:
104
+ arf.policy_engine.update_confidence_threshold(config.confidenceThreshold)
105
+
106
+ if config.maxAutonomousRisk:
107
+ arf.policy_engine.update_max_risk(config.maxAutonomousRisk)
108
+
109
+ # Log config change for audit
110
+ logger.info(f"Config updated: {config.dict(exclude_unset=True)}")
111
+
112
+ return await get_config()
113
+ except Exception as e:
114
+ logger.error(f"Config update failed: {e}")
115
+ raise HTTPException(status_code=400, detail=str(e))
116
+
117
+ @app.post("/api/v1/evaluate")
118
+ async def evaluate_action(action: ActionRequest):
119
+ """
120
+ Real ARF OSS evaluation pipeline
121
+ Used by Replit UI's ARFPlayground component
122
+ """
123
+ try:
124
+ start_time = datetime.utcnow()
125
+
126
+ # 1. Bayesian risk assessment (real)
127
+ risk_assessment = arf.risk_engine.assess(
128
+ action_text=action.proposedAction,
129
+ context={
130
+ "description": action.description,
131
+ "risk_level": action.riskLevel,
132
+ "requires_human": action.requiresHuman,
133
+ "rollback_feasible": action.rollbackFeasible
134
+ }
135
+ )
136
+
137
+ # 2. MCP client check (real)
138
+ mcp_result = await arf.mcp_client.evaluate(
139
+ action=action.proposedAction,
140
+ risk_score=risk_assessment.score,
141
+ confidence=action.confidenceScore
142
+ )
143
+
144
+ # 3. Policy evaluation (real OSS - advisory)
145
+ policy_result = arf.policy_engine.evaluate(
146
+ action=action.proposedAction,
147
+ risk_assessment=risk_assessment,
148
+ confidence=action.confidenceScore,
149
+ mode="advisory" # OSS mode
150
+ )
151
+
152
+ # 4. RAG memory recall (light persistence)
153
+ similar_incidents = memory.find_similar(
154
+ action=action.proposedAction,
155
+ risk_score=risk_assessment.score,
156
+ limit=5
157
+ )
158
+
159
+ # 5. Build gate results for Replit UI
160
+ gates = [
161
+ GateResult(
162
+ gate="confidence_threshold",
163
+ reason=f"Confidence {action.confidenceScore:.2f} meets threshold {arf.policy_engine.config.confidence_threshold}"
164
+ if action.confidenceScore >= arf.policy_engine.config.confidence_threshold
165
+ else f"Confidence {action.confidenceScore:.2f} below threshold {arf.policy_engine.config.confidence_threshold}",
166
+ passed=action.confidenceScore >= arf.policy_engine.config.confidence_threshold,
167
+ threshold=arf.policy_engine.config.confidence_threshold,
168
+ actual=action.confidenceScore
169
+ ),
170
+ GateResult(
171
+ gate="risk_assessment",
172
+ reason=f"Risk level {action.riskLevel} within autonomous range (≤ {arf.policy_engine.config.max_autonomous_risk})"
173
+ if arf._risk_level_allowed(action.riskLevel)
174
+ else f"Risk level {action.riskLevel} exceeds autonomous threshold",
175
+ passed=arf._risk_level_allowed(action.riskLevel),
176
+ metadata={
177
+ "maxAutonomousRisk": arf.policy_engine.config.max_autonomous_risk,
178
+ "actionRisk": action.riskLevel
179
+ }
180
+ ),
181
+ GateResult(
182
+ gate="rollback_feasibility",
183
+ reason="Non-destructive operation" if not arf._is_destructive(action.proposedAction)
184
+ else "Has rollback plan" if action.rollbackFeasible
185
+ else "Destructive operation lacks rollback plan",
186
+ passed=not arf._is_destructive(action.proposedAction) or action.rollbackFeasible,
187
+ metadata={
188
+ "isDestructive": arf._is_destructive(action.proposedAction),
189
+ "requiresRollback": arf._is_destructive(action.proposedAction)
190
+ }
191
+ ),
192
+ GateResult(
193
+ gate="human_review",
194
+ reason="Human review not required" if not action.requiresHuman
195
+ else "Human review required by policy",
196
+ passed=not action.requiresHuman,
197
+ metadata={"policyRequiresHuman": action.requiresHuman}
198
+ ),
199
+ GateResult(
200
+ gate="license_check",
201
+ reason="OSS edition - advisory only",
202
+ passed=True, # OSS always passes license check
203
+ metadata={"licenseSensitive": False, "edition": "OSS"}
204
+ )
205
+ ]
206
+
207
+ # Add MCP result as gate
208
+ if mcp_result:
209
+ gates.append(GateResult(
210
+ gate="mcp_validation",
211
+ reason=mcp_result.reason,
212
+ passed=mcp_result.passed,
213
+ metadata=mcp_result.metadata
214
+ ))
215
+
216
+ # Add novel action check if similar incidents exist
217
+ if similar_incidents and len(similar_incidents) < 2:
218
+ gates.append(GateResult(
219
+ gate="novel_action_review",
220
+ reason="Action pattern rarely seen in historical data",
221
+ passed=False,
222
+ metadata={"similar_count": len(similar_incidents)}
223
+ ))
224
+
225
+ # Determine final decision
226
+ all_passed = all(g.passed for g in gates)
227
+
228
+ # Store in memory for future recall
229
+ memory.store_evaluation(
230
+ action=action.proposedAction,
231
+ risk_score=risk_assessment.score,
232
+ gates=gates,
233
+ allowed=all_passed,
234
+ timestamp=start_time
235
+ )
236
+
237
+ # Log for lead scoring
238
+ logger.info(f"Evaluation complete: action={action.description[:30]}..., allowed={all_passed}")
239
+
240
+ # Track enterprise interest signals
241
+ if not all_passed and any(g.gate == "novel_action_review" for g in gates if not g.passed):
242
+ # Novel action that would need Enterprise review board
243
+ memory.track_enterprise_signal("novel_action", action.proposedAction)
244
+ elif risk_assessment.score > 0.8 and not all_passed:
245
+ memory.track_enterprise_signal("high_risk_blocked", action.proposedAction)
246
+
247
+ return EvaluationResponse(
248
+ allowed=all_passed,
249
+ requiredLevel=arf._determine_required_level(all_passed, action.riskLevel),
250
+ gatesTriggered=gates,
251
+ shouldEscalate=not all_passed,
252
+ escalationReason=None if all_passed else "Failed mechanical gates",
253
+ executionLadder=arf._build_execution_ladder(gates)
254
+ )
255
+
256
+ except Exception as e:
257
+ logger.error(f"Evaluation failed: {e}", exc_info=True)
258
+ raise HTTPException(status_code=500, detail=str(e))
259
+
260
+ @app.get("/api/v1/memory/similar")
261
+ async def get_similar_actions(action: str, limit: int = 5):
262
+ """RAG memory recall - similar historical evaluations"""
263
+ return memory.find_similar(action, limit=limit)
264
+
265
+ @app.get("/api/v1/audit/stream")
266
+ async def get_audit_logs(limit: int = 50):
267
+ """Audit stream for Replit UI"""
268
+ return memory.get_recent_logs(limit)
269
+
270
+ @app.post("/api/v1/process")
271
+ async def process_action(action: ActionRequest):
272
+ """
273
+ Full ARF pipeline with MCP
274
+ Still advisory only in OSS
275
+ """
276
+ evaluation = await evaluate_action(action)
277
+
278
+ # In OSS, always advisory
279
+ return {
280
+ "evaluation": evaluation.dict(),
281
+ "execution": {
282
+ "status": "advisory_only",
283
+ "message": "OSS edition provides advisory only. Enterprise adds execution.",
284
+ "would_execute": evaluation.allowed and not evaluation.shouldEscalate
285
+ },
286
+ "next_steps": {
287
+ "enterprise_demo": "https://calendly.com/petter2025us/arf-demo" if evaluation.allowed else None
288
+ }
289
+ }
290
+
291
+ @app.get("/api/v1/enterprise/signals")
292
+ async def get_enterprise_signals():
293
+ """Lead intelligence - actions that indicate Enterprise need"""
294
+ return memory.get_enterprise_signals()
295
+
296
+ # Health check
297
+ @app.get("/health")
298
+ async def health_check():
299
+ return {
300
+ "status": "healthy",
301
+ "arf_version": "3.3.9",
302
+ "oss_mode": True,
303
+ "memory_enabled": memory.is_enabled
304
+ }
hf_demo.py DELETED
@@ -1,1249 +0,0 @@
1
- # COMPLETE FIXED hf_demo.py with Gradio 4.x for Hugging Face Spaces
2
- # ARF 3.3.9 DEMO WITH PROPER HUGGING FACE SPACES COMPATIBILITY
3
-
4
- import gradio as gr
5
- import time
6
- import random
7
- import json
8
- import uuid
9
- import subprocess
10
- import sys
11
- import importlib
12
- import os
13
- import threading
14
- import socket
15
- from datetime import datetime, timedelta
16
- from typing import Dict, List, Optional, Tuple, Any, Union
17
- import numpy as np
18
-
19
- # ============== FASTAPI INTEGRATION ==============
20
- try:
21
- from fastapi import FastAPI, HTTPException
22
- from fastapi.middleware.cors import CORSMiddleware
23
- from pydantic import BaseModel, Field
24
- from gradio import mount_gradio_app
25
- from typing import Optional
26
- FASTAPI_AVAILABLE = True
27
- print("✅ FastAPI available")
28
- except ImportError as e:
29
- print(f"⚠️ FastAPI not available: {e}")
30
- FASTAPI_AVAILABLE = False
31
-
32
- # Create dummy classes if FastAPI not installed
33
- class BaseModel:
34
- def dict(self): return {}
35
- class FastAPI: pass
36
- class HTTPException(Exception): pass
37
- class CORSMiddleware: pass
38
- def Field(*args, **kwargs): return None
39
- Optional = lambda x: x
40
-
41
- if FASTAPI_AVAILABLE:
42
- # Create FastAPI app
43
- api_app = FastAPI(title="ARF Mathematical Engine", version="3.3.9")
44
-
45
- # Add CORS middleware
46
- api_app.add_middleware(
47
- CORSMiddleware,
48
- allow_origins=["*"], # In production, restrict to your Replit domain
49
- allow_credentials=True,
50
- allow_methods=["*"],
51
- allow_headers=["*"],
52
- )
53
-
54
- # ============== IN-MEMORY CONFIGURATION STORAGE ==============
55
- # This is the key fix - persistent storage for config
56
- current_config = {
57
- "confidenceThreshold": 0.9,
58
- "maxAutonomousRisk": "MEDIUM",
59
- "riskScoreThresholds": {
60
- "LOW": 0.7,
61
- "MEDIUM": 0.5,
62
- "HIGH": 0.3,
63
- "CRITICAL": 0.1
64
- }
65
- }
66
-
67
- # Define Pydantic models
68
- class ActionEvaluationRequest(BaseModel):
69
- proposed_action: str = Field(..., description="The command the AI wants to execute")
70
- confidence_score: float = Field(..., ge=0.0, le=1.0, description="AI confidence score")
71
- risk_level: str = Field(..., description="Risk level (LOW/MEDIUM/HIGH/CRITICAL)")
72
- requires_human: bool = Field(..., description="Whether action requires human oversight")
73
- rollback_feasible: bool = Field(..., description="Whether action can be rolled back")
74
- description: Optional[str] = Field(None, description="Optional action description")
75
- incident_id: Optional[int] = Field(None, description="Optional incident ID")
76
-
77
- class GateEvaluationResponse(BaseModel):
78
- gate: str
79
- reason: str
80
- passed: bool
81
- threshold: Optional[float] = None
82
- actual: Optional[float] = None
83
- metadata: Optional[dict] = None
84
-
85
- class ActionEvaluationResponse(BaseModel):
86
- allowed: bool
87
- required_level: str
88
- gates_triggered: list[GateEvaluationResponse]
89
- should_escalate: bool
90
- escalation_reason: Optional[str] = None
91
-
92
- class ConfigResponse(BaseModel):
93
- confidenceThreshold: float
94
- maxAutonomousRisk: str
95
- riskScoreThresholds: dict
96
-
97
- class ConfigUpdateRequest(BaseModel):
98
- confidenceThreshold: Optional[float] = Field(None, ge=0.5, le=1.0)
99
- maxAutonomousRisk: Optional[str] = Field(None, pattern="^(LOW|MEDIUM|HIGH|CRITICAL)$")
100
-
101
- # ============== CONFIGURATION ENDPOINTS ==============
102
-
103
- @api_app.get("/api/v1/config", response_model=ConfigResponse)
104
- async def get_config():
105
- """Get current ARF configuration"""
106
- print(f"📊 GET /api/v1/config -> {current_config}")
107
- return current_config
108
-
109
- @api_app.post("/api/v1/config", response_model=ConfigResponse)
110
- async def update_config(config_update: ConfigUpdateRequest):
111
- """Update ARF configuration"""
112
- global current_config
113
- print(f"🔄 POST /api/v1/config with: {config_update}")
114
-
115
- # Update only the fields that were sent
116
- if config_update.confidenceThreshold is not None:
117
- current_config["confidenceThreshold"] = config_update.confidenceThreshold
118
- print(f" Updated confidenceThreshold to {config_update.confidenceThreshold}")
119
-
120
- if config_update.maxAutonomousRisk is not None:
121
- current_config["maxAutonomousRisk"] = config_update.maxAutonomousRisk
122
- print(f" Updated maxAutonomousRisk to {config_update.maxAutonomousRisk}")
123
-
124
- print(f"✅ New config: {current_config}")
125
- return current_config
126
-
127
- # ============== EVALUATION ENDPOINTS ==============
128
-
129
- @api_app.post("/api/v1/evaluate", response_model=ActionEvaluationResponse)
130
- async def evaluate_action(request: ActionEvaluationRequest):
131
- """Evaluate an action using mathematical Bayesian assessment"""
132
- try:
133
- print(f"🔍 Evaluating action: {request.proposed_action}")
134
- print(f" Using config: confidence={current_config['confidenceThreshold']}, maxRisk={current_config['maxAutonomousRisk']}")
135
-
136
- gates = []
137
-
138
- # Confidence gate - using current_config
139
- confidence_passed = request.confidence_score >= current_config["confidenceThreshold"]
140
- gates.append(GateEvaluationResponse(
141
- gate="confidence_threshold",
142
- reason=f"Confidence {request.confidence_score:.2f} meets threshold {current_config['confidenceThreshold']}" if confidence_passed
143
- else f"Confidence {request.confidence_score:.2f} below threshold {current_config['confidenceThreshold']}",
144
- passed=confidence_passed,
145
- threshold=current_config["confidenceThreshold"],
146
- actual=request.confidence_score
147
- ))
148
-
149
- # Risk gate - using current_config
150
- risk_levels = ["LOW", "MEDIUM", "HIGH", "CRITICAL"]
151
- max_risk_index = risk_levels.index(current_config["maxAutonomousRisk"])
152
- action_risk_index = risk_levels.index(request.risk_level)
153
- risk_passed = action_risk_index <= max_risk_index
154
-
155
- gates.append(GateEvaluationResponse(
156
- gate="risk_assessment",
157
- reason=f"Risk level {request.risk_level} within autonomous range (≤ {current_config['maxAutonomousRisk']})" if risk_passed
158
- else f"Risk level {request.risk_level} exceeds autonomous threshold (max: {current_config['maxAutonomousRisk']})",
159
- passed=risk_passed,
160
- metadata={"maxAutonomousRisk": current_config["maxAutonomousRisk"], "actionRisk": request.risk_level}
161
- ))
162
-
163
- # Rollback gate
164
- destructive_keywords = ['delete', 'drop', 'terminate', 'remove', 'destroy']
165
- is_destructive = any(keyword in request.proposed_action.lower() for keyword in destructive_keywords)
166
- rollback_passed = not is_destructive or request.rollback_feasible
167
- gates.append(GateEvaluationResponse(
168
- gate="rollback_feasibility",
169
- reason="Non-destructive operation" if not is_destructive
170
- else "Has rollback plan" if request.rollback_feasible
171
- else "Destructive operation lacks rollback plan",
172
- passed=rollback_passed,
173
- metadata={"isDestructive": is_destructive, "requiresRollback": is_destructive}
174
- ))
175
-
176
- # Human review gate
177
- human_passed = not request.requires_human
178
- gates.append(GateEvaluationResponse(
179
- gate="human_review",
180
- reason="Human review not required" if human_passed else "Human review required by policy",
181
- passed=human_passed,
182
- metadata={"policyRequiresHuman": request.requires_human}
183
- ))
184
-
185
- # License gate (always passes in this simulation)
186
- gates.append(GateEvaluationResponse(
187
- gate="license_check",
188
- reason="No license violations detected",
189
- passed=True,
190
- metadata={"licenseSensitive": False}
191
- ))
192
-
193
- all_passed = all(g.passed for g in gates)
194
-
195
- # Determine required level based on gates and config
196
- if all_passed:
197
- if request.risk_level == "LOW":
198
- required_level = "AUTONOMOUS_LOW"
199
- elif request.risk_level == "MEDIUM":
200
- required_level = "AUTONOMOUS_HIGH"
201
- else:
202
- required_level = "SUPERVISED"
203
- else:
204
- required_level = "OPERATOR_REVIEW"
205
-
206
- result = ActionEvaluationResponse(
207
- allowed=all_passed,
208
- required_level=required_level,
209
- gates_triggered=gates,
210
- should_escalate=not all_passed,
211
- escalation_reason=None if all_passed else "Failed critical gates"
212
- )
213
-
214
- print(f"✅ Evaluation complete: allowed={result.allowed}, required_level={result.required_level}")
215
- return result
216
-
217
- except Exception as e:
218
- print(f"❌ Evaluation error: {e}")
219
- raise HTTPException(status_code=500, detail=str(e))
220
-
221
- @api_app.post("/api/v1/process")
222
- async def process_action(request: ActionEvaluationRequest):
223
- """Process action through full ARF pipeline"""
224
- print(f"⚙️ Processing action: {request.proposed_action}")
225
- evaluation = await evaluate_action(request)
226
-
227
- # Determine final status based on evaluation
228
- if evaluation.allowed and not evaluation.should_escalate:
229
- final_status = "executed"
230
- elif evaluation.should_escalate:
231
- final_status = "needs_approval"
232
- else:
233
- final_status = "blocked"
234
-
235
- result = {
236
- "action": request.dict(),
237
- "evaluation": evaluation.dict(),
238
- "finalStatus": final_status
239
- }
240
- print(f"✅ Process complete: {final_status}")
241
- return result
242
-
243
- @api_app.post("/api/v1/simulate")
244
- async def simulate_action(request: ActionEvaluationRequest, config: dict = None):
245
- """Simulate action with temporary configuration"""
246
- print(f"🎮 Simulating action with custom config: {config}")
247
- evaluation = await evaluate_action(request)
248
- return evaluation
249
-
250
- print("\n" + "="*80)
251
- print("✅ FASTAPI ENDPOINTS CONFIGURED")
252
- print("="*80)
253
- print(" 📍 GET /api/v1/config")
254
- print(" 📍 POST /api/v1/config")
255
- print(" 📍 POST /api/v1/evaluate")
256
- print(" 📍 POST /api/v1/process")
257
- print(" 📍 POST /api/v1/simulate")
258
- print("="*80 + "\n")
259
-
260
- # ============== HUGGING FACE SPACES DETECTION ==============
261
- def is_huggingface_spaces():
262
- """Detect if running in Hugging Face Spaces environment"""
263
- return os.environ.get('SPACE_ID') is not None or \
264
- os.environ.get('HF_SPACE') is not None or \
265
- os.environ.get('SYSTEM') == 'spaces' or \
266
- os.path.exists('/.dockerenv') and 'space' in os.environ.get('HOSTNAME', '')
267
-
268
- # Set environment variables for Hugging Face Spaces
269
- if is_huggingface_spaces():
270
- os.environ['GRADIO_ANALYTICS_ENABLED'] = 'False'
271
- os.environ['GRADIO_SERVER_NAME'] = '0.0.0.0'
272
- os.environ['GRADIO_SERVER_PORT'] = '7860'
273
-
274
- # Import enhanced engines
275
- try:
276
- from utils.arf_engine_enhanced import EnhancedARFEngine, BayesianRiskAssessment, RiskCategory
277
- from utils.psychology_layer_enhanced import EnhancedPsychologyEngine
278
- ARF_ENGINE_ENHANCED = True
279
- print("✅ Enhanced ARF Engine loaded successfully")
280
- except ImportError as e:
281
- print(f"⚠️ Enhanced engines not available: {e}")
282
- print("📝 Creating fallback engines...")
283
- ARF_ENGINE_ENHANCED = False
284
-
285
- # Fallback classes
286
- class EnhancedARFEngine:
287
- def __init__(self):
288
- self.arf_status = "SIMULATION"
289
-
290
- def assess_action(self, action, context, license_key):
291
- return {
292
- "risk_assessment": {"score": 0.5, "confidence": 0.8},
293
- "recommendation": "Simulated assessment",
294
- "arf_status": "SIMULATION"
295
- }
296
-
297
- class EnhancedPsychologyEngine:
298
- def generate_comprehensive_insights(self, *args, **kwargs):
299
- return {"psychological_summary": "Basic psychological framing"}
300
-
301
- # ============== UNIFIED ARF DETECTION ==============
302
- print("=" * 80)
303
- print("🚀 ARF 3.3.9 ENHANCED DEMO INITIALIZATION")
304
- print("🔍 UNIFIED DETECTION: Single Source of Truth")
305
- print("=" * 80)
306
-
307
- def detect_unified_arf() -> Dict[str, Any]:
308
- """Unified ARF detection that correctly shows REAL OSS when installed"""
309
- print("\n🔍 INITIATING UNIFIED ARF DETECTION...")
310
-
311
- # Try REAL ARF OSS 3.3.9 first
312
- try:
313
- print("🔍 Attempting import: agentic_reliability_framework")
314
- import agentic_reliability_framework as arf
315
-
316
- version = getattr(arf, '__version__', '3.3.9')
317
- print(f"✅ REAL ARF OSS {version} DETECTED")
318
-
319
- return {
320
- 'status': 'REAL_OSS',
321
- 'is_real': True,
322
- 'version': version,
323
- 'source': 'agentic_reliability_framework',
324
- 'display_text': f'✅ REAL OSS {version}',
325
- 'badge_class': 'arf-real-badge',
326
- 'badge_css': 'arf-real',
327
- 'unified_truth': True,
328
- 'enterprise_ready': True
329
- }
330
-
331
- except ImportError:
332
- print("⚠️ agentic_reliability_framework not directly importable")
333
-
334
- # Try pip installation check
335
- try:
336
- print("🔍 Checking pip installation...")
337
- result = subprocess.run(
338
- [sys.executable, "-m", "pip", "show", "agentic-reliability-framework"],
339
- capture_output=True,
340
- text=True,
341
- timeout=5
342
- )
343
-
344
- if result.returncode == 0:
345
- version = "3.3.9"
346
- for line in result.stdout.split('\n'):
347
- if line.startswith('Version:'):
348
- version = line.split(':')[1].strip()
349
-
350
- print(f"✅ ARF {version} installed via pip")
351
-
352
- return {
353
- 'status': 'PIP_INSTALLED',
354
- 'is_real': True,
355
- 'version': version,
356
- 'source': 'pip_installation',
357
- 'display_text': f'✅ REAL OSS {version} (pip)',
358
- 'badge_class': 'arf-real-badge',
359
- 'badge_css': 'arf-real',
360
- 'unified_truth': True,
361
- 'enterprise_ready': True
362
- }
363
-
364
- except Exception as e:
365
- print(f"⚠️ Pip check failed: {e}")
366
-
367
- # Fallback to enhanced simulation
368
- print("⚠️ Using enhanced enterprise simulation")
369
-
370
- return {
371
- 'status': 'ENHANCED_SIMULATION',
372
- 'is_real': False,
373
- 'version': '3.3.9',
374
- 'source': 'enhanced_simulation',
375
- 'display_text': '⚠️ ENTERPRISE SIMULATION 3.3.9',
376
- 'badge_class': 'arf-sim-badge',
377
- 'badge_css': 'arf-sim',
378
- 'unified_truth': True,
379
- 'enterprise_ready': True
380
- }
381
-
382
- # Get unified ARF status
383
- ARF_UNIFIED_STATUS = detect_unified_arf()
384
-
385
- print(f"\n{'='*80}")
386
- print("📊 UNIFIED ARF STATUS CONFIRMED:")
387
- print(f" Display: {ARF_UNIFIED_STATUS['display_text']}")
388
- print(f" Real ARF: {'✅ YES' if ARF_UNIFIED_STATUS['is_real'] else '⚠️ SIMULATION'}")
389
- print(f" Version: {ARF_UNIFIED_STATUS['version']}")
390
- print(f" Source: {ARF_UNIFIED_STATUS['source']}")
391
- print(f"{'='*80}\n")
392
-
393
- # ============== INITIALIZE ENGINES ==============
394
- arf_engine = EnhancedARFEngine()
395
- psychology_engine = EnhancedPsychologyEngine()
396
-
397
- # ============== ENHANCED CSS ==============
398
- ENHANCED_CSS = """
399
- .arf-real-badge {
400
- background: linear-gradient(135deg, #4CAF50, #2E7D32, #1B5E20, #0D47A1);
401
- color: white;
402
- padding: 10px 22px;
403
- border-radius: 25px;
404
- font-size: 16px;
405
- font-weight: bold;
406
- display: inline-flex;
407
- align-items: center;
408
- gap: 10px;
409
- margin: 5px;
410
- box-shadow: 0 6px 20px rgba(76, 175, 80, 0.4);
411
- border: 3px solid rgba(255, 255, 255, 0.4);
412
- animation: pulse-mathematical 2.5s infinite;
413
- }
414
- .arf-sim-badge {
415
- background: linear-gradient(135deg, #FF9800, #F57C00, #E65100, #BF360C);
416
- color: white;
417
- padding: 10px 22px;
418
- border-radius: 25px;
419
- font-size: 16px;
420
- font-weight: bold;
421
- display: inline-flex;
422
- align-items: center;
423
- gap: 10px;
424
- margin: 5px;
425
- box-shadow: 0 6px 20px rgba(255, 152, 0, 0.4);
426
- border: 3px solid rgba(255, 255, 255, 0.4);
427
- }
428
- @keyframes pulse-mathematical {
429
- 0% { box-shadow: 0 0 0 0 rgba(76, 175, 80, 0.7), 0 6px 20px rgba(76, 175, 80, 0.4); }
430
- 70% { box-shadow: 0 0 0 15px rgba(76, 175, 80, 0), 0 6px 20px rgba(76, 175, 80, 0.4); }
431
- 100% { box-shadow: 0 0 0 0 rgba(76, 175, 80, 0), 0 6px 20px rgba(76, 175, 80, 0.4); }
432
- }
433
- .mathematical-gate {
434
- width: 70px;
435
- height: 70px;
436
- border-radius: 50%;
437
- display: flex;
438
- align-items: center;
439
- justify-content: center;
440
- font-weight: bold;
441
- color: white;
442
- font-size: 24px;
443
- position: relative;
444
- box-shadow: 0 8px 25px rgba(0,0,0,0.3);
445
- z-index: 2;
446
- transition: all 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
447
- }
448
- .gate-passed { background: linear-gradient(135deg, #4CAF50, #2E7D32); }
449
- .gate-failed { background: linear-gradient(135deg, #F44336, #D32F2F); }
450
- .gate-pending { background: linear-gradient(135deg, #9E9E9E, #616161); }
451
- .gate-container {
452
- display: flex;
453
- align-items: center;
454
- justify-content: center;
455
- gap: 10px;
456
- margin: 20px 0;
457
- flex-wrap: wrap;
458
- }
459
- .gate-line {
460
- width: 40px;
461
- height: 4px;
462
- background: linear-gradient(90deg, #E0E0E0, #BDBDBD);
463
- border-radius: 2px;
464
- }
465
- .mathematical-card {
466
- border-radius: 15px;
467
- padding: 25px;
468
- margin: 15px 0;
469
- transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
470
- border-top: 6px solid;
471
- position: relative;
472
- overflow: hidden;
473
- background: #FFFFFF;
474
- box-shadow: 0 8px 30px rgba(0,0,0,0.08);
475
- }
476
- .mathematical-card:hover {
477
- transform: translateY(-5px);
478
- box-shadow: 0 15px 40px rgba(0,0,0,0.15);
479
- }
480
- .license-oss {
481
- border-top-color: #1E88E5;
482
- background: linear-gradient(145deg, #E3F2FD, #FFFFFF);
483
- }
484
- .license-trial {
485
- border-top-color: #FFB300;
486
- background: linear-gradient(145deg, #FFF8E1, #FFFFFF);
487
- }
488
- @media (max-width: 768px) {
489
- .gradio-container { padding: 10px !important; }
490
- .arf-real-badge, .arf-sim-badge { padding: 6px 14px; font-size: 12px; }
491
- .mathematical-gate { width: 50px; height: 50px; font-size: 18px; }
492
- .gate-line { width: 20px; }
493
- .mathematical-card { padding: 15px; margin: 10px 0; }
494
- }
495
- @media (max-width: 480px) {
496
- .gradio-container { padding: 5px !important; }
497
- .arf-real-badge, .arf-sim-badge { padding: 4px 10px; font-size: 11px; }
498
- .mathematical-gate { width: 40px; height: 40px; font-size: 16px; }
499
- }
500
- """
501
-
502
- # ============== HELPER FUNCTIONS ==============
503
- def generate_mathematical_trial_license() -> str:
504
- """Generate mathematically structured trial license"""
505
- segments = []
506
- for _ in range(4):
507
- segment = ''.join(random.choices('0123456789ABCDEF', k=4))
508
- segments.append(segment)
509
- return f"ARF-TRIAL-{segments[0]}-{segments[1]}-{segments[2]}-{segments[3]}"
510
-
511
- def format_mathematical_risk(risk_score: float, confidence: float = None) -> str:
512
- """Format risk with mathematical precision"""
513
- if risk_score > 0.8:
514
- color = "#F44336"
515
- emoji = "🚨"
516
- category = "CRITICAL"
517
- elif risk_score > 0.6:
518
- color = "#FF9800"
519
- emoji = "⚠️"
520
- category = "HIGH"
521
- elif risk_score > 0.4:
522
- color = "#FFC107"
523
- emoji = "🔶"
524
- category = "MEDIUM"
525
- else:
526
- color = "#4CAF50"
527
- emoji = "✅"
528
- category = "LOW"
529
-
530
- risk_text = f"{risk_score:.1%}"
531
-
532
- if confidence:
533
- return f'<span style="color: {color}; font-weight: bold;">{emoji} {risk_text} ({category})</span><br><span style="font-size: 0.8em; color: #666;">{confidence:.0%} conf</span>'
534
- else:
535
- return f'<span style="color: {color}; font-weight: bold;">{emoji} {risk_text} ({category})</span>'
536
-
537
- def create_confidence_interval_html(lower: float, upper: float, score: float) -> str:
538
- """Create HTML visualization of confidence interval"""
539
- lower_pct = lower * 100
540
- upper_pct = upper * 100
541
- score_pct = score * 100
542
-
543
- return f"""
544
- <div style="width: 100%; height: 30px; background: linear-gradient(90deg,
545
- rgba(244, 67, 54, 0.3) 0%,
546
- rgba(255, 152, 0, 0.3) 50%,
547
- rgba(76, 175, 80, 0.3) 100%
548
- ); border-radius: 15px; margin: 15px 0; position: relative;">
549
- <div style="position: absolute; left: {lower_pct}%; width: {upper_pct - lower_pct}%; height: 100%;
550
- background: linear-gradient(90deg, rgba(33, 150, 243, 0.6), rgba(33, 150, 243, 0.3));
551
- border-radius: 15px;"></div>
552
- <div style="position: absolute; left: {score_pct}%; height: 100%; width: 4px; background: white;
553
- box-shadow: 0 0 10px rgba(0,0,0,0.5); transform: translateX(-50%);"></div>
554
- </div>
555
- <div style="text-align: center; font-size: 12px; color: #666; margin-top: 5px;">
556
- 95% CI: {lower_pct:.0f}% - {upper_pct:.0f}% | Score: {score_pct:.0f}%
557
- </div>
558
- """
559
-
560
- # ============== DEMO STATE ==============
561
- class EnhancedDemoState:
562
- """Demo state with mathematical tracking"""
563
-
564
- def __init__(self, arf_status: Dict[str, Any]):
565
- self.arf_status = arf_status
566
- self.stats = {
567
- 'actions_tested': 0,
568
- 'start_time': time.time(),
569
- 'real_arf_used': arf_status['is_real'],
570
- 'arf_version': arf_status['version']
571
- }
572
- self.action_history = []
573
- self.license_state = {'current_tier': 'oss'}
574
-
575
- def update_license(self, license_key: Optional[str] = None):
576
- """Update license state"""
577
- if not license_key:
578
- self.license_state = {'current_tier': 'oss'}
579
- return
580
-
581
- license_upper = license_key.upper()
582
-
583
- if 'ARF-TRIAL' in license_upper:
584
- self.license_state = {'current_tier': 'trial'}
585
- elif 'ARF-ENTERPRISE' in license_upper:
586
- self.license_state = {'current_tier': 'enterprise'}
587
- elif 'ARF-PRO' in license_upper:
588
- self.license_state = {'current_tier': 'professional'}
589
- elif 'ARF-STARTER' in license_upper:
590
- self.license_state = {'current_tier': 'starter'}
591
- else:
592
- self.license_state = {'current_tier': 'oss'}
593
-
594
- def add_action(self, action_data: Dict[str, Any]):
595
- """Add action to history"""
596
- self.action_history.insert(0, action_data)
597
- if len(self.action_history) > 10:
598
- self.action_history = self.action_history[:10]
599
- self.stats['actions_tested'] += 1
600
-
601
- # Initialize demo state
602
- demo_state = EnhancedDemoState(ARF_UNIFIED_STATUS)
603
-
604
- # ============== GRADIO INTERFACE ==============
605
- def create_enhanced_demo():
606
- """Create enhanced demo with Gradio 4.x for Hugging Face Spaces compatibility"""
607
-
608
- # Get unified status
609
- arf_display = ARF_UNIFIED_STATUS['display_text']
610
- arf_badge_class = ARF_UNIFIED_STATUS['badge_class']
611
-
612
- # GRADIO 4.x - theme and CSS go in Blocks constructor
613
- with gr.Blocks(
614
- title=f"ARF {ARF_UNIFIED_STATUS['version']} - Mathematical Sophistication",
615
- theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"),
616
- css=ENHANCED_CSS
617
- ) as demo:
618
-
619
- # ===== HEADER =====
620
- gr.HTML(f"""
621
- <div style="background: linear-gradient(135deg, #0D47A1, #1565C0); color: white; padding: 30px; border-radius: 15px; margin-bottom: 30px; box-shadow: 0 10px 30px rgba(13, 71, 161, 0.4); position: relative; overflow: hidden;">
622
- <div style="position: absolute; top: 0; right: 0; width: 300px; height: 300px; background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);"></div>
623
-
624
- <h1 style="margin: 0; font-size: 3em; text-shadow: 0 4px 8px rgba(0,0,0,0.3);">🤖 ARF {ARF_UNIFIED_STATUS['version']}</h1>
625
- <h2 style="margin: 10px 0; font-weight: 300; font-size: 1.6em;">Agentic Reliability Framework</h2>
626
- <h3 style="margin: 5px 0; font-weight: 400; font-size: 1.3em; opacity: 0.95;">
627
- PhD-Level Mathematical Sophistication • Prospect Theory Optimization
628
- </h3>
629
-
630
- <div style="display: flex; justify-content: center; align-items: center; gap: 20px; margin-top: 30px; flex-wrap: wrap;">
631
- <span class="{arf_badge_class}">{arf_display}</span>
632
- <span style="background: linear-gradient(135deg, #9C27B0, #7B1FA2); color: white; padding: 8px 18px; border-radius: 25px; font-size: 14px; font-weight: bold; border: 3px solid rgba(255,255,255,0.3);">
633
- 🤗 Hugging Face Spaces
634
- </span>
635
- <span style="background: linear-gradient(135deg, #2196F3, #0D47A1); color: white; padding: 8px 18px; border-radius: 25px; font-size: 14px; font-weight: bold; border: 3px solid rgba(255,255,255,0.3);">
636
- License-Gated Execution Authority
637
- </span>
638
- </div>
639
-
640
- <p style="text-align: center; margin-top: 25px; font-size: 1.1em; opacity: 0.9; max-width: 900px; margin-left: auto; margin-right: auto; line-height: 1.6;">
641
- <strong>Mathematical Foundation:</strong> Bayesian Inference • Prospect Theory • Confidence Intervals<br>
642
- <strong>Business Model:</strong> License-Gated Execution Authority •
643
- <strong>Market:</strong> Enterprise AI Infrastructure •
644
- <strong>Investor-Ready:</strong> PhD-Level Mathematical Sophistication
645
- </p>
646
- </div>
647
- """)
648
-
649
- # ===== METRICS =====
650
- with gr.Row():
651
- metrics = [
652
- ("92%", "Incident Prevention", "Bayesian confidence: 95%", "#4CAF50", "📊"),
653
- ("$3.9M", "Avg. Breach Cost", "Preventable with mechanical gates", "#2196F3", "💰"),
654
- ("3.2 mo", "Payback Period", "Mathematical ROI calculation", "#FF9800", "📈"),
655
- ("1K+", "Active Developers", "Social proof optimization", "#9C27B0", "👨‍💻")
656
- ]
657
-
658
- for value, title, subtitle, color, icon in metrics:
659
- with gr.Column(scale=1, min_width=200):
660
- gr.HTML(f"""
661
- <div style="text-align: center; padding: 25px; background: #f8f9fa; border-radius: 15px; border-top: 6px solid {color}; box-shadow: 0 8px 25px rgba(0,0,0,0.1); transition: all 0.3s; margin: 10px;">
662
- <div style="font-size: 40px; color: {color}; margin-bottom: 10px; display: flex; align-items: center; justify-content: center; gap: 10px;">
663
- <span style="font-size: 30px;">{icon}</span>
664
- <span style="font-weight: bold;">{value}</span>
665
- </div>
666
- <div style="font-size: 16px; color: #333; font-weight: 600; margin-bottom: 8px;">{title}</div>
667
- <div style="font-size: 13px; color: #666; line-height: 1.4;">{subtitle}</div>
668
- </div>
669
- """)
670
-
671
- # ===== SECTION HEADER =====
672
- gr.HTML("""
673
- <div style="margin: 30px 0 20px 0;">
674
- <h2 style="font-size: 1.8em; color: #0D47A1; margin-bottom: 10px;">🧮 Mathematical Execution Authority Demo</h2>
675
- <p style="color: #666; font-size: 1.05em;">Test how Bayesian risk assessment and mechanical gates prevent unsafe AI actions</p>
676
- </div>
677
- """)
678
-
679
- # ===== CONTROL PANEL =====
680
- with gr.Row():
681
- with gr.Column(scale=2):
682
- scenario = gr.Dropdown(
683
- label="🏢 Select Enterprise Scenario",
684
- choices=[
685
- "DROP DATABASE production",
686
- "DELETE FROM users WHERE status='active'",
687
- "GRANT admin TO new_intern",
688
- "SHUTDOWN production cluster",
689
- "UPDATE financial_records SET balance=0",
690
- "DEPLOY untested_model production"
691
- ],
692
- value="DROP DATABASE production",
693
- interactive=True
694
- )
695
-
696
- context = gr.Textbox(
697
- label="📋 Mathematical Context Analysis",
698
- value="Environment: production, User: junior_dev, Time: 2AM, Backup: 24h old, Compliance: PCI-DSS",
699
- interactive=False
700
- )
701
-
702
- license_key = gr.Textbox(
703
- label="🔐 License Key (Mechanical Gate)",
704
- placeholder="Enter ARF-TRIAL-XXXX for 14-day trial or ARF-ENTERPRISE-XXXX",
705
- value=""
706
- )
707
-
708
- with gr.Row():
709
- test_btn = gr.Button("⚡ Test Mathematical Assessment", variant="primary", scale=2)
710
- trial_btn = gr.Button("🎁 Generate Mathematical Trial", variant="secondary", scale=1)
711
-
712
- # ===== LICENSE DISPLAY =====
713
- with gr.Column(scale=1):
714
- license_display = gr.HTML(f"""
715
- <div class="mathematical-card license-oss">
716
- <h3 style="margin-top: 0; color: #1E88E5; display: flex; align-items: center;">
717
- <span>OSS Edition</span>
718
- <span style="margin-left: auto; font-size: 0.7em; background: #1E88E5; color: white; padding: 4px 12px; border-radius: 15px; box-shadow: 0 3px 10px rgba(30, 136, 229, 0.3);">
719
- Advisory Only
720
- </span>
721
- </h3>
722
- <p style="color: #666; font-size: 0.95em; margin-bottom: 20px; line-height: 1.5;">
723
- ⚠️ <strong>No Mechanical Enforcement</strong><br>
724
- Bayesian risk assessment only
725
- </p>
726
- <div style="background: rgba(30, 136, 229, 0.12); padding: 15px; border-radius: 10px; border-left: 4px solid #1E88E5;">
727
- <div style="font-size: 0.9em; color: #1565C0; line-height: 1.6;">
728
- <strong>Execution Level:</strong> ADVISORY_ONLY<br>
729
- <strong>Risk Prevention:</strong> 0%<br>
730
- <strong>Confidence Threshold:</strong> None<br>
731
- <strong>ARF Status:</strong> {arf_display}
732
- </div>
733
- </div>
734
- </div>
735
- """)
736
-
737
- # ===== RESULTS PANELS =====
738
- with gr.Row():
739
- with gr.Column(scale=1):
740
- oss_results = gr.HTML("""
741
- <div class="mathematical-card license-oss">
742
- <h3 style="margin-top: 0; color: #1E88E5; display: flex; align-items: center;">
743
- <span>OSS Bayesian Assessment</span>
744
- <span style="margin-left: auto; font-size: 0.7em; background: #1E88E5; color: white; padding: 4px 12px; border-radius: 15px;">Advisory</span>
745
- </h3>
746
-
747
- <div style="text-align: center; margin: 30px 0;">
748
- <div style="font-size: 56px; font-weight: bold; color: #1E88E5; margin-bottom: 5px;">--</div>
749
- <div style="font-size: 14px; color: #666; margin-bottom: 15px;">Risk Score (Bayesian)</div>
750
- <div style="margin-top: 10px;"></div>
751
- </div>
752
-
753
- <div style="background: rgba(244, 67, 54, 0.1); padding: 18px; border-radius: 10px; margin: 15px 0; border-left: 5px solid #F44336;">
754
- <strong style="color: #D32F2F; font-size: 1.1em;">🚨 Mathematical Risk Analysis:</strong>
755
- <div style="font-size: 0.95em; color: #666; margin-top: 10px; line-height: 1.6;">
756
- • <strong>$3.9M</strong> expected financial exposure<br>
757
- • <strong>0%</strong> mechanical prevention rate<br>
758
- • <strong>No confidence intervals</strong> for execution
759
- </div>
760
- </div>
761
-
762
- <div style="background: rgba(255, 152, 0, 0.1); padding: 16px; border-radius: 10px; margin-top: 20px;">
763
- <strong style="color: #F57C00; font-size: 1.05em;">📋 Bayesian Recommendation:</strong>
764
- <div style="font-size: 0.95em; margin-top: 8px; line-height: 1.5;">
765
- Awaiting mathematical assessment...
766
- </div>
767
- </div>
768
- </div>
769
- """)
770
-
771
- with gr.Column(scale=1):
772
- enterprise_results = gr.HTML(f"""
773
- <div class="mathematical-card license-trial">
774
- <h3 style="margin-top: 0; color: #FFB300; display: flex; align-items: center;">
775
- <span>Trial Edition</span>
776
- <span style="margin-left: auto; font-size: 0.7em; background: #FFB300; color: white; padding: 4px 12px; border-radius: 15px;">Mechanical</span>
777
- </h3>
778
-
779
- <div style="text-align: center; margin: 30px 0;">
780
- <div style="font-size: 56px; font-weight: bold; color: #FFB300; margin-bottom: 5px;">--</div>
781
- <div style="font-size: 14px; color: #666; margin-bottom: 15px;">Risk Score (Bayesian)</div>
782
- <div style="margin-top: 10px;"></div>
783
- </div>
784
-
785
- <div>
786
- <div style="font-size: 14px; color: #666; margin-bottom: 15px; font-weight: 600;">Mathematical Gates:</div>
787
- <div class="gate-container">
788
- <div class="mathematical-gate gate-pending">1</div>
789
- <div class="gate-line"></div>
790
- <div class="mathematical-gate gate-pending">2</div>
791
- <div class="gate-line"></div>
792
- <div class="mathematical-gate gate-pending">3</div>
793
- </div>
794
- </div>
795
-
796
- <div style="background: rgba(255, 152, 0, 0.1); padding: 18px; border-radius: 10px; margin-top: 25px;">
797
- <strong style="color: #F57C00; font-size: 1.1em;">🛡️ Mechanical Enforcement:</strong>
798
- <div style="font-size: 0.95em; margin-top: 8px; line-height: 1.5;">
799
- Awaiting mathematical assessment...
800
- </div>
801
- </div>
802
- </div>
803
- """)
804
-
805
- # ===== ACTION HISTORY =====
806
- history_display = gr.HTML("""
807
- <div style="border: 1px solid #E0E0E0; border-radius: 15px; padding: 20px; background: #fafafa; box-shadow: 0 8px 30px rgba(0,0,0,0.08); margin-top: 20px;">
808
- <h4 style="margin-top: 0; margin-bottom: 15px; color: #333;">📊 Mathematical Action History</h4>
809
- <div style="overflow-x: auto;">
810
- <div style="text-align: center; padding: 40px; color: #999; font-style: italic;">
811
- No mathematical assessments yet. Test an action to see Bayesian analysis in action.
812
- </div>
813
- </div>
814
- </div>
815
- """)
816
-
817
- # ===== EVENT HANDLERS =====
818
- def update_context(scenario_name):
819
- """Update context with mathematical analysis"""
820
- scenarios = {
821
- "DROP DATABASE production": "Environment: production, User: junior_dev, Time: 2AM, Backup: 24h old, Compliance: PCI-DSS, Risk Multiplier: 1.5x",
822
- "DELETE FROM users WHERE status='active'": "Environment: production, User: admin, Records: 50,000, Backup: none, Business Hours: Yes, Risk Multiplier: 1.3x",
823
- "GRANT admin TO new_intern": "Environment: production, User: team_lead, New User: intern, MFA: false, Approval: Pending, Risk Multiplier: 1.2x",
824
- "SHUTDOWN production cluster": "Environment: production, User: devops, Nodes: 50, Redundancy: none, Business Impact: Critical, Risk Multiplier: 1.8x",
825
- "UPDATE financial_records SET balance=0": "Environment: production, User: finance_bot, Table: financial_records, Audit Trail: Incomplete, Risk Multiplier: 1.4x",
826
- "DEPLOY untested_model production": "Environment: production, User: ml_engineer, Model: untested, Tests: none, Rollback: difficult, Risk Multiplier: 1.6x"
827
- }
828
- return scenarios.get(scenario_name, "Environment: production, Risk Multiplier: 1.0x")
829
-
830
- def test_mathematical_assessment(scenario_name, context_text, license_text):
831
- """Test action with mathematical sophistication"""
832
- start_time = time.time()
833
-
834
- # Update license
835
- demo_state.update_license(license_text)
836
-
837
- # Parse context
838
- context = {}
839
- multipliers = {}
840
- for item in context_text.split(','):
841
- if ':' in item:
842
- key, value = item.split(':', 1)
843
- key = key.strip().lower()
844
- value = value.strip()
845
- context[key] = value
846
-
847
- # Extract multipliers
848
- if 'multiplier' in key:
849
- try:
850
- multipliers[key] = float(value.replace('x', ''))
851
- except:
852
- pass
853
-
854
- # Simulate enhanced assessment
855
- action_lower = scenario_name.lower()
856
-
857
- # Base risk calculation
858
- base_risk = 0.3
859
-
860
- if 'drop database' in action_lower:
861
- base_risk = 0.85
862
- risk_factors = ["Irreversible data destruction", "Service outage", "High financial impact"]
863
- elif 'delete' in action_lower:
864
- base_risk = 0.65
865
- risk_factors = ["Data loss", "Write operation", "Recovery complexity"]
866
- elif 'grant' in action_lower and 'admin' in action_lower:
867
- base_risk = 0.55
868
- risk_factors = ["Privilege escalation", "Security risk", "Access control"]
869
- elif 'shutdown' in action_lower:
870
- base_risk = 0.9
871
- risk_factors = ["Service disruption", "Revenue impact", "Recovery time"]
872
- elif 'update' in action_lower and 'financial' in action_lower:
873
- base_risk = 0.75
874
- risk_factors = ["Financial data", "Audit impact", "Compliance risk"]
875
- elif 'deploy' in action_lower and 'untested' in action_lower:
876
- base_risk = 0.7
877
- risk_factors = ["Untested model", "Production risk", "Rollback difficulty"]
878
- else:
879
- base_risk = 0.45
880
- risk_factors = ["Standard operation", "Moderate risk"]
881
-
882
- # Apply context multipliers
883
- risk_multiplier = 1.0
884
- if context.get('environment') == 'production':
885
- risk_multiplier *= 1.5
886
- if 'junior' in context.get('user', '').lower() or 'intern' in context.get('user', '').lower():
887
- risk_multiplier *= 1.3
888
- if context.get('backup') in ['none', 'none available', 'old']:
889
- risk_multiplier *= 1.6
890
- if '2am' in context.get('time', '').lower() or 'night' in context.get('time', '').lower():
891
- risk_multiplier *= 1.4
892
- if 'pci' in context.get('compliance', '').lower() or 'hipaa' in context.get('compliance', '').lower():
893
- risk_multiplier *= 1.3
894
-
895
- # Apply any explicit multipliers
896
- for mult_key, mult_value in multipliers.items():
897
- risk_multiplier *= mult_value
898
-
899
- final_risk = base_risk * risk_multiplier
900
- final_risk = min(0.99, max(0.1, final_risk))
901
-
902
- # Calculate confidence
903
- confidence = 0.8 + (random.random() * 0.15)
904
-
905
- # Confidence interval
906
- ci_lower = max(0.1, final_risk - (0.2 * (1 - confidence)))
907
- ci_upper = min(1.0, final_risk + (0.2 * (1 - confidence)))
908
-
909
- # Risk category
910
- if final_risk > 0.8:
911
- risk_category = "CRITICAL"
912
- elif final_risk > 0.6:
913
- risk_category = "HIGH"
914
- elif final_risk > 0.4:
915
- risk_category = "MEDIUM"
916
- else:
917
- risk_category = "LOW"
918
-
919
- # Mechanical gates simulation
920
- gates_passed = 0
921
- total_gates = 3
922
-
923
- license_tier = demo_state.license_state['current_tier']
924
-
925
- # Gate 1: Risk Assessment
926
- if final_risk < 0.8:
927
- gates_passed += 1
928
-
929
- # Gate 2: License Validation
930
- if license_tier != 'oss':
931
- gates_passed += 1
932
-
933
- # Gate 3: Context Check
934
- if 'production' not in context.get('environment', '').lower() or final_risk < 0.7:
935
- gates_passed += 1
936
-
937
- # Additional gates for higher tiers
938
- if license_tier == 'professional':
939
- total_gates = 5
940
- if final_risk < 0.6:
941
- gates_passed += 1
942
- if 'backup' not in context or context.get('backup') not in ['none', 'none available']:
943
- gates_passed += 1
944
-
945
- if license_tier == 'enterprise':
946
- total_gates = 7
947
- if final_risk < 0.5:
948
- gates_passed += 1
949
- if context.get('compliance') in ['pci-dss', 'hipaa', 'gdpr']:
950
- gates_passed += 1
951
- if 'approval' in context.get('user', '').lower() or 'senior' in context.get('user', '').lower():
952
- gates_passed += 1
953
-
954
- # Gate decision
955
- if gates_passed == total_gates:
956
- gate_decision = "AUTONOMOUS"
957
- gate_reason = "All mathematical gates passed"
958
- elif gates_passed >= total_gates * 0.7:
959
- gate_decision = "SUPERVISED"
960
- gate_reason = "Most gates passed, requires monitoring"
961
- elif gates_passed >= total_gates * 0.5:
962
- gate_decision = "HUMAN_APPROVAL"
963
- gate_reason = "Requires human review and approval"
964
- else:
965
- gate_decision = "BLOCKED"
966
- gate_reason = "Failed critical mathematical gates"
967
-
968
- # Create action data
969
- action_data = {
970
- 'time': datetime.now().strftime("%H:%M:%S"),
971
- 'action': scenario_name[:40] + "..." if len(scenario_name) > 40 else scenario_name,
972
- 'risk_score': final_risk,
973
- 'confidence': confidence,
974
- 'risk_category': risk_category,
975
- 'license_tier': license_tier.upper(),
976
- 'gates_passed': gates_passed,
977
- 'total_gates': total_gates,
978
- 'gate_decision': gate_decision,
979
- 'processing_time_ms': round((time.time() - start_time) * 1000, 1),
980
- 'arf_status': 'REAL' if ARF_UNIFIED_STATUS['is_real'] else 'SIM'
981
- }
982
-
983
- demo_state.add_action(action_data)
984
-
985
- # Format outputs
986
- risk_formatted = format_mathematical_risk(final_risk, confidence)
987
- confidence_interval_html = create_confidence_interval_html(ci_lower, ci_upper, final_risk)
988
-
989
- # OSS recommendation
990
- if final_risk > 0.8:
991
- oss_rec = "🚨 CRITICAL RISK: Would be mathematically blocked by mechanical gates. Enterprise license required for protection."
992
- elif final_risk > 0.6:
993
- oss_rec = "⚠️ HIGH RISK: Requires Bayesian analysis and human review. Mechanical gates automate this mathematically."
994
- elif final_risk > 0.4:
995
- oss_rec = "🔶 MODERATE RISK: Bayesian confidence suggests review. Mathematical gates provide probabilistic safety."
996
- else:
997
- oss_rec = "✅ LOW RISK: Bayesian analysis indicates safety. Mathematical gates add confidence intervals."
998
-
999
- # Enterprise enforcement
1000
- if gate_decision == "BLOCKED":
1001
- enforcement = f"❌ MATHEMATICALLY BLOCKED: {gate_reason}. Risk factors: {', '.join(risk_factors[:2])}"
1002
- elif gate_decision == "HUMAN_APPROVAL":
1003
- enforcement = f"🔄 MATHEMATICAL REVIEW: {gate_reason}. Bayesian confidence: {confidence:.0%}"
1004
- elif gate_decision == "SUPERVISED":
1005
- enforcement = f"👁️ MATHEMATICAL SUPERVISION: {gate_reason}. Gates passed: {gates_passed}/{total_gates}"
1006
- else:
1007
- enforcement = f"✅ MATHEMATICAL APPROVAL: {gate_reason}. Confidence interval: {ci_lower:.0%}-{ci_upper:.0%}"
1008
-
1009
- # Gate visualization
1010
- gates_visualization = ""
1011
- for i in range(total_gates):
1012
- gate_class = "gate-passed" if i < gates_passed else "gate-failed" if i < 3 else "gate-pending"
1013
- gates_visualization += f'<div class="mathematical-gate {gate_class}">{i+1}</div>'
1014
- if i < total_gates - 1:
1015
- gates_visualization += '<div class="gate-line"></div>'
1016
-
1017
- gates_html = f"""
1018
- <div style="font-size: 14px; color: #666; margin-bottom: 15px; font-weight: 600;">
1019
- Mathematical Gates: {gates_passed}/{total_gates} passed ({(gates_passed/total_gates)*100:.0f}%)
1020
- </div>
1021
- <div class="gate-container">
1022
- {gates_visualization}
1023
- </div>
1024
- """
1025
-
1026
- # Tier info
1027
- tier_data = {
1028
- 'oss': {'color': '#1E88E5', 'bg': '#E3F2FD', 'name': 'OSS Edition'},
1029
- 'trial': {'color': '#FFB300', 'bg': '#FFF8E1', 'name': 'Trial Edition'},
1030
- 'starter': {'color': '#FF9800', 'bg': '#FFF3E0', 'name': 'Starter Edition'},
1031
- 'professional': {'color': '#FF6F00', 'bg': '#FFEBEE', 'name': 'Professional Edition'},
1032
- 'enterprise': {'color': '#D84315', 'bg': '#FBE9E7', 'name': 'Enterprise Edition'}
1033
- }
1034
-
1035
- current_tier = license_tier
1036
- tier_info = tier_data.get(current_tier, tier_data['oss'])
1037
-
1038
- # Update panels
1039
- oss_html = f"""
1040
- <div class="mathematical-card license-oss">
1041
- <h3 style="margin-top: 0; color: #1E88E5; display: flex; align-items: center;">
1042
- <span>OSS Bayesian Assessment</span>
1043
- <span style="margin-left: auto; font-size: 0.7em; background: #1E88E5; color: white; padding: 4px 12px; border-radius: 15px;">Advisory</span>
1044
- </h3>
1045
-
1046
- <div style="text-align: center; margin: 30px 0;">
1047
- <div style="font-size: 56px; font-weight: bold; color: #1E88E5; margin-bottom: 5px;">{risk_formatted}</div>
1048
- <div style="font-size: 14px; color: #666; margin-bottom: 15px;">Risk Score (Bayesian)</div>
1049
- {confidence_interval_html}
1050
- </div>
1051
-
1052
- <div style="background: rgba(244, 67, 54, 0.1); padding: 18px; border-radius: 10px; margin: 15px 0; border-left: 5px solid #F44336;">
1053
- <strong style="color: #D32F2F; font-size: 1.1em;">🚨 Mathematical Risk Analysis:</strong>
1054
- <div style="font-size: 0.95em; color: #666; margin-top: 10px; line-height: 1.6;">
1055
- • <strong>${final_risk * 5000000:,.0f}</strong> expected financial exposure<br>
1056
- • <strong>0%</strong> mechanical prevention rate<br>
1057
- • <strong>{ci_lower:.0%}-{ci_upper:.0%}</strong> confidence interval
1058
- </div>
1059
- </div>
1060
-
1061
- <div style="background: rgba(255, 152, 0, 0.1); padding: 16px; border-radius: 10px; margin-top: 20px;">
1062
- <strong style="color: #F57C00; font-size: 1.05em;">📋 Bayesian Recommendation:</strong>
1063
- <div style="font-size: 0.95em; margin-top: 8px; line-height: 1.5;">{oss_rec}</div>
1064
- </div>
1065
- </div>
1066
- """
1067
-
1068
- enterprise_html = f"""
1069
- <div class="mathematical-card" style="border-top: 6px solid {tier_info['color']}; background: linear-gradient(145deg, {tier_info['bg']}, #FFFFFF);">
1070
- <h3 style="margin-top: 0; color: {tier_info['color']}; display: flex; align-items: center;">
1071
- <span>{tier_info['name']}</span>
1072
- <span style="margin-left: auto; font-size: 0.7em; background: {tier_info['color']}; color: white; padding: 4px 12px; border-radius: 15px; box-shadow: 0 3px 10px rgba(30, 136, 229, 0.3);">
1073
- Mechanical
1074
- </span>
1075
- </h3>
1076
-
1077
- <div style="text-align: center; margin: 30px 0;">
1078
- <div style="font-size: 56px; font-weight: bold; color: {tier_info['color']}; margin-bottom: 5px;">{risk_formatted}</div>
1079
- <div style="font-size: 14px; color: #666; margin-bottom: 15px;">Risk Score (Bayesian)</div>
1080
- {confidence_interval_html}
1081
- </div>
1082
-
1083
- {gates_html}
1084
-
1085
- <div style="background: rgba(255, 152, 0, 0.1); padding: 18px; border-radius: 10px; margin-top: 25px;">
1086
- <strong style="color: {tier_info['color']}; font-size: 1.1em;">🛡️ Mechanical Enforcement:</strong>
1087
- <div style="font-size: 0.95em; margin-top: 8px; line-height: 1.5;">{enforcement}</div>
1088
- </div>
1089
- </div>
1090
- """
1091
-
1092
- license_html = f"""
1093
- <div class="mathematical-card" style="border-top: 6px solid {tier_info['color']}; background: linear-gradient(145deg, {tier_info['bg']}, #FFFFFF);">
1094
- <h3 style="margin-top: 0; color: {tier_info['color']}; display: flex; align-items: center;">
1095
- <span>{tier_info['name']}</span>
1096
- <span style="margin-left: auto; font-size: 0.7em; background: {tier_info['color']}; color: white; padding: 4px 12px; border-radius: 15px;">
1097
- Active
1098
- </span>
1099
- </h3>
1100
- <p style="color: #666; font-size: 0.95em; margin-bottom: 20px; line-height: 1.5;">
1101
- {'⚠️ <strong>14-Day Mathematical Trial</strong><br>Bayesian analysis + mechanical gates' if current_tier == 'trial' else '✅ <strong>Enterprise License</strong><br>PhD-level mathematical sophistication' if current_tier != 'oss' else '⚠️ <strong>OSS Edition</strong><br>Bayesian advisory only'}
1102
- </p>
1103
- <div style="background: rgba(30, 136, 229, 0.12); padding: 15px; border-radius: 10px; border-left: 4px solid {tier_info['color']};">
1104
- <div style="font-size: 0.9em; color: {tier_info['color']}; line-height: 1.6;">
1105
- <strong>Execution Level:</strong> {'AUTONOMOUS_HIGH' if current_tier == 'enterprise' else 'OPERATOR_REVIEW' if current_tier == 'trial' else 'ADVISORY_ONLY'}<br>
1106
- <strong>Risk Prevention:</strong> {92 if current_tier == 'enterprise' else 85 if current_tier == 'professional' else 70 if current_tier == 'starter' else 50 if current_tier == 'trial' else 0}%<br>
1107
- <strong>Confidence Threshold:</strong> {90 if current_tier == 'enterprise' else 80 if current_tier == 'professional' else 70 if current_tier == 'starter' else 60 if current_tier == 'trial' else 0}%<br>
1108
- <strong>ARF Status:</strong> {arf_display}
1109
- </div>
1110
- </div>
1111
- </div>
1112
- """
1113
-
1114
- # Build history rows
1115
- history_rows_html = ""
1116
- for entry in demo_state.action_history:
1117
- risk_text = format_mathematical_risk(entry['risk_score'])
1118
- confidence_text = f"{entry.get('confidence', 0.8):.0%}"
1119
- gates_text = f"{entry['gates_passed']}/{entry['total_gates']}"
1120
- gates_color = "#4CAF50" if entry['gates_passed'] == entry['total_gates'] else "#F44336" if entry['gates_passed'] == 0 else "#FF9800"
1121
- arf_emoji = "✅" if entry['arf_status'] == 'REAL' else "⚠️"
1122
-
1123
- decision_emoji = {
1124
- "AUTONOMOUS": "✅",
1125
- "SUPERVISED": "👁️",
1126
- "HUMAN_APPROVAL": "🔄",
1127
- "BLOCKED": "❌"
1128
- }.get(entry['gate_decision'], "⚡")
1129
-
1130
- history_rows_html += f'''
1131
- <tr>
1132
- <td style="padding: 12px; border-bottom: 1px solid #eee; color: #555; font-size: 13px;">{entry['time']}</td>
1133
- <td style="padding: 12px; border-bottom: 1px solid #eee; color: #555; font-size: 13px;">{entry['action'][:35]}...</td>
1134
- <td style="padding: 12px; border-bottom: 1px solid #eee; font-size: 13px;">{risk_text}</td>
1135
- <td style="padding: 12px; border-bottom: 1px solid #eee; color: #555; font-size: 13px;">{confidence_text}</td>
1136
- <td style="padding: 12px; border-bottom: 1px solid #eee; color: #555; font-size: 13px;">{entry['license_tier']}</td>
1137
- <td style="padding: 12px; border-bottom: 1px solid #eee; color: {gates_color}; font-weight: bold; font-size: 13px;">{gates_text}</td>
1138
- <td style="padding: 12px; border-bottom: 1px solid #eee; font-size: 16px;">{decision_emoji}</td>
1139
- <td style="padding: 12px; border-bottom: 1px solid #eee; text-align: center; font-size: 16px;">{arf_emoji}</td>
1140
- </tr>
1141
- '''
1142
-
1143
- # Build history table
1144
- if history_rows_html:
1145
- history_table = f"""
1146
- <table style="width: 100%; border-collapse: collapse; font-size: 13px; min-width: 600px;">
1147
- <thead>
1148
- <tr style="background: #f5f5f5;">
1149
- <th style="padding: 12px; border-bottom: 2px solid #E0E0E0; text-align: left;">Time</th>
1150
- <th style="padding: 12px; border-bottom: 2px solid #E0E0E0; text-align: left;">Action</th>
1151
- <th style="padding: 12px; border-bottom: 2px solid #E0E0E0; text-align: left;">Risk</th>
1152
- <th style="padding: 12px; border-bottom: 2px solid #E0E0E0; text-align: left;">Confidence</th>
1153
- <th style="padding: 12px; border-bottom: 2px solid #E0E0E0; text-align: left;">License</th>
1154
- <th style="padding: 12px; border-bottom: 2px solid #E0E0E0; text-align: left;">Gates</th>
1155
- <th style="padding: 12px; border-bottom: 2px solid #E0E0E0; text-align: left;">Decision</th>
1156
- <th style="padding: 12px; border-bottom: 2px solid #E0E0E0; text-align: left;">ARF</th>
1157
- </tr>
1158
- </thead>
1159
- <tbody>
1160
- {history_rows_html}
1161
- </tbody>
1162
- </table>
1163
- """
1164
- else:
1165
- history_table = """
1166
- <div style="text-align: center; padding: 40px; color: #999; font-style: italic;">
1167
- No mathematical assessments yet. Test an action to see Bayesian analysis in action.
1168
- </div>
1169
- """
1170
-
1171
- # Final history HTML
1172
- history_html = f"""
1173
- <div style="border: 1px solid #E0E0E0; border-radius: 15px; padding: 20px; background: #fafafa; box-shadow: 0 8px 30px rgba(0,0,0,0.08); margin-top: 20px;">
1174
- <h4 style="margin-top: 0; margin-bottom: 15px; color: #333;">📊 Mathematical Action History</h4>
1175
- <div style="overflow-x: auto;">
1176
- {history_table}
1177
- </div>
1178
- </div>
1179
- """
1180
-
1181
- return oss_html, enterprise_html, license_html, history_html
1182
-
1183
- def generate_trial():
1184
- """Generate mathematical trial license"""
1185
- license_key = generate_mathematical_trial_license()
1186
- return license_key
1187
-
1188
- # Connect handlers
1189
- scenario.change(
1190
- fn=update_context,
1191
- inputs=[scenario],
1192
- outputs=[context]
1193
- )
1194
-
1195
- test_btn.click(
1196
- fn=test_mathematical_assessment,
1197
- inputs=[scenario, context, license_key],
1198
- outputs=[oss_results, enterprise_results, license_display, history_display]
1199
- )
1200
-
1201
- trial_btn.click(
1202
- fn=generate_trial,
1203
- inputs=[],
1204
- outputs=[license_key]
1205
- )
1206
-
1207
- return demo
1208
-
1209
- # ============== MAIN EXECUTION ==============
1210
- if __name__ == "__main__":
1211
- print("\n" + "="*80)
1212
- print("🚀 LAUNCHING FIXED ARF 3.3.9 DEMO")
1213
- print("📊 ARF Status:", ARF_UNIFIED_STATUS['display_text'])
1214
- print("🌐 Environment:", "Hugging Face Spaces" if is_huggingface_spaces() else "Local Development")
1215
- print("="*80)
1216
-
1217
- # Create the Gradio demo
1218
- demo = create_enhanced_demo()
1219
-
1220
- # Mount FastAPI on the Gradio app if available
1221
- if FASTAPI_AVAILABLE:
1222
- print("🔄 Mounting FastAPI endpoints on Gradio app...")
1223
- # This returns a FastAPI app that includes both FastAPI routes and Gradio
1224
- app = mount_gradio_app(api_app, demo, path="/")
1225
- print("✅ FastAPI endpoints mounted successfully")
1226
- print(" Access API at: https://petter2025-agentic-reliability-framework.hf.space/api/v1/...")
1227
-
1228
- # For FastAPI app, we need to use uvicorn to run it
1229
- import uvicorn
1230
- print("🚀 Starting combined FastAPI+Gradio server on port 7860...")
1231
- uvicorn.run(app, host="0.0.0.0", port=7860, log_level="info")
1232
- else:
1233
- # Fallback to Gradio-only mode
1234
- print("⚠️ FastAPI not available, running Gradio only")
1235
- demo.launch(
1236
- server_name="0.0.0.0",
1237
- server_port=7860,
1238
- share=False,
1239
- debug=False,
1240
- prevent_thread_lock=True,
1241
- show_error=True,
1242
- quiet=False
1243
- )
1244
-
1245
- # Keep the app alive (only needed for Gradio fallback)
1246
- if not FASTAPI_AVAILABLE:
1247
- import time
1248
- while True:
1249
- time.sleep(1)