import Heading from "@/components/ui/heading"; import { FrigateConfig, SearchModelSize } from "@/types/frigateConfig"; import useSWR from "swr"; import axios from "axios"; import ActivityIndicator from "@/components/indicators/activity-indicator"; import { useCallback, useContext, useEffect, useState } from "react"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; import { Switch } from "@/components/ui/switch"; import { Toaster } from "@/components/ui/sonner"; import { toast } from "sonner"; import { Separator } from "@/components/ui/separator"; import { Link } from "react-router-dom"; import { LuExternalLink } from "react-icons/lu"; import { StatusBarMessagesContext } from "@/context/statusbar-provider"; import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, } from "@/components/ui/select"; type SearchSettingsViewProps = { setUnsavedChanges: React.Dispatch>; }; type SearchSettings = { enabled?: boolean; reindex?: boolean; model_size?: SearchModelSize; }; export default function SearchSettingsView({ setUnsavedChanges, }: SearchSettingsViewProps) { const { data: config, mutate: updateConfig } = useSWR("config"); const [changedValue, setChangedValue] = useState(false); const [isLoading, setIsLoading] = useState(false); const { addMessage, removeMessage } = useContext(StatusBarMessagesContext)!; const [searchSettings, setSearchSettings] = useState({ enabled: undefined, reindex: undefined, model_size: undefined, }); const [origSearchSettings, setOrigSearchSettings] = useState({ enabled: undefined, reindex: undefined, model_size: undefined, }); useEffect(() => { if (config) { if (searchSettings?.enabled == undefined) { setSearchSettings({ enabled: config.semantic_search.enabled, reindex: config.semantic_search.reindex, model_size: config.semantic_search.model_size, }); } setOrigSearchSettings({ enabled: config.semantic_search.enabled, reindex: config.semantic_search.reindex, model_size: config.semantic_search.model_size, }); } // we know that these deps are correct // eslint-disable-next-line react-hooks/exhaustive-deps }, [config]); const handleSearchConfigChange = (newConfig: Partial) => { setSearchSettings((prevConfig) => ({ ...prevConfig, ...newConfig })); setUnsavedChanges(true); setChangedValue(true); }; const saveToConfig = useCallback(async () => { setIsLoading(true); axios .put( `config/set?semantic_search.enabled=${searchSettings.enabled ? "True" : "False"}&semantic_search.reindex=${searchSettings.reindex ? "True" : "False"}&semantic_search.model_size=${searchSettings.model_size}`, { requires_restart: 0, }, ) .then((res) => { if (res.status === 200) { toast.success("Explore settings have been saved.", { position: "top-center", }); setChangedValue(false); updateConfig(); } else { toast.error(`Failed to save config changes: ${res.statusText}`, { position: "top-center", }); } }) .catch((error) => { const errorMessage = error.response?.data?.message || error.response?.data?.detail || "Unknown error"; toast.error(`Failed to save config changes: ${errorMessage}`, { position: "top-center", }); }) .finally(() => { setIsLoading(false); }); }, [ updateConfig, searchSettings.enabled, searchSettings.reindex, searchSettings.model_size, ]); const onCancel = useCallback(() => { setSearchSettings(origSearchSettings); setChangedValue(false); removeMessage("search_settings", "search_settings"); }, [origSearchSettings, removeMessage]); useEffect(() => { if (changedValue) { addMessage( "search_settings", `Unsaved Explore settings changes`, undefined, "search_settings", ); } else { removeMessage("search_settings", "search_settings"); } // we know that these deps are correct // eslint-disable-next-line react-hooks/exhaustive-deps }, [changedValue]); useEffect(() => { document.title = "Explore Settings - Frigate"; }, []); if (!config) { return ; } return (
Explore Settings Semantic Search

Semantic Search in Frigate allows you to find tracked objects within your review items using either the image itself, a user-defined text description, or an automatically generated one.

Read the Documentation
{ handleSearchConfigChange({ enabled: isChecked }); }} />
{ handleSearchConfigChange({ reindex: isChecked }); }} />
Re-indexing will reprocess all thumbnails and descriptions (if enabled) and apply the embeddings on each startup.{" "} Don't forget to disable the option after restarting!
Model Size

The size of the model used for Semantic Search embeddings.

  • Using small employs a quantized version of the model that uses less RAM and runs faster on CPU with a very negligible difference in embedding quality.
  • Using large employs the full Jina model and will automatically run on the GPU if applicable.
); }