Use friendly name in review genai prompt

This commit is contained in:
Nicolas Mowen 2025-11-10 09:54:29 -07:00
parent d8dff40987
commit cecb67078a
4 changed files with 29 additions and 8 deletions

View File

@ -177,6 +177,12 @@ class CameraConfig(FrigateBaseModel):
def ffmpeg_cmds(self) -> list[dict[str, list[str]]]: def ffmpeg_cmds(self) -> list[dict[str, list[str]]]:
return self._ffmpeg_cmds return self._ffmpeg_cmds
def get_formatted_name(self) -> str:
"""Return the friendly name if set, otherwise return a formatted version of the camera name."""
if self.friendly_name:
return self.friendly_name
return self.name.replace("_", " ").title() if self.name else ""
def create_ffmpeg_cmds(self): def create_ffmpeg_cmds(self):
if "_ffmpeg_cmds" in self: if "_ffmpeg_cmds" in self:
return return

View File

@ -56,6 +56,12 @@ class ZoneConfig(BaseModel):
def contour(self) -> np.ndarray: def contour(self) -> np.ndarray:
return self._contour return self._contour
def get_formatted_name(self, zone_name: str) -> str:
"""Return the friendly name if set, otherwise return a formatted version of the zone name."""
if self.friendly_name:
return self.friendly_name
return zone_name.replace("_", " ").title()
@field_validator("objects", mode="before") @field_validator("objects", mode="before")
@classmethod @classmethod
def validate_objects(cls, v): def validate_objects(cls, v):

View File

@ -16,6 +16,7 @@ from peewee import DoesNotExist
from frigate.comms.embeddings_updater import EmbeddingsRequestEnum from frigate.comms.embeddings_updater import EmbeddingsRequestEnum
from frigate.comms.inter_process import InterProcessRequestor from frigate.comms.inter_process import InterProcessRequestor
from frigate.config import FrigateConfig from frigate.config import FrigateConfig
from frigate.config.camera import CameraConfig
from frigate.config.camera.review import GenAIReviewConfig, ImageSourceEnum from frigate.config.camera.review import GenAIReviewConfig, ImageSourceEnum
from frigate.const import CACHE_DIR, CLIPS_DIR, UPDATE_REVIEW_DESCRIPTION from frigate.const import CACHE_DIR, CLIPS_DIR, UPDATE_REVIEW_DESCRIPTION
from frigate.data_processing.types import PostProcessDataEnum from frigate.data_processing.types import PostProcessDataEnum
@ -193,7 +194,7 @@ class ReviewDescriptionProcessor(PostProcessorApi):
self.requestor, self.requestor,
self.genai_client, self.genai_client,
self.review_desc_speed, self.review_desc_speed,
camera, camera_config,
final_data, final_data,
thumbs, thumbs,
camera_config.review.genai, camera_config.review.genai,
@ -422,7 +423,7 @@ def run_analysis(
requestor: InterProcessRequestor, requestor: InterProcessRequestor,
genai_client: GenAIClient, genai_client: GenAIClient,
review_inference_speed: InferenceSpeed, review_inference_speed: InferenceSpeed,
camera: str, camera_config: CameraConfig,
final_data: dict[str, str], final_data: dict[str, str],
thumbs: list[bytes], thumbs: list[bytes],
genai_config: GenAIReviewConfig, genai_config: GenAIReviewConfig,
@ -430,10 +431,19 @@ def run_analysis(
attribute_labels: list[str], attribute_labels: list[str],
) -> None: ) -> None:
start = datetime.datetime.now().timestamp() start = datetime.datetime.now().timestamp()
# Format zone names using zone config friendly names if available
formatted_zones = []
for zone_name in final_data["data"]["zones"]:
if zone_name in camera_config.zones:
formatted_zones.append(
camera_config.zones[zone_name].get_formatted_name(zone_name)
)
analytics_data = { analytics_data = {
"id": final_data["id"], "id": final_data["id"],
"camera": camera, "camera": camera_config.get_formatted_name(),
"zones": final_data["data"]["zones"], "zones": formatted_zones,
"start": datetime.datetime.fromtimestamp(final_data["start_time"]).strftime( "start": datetime.datetime.fromtimestamp(final_data["start_time"]).strftime(
"%A, %I:%M %p" "%A, %I:%M %p"
), ),

View File

@ -51,8 +51,7 @@ class GenAIClient:
def get_concern_prompt() -> str: def get_concern_prompt() -> str:
if concerns: if concerns:
concern_list = "\n - ".join(concerns) concern_list = "\n - ".join(concerns)
return f""" return f"""- `other_concerns` (list of strings): Include a list of any of the following concerns that are occurring:
- `other_concerns` (list of strings): Include a list of any of the following concerns that are occurring:
- {concern_list}""" - {concern_list}"""
else: else:
return "" return ""
@ -70,7 +69,7 @@ class GenAIClient:
return "\n- (No objects detected)" return "\n- (No objects detected)"
context_prompt = f""" context_prompt = f"""
Your task is to analyze the sequence of images ({len(thumbnails)} total) taken in chronological order from the perspective of the {review_data["camera"].replace("_", " ")} security camera. Your task is to analyze the sequence of images ({len(thumbnails)} total) taken in chronological order from the perspective of the {review_data["camera"]} security camera.
## Normal Activity Patterns for This Property ## Normal Activity Patterns for This Property
@ -110,7 +109,7 @@ Your response MUST be a flat JSON object with:
- Frame 1 = earliest, Frame {len(thumbnails)} = latest - Frame 1 = earliest, Frame {len(thumbnails)} = latest
- Activity started at {review_data["start"]} and lasted {review_data["duration"]} seconds - Activity started at {review_data["start"]} and lasted {review_data["duration"]} seconds
- Zones involved: {", ".join(z.replace("_", " ").title() for z in review_data["zones"]) or "None"} - Zones involved: {", ".join(review_data["zones"]) if review_data["zones"] else "None"}
## Objects in Scene ## Objects in Scene