File size: 2,166 Bytes
435d673
77079a2
435d673
 
 
77079a2
435d673
 
 
 
 
 
 
 
77079a2
435d673
 
 
 
 
77079a2
 
 
 
 
 
435d673
77079a2
435d673
 
 
 
 
 
 
 
 
 
77079a2
 
435d673
 
 
 
 
 
 
 
 
 
 
 
77079a2
435d673
 
 
 
 
 
 
 
 
 
 
 
 
 
77079a2
 
 
 
 
435d673
77079a2
435d673
77079a2
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
from fastapi import FastAPI, HTTPException
from fastapi.responses import RedirectResponse
from pydantic import BaseModel
import uvicorn
import logging
import os

# Import our custom modules
from anomaly_detector import AnomalyDetector
from rag_agent import SentinelAgent

# 1. Initialize the App
app = FastAPI(
    title="Sentinel MLOps Agent",
    description="Autonomous Anomaly Detection & RAG Investigation API. Powered by Gemini 2.5.",
    version="1.0"
)

# 2. Load the Engines
print("🔋 Starting Sentinel Engines...")
try:
    detector = AnomalyDetector()
    agent = SentinelAgent()
    print("✅ Engines Active.")
except Exception as e:
    print(f"❌ Error loading engines: {e}")

# 3. Define the Data Format
class MetricData(BaseModel):
    timestamp: str
    service_name: str
    cpu_usage: float

# 4. The API Endpoint
@app.post("/monitor")
async def monitor_system(data: MetricData):
    """
    Receives live system data.
    - If Normal (< 2.5 sigma): Returns OK.
    - If Anomaly (> 2.5 sigma): Triggers Gemini 2.5 to investigate logs.
    """
    # Step A: Check for Physics/Math Anomaly
    is_anomaly, msg, z_score = detector.update(data.cpu_usage)
    
    if not is_anomaly:
        return {
            "status": "Healthy", 
            "message": msg, 
            "z_score": z_score
        }
    
    # Step B: If Anomaly, Wake up the Agent
    print(f"🚨 ALERT: Anomaly on {data.service_name} detected! (Z={z_score:.2f})")
    
    report = agent.investigate(
        anomaly_value=data.cpu_usage, 
        z_score=z_score
    )
    
    # Return the Full Incident Report
    return {
        "status": "CRITICAL",
        "service": data.service_name,
        "deviation": f"{z_score:.2f} sigma",
        "investigation_report": report
    }

# 5. Root Redirect (The Magic Trick)
@app.get("/", include_in_schema=False)
def root():
    # Automatically redirects users to the Swagger UI
    return RedirectResponse(url="/docs")

# 6. Run the Server
if __name__ == "__main__":
    # Use the port required by Hugging Face (7860) or default to 8000
    port = int(os.getenv("PORT", 7860))
    uvicorn.run(app, host="0.0.0.0", port=port)