use IPC to write description, update docs for reindex

This commit is contained in:
Jason Hunter 2024-06-16 00:37:30 -04:00
parent e5d336ff99
commit e656913316
7 changed files with 29 additions and 9 deletions

View File

@ -469,6 +469,8 @@ snapshots:
semantic_search: semantic_search:
# Optional: Enable semantic search (default: shown below) # Optional: Enable semantic search (default: shown below)
enabled: False enabled: False
# Optional: Re-index embeddings database from historical events (default: shown below)
reindex: False
# Optional: Configuration for AI generated event descriptions # Optional: Configuration for AI generated event descriptions
# NOTE: Semantic Search must be enabled for this to do anything. # NOTE: Semantic Search must be enabled for this to do anything.

View File

@ -12,11 +12,12 @@ Semantic Search is a global configuration setting.
```yaml ```yaml
semantic_search: semantic_search:
enabled: True enabled: True
reindex: False
``` ```
:::tip :::tip
The embeddings database can be re-indexed from the existing detections in your database by adding an empty file named `.reindex` to the root of your configuration directory. Depending on the number of detections you have, it can take up to 30 minutes to complete and may max out your CPU while indexing. The embeddings database can be re-indexed from the existing detections in your database by adding `reindex: True` to your `semantic_search` configuration. Depending on the number of detections you have, it can take up to 30 minutes to complete and may max out your CPU while indexing. Make sure to set the config back to `False` before restarting Frigate again.
::: :::

View File

@ -14,9 +14,10 @@ from frigate.const import (
INSERT_PREVIEW, INSERT_PREVIEW,
REQUEST_REGION_GRID, REQUEST_REGION_GRID,
UPDATE_CAMERA_ACTIVITY, UPDATE_CAMERA_ACTIVITY,
UPDATE_EVENT_DESCRIPTION,
UPSERT_REVIEW_SEGMENT, UPSERT_REVIEW_SEGMENT,
) )
from frigate.models import Previews, Recordings, ReviewSegment from frigate.models import Event, Previews, Recordings, ReviewSegment
from frigate.ptz.onvif import OnvifCommandEnum, OnvifController from frigate.ptz.onvif import OnvifCommandEnum, OnvifController
from frigate.types import PTZMetricsTypes from frigate.types import PTZMetricsTypes
from frigate.util.object import get_camera_regions_grid from frigate.util.object import get_camera_regions_grid
@ -128,6 +129,10 @@ class Dispatcher:
).execute() ).execute()
elif topic == UPDATE_CAMERA_ACTIVITY: elif topic == UPDATE_CAMERA_ACTIVITY:
self.camera_activity = payload self.camera_activity = payload
elif topic == UPDATE_EVENT_DESCRIPTION:
event: Event = Event.get(Event.id == payload["id"])
event.data["description"] = payload["description"]
event.save()
elif topic == "onConnect": elif topic == "onConnect":
self.publish("camera_activity", json.dumps(self.camera_activity)) self.publish("camera_activity", json.dumps(self.camera_activity))
else: else:

View File

@ -725,6 +725,9 @@ class ReviewConfig(FrigateBaseModel):
class SemanticSearchConfig(FrigateBaseModel): class SemanticSearchConfig(FrigateBaseModel):
enabled: bool = Field(default=True, title="Enable semantic search.") enabled: bool = Field(default=True, title="Enable semantic search.")
reindex: Optional[bool] = Field(
default=False, title="Reindex all detections on startup."
)
class GenAIProviderEnum(str, Enum): class GenAIProviderEnum(str, Enum):
@ -746,9 +749,6 @@ class GenAIConfig(FrigateBaseModel):
title="Default caption prompt.", title="Default caption prompt.",
) )
object_prompts: Dict[str, str] = Field(default={}, title="Object specific prompts.") object_prompts: Dict[str, str] = Field(default={}, title="Object specific prompts.")
reindex: Optional[bool] = Field(
default=False, title="Reindex all detections on startup."
)
class GenAICameraConfig(FrigateBaseModel): class GenAICameraConfig(FrigateBaseModel):

View File

@ -81,6 +81,7 @@ REQUEST_REGION_GRID = "request_region_grid"
UPSERT_REVIEW_SEGMENT = "upsert_review_segment" UPSERT_REVIEW_SEGMENT = "upsert_review_segment"
CLEAR_ONGOING_REVIEW_SEGMENTS = "clear_ongoing_review_segments" CLEAR_ONGOING_REVIEW_SEGMENTS = "clear_ongoing_review_segments"
UPDATE_CAMERA_ACTIVITY = "update_camera_activity" UPDATE_CAMERA_ACTIVITY = "update_camera_activity"
UPDATE_EVENT_DESCRIPTION = "update_event_description"
# Autotracking # Autotracking

View File

@ -57,7 +57,7 @@ def manage_embeddings(config: FrigateConfig) -> None:
embeddings = Embeddings() embeddings = Embeddings()
# Check if we need to re-index events # Check if we need to re-index events
if config.genai.reindex: if config.semantic_search.reindex:
embeddings.reindex() embeddings.reindex()
maintainer = EmbeddingMaintainer( maintainer = EmbeddingMaintainer(

View File

@ -13,7 +13,9 @@ from peewee import DoesNotExist
from PIL import Image from PIL import Image
from frigate.comms.events_updater import EventEndSubscriber, EventUpdateSubscriber from frigate.comms.events_updater import EventEndSubscriber, EventUpdateSubscriber
from frigate.comms.inter_process import InterProcessRequestor
from frigate.config import FrigateConfig from frigate.config import FrigateConfig
from frigate.const import UPDATE_EVENT_DESCRIPTION
from frigate.events.types import EventTypeEnum from frigate.events.types import EventTypeEnum
from frigate.genai import get_genai_client from frigate.genai import get_genai_client
from frigate.models import Event from frigate.models import Event
@ -39,6 +41,8 @@ class EmbeddingMaintainer(threading.Thread):
self.event_subscriber = EventUpdateSubscriber() self.event_subscriber = EventUpdateSubscriber()
self.event_end_subscriber = EventEndSubscriber() self.event_end_subscriber = EventEndSubscriber()
self.frame_manager = SharedMemoryFrameManager() self.frame_manager = SharedMemoryFrameManager()
# create communication for updating event descriptions
self.requestor = InterProcessRequestor()
self.stop_event = stop_event self.stop_event = stop_event
self.tracked_events = {} self.tracked_events = {}
self.genai_client = get_genai_client(config.genai) self.genai_client = get_genai_client(config.genai)
@ -49,6 +53,11 @@ class EmbeddingMaintainer(threading.Thread):
self._process_updates() self._process_updates()
self._process_finalized() self._process_finalized()
self.event_subscriber.stop()
self.event_end_subscriber.stop()
self.requestor.stop()
logger.info("Exiting embeddings maintenance...")
def _process_updates(self) -> None: def _process_updates(self) -> None:
"""Process event updates""" """Process event updates"""
update = self.event_subscriber.check_for_update() update = self.event_subscriber.check_for_update()
@ -167,9 +176,11 @@ class EmbeddingMaintainer(threading.Thread):
logger.debug("Failed to generate description for %s", event.id) logger.debug("Failed to generate description for %s", event.id)
return return
# Update the event to add the description # fire and forget description update
event.data["description"] = description self.requestor.send_data(
event.save() UPDATE_EVENT_DESCRIPTION,
{"id": event.id, "description": description},
)
# Encode the description # Encode the description
self.embeddings.description.upsert( self.embeddings.description.upsert(