Spaces:
Sleeping
Sleeping
File size: 5,447 Bytes
506c307 fe74762 506c307 fe74762 506c307 fe74762 506c307 fe74762 506c307 fe74762 506c307 fe74762 506c307 fe74762 506c307 fe74762 506c307 fe74762 506c307 fe74762 506c307 fe74762 506c307 fe74762 506c307 fe74762 506c307 fe74762 | 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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | """
agent_workflow.py
Agentic AI workflow using Groq (LLaMA-3).
Falls back to rule-based mock if the key is missing or the call fails.
"""
import json
import os
def run_groq_agent(
detection_summary: dict,
video_meta: dict,
ai_summary: str,
) -> dict:
"""
Run a Groq-powered analysis and return a JSON report.
Falls back to mock if Groq is unavailable.
"""
try:
from groq import Groq
client = Groq(api_key=os.getenv("GROQ_API_KEY"))
payload = {
"detection_summary": detection_summary,
"video_meta": video_meta,
"ai_summary": ai_summary,
}
prompt = f"""
You are a professional video-analysis assistant.
Analyze the following structured data and return ONLY valid JSON.
Required JSON schema:
{{
"insights": ["...", "...", "..."],
"risk_flags": ["..."],
"recommended_actions": ["...", "...", "..."]
}}
Rules:
- Return ONLY JSON.
- "insights" should contain exactly 3 concise observations.
- "risk_flags" should be an empty list [] if there are no meaningful risks.
- "recommended_actions" should contain 2 or 3 useful next steps.
- Be factual and do not invent details beyond the provided data.
DATA:
{json.dumps(payload, indent=2)}
""".strip()
response = client.chat.completions.create(
model="llama3-8b-8192",
messages=[{"role": "user", "content": prompt}],
temperature=0.2,
max_tokens=400,
)
content = response.choices[0].message.content.strip()
clean = content.removeprefix("```json").removeprefix("```").removesuffix("```").strip()
result = json.loads(clean)
if not isinstance(result, dict):
raise ValueError("LLM output is not a dictionary.")
result.setdefault("insights", [])
result.setdefault("risk_flags", [])
result.setdefault("recommended_actions", [])
if not isinstance(result["insights"], list):
result["insights"] = []
if not isinstance(result["risk_flags"], list):
result["risk_flags"] = []
if not isinstance(result["recommended_actions"], list):
result["recommended_actions"] = []
if len(result["insights"]) < 3:
result["insights"] += [
"Detected objects were analyzed across extracted frames.",
"The summary is based on object frequency and video metadata.",
"Manual review of annotated frames can provide additional context.",
]
result["insights"] = result["insights"][:3]
if len(result["recommended_actions"]) < 2:
result["recommended_actions"] += [
"Review the annotated frames to validate detections.",
"Export the report for further analysis or archiving.",
]
result["recommended_actions"] = result["recommended_actions"][:3]
return result
except Exception as e:
return run_mock_agent(detection_summary, video_meta, ai_summary, error=str(e))
def run_mock_agent(
detection_summary: dict,
video_meta: dict,
ai_summary: str,
error: str = "",
) -> dict:
"""
Rule-based fallback report.
"""
total = sum(detection_summary.values())
categories = len(detection_summary)
top_class = max(detection_summary, key=detection_summary.get) if detection_summary else "none"
top_count = detection_summary.get(top_class, 0)
fps = max(video_meta.get("fps", 25), 1)
duration = round(video_meta.get("total_frames", 0) / fps, 1)
w = video_meta.get("width", "N/A")
h = video_meta.get("height", "N/A")
insights = [
f"Dominant object: '{top_class}' detected {top_count} times across analyzed frames.",
f"Total: {total} detections across {categories} categories in a {duration}s video.",
f"Video resolution {w}x{h} @ {fps:.0f} fps — suitable for detailed object analysis.",
]
risk_flags = []
if detection_summary.get("person", 0) > 20:
risk_flags.append("High person density — possible crowd or public-safety scenario.")
if detection_summary.get("knife", 0) > 0 or detection_summary.get("gun", 0) > 0:
risk_flags.append("Potentially dangerous object detected — manual review recommended.")
if total == 0:
risk_flags.append("Zero detections — video may be blank, very dark, or corrupted.")
if categories == 1 and total > 15:
risk_flags.append(
f"Unusually high concentration of a single class ('{top_class}') — verify context."
)
if error:
risk_flags.append(f"Groq agent unavailable, fallback mock analysis used: {error[:120]}")
recommended_actions = [
f"Review annotated frames focusing on '{top_class}' detections for context validation.",
"Lower the confidence threshold if important objects appear to be missed.",
"Export the JSON report for downstream analytics or alerting integration.",
]
return {
"insights": insights,
"risk_flags": risk_flags,
"recommended_actions": recommended_actions,
}
def run_agent(
detection_summary: dict,
video_meta: dict,
ai_summary: str,
mode: str = "mock",
) -> dict:
if mode == "groq":
return run_groq_agent(detection_summary, video_meta, ai_summary)
return run_mock_agent(detection_summary, video_meta, ai_summary) |