mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-08-04 01:48:54 +03:00
Reject non-finite numbers in GenAI review descriptions
A model returning NaN for confidence or potential_threat_level slipped through the model_construct fallback, which skips validation, and was written into the review segment's JSON data. NaN is not valid JSON, so every subsequent /review request failed with "Out of range float values are not JSON compliant", blanking the review page for any time range containing the poisoned row.
This commit is contained in:
@@ -23,6 +23,7 @@ from frigate.genai.prompts import (
|
|||||||
build_review_summary_prompt,
|
build_review_summary_prompt,
|
||||||
)
|
)
|
||||||
from frigate.models import Event
|
from frigate.models import Event
|
||||||
|
from frigate.util.builtin import has_non_finite_number
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -164,6 +165,15 @@ class GenAIClient:
|
|||||||
except json.JSONDecodeError as je:
|
except json.JSONDecodeError as je:
|
||||||
logger.error("Failed to parse review description JSON: %s", je)
|
logger.error("Failed to parse review description JSON: %s", je)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# model_construct skips validation, so non-finite numbers that
|
||||||
|
# the validated path would have rejected have to be caught here
|
||||||
|
if has_non_finite_number(raw):
|
||||||
|
logger.error(
|
||||||
|
"Discarding review description containing non-finite numbers."
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
# observations and confidence are required on the model; fill an empty default
|
# observations and confidence are required on the model; fill an empty default
|
||||||
# if the response omitted it so attribute access stays safe.
|
# if the response omitted it so attribute access stays safe.
|
||||||
raw.setdefault("observations", [])
|
raw.setdefault("observations", [])
|
||||||
|
|||||||
@@ -472,6 +472,18 @@ def sanitize_float(value):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def has_non_finite_number(value: Any) -> bool:
|
||||||
|
"""Return True if any number in a parsed JSON value is NaN or infinite."""
|
||||||
|
if isinstance(value, float):
|
||||||
|
return not math.isfinite(value)
|
||||||
|
if isinstance(value, dict):
|
||||||
|
return any(has_non_finite_number(v) for v in value.values())
|
||||||
|
if isinstance(value, list):
|
||||||
|
return any(has_non_finite_number(v) for v in value)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def cosine_similarity(a: np.ndarray, b: np.ndarray) -> float:
|
def cosine_similarity(a: np.ndarray, b: np.ndarray) -> float:
|
||||||
return 1 - cosine_distance(a, b)
|
return 1 - cosine_distance(a, b)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user