Allow GenAI providers to be initialized lazily (#23482)
Some checks are pending
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions

* allow GenAI providers to be initialized even if they failed on previous attempts

* mypy
This commit is contained in:
Nicolas Mowen 2026-06-14 10:40:33 -06:00 committed by GitHub
parent bc816926a5
commit 32e433cafc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 37 additions and 2 deletions

View File

@ -5,6 +5,7 @@ import json
import logging import logging
import os import os
import re import re
import time
from typing import Any, AsyncGenerator, Callable, Optional from typing import Any, AsyncGenerator, Callable, Optional
import numpy as np import numpy as np
@ -50,6 +51,10 @@ def register_genai_provider(key: GenAIProviderEnum) -> Callable:
class GenAIClient: class GenAIClient:
"""Generative AI client for Frigate.""" """Generative AI client for Frigate."""
# Minimum seconds between re-initialization attempts when the provider was
# offline at startup
REINIT_INTERVAL = 60.0
def __init__( def __init__(
self, self,
genai_config: GenAIConfig, genai_config: GenAIConfig,
@ -60,6 +65,34 @@ class GenAIClient:
self.timeout = timeout self.timeout = timeout
self.validate_model = validate_model self.validate_model = validate_model
self.provider = self._init_provider() self.provider = self._init_provider()
self._last_init_attempt = time.monotonic()
def ensure_provider(self) -> bool:
"""Ensure a provider is available, retrying initialization if needed.
Providers can fail to initialize at startup when their backing service
isn't online yet (common when both are started together). This retries
``_init_provider`` lazily throttled to ``REINIT_INTERVAL`` so the
client recovers on its own once the service is reachable, without a
config reload.
Returns True if a provider is available.
"""
if self.provider is not None:
return True
now = time.monotonic()
if now - self._last_init_attempt < self.REINIT_INTERVAL:
return False
self._last_init_attempt = now
self.provider = self._init_provider()
if self.provider is not None:
logger.info(
"GenAI provider %s is now available",
self.genai_config.provider,
)
return self.provider is not None
def generate_review_description( def generate_review_description(
self, self,

View File

@ -62,7 +62,9 @@ class GenAIClientManager:
def _get_client(self, name: str) -> "Optional[GenAIClient]": def _get_client(self, name: str) -> "Optional[GenAIClient]":
"""Return the client for *name*, creating it on first access.""" """Return the client for *name*, creating it on first access."""
if name in self._clients: if name in self._clients:
return self._clients[name] client = self._clients[name]
client.ensure_provider()
return client
from frigate.genai import PROVIDERS from frigate.genai import PROVIDERS
@ -78,7 +80,7 @@ class GenAIClientManager:
return None return None
try: try:
client: "GenAIClient" = provider_cls(genai_cfg) client = provider_cls(genai_cfg)
except Exception as e: except Exception as e:
logger.exception( logger.exception(
"Failed to create GenAI client for provider %s: %s", "Failed to create GenAI client for provider %s: %s",