mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-07-15 00:11:15 +03:00
Make it possible to update genai without restarting
This commit is contained in:
parent
3a79f3952e
commit
a613062c8f
@ -16,7 +16,7 @@ from frigate.config import CameraConfig, FrigateConfig
|
|||||||
from frigate.const import CLIPS_DIR, UPDATE_EVENT_DESCRIPTION
|
from frigate.const import CLIPS_DIR, UPDATE_EVENT_DESCRIPTION
|
||||||
from frigate.data_processing.post.semantic_trigger import SemanticTriggerProcessor
|
from frigate.data_processing.post.semantic_trigger import SemanticTriggerProcessor
|
||||||
from frigate.data_processing.types import PostProcessDataEnum
|
from frigate.data_processing.types import PostProcessDataEnum
|
||||||
from frigate.genai import GenAIClient
|
from frigate.genai.manager import GenAIClientManager
|
||||||
from frigate.models import Event
|
from frigate.models import Event
|
||||||
from frigate.types import TrackedObjectUpdateTypesEnum
|
from frigate.types import TrackedObjectUpdateTypesEnum
|
||||||
from frigate.util.builtin import EventsPerSecond, InferenceSpeed
|
from frigate.util.builtin import EventsPerSecond, InferenceSpeed
|
||||||
@ -41,7 +41,7 @@ class ObjectDescriptionProcessor(PostProcessorApi):
|
|||||||
embeddings: "Embeddings",
|
embeddings: "Embeddings",
|
||||||
requestor: InterProcessRequestor,
|
requestor: InterProcessRequestor,
|
||||||
metrics: DataProcessorMetrics,
|
metrics: DataProcessorMetrics,
|
||||||
client: GenAIClient,
|
genai_manager: GenAIClientManager,
|
||||||
semantic_trigger_processor: SemanticTriggerProcessor | None,
|
semantic_trigger_processor: SemanticTriggerProcessor | None,
|
||||||
):
|
):
|
||||||
super().__init__(config, metrics, None)
|
super().__init__(config, metrics, None)
|
||||||
@ -49,7 +49,7 @@ class ObjectDescriptionProcessor(PostProcessorApi):
|
|||||||
self.embeddings = embeddings
|
self.embeddings = embeddings
|
||||||
self.requestor = requestor
|
self.requestor = requestor
|
||||||
self.metrics = metrics
|
self.metrics = metrics
|
||||||
self.genai_client = client
|
self.genai_manager = genai_manager
|
||||||
self.semantic_trigger_processor = semantic_trigger_processor
|
self.semantic_trigger_processor = semantic_trigger_processor
|
||||||
self.tracked_events: dict[str, list[Any]] = {}
|
self.tracked_events: dict[str, list[Any]] = {}
|
||||||
self.early_request_sent: dict[str, bool] = {}
|
self.early_request_sent: dict[str, bool] = {}
|
||||||
@ -198,6 +198,9 @@ class ObjectDescriptionProcessor(PostProcessorApi):
|
|||||||
if data_type != PostProcessDataEnum.tracked_object:
|
if data_type != PostProcessDataEnum.tracked_object:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if self.genai_manager.description_client is None:
|
||||||
|
return
|
||||||
|
|
||||||
state: str | None = frame_data.get("state", None)
|
state: str | None = frame_data.get("state", None)
|
||||||
|
|
||||||
if state is not None:
|
if state is not None:
|
||||||
@ -329,7 +332,7 @@ class ObjectDescriptionProcessor(PostProcessorApi):
|
|||||||
"""Embed the description for an event."""
|
"""Embed the description for an event."""
|
||||||
start = datetime.datetime.now().timestamp()
|
start = datetime.datetime.now().timestamp()
|
||||||
camera_config = self.config.cameras[str(event.camera)]
|
camera_config = self.config.cameras[str(event.camera)]
|
||||||
description = self.genai_client.generate_object_description(
|
description = self.genai_manager.description_client.generate_object_description(
|
||||||
camera_config, thumbnails, event
|
camera_config, thumbnails, event
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,7 @@ 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
|
||||||
from frigate.genai import GenAIClient
|
from frigate.genai import GenAIClient
|
||||||
|
from frigate.genai.manager import GenAIClientManager
|
||||||
from frigate.models import Recordings, ReviewSegment
|
from frigate.models import Recordings, ReviewSegment
|
||||||
from frigate.util.builtin import EventsPerSecond, InferenceSpeed
|
from frigate.util.builtin import EventsPerSecond, InferenceSpeed
|
||||||
from frigate.util.image import get_image_from_recording
|
from frigate.util.image import get_image_from_recording
|
||||||
@ -41,12 +42,12 @@ class ReviewDescriptionProcessor(PostProcessorApi):
|
|||||||
config: FrigateConfig,
|
config: FrigateConfig,
|
||||||
requestor: InterProcessRequestor,
|
requestor: InterProcessRequestor,
|
||||||
metrics: DataProcessorMetrics,
|
metrics: DataProcessorMetrics,
|
||||||
client: GenAIClient,
|
genai_manager: GenAIClientManager,
|
||||||
):
|
):
|
||||||
super().__init__(config, metrics, None)
|
super().__init__(config, metrics, None)
|
||||||
self.requestor = requestor
|
self.requestor = requestor
|
||||||
self.metrics = metrics
|
self.metrics = metrics
|
||||||
self.genai_client = client
|
self.genai_manager = genai_manager
|
||||||
self.review_desc_speed = InferenceSpeed(self.metrics.review_desc_speed)
|
self.review_desc_speed = InferenceSpeed(self.metrics.review_desc_speed)
|
||||||
self.review_desc_dps = EventsPerSecond()
|
self.review_desc_dps = EventsPerSecond()
|
||||||
self.review_desc_dps.start()
|
self.review_desc_dps.start()
|
||||||
@ -63,7 +64,7 @@ class ReviewDescriptionProcessor(PostProcessorApi):
|
|||||||
Estimates ~1 token per 1250 pixels. Targets 98% context utilization with safety margin.
|
Estimates ~1 token per 1250 pixels. Targets 98% context utilization with safety margin.
|
||||||
Capped at 20 frames.
|
Capped at 20 frames.
|
||||||
"""
|
"""
|
||||||
context_size = self.genai_client.get_context_size()
|
context_size = self.genai_manager.description_client.get_context_size()
|
||||||
camera_config = self.config.cameras[camera]
|
camera_config = self.config.cameras[camera]
|
||||||
|
|
||||||
detect_width = camera_config.detect.width
|
detect_width = camera_config.detect.width
|
||||||
@ -111,6 +112,9 @@ class ReviewDescriptionProcessor(PostProcessorApi):
|
|||||||
if data_type != PostProcessDataEnum.review:
|
if data_type != PostProcessDataEnum.review:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if self.genai_manager.description_client is None:
|
||||||
|
return
|
||||||
|
|
||||||
camera = data["after"]["camera"]
|
camera = data["after"]["camera"]
|
||||||
camera_config = self.config.cameras[camera]
|
camera_config = self.config.cameras[camera]
|
||||||
|
|
||||||
@ -200,7 +204,7 @@ class ReviewDescriptionProcessor(PostProcessorApi):
|
|||||||
target=run_analysis,
|
target=run_analysis,
|
||||||
args=(
|
args=(
|
||||||
self.requestor,
|
self.requestor,
|
||||||
self.genai_client,
|
self.genai_manager.description_client,
|
||||||
self.review_desc_speed,
|
self.review_desc_speed,
|
||||||
camera_config,
|
camera_config,
|
||||||
final_data,
|
final_data,
|
||||||
@ -316,7 +320,7 @@ class ReviewDescriptionProcessor(PostProcessorApi):
|
|||||||
os.path.join(CLIPS_DIR, "genai-requests", f"{start_ts}-{end_ts}")
|
os.path.join(CLIPS_DIR, "genai-requests", f"{start_ts}-{end_ts}")
|
||||||
).mkdir(parents=True, exist_ok=True)
|
).mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
return self.genai_client.generate_review_summary(
|
return self.genai_manager.description_client.generate_review_summary(
|
||||||
start_ts,
|
start_ts,
|
||||||
end_ts,
|
end_ts,
|
||||||
events_with_context,
|
events_with_context,
|
||||||
|
|||||||
@ -202,7 +202,7 @@ class EmbeddingMaintainer(threading.Thread):
|
|||||||
# post processors
|
# post processors
|
||||||
self.post_processors: list[PostProcessorApi] = []
|
self.post_processors: list[PostProcessorApi] = []
|
||||||
|
|
||||||
if self.genai_manager.description_client is not None and any(
|
if any(
|
||||||
c.review.genai.enabled_in_config for c in self.config.cameras.values()
|
c.review.genai.enabled_in_config for c in self.config.cameras.values()
|
||||||
):
|
):
|
||||||
self.post_processors.append(
|
self.post_processors.append(
|
||||||
@ -210,7 +210,7 @@ class EmbeddingMaintainer(threading.Thread):
|
|||||||
self.config,
|
self.config,
|
||||||
self.requestor,
|
self.requestor,
|
||||||
self.metrics,
|
self.metrics,
|
||||||
self.genai_manager.description_client,
|
self.genai_manager,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -248,7 +248,7 @@ class EmbeddingMaintainer(threading.Thread):
|
|||||||
)
|
)
|
||||||
self.post_processors.append(semantic_trigger_processor)
|
self.post_processors.append(semantic_trigger_processor)
|
||||||
|
|
||||||
if self.genai_manager.description_client is not None and any(
|
if any(
|
||||||
c.objects.genai.enabled_in_config for c in self.config.cameras.values()
|
c.objects.genai.enabled_in_config for c in self.config.cameras.values()
|
||||||
):
|
):
|
||||||
self.post_processors.append(
|
self.post_processors.append(
|
||||||
@ -257,7 +257,7 @@ class EmbeddingMaintainer(threading.Thread):
|
|||||||
self.embeddings,
|
self.embeddings,
|
||||||
self.requestor,
|
self.requestor,
|
||||||
self.metrics,
|
self.metrics,
|
||||||
self.genai_manager.description_client,
|
self.genai_manager,
|
||||||
semantic_trigger_processor,
|
semantic_trigger_processor,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -3,14 +3,6 @@ import type { SectionConfigOverrides } from "./types";
|
|||||||
const genai: SectionConfigOverrides = {
|
const genai: SectionConfigOverrides = {
|
||||||
base: {
|
base: {
|
||||||
sectionDocs: "/configuration/genai/config",
|
sectionDocs: "/configuration/genai/config",
|
||||||
restartRequired: [
|
|
||||||
"*.provider",
|
|
||||||
"*.api_key",
|
|
||||||
"*.base_url",
|
|
||||||
"*.model",
|
|
||||||
"*.provider_options",
|
|
||||||
"*.runtime_options",
|
|
||||||
],
|
|
||||||
advancedFields: ["*.base_url", "*.provider_options", "*.runtime_options"],
|
advancedFields: ["*.base_url", "*.provider_options", "*.runtime_options"],
|
||||||
hiddenFields: ["genai.enabled_in_config"],
|
hiddenFields: ["genai.enabled_in_config"],
|
||||||
uiSchema: {
|
uiSchema: {
|
||||||
|
|||||||
@ -44,10 +44,9 @@ export function GenAIModelWidget(props: WidgetProps) {
|
|||||||
const fieldClassName = getSizedFieldClassName(options, "sm");
|
const fieldClassName = getSizedFieldClassName(options, "sm");
|
||||||
const providerKey = useMemo(() => getProviderKey(id), [id]);
|
const providerKey = useMemo(() => getProviderKey(id), [id]);
|
||||||
|
|
||||||
const { data: allModels } = useSWR<Record<string, string[]>>(
|
const { data: allModels } = useSWR<Record<string, string[]>>("genai/models", {
|
||||||
"genai/models",
|
revalidateOnFocus: false,
|
||||||
{ revalidateOnFocus: false },
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const models = useMemo(() => {
|
const models = useMemo(() => {
|
||||||
if (!allModels || !providerKey) return [];
|
if (!allModels || !providerKey) return [];
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user