| 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() |
|
|
| |
| 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}") |
|
|