From 72c73b153c6ac29fb52f4ebcf06c58326da2cd00 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Thu, 19 Feb 2026 08:24:19 -0700 Subject: [PATCH] Fix sending images --- frigate/genai/llama_cpp.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/frigate/genai/llama_cpp.py b/frigate/genai/llama_cpp.py index 146f67726..654fdf5ca 100644 --- a/frigate/genai/llama_cpp.py +++ b/frigate/genai/llama_cpp.py @@ -1,12 +1,14 @@ """llama.cpp Provider for Frigate AI.""" import base64 +import io import json import logging from typing import Any, Optional import numpy as np import requests +from PIL import Image from frigate.config import GenAIProviderEnum from frigate.genai import GenAIClient, register_genai_provider @@ -14,6 +16,20 @@ from frigate.genai import GenAIClient, register_genai_provider logger = logging.getLogger(__name__) +def _to_jpeg(img_bytes: bytes) -> bytes | None: + """Convert image bytes to JPEG. llama.cpp/STB does not support WebP.""" + try: + img = Image.open(io.BytesIO(img_bytes)) + if img.mode != "RGB": + img = img.convert("RGB") + buf = io.BytesIO() + img.save(buf, format="JPEG", quality=85) + return buf.getvalue() + except Exception as e: + logger.warning("Failed to convert image to JPEG: %s", e) + return None + + @register_genai_provider(GenAIProviderEnum.llamacpp) class LlamaCppClient(GenAIClient): """Generative AI client for Frigate using llama.cpp server.""" @@ -130,8 +146,15 @@ class LlamaCppClient(GenAIClient): for text in texts: content.append({"prompt_string": text}) for img in images: - encoded = base64.b64encode(img).decode("utf-8") - content.append({"prompt_string": "", "multimodal_data": [encoded]}) + # llama.cpp uses STB which does not support WebP; convert to JPEG + jpeg_bytes = _to_jpeg(img) + to_encode = jpeg_bytes if jpeg_bytes is not None else img + encoded = base64.b64encode(to_encode).decode("utf-8") + # prompt_string must contain <__media__> placeholder for image tokenization + content.append({ + "prompt_string": "<__media__>\n", + "multimodal_data": [encoded], + }) try: response = requests.post(