File size: 2,960 Bytes
cd0c7a9 | 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 79 80 81 82 83 84 85 86 87 88 | import json
import logging
import os
from app.services.supabase import get_supabase
from app.config import settings
logger = logging.getLogger(__name__)
AUDIT_MODEL = "groq/llama-3.3-70b-versatile"
ANALYSIS_PROMPT = """
You are an intelligent observability engine for BioNexus, a bioinformatics SaaS platform.
Below is the ordered sequence of events from a user session.
Your job:
1. Identify what the user is trying to accomplish
2. Find any steps that failed, produced unexpected output, or took unusually long
3. Detect patterns — e.g. user retried the same step 3 times, or a tool returned 0 results silently
4. Output a JSON object with this exact shape:
{
"severity": "info" | "warning" | "critical",
"insight": "Plain-language summary of what happened in this session",
"affected_steps": ["step_name_1", "step_name_2"],
"suggestion": "What should be fixed or what the user should try next",
"anomalies": ["list of specific anomalies detected"]
}
Session events:
{events_json}
Return ONLY the JSON object. No markdown, no preamble.
"""
def run_audit(session_id: str, triggered_by: str | None = None) -> None:
sb = get_supabase()
resp = sb.table("audit_events") \
.select("*") \
.eq("session_id", session_id) \
.order("timestamp") \
.execute()
events = resp.data
if not events:
return
try:
import litellm
response = litellm.completion(
model=AUDIT_MODEL,
messages=[{
"role": "user",
"content": ANALYSIS_PROMPT.format(
events_json=json.dumps(events, indent=2, default=str)
),
}],
max_tokens=1000,
temperature=0.1,
api_key=settings.GROQ_API_KEY,
timeout=15,
)
raw = response.choices[0].message.content.strip()
# Strip markdown code fences if present
if raw.startswith("```"):
raw = raw.split("\n", 1)[-1] if "\n" in raw else raw[3:]
raw = raw.rsplit("```", 1)[0].strip()
insight_data = json.loads(raw)
sb.table("audit_insights").insert({
"session_id": session_id,
"triggered_by": triggered_by,
"severity": insight_data.get("severity", "info"),
"insight": insight_data.get("insight", ""),
"affected_steps": insight_data.get("affected_steps", []),
"suggestion": insight_data.get("suggestion", ""),
"raw_audit": {"events": events, "anomalies": insight_data.get("anomalies", [])},
}).execute()
logger.info(f"Audit insight stored for session {session_id[:8]}...")
except json.JSONDecodeError:
logger.warning(f"Audit engine failed for session {session_id[:8]}...: LLM returned malformed JSON (key restricted?)")
except Exception as e:
logger.warning(f"Audit engine failed for session {session_id[:8]}...: {e}")
|