Implement similarity search

This commit is contained in:
Nicolas Mowen 2024-06-22 15:29:48 -06:00
parent 2418111cd4
commit ebcae504cd
3 changed files with 67 additions and 18 deletions

View File

@ -16,10 +16,12 @@ import { toast } from "sonner";
type SearchDetailDialogProps = {
search?: SearchResult;
setSearch: (search: SearchResult | undefined) => void;
setSimilarity?: () => void;
};
export default function SearchDetailDialog({
search,
setSearch,
setSimilarity,
}: SearchDetailDialogProps) {
const { data: config } = useSWR<FrigateConfig>("config", {
revalidateOnFocus: false,
@ -31,6 +33,7 @@ export default function SearchDetailDialog({
const [desc, setDesc] = useState(search?.description);
// we have to make sure the current selected search item stays in sync
useEffect(() => setDesc(search?.description), [search]);
const formattedDate = useFormattedTimestamp(
@ -129,7 +132,17 @@ export default function SearchDetailDialog({
: `${apiHost}api/events/${search.id}/thumbnail.jpg`
}
/>
<Button>Find Similar</Button>
<Button
onClick={() => {
setSearch(undefined);
if (setSimilarity) {
setSimilarity();
}
}}
>
Find Similar
</Button>
</div>
</div>
<div className="flex flex-col gap-1.5">

View File

@ -38,7 +38,13 @@ export default function Search() {
// search api
const [similaritySearch, setSimilaritySearch] = useState<SearchResult>();
useEffect(() => {
if (similaritySearch) {
setSimilaritySearch(undefined);
}
if (searchTimeout) {
clearTimeout(searchTimeout);
}
@ -53,22 +59,43 @@ export default function Search() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [search]);
const { data: searchResults, isLoading } = useSWR<SearchResult[]>(
searchTerm.length > 0
? [
"events/search",
{
query: searchTerm,
cameras: searchSearchParams["cameras"],
labels: searchSearchParams["labels"],
zones: searchSearchParams["zones"],
before: searchSearchParams["before"],
after: searchSearchParams["after"],
include_thumbnails: 0,
},
]
: null,
);
const searchQuery = useMemo(() => {
if (searchTerm.length == 0) {
return null;
}
if (similaritySearch) {
return [
"events/search",
{
query: similaritySearch.id,
cameras: searchSearchParams["cameras"],
labels: searchSearchParams["labels"],
zones: searchSearchParams["zones"],
before: searchSearchParams["before"],
after: searchSearchParams["after"],
include_thumbnails: 0,
search_type: "thumbnail",
},
];
}
return [
"events/search",
{
query: searchTerm,
cameras: searchSearchParams["cameras"],
labels: searchSearchParams["labels"],
zones: searchSearchParams["zones"],
before: searchSearchParams["before"],
after: searchSearchParams["after"],
include_thumbnails: 0,
},
];
}, [searchTerm, searchSearchParams, similaritySearch]);
const { data: searchResults, isLoading } =
useSWR<SearchResult[]>(searchQuery);
const previewTimeRange = useMemo<TimeRange>(() => {
if (!searchResults) {
@ -164,6 +191,7 @@ export default function Search() {
allPreviews={allPreviews}
isLoading={isLoading}
setSearch={setSearch}
setSimilaritySearch={setSimilaritySearch}
onUpdateFilter={onUpdateFilter}
onOpenSearch={onOpenSearch}
/>

View File

@ -18,6 +18,7 @@ type SearchViewProps = {
allPreviews?: Preview[];
isLoading: boolean;
setSearch: (search: string) => void;
setSimilaritySearch: (search: SearchResult) => void;
onUpdateFilter: (filter: SearchFilter) => void;
onOpenSearch: (item: SearchResult) => void;
};
@ -29,6 +30,7 @@ export default function SearchView({
allPreviews,
isLoading,
setSearch,
setSimilaritySearch,
onUpdateFilter,
onOpenSearch,
}: SearchViewProps) {
@ -52,7 +54,13 @@ export default function SearchView({
return (
<div className="flex size-full flex-col pt-2 md:py-2">
<Toaster closeButton={true} />
<SearchDetailDialog search={searchDetail} setSearch={setSearchDetail} />
<SearchDetailDialog
search={searchDetail}
setSearch={setSearchDetail}
setSimilarity={
searchDetail && (() => setSimilaritySearch(searchDetail))
}
/>
<div className="relative mb-2 flex h-11 items-center justify-between pl-2 pr-2 md:pl-3">
<Input