mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
Search UI tweaks and bugfixes (#14328)
* Publish model state and embeddings reindex in dispatcher onConnect * remove unneeded from explore * add embeddings reindex progress to statusbar * don't allow right click or show similar button if semantic search is disabled * fix status bar
This commit is contained in:
parent
833768172d
commit
4ca267ea17
@ -179,6 +179,11 @@ class Dispatcher:
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.publish("camera_activity", json.dumps(camera_status))
|
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
|
# Dictionary mapping topic to handlers
|
||||||
topic_handlers = {
|
topic_handlers = {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { useEmbeddingsReindexProgress } from "@/api/ws";
|
||||||
import {
|
import {
|
||||||
StatusBarMessagesContext,
|
StatusBarMessagesContext,
|
||||||
StatusMessage,
|
StatusMessage,
|
||||||
@ -41,6 +42,23 @@ export default function Statusbar() {
|
|||||||
});
|
});
|
||||||
}, [potentialProblems, addMessage, clearMessages]);
|
}, [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 (
|
return (
|
||||||
<div className="absolute bottom-0 left-0 right-0 z-10 flex h-8 w-full items-center justify-between border-t border-secondary-highlight bg-background_alt px-4 dark:text-secondary-foreground">
|
<div className="absolute bottom-0 left-0 right-0 z-10 flex h-8 w-full items-center justify-between border-t border-secondary-highlight bg-background_alt px-4 dark:text-secondary-foreground">
|
||||||
<div className="flex h-full items-center gap-2">
|
<div className="flex h-full items-center gap-2">
|
||||||
|
@ -396,6 +396,7 @@ function ObjectDetailsTab({
|
|||||||
draggable={false}
|
draggable={false}
|
||||||
src={`${apiHost}api/events/${search.id}/thumbnail.jpg`}
|
src={`${apiHost}api/events/${search.id}/thumbnail.jpg`}
|
||||||
/>
|
/>
|
||||||
|
{config?.semantic_search.enabled && (
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSearch(undefined);
|
setSearch(undefined);
|
||||||
@ -407,6 +408,7 @@ function ObjectDetailsTab({
|
|||||||
>
|
>
|
||||||
Find Similar
|
Find Similar
|
||||||
</Button>
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-1.5">
|
<div className="flex flex-col gap-1.5">
|
||||||
|
@ -2,7 +2,6 @@ import {
|
|||||||
useEmbeddingsReindexProgress,
|
useEmbeddingsReindexProgress,
|
||||||
useEventUpdate,
|
useEventUpdate,
|
||||||
useModelState,
|
useModelState,
|
||||||
useWs,
|
|
||||||
} from "@/api/ws";
|
} from "@/api/ws";
|
||||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||||
import AnimatedCircularProgressBar from "@/components/ui/circular-progress-bar";
|
import AnimatedCircularProgressBar from "@/components/ui/circular-progress-bar";
|
||||||
@ -193,22 +192,11 @@ export default function Explore() {
|
|||||||
|
|
||||||
// embeddings reindex progress
|
// embeddings reindex progress
|
||||||
|
|
||||||
const { send: sendReindexCommand } = useWs(
|
const { payload: reindexState } = useEmbeddingsReindexProgress();
|
||||||
"embeddings_reindex_progress",
|
|
||||||
"embeddingsReindexProgress",
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
sendReindexCommand("embeddingsReindexProgress");
|
|
||||||
// only run on mount
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const { payload: reindexProgress } = useEmbeddingsReindexProgress();
|
|
||||||
|
|
||||||
const embeddingsReindexing = useMemo(() => {
|
const embeddingsReindexing = useMemo(() => {
|
||||||
if (reindexProgress) {
|
if (reindexState) {
|
||||||
switch (reindexProgress.status) {
|
switch (reindexState.status) {
|
||||||
case "indexing":
|
case "indexing":
|
||||||
return true;
|
return true;
|
||||||
case "completed":
|
case "completed":
|
||||||
@ -217,18 +205,10 @@ export default function Explore() {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [reindexProgress]);
|
}, [reindexState]);
|
||||||
|
|
||||||
// model states
|
// 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(
|
const { payload: textModelState } = useModelState(
|
||||||
"jinaai/jina-clip-v1-text_model_fp16.onnx",
|
"jinaai/jina-clip-v1-text_model_fp16.onnx",
|
||||||
);
|
);
|
||||||
@ -274,7 +254,8 @@ export default function Explore() {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
config?.semantic_search.enabled &&
|
config?.semantic_search.enabled &&
|
||||||
(!textModelState ||
|
(!reindexState ||
|
||||||
|
!textModelState ||
|
||||||
!textTokenizerState ||
|
!textTokenizerState ||
|
||||||
!visionModelState ||
|
!visionModelState ||
|
||||||
!visionFeatureExtractorState)
|
!visionFeatureExtractorState)
|
||||||
@ -303,24 +284,22 @@ export default function Explore() {
|
|||||||
<div className="pt-5 text-center">
|
<div className="pt-5 text-center">
|
||||||
<AnimatedCircularProgressBar
|
<AnimatedCircularProgressBar
|
||||||
min={0}
|
min={0}
|
||||||
max={reindexProgress.total_objects}
|
max={reindexState.total_objects}
|
||||||
value={reindexProgress.processed_objects}
|
value={reindexState.processed_objects}
|
||||||
gaugePrimaryColor="hsl(var(--selected))"
|
gaugePrimaryColor="hsl(var(--selected))"
|
||||||
gaugeSecondaryColor="hsl(var(--secondary))"
|
gaugeSecondaryColor="hsl(var(--secondary))"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex w-96 flex-col gap-2 py-5">
|
<div className="flex w-96 flex-col gap-2 py-5">
|
||||||
{reindexProgress.time_remaining !== null && (
|
{reindexState.time_remaining !== null && (
|
||||||
<div className="mb-3 flex flex-col items-center justify-center gap-1">
|
<div className="mb-3 flex flex-col items-center justify-center gap-1">
|
||||||
<div className="text-primary-variant">
|
<div className="text-primary-variant">
|
||||||
{reindexProgress.time_remaining === -1
|
{reindexState.time_remaining === -1
|
||||||
? "Starting up..."
|
? "Starting up..."
|
||||||
: "Estimated time remaining:"}
|
: "Estimated time remaining:"}
|
||||||
</div>
|
</div>
|
||||||
{reindexProgress.time_remaining >= 0 &&
|
{reindexState.time_remaining >= 0 &&
|
||||||
(formatSecondsToDuration(
|
(formatSecondsToDuration(reindexState.time_remaining) ||
|
||||||
reindexProgress.time_remaining,
|
|
||||||
) ||
|
|
||||||
"Finishing shortly")}
|
"Finishing shortly")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -328,20 +307,20 @@ export default function Explore() {
|
|||||||
<span className="text-primary-variant">
|
<span className="text-primary-variant">
|
||||||
Thumbnails embedded:
|
Thumbnails embedded:
|
||||||
</span>
|
</span>
|
||||||
{reindexProgress.thumbnails}
|
{reindexState.thumbnails}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row items-center justify-center gap-3">
|
<div className="flex flex-row items-center justify-center gap-3">
|
||||||
<span className="text-primary-variant">
|
<span className="text-primary-variant">
|
||||||
Descriptions embedded:
|
Descriptions embedded:
|
||||||
</span>
|
</span>
|
||||||
{reindexProgress.descriptions}
|
{reindexState.descriptions}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row items-center justify-center gap-3">
|
<div className="flex flex-row items-center justify-center gap-3">
|
||||||
<span className="text-primary-variant">
|
<span className="text-primary-variant">
|
||||||
Tracked objects processed:
|
Tracked objects processed:
|
||||||
</span>
|
</span>
|
||||||
{reindexProgress.processed_objects} /{" "}
|
{reindexState.processed_objects} /{" "}
|
||||||
{reindexProgress.total_objects}
|
{reindexState.total_objects}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@ -393,7 +393,11 @@ export default function SearchView({
|
|||||||
>
|
>
|
||||||
<SearchThumbnail
|
<SearchThumbnail
|
||||||
searchResult={value}
|
searchResult={value}
|
||||||
findSimilar={() => setSimilaritySearch(value)}
|
findSimilar={() => {
|
||||||
|
if (config?.semantic_search.enabled) {
|
||||||
|
setSimilaritySearch(value);
|
||||||
|
}
|
||||||
|
}}
|
||||||
onClick={() => onSelectSearch(value, index)}
|
onClick={() => onSelectSearch(value, index)}
|
||||||
/>
|
/>
|
||||||
{(searchTerm ||
|
{(searchTerm ||
|
||||||
|
Loading…
Reference in New Issue
Block a user