diff --git a/frigate/comms/dispatcher.py b/frigate/comms/dispatcher.py
index 4a3862eaf..1f480fa9c 100644
--- a/frigate/comms/dispatcher.py
+++ b/frigate/comms/dispatcher.py
@@ -179,6 +179,11 @@ class Dispatcher:
}
self.publish("camera_activity", json.dumps(camera_status))
+ self.publish("model_state", json.dumps(self.model_state.copy()))
+ self.publish(
+ "embeddings_reindex_progress",
+ json.dumps(self.embeddings_reindex.copy()),
+ )
# Dictionary mapping topic to handlers
topic_handlers = {
diff --git a/web/src/components/Statusbar.tsx b/web/src/components/Statusbar.tsx
index 41bd9372f..1b20b26f6 100644
--- a/web/src/components/Statusbar.tsx
+++ b/web/src/components/Statusbar.tsx
@@ -1,3 +1,4 @@
+import { useEmbeddingsReindexProgress } from "@/api/ws";
import {
StatusBarMessagesContext,
StatusMessage,
@@ -41,6 +42,23 @@ export default function Statusbar() {
});
}, [potentialProblems, addMessage, clearMessages]);
+ const { payload: reindexState } = useEmbeddingsReindexProgress();
+
+ useEffect(() => {
+ if (reindexState) {
+ if (reindexState.status == "indexing") {
+ clearMessages("embeddings-reindex");
+ addMessage(
+ "embeddings-reindex",
+ `Reindexing embeddings (${Math.floor((reindexState.processed_objects / reindexState.total_objects) * 100)}% complete)`,
+ );
+ }
+ if (reindexState.status === "completed") {
+ clearMessages("embeddings-reindex");
+ }
+ }
+ }, [reindexState, addMessage, clearMessages]);
+
return (
diff --git a/web/src/components/overlay/detail/SearchDetailDialog.tsx b/web/src/components/overlay/detail/SearchDetailDialog.tsx
index 94d28c7c8..1cee70aaa 100644
--- a/web/src/components/overlay/detail/SearchDetailDialog.tsx
+++ b/web/src/components/overlay/detail/SearchDetailDialog.tsx
@@ -396,17 +396,19 @@ function ObjectDetailsTab({
draggable={false}
src={`${apiHost}api/events/${search.id}/thumbnail.jpg`}
/>
-
+ )}
diff --git a/web/src/pages/Explore.tsx b/web/src/pages/Explore.tsx
index e4bb49521..03a60a8d0 100644
--- a/web/src/pages/Explore.tsx
+++ b/web/src/pages/Explore.tsx
@@ -2,7 +2,6 @@ import {
useEmbeddingsReindexProgress,
useEventUpdate,
useModelState,
- useWs,
} from "@/api/ws";
import ActivityIndicator from "@/components/indicators/activity-indicator";
import AnimatedCircularProgressBar from "@/components/ui/circular-progress-bar";
@@ -193,22 +192,11 @@ export default function Explore() {
// embeddings reindex progress
- const { send: sendReindexCommand } = useWs(
- "embeddings_reindex_progress",
- "embeddingsReindexProgress",
- );
-
- useEffect(() => {
- sendReindexCommand("embeddingsReindexProgress");
- // only run on mount
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
-
- const { payload: reindexProgress } = useEmbeddingsReindexProgress();
+ const { payload: reindexState } = useEmbeddingsReindexProgress();
const embeddingsReindexing = useMemo(() => {
- if (reindexProgress) {
- switch (reindexProgress.status) {
+ if (reindexState) {
+ switch (reindexState.status) {
case "indexing":
return true;
case "completed":
@@ -217,18 +205,10 @@ export default function Explore() {
return undefined;
}
}
- }, [reindexProgress]);
+ }, [reindexState]);
// model states
- const { send: sendModelCommand } = useWs("model_state", "modelState");
-
- useEffect(() => {
- sendModelCommand("modelState");
- // only run on mount
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
-
const { payload: textModelState } = useModelState(
"jinaai/jina-clip-v1-text_model_fp16.onnx",
);
@@ -274,7 +254,8 @@ export default function Explore() {
if (
config?.semantic_search.enabled &&
- (!textModelState ||
+ (!reindexState ||
+ !textModelState ||
!textTokenizerState ||
!visionModelState ||
!visionFeatureExtractorState)
@@ -303,24 +284,22 @@ export default function Explore() {
- {reindexProgress.time_remaining !== null && (
+ {reindexState.time_remaining !== null && (
- {reindexProgress.time_remaining === -1
+ {reindexState.time_remaining === -1
? "Starting up..."
: "Estimated time remaining:"}
- {reindexProgress.time_remaining >= 0 &&
- (formatSecondsToDuration(
- reindexProgress.time_remaining,
- ) ||
+ {reindexState.time_remaining >= 0 &&
+ (formatSecondsToDuration(reindexState.time_remaining) ||
"Finishing shortly")}
)}
@@ -328,20 +307,20 @@ export default function Explore() {
Thumbnails embedded:
- {reindexProgress.thumbnails}
+ {reindexState.thumbnails}
Descriptions embedded:
- {reindexProgress.descriptions}
+ {reindexState.descriptions}
Tracked objects processed:
- {reindexProgress.processed_objects} /{" "}
- {reindexProgress.total_objects}
+ {reindexState.processed_objects} /{" "}
+ {reindexState.total_objects}
>
diff --git a/web/src/views/search/SearchView.tsx b/web/src/views/search/SearchView.tsx
index 4c33f7dc8..e64affa36 100644
--- a/web/src/views/search/SearchView.tsx
+++ b/web/src/views/search/SearchView.tsx
@@ -393,7 +393,11 @@ export default function SearchView({
>
setSimilaritySearch(value)}
+ findSimilar={() => {
+ if (config?.semantic_search.enabled) {
+ setSimilaritySearch(value);
+ }
+ }}
onClick={() => onSelectSearch(value, index)}
/>
{(searchTerm ||