Add config for users to define additional concerns that GenAI should make note of in review summary (#19463)

* Don't default to openai

* Improve UI

* Allow configuring additional concerns that users may want the AI to note

* Formatting

* Add preferred language config

* Remove unused
This commit is contained in:
Nicolas Mowen
2025-08-16 10:20:33 -05:00
committed by Blake Blackshear
parent 3cf86767f1
commit cc18d7f786
7 changed files with 93 additions and 42 deletions
+49 -25
View File
@@ -36,39 +36,60 @@ class GenAIClient:
self.provider = self._init_provider()
def generate_review_description(
self, review_data: dict[str, Any], thumbnails: list[bytes]
self,
review_data: dict[str, Any],
thumbnails: list[bytes],
concerns: list[str],
preferred_language: str | None,
) -> ReviewMetadata | None:
"""Generate a description for the review item activity."""
if concerns:
concern_list = "\n - ".join(concerns)
concern_prompt = f"""
- `other_concerns` (list of strings): Include a list of any of the following concerns that are occurring:
- {concern_list}
"""
else:
concern_prompt = ""
if preferred_language:
language_prompt = f"Provide your answer in {preferred_language}"
else:
language_prompt = ""
context_prompt = f"""
Please analyze the image(s), which are in chronological order, strictly from the perspective of the {review_data["camera"].replace("_", " ")} security camera.
Please analyze the image(s), which are in chronological order, strictly from the perspective of the {review_data["camera"].replace("_", " ")} security camera.
Your task is to provide a **neutral, factual, and objective description** of the scene, while also:
- Clearly stating **what is happening** based on observable actions and movements.
- Including **reasonable, evidence-based inferences** about the likely activity or context, but only if directly supported by visible details.
Your task is to provide a **neutral, factual, and objective description** of the scene, while also:
- Clearly stating **what is happening** based on observable actions and movements.
- Including **reasonable, evidence-based inferences** about the likely activity or context, but only if directly supported by visible details.
When forming your description:
- **Facts first**: Describe the physical setting, people, and objects exactly as seen.
- **Then context**: Briefly note plausible purposes or activities (e.g., “appears to be delivering a package” if carrying a box to a door).
- Clearly separate certain facts (“A person is holding a ladder”) from reasonable inferences (“likely performing maintenance”).
- Do not speculate beyond what is visible, and do not imply hostility, criminal intent, or other strong judgments unless there is unambiguous visual evidence.
When forming your description:
- **Facts first**: Describe the time, physical setting, people, and objects exactly as seen.
- **Then context**: Briefly note plausible purposes or activities (e.g., “appears to be delivering a package” if carrying a box to a door).
- Clearly separate certain facts (“A person is holding an object with horizontal rungs”) from reasonable inferences (“likely a ladder”).
- Do not speculate beyond what is visible, and do not imply hostility, criminal intent, or other strong judgments unless there is unambiguous visual evidence.
Here is information already known:
- Activity occurred at {review_data["timestamp"].strftime("%I:%M %p")}
- Detected objects: {review_data["objects"]}
- Recognized objects: {review_data["recognized_objects"]}
- Zones involved: {review_data["zones"]}
Here is information already known:
- Activity occurred at {review_data["timestamp"].strftime("%I:%M %p")}
- Detected objects: {review_data["objects"]}
- Recognized objects: {review_data["recognized_objects"]}
- Zones involved: {review_data["zones"]}
Your response **MUST** be a flat JSON object with:
- `scene` (string): A full description including setting, entities, actions, and any plausible supported inferences.
- `confidence` (float): A number 0–1 for overall confidence in the analysis.
- `potential_threat_level` (integer, optional): Include only if there is a clear, observable security concern:
- 0 = Normal activity is occurring
- 1 = Unusual but not overtly threatening
- 2 = Suspicious or potentially harmful
- 3 = Clear and immediate threat
Your response **MUST** be a flat JSON object with:
- `scene` (string): A full description including setting, entities, actions, and any plausible supported inferences.
- `confidence` (float): A number 0-1 for overall confidence in the analysis.
- `potential_threat_level` (integer, optional): Include only if there is a clear, observable security concern:
- 0 = Normal activity is occurring
- 1 = Unusual but not overtly threatening
- 2 = Suspicious or potentially harmful
- 3 = Clear and immediate threat
{concern_prompt}
**IMPORTANT:**
- Values must be plain strings, floats, or integers — no nested objects, no extra commentary.
**IMPORTANT:**
- Values must be plain strings, floats, or integers — no nested objects, no extra commentary.
{language_prompt}
"""
logger.debug(
f"Sending {len(thumbnails)} images to create review description on {review_data['camera']}"
@@ -116,6 +137,9 @@ class GenAIClient:
def get_genai_client(config: FrigateConfig) -> Optional[GenAIClient]:
"""Get the GenAI client."""
if not config.genai.provider:
return None
load_providers()
provider = PROVIDERS.get(config.genai.provider)
if provider: