more
This commit is contained in:
1 parent
8f670dfa2f
commit
2237fbda55
15 files changed
+594
-52
No files matched your search
@@ -8,6 +8,8 @@ import os
|
||||
import sys
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
import hashlib
|
||||
from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler
|
||||
import needle
|
||||
|
||||
@@ -50,6 +52,31 @@ def escalate_backend_outage(service: str, error_message: str):
|
||||
"""Escalate severe backend 5xx crash or unhandled panic to on-call."""
|
||||
return {"action": "escalate_outage", "service": service, "error": error_message}
|
||||
|
||||
@needle.tool
|
||||
def report_unclassified(service: str, summary: str):
|
||||
"""Fallback when the event matches none of the other categories: retries, cancellations, restarts, OOM, health checks, or anything unclear."""
|
||||
return {"action": "unclassified", "service": service, "summary": summary}
|
||||
|
||||
# --- Redaction: nothing PII-bearing should reach the model or the cache ---
|
||||
_REDACTIONS = [
|
||||
(re.compile(r"[\w.+-]+@[\w-]+\.[\w.-]+"), "<email>"),
|
||||
(re.compile(r"\b(?:\d{1,3}\.){3}\d{1,3}\b"), "<ip>"),
|
||||
(re.compile(r"\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b"), "<uuid>"),
|
||||
(re.compile(r"\beyJ[\w-]+\.[\w-]+\.[\w-]+\b"), "<jwt>"),
|
||||
(re.compile(r"\b[0-9a-fA-F]{16,}\b"), "<hex>"),
|
||||
(re.compile(r"([?&][\w.-]+=)[^&\s|]+"), r"\1<v>"),
|
||||
]
|
||||
|
||||
def redact(text: str) -> str:
|
||||
for rx, sub in _REDACTIONS:
|
||||
text = rx.sub(sub, text)
|
||||
return text[:1000]
|
||||
|
||||
# Cache keyed on the redacted text: repeated signatures cost nothing.
|
||||
CACHE_MAX = int(os.environ.get("NEEDLE_CACHE_MAX", 2000))
|
||||
_cache = {}
|
||||
_stats = {"hits": 0, "misses": 0}
|
||||
|
||||
# Initialize Needle Agent once
|
||||
print(f"Loading Needle 3 model (Cactus-Compute/needle3)...")
|
||||
t0 = time.perf_counter()
|
||||
@@ -60,7 +87,8 @@ agent = needle.Needle(tools=[
|
||||
log_missing_resource_404,
|
||||
report_database_error,
|
||||
report_auth_failure,
|
||||
escalate_backend_outage
|
||||
escalate_backend_outage,
|
||||
report_unclassified
|
||||
])
|
||||
print(f"Needle 3 loaded in {(time.perf_counter() - t0):.2f}s")
|
||||
|
||||
@@ -86,6 +114,7 @@ class NeedleHandler(BaseHTTPRequestHandler):
|
||||
"status": "ok",
|
||||
"available": True,
|
||||
"model": "Cactus-Compute/needle3",
|
||||
"cache": {**_stats, "size": len(_cache)},
|
||||
"tools": [
|
||||
"client_js_crash",
|
||||
"security_alert",
|
||||
@@ -93,7 +122,8 @@ class NeedleHandler(BaseHTTPRequestHandler):
|
||||
"log_404",
|
||||
"database_error",
|
||||
"auth_failure",
|
||||
"escalate_outage"
|
||||
"escalate_outage",
|
||||
"unclassified"
|
||||
]
|
||||
}
|
||||
self.wfile.write(json.dumps(resp).encode("utf-8"))
|
||||
@@ -142,6 +172,20 @@ class NeedleHandler(BaseHTTPRequestHandler):
|
||||
self.wfile.write(json.dumps({"error": "Missing 'text' or telemetry fields"}).encode("utf-8"))
|
||||
return
|
||||
|
||||
text = redact(text)
|
||||
key = hashlib.sha256(text.encode()).hexdigest()
|
||||
cached = _cache.get(key)
|
||||
if cached is not None:
|
||||
_stats["hits"] += 1
|
||||
out = {**cached, "cached": True}
|
||||
self.send_response(200)
|
||||
self._send_cors()
|
||||
self.send_header("Content-Type", "application/json")
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps(out).encode("utf-8"))
|
||||
return
|
||||
_stats["misses"] += 1
|
||||
|
||||
t_start = time.perf_counter()
|
||||
agent.reset()
|
||||
res = agent.run(text, strict=False)
|
||||
@@ -166,6 +210,10 @@ class NeedleHandler(BaseHTTPRequestHandler):
|
||||
"model": "Cactus-Compute/needle3"
|
||||
}
|
||||
|
||||
if len(_cache) >= CACHE_MAX:
|
||||
_cache.pop(next(iter(_cache)))
|
||||
_cache[key] = out
|
||||
|
||||
self.send_response(200)
|
||||
self._send_cors()
|
||||
self.send_header("Content-Type", "application/json")
|
||||
|
||||
Reference in new issue
Block a user