mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-08-02 17:12:16 +03:00
Increase ruff coverage (#23644)
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (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
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (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
CI / Jetson Jetpack 6 (push) Waiting to run
* Pin ruff * Add python upgrade fixes This enables python upgrade checks in ruff to look for deprecated types and patterns. This namely fixes: - usage of deprecated `Typing` which is now built in - some specific exceptions which are caught and have new aliases Some specific UP checks were also ignored as they are stylistic / unimportant and likely to cause bugs * Remove async blocking calls Use asyncio.to_thread on two remaining blocking calls to fix hanging event thread loop. Enable this specific rule to block it in the future. * Use proper logging mechanism * Correctly format logs * Raise with context When raising an exception include the from context to improve debugging * Cleanup
This commit is contained in:
+11
-10
@@ -6,7 +6,8 @@ import logging
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
from typing import Any, AsyncGenerator, Callable, Optional
|
||||
from collections.abc import AsyncGenerator, Callable
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
from pydantic import ValidationError
|
||||
@@ -235,7 +236,7 @@ class GenAIClient:
|
||||
camera_config: CameraConfig,
|
||||
thumbnails: list[bytes],
|
||||
event: Event,
|
||||
) -> Optional[str]:
|
||||
) -> str | None:
|
||||
"""Generate a description for the frame."""
|
||||
try:
|
||||
prompt = build_object_description_prompt(camera_config, event)
|
||||
@@ -254,9 +255,9 @@ class GenAIClient:
|
||||
self,
|
||||
prompt: str,
|
||||
images: list[bytes],
|
||||
response_format: Optional[dict] = None,
|
||||
response_format: dict | None = None,
|
||||
enable_thinking: bool = False,
|
||||
) -> Optional[str]:
|
||||
) -> str | None:
|
||||
"""Submit a request to the provider.
|
||||
|
||||
``enable_thinking`` is honored only by providers that report
|
||||
@@ -321,9 +322,9 @@ class GenAIClient:
|
||||
def chat_with_tools(
|
||||
self,
|
||||
messages: list[dict[str, Any]],
|
||||
tools: Optional[list[dict[str, Any]]] = None,
|
||||
tool_choice: Optional[str] = "auto",
|
||||
enable_thinking: Optional[bool] = None,
|
||||
tools: list[dict[str, Any]] | None = None,
|
||||
tool_choice: str | None = "auto",
|
||||
enable_thinking: bool | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""
|
||||
Send chat messages to LLM with optional tool definitions.
|
||||
@@ -395,9 +396,9 @@ class GenAIClient:
|
||||
async def chat_with_tools_stream(
|
||||
self,
|
||||
messages: list[dict[str, Any]],
|
||||
tools: Optional[list[dict[str, Any]]] = None,
|
||||
tool_choice: Optional[str] = "auto",
|
||||
enable_thinking: Optional[bool] = None,
|
||||
tools: list[dict[str, Any]] | None = None,
|
||||
tool_choice: str | None = "auto",
|
||||
enable_thinking: bool | None = None,
|
||||
) -> AsyncGenerator[tuple[str, Any], None]:
|
||||
"""Streaming counterpart to `chat_with_tools`.
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ no chat feature is active) are never initialized.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Any, Optional
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from frigate.config import FrigateConfig
|
||||
from frigate.config.camera.genai import GenAIConfig, GenAIRoleEnum
|
||||
@@ -23,7 +23,7 @@ class GenAIClientManager:
|
||||
def __init__(self, config: FrigateConfig) -> None:
|
||||
self._configs: dict[str, GenAIConfig] = {}
|
||||
self._role_map: dict[GenAIRoleEnum, str] = {}
|
||||
self._clients: dict[str, "GenAIClient"] = {}
|
||||
self._clients: dict[str, GenAIClient] = {}
|
||||
self.update_config(config)
|
||||
|
||||
def update_config(self, config: FrigateConfig) -> None:
|
||||
@@ -59,7 +59,7 @@ class GenAIClientManager:
|
||||
for role in genai_cfg.roles:
|
||||
self._role_map[role] = name
|
||||
|
||||
def _get_client(self, name: str) -> "Optional[GenAIClient]":
|
||||
def _get_client(self, name: str) -> "GenAIClient | None":
|
||||
"""Return the client for *name*, creating it on first access."""
|
||||
if name in self._clients:
|
||||
client = self._clients[name]
|
||||
@@ -93,19 +93,19 @@ class GenAIClientManager:
|
||||
return client
|
||||
|
||||
@property
|
||||
def chat_client(self) -> "Optional[GenAIClient]":
|
||||
def chat_client(self) -> "GenAIClient | None":
|
||||
"""Client configured for the chat role (e.g. chat with function calling)."""
|
||||
name = self._role_map.get(GenAIRoleEnum.chat)
|
||||
return self._get_client(name) if name else None
|
||||
|
||||
@property
|
||||
def description_client(self) -> "Optional[GenAIClient]":
|
||||
def description_client(self) -> "GenAIClient | None":
|
||||
"""Client configured for the descriptions role (e.g. review descriptions, object descriptions)."""
|
||||
name = self._role_map.get(GenAIRoleEnum.descriptions)
|
||||
return self._get_client(name) if name else None
|
||||
|
||||
@property
|
||||
def embeddings_client(self) -> "Optional[GenAIClient]":
|
||||
def embeddings_client(self) -> "GenAIClient | None":
|
||||
"""Client configured for the embeddings role."""
|
||||
name = self._role_map.get(GenAIRoleEnum.embeddings)
|
||||
return self._get_client(name) if name else None
|
||||
|
||||
@@ -4,7 +4,8 @@ import base64
|
||||
import binascii
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, AsyncGenerator, Optional
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Any
|
||||
|
||||
from google import genai
|
||||
from google.genai import errors, types
|
||||
@@ -16,7 +17,7 @@ from frigate.genai import GenAIClient, register_genai_provider
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _decode_thought_signature(value: Any) -> Optional[bytes]:
|
||||
def _decode_thought_signature(value: Any) -> bytes | None:
|
||||
"""Decode a base64-encoded thought_signature carried across conversation turns."""
|
||||
if not value:
|
||||
return None
|
||||
@@ -30,14 +31,14 @@ def _decode_thought_signature(value: Any) -> Optional[bytes]:
|
||||
return None
|
||||
|
||||
|
||||
def _encode_thought_signature(signature: Optional[bytes]) -> Optional[str]:
|
||||
def _encode_thought_signature(signature: bytes | None) -> str | None:
|
||||
"""Encode bytes thought_signature as base64 so it survives JSON-friendly transport."""
|
||||
if not signature:
|
||||
return None
|
||||
return base64.b64encode(signature).decode("ascii")
|
||||
|
||||
|
||||
def _stats_from_gemini_usage(usage: Any) -> Optional[dict[str, Any]]:
|
||||
def _stats_from_gemini_usage(usage: Any) -> dict[str, Any] | None:
|
||||
"""Build a stats dict from a Gemini usage_metadata object."""
|
||||
prompt_tokens = getattr(usage, "prompt_token_count", None)
|
||||
completion_tokens = getattr(usage, "candidates_token_count", None)
|
||||
@@ -84,9 +85,9 @@ class GeminiClient(GenAIClient):
|
||||
self,
|
||||
prompt: str,
|
||||
images: list[bytes],
|
||||
response_format: Optional[dict] = None,
|
||||
response_format: dict | None = None,
|
||||
enable_thinking: bool = False,
|
||||
) -> Optional[str]:
|
||||
) -> str | None:
|
||||
"""Submit a request to Gemini."""
|
||||
contents = [prompt] + [
|
||||
types.Part.from_bytes(data=img, mime_type="image/jpeg") for img in images
|
||||
@@ -141,9 +142,9 @@ class GeminiClient(GenAIClient):
|
||||
def chat_with_tools(
|
||||
self,
|
||||
messages: list[dict[str, Any]],
|
||||
tools: Optional[list[dict[str, Any]]] = None,
|
||||
tool_choice: Optional[str] = "auto",
|
||||
enable_thinking: Optional[bool] = None,
|
||||
tools: list[dict[str, Any]] | None = None,
|
||||
tool_choice: str | None = "auto",
|
||||
enable_thinking: bool | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""
|
||||
Send chat messages to Gemini with optional tool definitions.
|
||||
@@ -399,9 +400,9 @@ class GeminiClient(GenAIClient):
|
||||
async def chat_with_tools_stream(
|
||||
self,
|
||||
messages: list[dict[str, Any]],
|
||||
tools: Optional[list[dict[str, Any]]] = None,
|
||||
tool_choice: Optional[str] = "auto",
|
||||
enable_thinking: Optional[bool] = None,
|
||||
tools: list[dict[str, Any]] | None = None,
|
||||
tool_choice: str | None = "auto",
|
||||
enable_thinking: bool | None = None,
|
||||
) -> AsyncGenerator[tuple[str, Any], None]:
|
||||
"""
|
||||
Stream chat with tools; yields content deltas then final message.
|
||||
@@ -554,7 +555,7 @@ class GeminiClient(GenAIClient):
|
||||
reasoning_parts: list[str] = []
|
||||
tool_calls_by_index: dict[int, dict[str, Any]] = {}
|
||||
finish_reason = "stop"
|
||||
usage_stats: Optional[dict[str, Any]] = None
|
||||
usage_stats: dict[str, Any] | None = None
|
||||
|
||||
stream = await self.provider.aio.models.generate_content_stream(
|
||||
model=self.genai_config.model,
|
||||
|
||||
@@ -4,7 +4,8 @@ import base64
|
||||
import io
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, AsyncGenerator, Optional, cast
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Any, cast
|
||||
|
||||
import httpx
|
||||
import numpy as np
|
||||
@@ -18,7 +19,7 @@ from frigate.genai.utils import parse_tool_calls_from_message
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _stats_from_llama_cpp_chunk(data: dict[str, Any]) -> Optional[dict[str, Any]]:
|
||||
def _stats_from_llama_cpp_chunk(data: dict[str, Any]) -> dict[str, Any] | None:
|
||||
"""Build a stats dict from a llama.cpp streaming chunk.
|
||||
|
||||
Final-chunk `usage` carries authoritative token counts. Per-chunk
|
||||
@@ -311,9 +312,9 @@ class LlamaCppClient(GenAIClient):
|
||||
self,
|
||||
prompt: str,
|
||||
images: list[bytes],
|
||||
response_format: Optional[dict] = None,
|
||||
response_format: dict | None = None,
|
||||
enable_thinking: bool = False,
|
||||
) -> Optional[str]:
|
||||
) -> str | None:
|
||||
"""Submit a request to llama.cpp server."""
|
||||
if self.provider is None:
|
||||
logger.warning(
|
||||
@@ -521,10 +522,10 @@ class LlamaCppClient(GenAIClient):
|
||||
def _build_payload(
|
||||
self,
|
||||
messages: list[dict[str, Any]],
|
||||
tools: Optional[list[dict[str, Any]]],
|
||||
tool_choice: Optional[str],
|
||||
tools: list[dict[str, Any]] | None,
|
||||
tool_choice: str | None,
|
||||
stream: bool = False,
|
||||
enable_thinking: Optional[bool] = None,
|
||||
enable_thinking: bool | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Build request payload for chat completions (sync or stream)."""
|
||||
openai_tool_choice = None
|
||||
@@ -588,7 +589,7 @@ class LlamaCppClient(GenAIClient):
|
||||
@staticmethod
|
||||
def _streamed_tool_calls_to_list(
|
||||
tool_calls_by_index: dict[int, dict[str, Any]],
|
||||
) -> Optional[list[dict[str, Any]]]:
|
||||
) -> list[dict[str, Any]] | None:
|
||||
"""Convert streamed tool_calls index map to list of {id, name, arguments}."""
|
||||
if not tool_calls_by_index:
|
||||
return None
|
||||
@@ -758,9 +759,9 @@ class LlamaCppClient(GenAIClient):
|
||||
def chat_with_tools(
|
||||
self,
|
||||
messages: list[dict[str, Any]],
|
||||
tools: Optional[list[dict[str, Any]]] = None,
|
||||
tool_choice: Optional[str] = "auto",
|
||||
enable_thinking: Optional[bool] = None,
|
||||
tools: list[dict[str, Any]] | None = None,
|
||||
tool_choice: str | None = "auto",
|
||||
enable_thinking: bool | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""
|
||||
Send chat messages to llama.cpp server with optional tool definitions.
|
||||
@@ -830,9 +831,9 @@ class LlamaCppClient(GenAIClient):
|
||||
async def chat_with_tools_stream(
|
||||
self,
|
||||
messages: list[dict[str, Any]],
|
||||
tools: Optional[list[dict[str, Any]]] = None,
|
||||
tool_choice: Optional[str] = "auto",
|
||||
enable_thinking: Optional[bool] = None,
|
||||
tools: list[dict[str, Any]] | None = None,
|
||||
tool_choice: str | None = "auto",
|
||||
enable_thinking: bool | None = None,
|
||||
) -> AsyncGenerator[tuple[str, Any], None]:
|
||||
"""Stream chat with tools via OpenAI-compatible streaming API."""
|
||||
if self.provider is None:
|
||||
|
||||
@@ -4,7 +4,8 @@ import base64
|
||||
import binascii
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, AsyncGenerator, Optional
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Any
|
||||
|
||||
from httpx import RemoteProtocolError, TimeoutException
|
||||
from ollama import AsyncClient as OllamaAsyncClient
|
||||
@@ -18,7 +19,7 @@ from frigate.genai.utils import parse_tool_calls_from_message
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _extract_ollama_stats(response: Any) -> Optional[dict[str, Any]]:
|
||||
def _extract_ollama_stats(response: Any) -> dict[str, Any] | None:
|
||||
"""Build a stats dict from Ollama's response metadata.
|
||||
|
||||
Ollama reports eval_count/eval_duration (generation) and
|
||||
@@ -51,7 +52,7 @@ def _extract_ollama_stats(response: Any) -> Optional[dict[str, Any]]:
|
||||
|
||||
def _normalize_multimodal_content(
|
||||
content: Any,
|
||||
) -> tuple[Optional[str], Optional[list[bytes]]]:
|
||||
) -> tuple[str | None, list[bytes] | None]:
|
||||
"""Convert OpenAI-style multimodal content to Ollama's (text, images) shape.
|
||||
|
||||
The chat API constructs user messages with content as a list of
|
||||
@@ -98,7 +99,7 @@ class OllamaClient(GenAIClient):
|
||||
|
||||
provider: ApiClient | None
|
||||
provider_options: dict[str, Any]
|
||||
_supports_thinking_cache: Optional[bool] = None
|
||||
_supports_thinking_cache: bool | None = None
|
||||
|
||||
@property
|
||||
def supports_toggleable_thinking(self) -> bool:
|
||||
@@ -193,9 +194,9 @@ class OllamaClient(GenAIClient):
|
||||
self,
|
||||
prompt: str,
|
||||
images: list[bytes],
|
||||
response_format: Optional[dict] = None,
|
||||
response_format: dict | None = None,
|
||||
enable_thinking: bool = False,
|
||||
) -> Optional[str]:
|
||||
) -> str | None:
|
||||
"""Submit a request to Ollama"""
|
||||
if self.provider is None:
|
||||
logger.warning(
|
||||
@@ -290,10 +291,10 @@ class OllamaClient(GenAIClient):
|
||||
def _build_request_params(
|
||||
self,
|
||||
messages: list[dict[str, Any]],
|
||||
tools: Optional[list[dict[str, Any]]],
|
||||
tool_choice: Optional[str],
|
||||
tools: list[dict[str, Any]] | None,
|
||||
tool_choice: str | None,
|
||||
stream: bool = False,
|
||||
enable_thinking: Optional[bool] = None,
|
||||
enable_thinking: bool | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Build request_messages and params for chat (sync or stream)."""
|
||||
request_messages = []
|
||||
@@ -385,9 +386,9 @@ class OllamaClient(GenAIClient):
|
||||
def chat_with_tools(
|
||||
self,
|
||||
messages: list[dict[str, Any]],
|
||||
tools: Optional[list[dict[str, Any]]] = None,
|
||||
tool_choice: Optional[str] = "auto",
|
||||
enable_thinking: Optional[bool] = None,
|
||||
tools: list[dict[str, Any]] | None = None,
|
||||
tool_choice: str | None = "auto",
|
||||
enable_thinking: bool | None = None,
|
||||
) -> dict[str, Any]:
|
||||
if self.provider is None:
|
||||
logger.warning(
|
||||
@@ -426,9 +427,9 @@ class OllamaClient(GenAIClient):
|
||||
async def chat_with_tools_stream(
|
||||
self,
|
||||
messages: list[dict[str, Any]],
|
||||
tools: Optional[list[dict[str, Any]]] = None,
|
||||
tool_choice: Optional[str] = "auto",
|
||||
enable_thinking: Optional[bool] = None,
|
||||
tools: list[dict[str, Any]] | None = None,
|
||||
tool_choice: str | None = "auto",
|
||||
enable_thinking: bool | None = None,
|
||||
) -> AsyncGenerator[tuple[str, Any], None]:
|
||||
"""Stream chat with tools; yields content deltas then final message.
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
import base64
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, AsyncGenerator, Optional
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Any
|
||||
|
||||
from httpx import TimeoutException
|
||||
from openai import OpenAI
|
||||
@@ -14,7 +15,7 @@ from frigate.genai import GenAIClient, register_genai_provider
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _stats_from_openai_usage(usage: Any) -> Optional[dict[str, Any]]:
|
||||
def _stats_from_openai_usage(usage: Any) -> dict[str, Any] | None:
|
||||
"""Build a stats dict from an OpenAI-compatible usage object."""
|
||||
if usage is None:
|
||||
return None
|
||||
@@ -35,7 +36,7 @@ class OpenAIClient(GenAIClient):
|
||||
"""Generative AI client for Frigate using OpenAI."""
|
||||
|
||||
provider: OpenAI
|
||||
context_size: Optional[int] = None
|
||||
context_size: int | None = None
|
||||
|
||||
def _init_provider(self) -> OpenAI:
|
||||
"""Initialize the client.
|
||||
@@ -60,9 +61,9 @@ class OpenAIClient(GenAIClient):
|
||||
self,
|
||||
prompt: str,
|
||||
images: list[bytes],
|
||||
response_format: Optional[dict] = None,
|
||||
response_format: dict | None = None,
|
||||
enable_thinking: bool = False,
|
||||
) -> Optional[str]:
|
||||
) -> str | None:
|
||||
"""Submit a request to OpenAI."""
|
||||
encoded_images = [base64.b64encode(image).decode("utf-8") for image in images]
|
||||
messages_content: list[dict] = [
|
||||
@@ -186,9 +187,9 @@ class OpenAIClient(GenAIClient):
|
||||
def chat_with_tools(
|
||||
self,
|
||||
messages: list[dict[str, Any]],
|
||||
tools: Optional[list[dict[str, Any]]] = None,
|
||||
tool_choice: Optional[str] = "auto",
|
||||
enable_thinking: Optional[bool] = None,
|
||||
tools: list[dict[str, Any]] | None = None,
|
||||
tool_choice: str | None = "auto",
|
||||
enable_thinking: bool | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""
|
||||
Send chat messages to OpenAI with optional tool definitions.
|
||||
@@ -307,9 +308,9 @@ class OpenAIClient(GenAIClient):
|
||||
async def chat_with_tools_stream(
|
||||
self,
|
||||
messages: list[dict[str, Any]],
|
||||
tools: Optional[list[dict[str, Any]]] = None,
|
||||
tool_choice: Optional[str] = "auto",
|
||||
enable_thinking: Optional[bool] = None,
|
||||
tools: list[dict[str, Any]] | None = None,
|
||||
tool_choice: str | None = "auto",
|
||||
enable_thinking: bool | None = None,
|
||||
) -> AsyncGenerator[tuple[str, Any], None]:
|
||||
"""
|
||||
Stream chat with tools; yields content deltas then final message.
|
||||
@@ -357,7 +358,7 @@ class OpenAIClient(GenAIClient):
|
||||
reasoning_parts: list[str] = []
|
||||
tool_calls_by_index: dict[int, dict[str, Any]] = {}
|
||||
finish_reason = "stop"
|
||||
usage_stats: Optional[dict[str, Any]] = None
|
||||
usage_stats: dict[str, Any] | None = None
|
||||
|
||||
stream = self.provider.chat.completions.create(**request_params)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ transport.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
from typing import Any, Dict, List, Optional
|
||||
from typing import Any
|
||||
|
||||
from playhouse.shortcuts import model_to_dict
|
||||
|
||||
@@ -216,7 +216,7 @@ def build_object_description_prompt(
|
||||
return template.format(**model_to_dict(event))
|
||||
|
||||
|
||||
def get_attribute_classifications(config: FrigateConfig) -> List[Dict[str, Any]]:
|
||||
def get_attribute_classifications(config: FrigateConfig) -> list[dict[str, Any]]:
|
||||
"""Return enabled custom classification models of `attribute` type.
|
||||
|
||||
Each entry: {"name": <model name>, "objects": [<object label>, ...]}.
|
||||
@@ -224,7 +224,7 @@ def get_attribute_classifications(config: FrigateConfig) -> List[Dict[str, Any]]
|
||||
types, which can later be filtered via the search_objects `attribute`
|
||||
field.
|
||||
"""
|
||||
result: List[Dict[str, Any]] = []
|
||||
result: list[dict[str, Any]] = []
|
||||
|
||||
for model_key, model_config in config.classification.custom.items():
|
||||
if not model_config.enabled or model_config.object_config is None:
|
||||
@@ -248,8 +248,8 @@ def get_attribute_classifications(config: FrigateConfig) -> List[Dict[str, Any]]
|
||||
|
||||
def get_tool_definitions(
|
||||
semantic_search_enabled: bool = False,
|
||||
attribute_classifications: Optional[List[Dict[str, Any]]] = None,
|
||||
) -> List[Dict[str, Any]]:
|
||||
attribute_classifications: list[dict[str, Any]] | None = None,
|
||||
) -> list[dict[str, Any]]:
|
||||
"""
|
||||
Get OpenAI-compatible tool definitions for Frigate.
|
||||
|
||||
@@ -260,7 +260,7 @@ def get_tool_definitions(
|
||||
included. When attribute classification models are configured, an
|
||||
`attribute` parameter is exposed for filtering by their labels.
|
||||
"""
|
||||
search_objects_properties: Dict[str, Any] = {
|
||||
search_objects_properties: dict[str, Any] = {
|
||||
"camera": {
|
||||
"type": "string",
|
||||
"description": "Camera name to filter by (optional).",
|
||||
@@ -657,9 +657,9 @@ def get_tool_definitions(
|
||||
|
||||
def build_chat_system_prompt(
|
||||
config: FrigateConfig,
|
||||
allowed_cameras: List[str],
|
||||
allowed_cameras: list[str],
|
||||
semantic_search_enabled: bool,
|
||||
attribute_classifications: List[Dict[str, Any]],
|
||||
attribute_classifications: list[dict[str, Any]],
|
||||
) -> str:
|
||||
"""Build the system prompt for the chat completion endpoint.
|
||||
|
||||
@@ -671,7 +671,7 @@ def build_chat_system_prompt(
|
||||
current_date_str = current_datetime.strftime("%Y-%m-%d")
|
||||
current_time_str = current_datetime.strftime("%I:%M:%S %p")
|
||||
|
||||
cameras_info: List[str] = []
|
||||
cameras_info: list[str] = []
|
||||
has_speed_zone = False
|
||||
for camera_id in allowed_cameras:
|
||||
if camera_id not in config.cameras:
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, List, Optional
|
||||
from typing import Any
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def parse_tool_calls_from_message(
|
||||
message: dict[str, Any],
|
||||
) -> Optional[list[dict[str, Any]]]:
|
||||
) -> list[dict[str, Any]] | None:
|
||||
"""
|
||||
Parse tool_calls from an OpenAI-style message dict.
|
||||
|
||||
@@ -52,7 +52,7 @@ def parse_tool_calls_from_message(
|
||||
|
||||
def build_assistant_message_for_conversation(
|
||||
content: Any,
|
||||
tool_calls_raw: Optional[List[dict[str, Any]]],
|
||||
tool_calls_raw: list[dict[str, Any]] | None,
|
||||
) -> dict[str, Any]:
|
||||
"""
|
||||
Build the assistant message dict in OpenAI format for appending to a conversation.
|
||||
|
||||
Reference in New Issue
Block a user