mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-04-11 09:37:37 +03:00
add jina clip as service provider
This commit is contained in:
parent
39fc9e37e1
commit
37dc0fd7cb
@ -82,13 +82,15 @@ Switching between V1 and V2 requires reindexing your embeddings. The embeddings
|
|||||||
|
|
||||||
### Remote Providers
|
### Remote Providers
|
||||||
|
|
||||||
Frigate can be configured to use remote services for generating embeddings. This is done by setting the `provider` field to `openai` or `ollama`.
|
Frigate can be configured to use remote services for generating embeddings. This is done by setting the `provider` field to `openai`, `ollama`, or `clip_as_service`.
|
||||||
|
|
||||||
For vision embeddings, remote providers use a two-step process:
|
#### OpenAI and Ollama
|
||||||
|
|
||||||
|
For OpenAI and Ollama, vision embeddings use a two-step process:
|
||||||
1. A text description of the image is generated using the configured GenAI provider.
|
1. A text description of the image is generated using the configured GenAI provider.
|
||||||
2. An embedding is created from that description using the configured remote embedding provider.
|
2. An embedding is created from that description using the configured remote embedding provider.
|
||||||
|
|
||||||
This means that you must have a GenAI provider configured to use vision embeddings with a remote provider.
|
This means that you must have a GenAI provider configured to use vision embeddings with these providers.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
semantic_search:
|
semantic_search:
|
||||||
@ -99,6 +101,21 @@ semantic_search:
|
|||||||
vision_model_prompt: "A detailed description of the image for semantic search."
|
vision_model_prompt: "A detailed description of the image for semantic search."
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Jina CLIP-as-Service
|
||||||
|
|
||||||
|
Frigate supports [Jina CLIP-as-Service](https://clip-as-service.jina.ai/) which provides a multi-modal embedding service that can be hosted locally or remotely. This provider supports both text and image embeddings directly, without requiring a separate GenAI provider for image descriptions.
|
||||||
|
|
||||||
|
You can run CLIP-as-Service using their [getting started guide](https://clip-as-service.jina.ai/user-guides/server/).
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
semantic_search:
|
||||||
|
enabled: True
|
||||||
|
provider: clip_as_service
|
||||||
|
remote:
|
||||||
|
url: "http://localhost:51000"
|
||||||
|
# model is typically handled by the service configuration
|
||||||
|
```
|
||||||
|
|
||||||
### GPU Acceleration
|
### GPU Acceleration
|
||||||
|
|
||||||
The CLIP models are downloaded in ONNX format, and the `large` model can be accelerated using GPU hardware, when available. This depends on the Docker build that is used. You can also target a specific device in a multi-GPU installation.
|
The CLIP models are downloaded in ONNX format, and the `large` model can be accelerated using GPU hardware, when available. This depends on the Docker build that is used. You can also target a specific device in a multi-GPU installation.
|
||||||
|
|||||||
@ -118,6 +118,7 @@ class SemanticSearchProviderEnum(str, Enum):
|
|||||||
local = "local"
|
local = "local"
|
||||||
openai = "openai"
|
openai = "openai"
|
||||||
ollama = "ollama"
|
ollama = "ollama"
|
||||||
|
clip_as_service = "clip_as_service"
|
||||||
|
|
||||||
|
|
||||||
class RemoteSemanticSearchConfig(FrigateBaseModel):
|
class RemoteSemanticSearchConfig(FrigateBaseModel):
|
||||||
|
|||||||
81
frigate/embeddings/remote/clip_as_service.py
Normal file
81
frigate/embeddings/remote/clip_as_service.py
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
"""Clip-as-service embedding client for Frigate."""
|
||||||
|
|
||||||
|
import base64
|
||||||
|
import logging
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from frigate.config import SemanticSearchProviderEnum
|
||||||
|
from frigate.embeddings.remote import (
|
||||||
|
RemoteEmbeddingClient,
|
||||||
|
register_embedding_provider,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@register_embedding_provider(SemanticSearchProviderEnum.clip_as_service)
|
||||||
|
class ClipAsServiceEmbeddingClient(RemoteEmbeddingClient):
|
||||||
|
"""Remote embedding client for Frigate using clip-as-service."""
|
||||||
|
|
||||||
|
def _init_provider(self):
|
||||||
|
"""Initialize the client."""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def embed_texts(self, texts: list[str]) -> Optional[list[list[float]]]:
|
||||||
|
"""Get embeddings for a list of texts."""
|
||||||
|
if not self.config.semantic_search.remote.url:
|
||||||
|
logger.error("Clip-as-service URL is not configured.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
"data": [{"text": t} for t in texts],
|
||||||
|
"exec_endpoint": "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.post(
|
||||||
|
f"{self.config.semantic_search.remote.url}/post",
|
||||||
|
json=payload,
|
||||||
|
timeout=self.timeout,
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
data = response.json()
|
||||||
|
if "data" in data:
|
||||||
|
return [item["embedding"] for item in data["data"]]
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("Clip-as-service error: %s", str(e))
|
||||||
|
return None
|
||||||
|
|
||||||
|
def embed_images(self, images: list[bytes]) -> Optional[list[list[float]]]:
|
||||||
|
"""Get embeddings for a list of images."""
|
||||||
|
if not self.config.semantic_search.remote.url:
|
||||||
|
logger.error("Clip-as-service URL is not configured.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
payload_data = []
|
||||||
|
for img_bytes in images:
|
||||||
|
b64_str = base64.b64encode(img_bytes).decode("utf-8")
|
||||||
|
payload_data.append({"blob": b64_str})
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
"data": payload_data,
|
||||||
|
"exec_endpoint": "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.post(
|
||||||
|
f"{self.config.semantic_search.remote.url}/post",
|
||||||
|
json=payload,
|
||||||
|
timeout=self.timeout,
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
data = response.json()
|
||||||
|
if "data" in data:
|
||||||
|
return [item["embedding"] for item in data["data"]]
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("Clip-as-service error: %s", str(e))
|
||||||
|
return None
|
||||||
Loading…
Reference in New Issue
Block a user