Skip to content

Commit efa7bcb

Browse files
committed
feat: enable vector search
1 parent 620e5ce commit efa7bcb

File tree

3 files changed

+28
-15
lines changed

3 files changed

+28
-15
lines changed

web/app/data/package.service.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { authorIdSchema } from "./author.shape";
77
import { groupBy, omit, uniqBy } from "es-toolkit";
88
import TTLCache from "@isaacs/ttlcache";
99
import { format, hoursToMilliseconds, minutesToMilliseconds } from "date-fns";
10+
import { google } from "@ai-sdk/google";
11+
import { embed } from "ai";
1012

1113
// import { embed } from "ai";
1214
// import { google } from "@ai-sdk/google";
@@ -207,16 +209,16 @@ export class PackageService {
207209
.ilike("name", query)
208210
.maybeSingle(),
209211
// TODO: Embedding search disabled until DB performance is improved.
210-
// isSimilaritySearchEnabled
211-
// ? supabase.rpc("match_package_embeddings", {
212-
// query_embedding: await embed({
213-
// value: query,
214-
// model: google.textEmbeddingModel("text-embedding-004"),
215-
// }).then((res) => res.embedding as unknown as string),
216-
// match_threshold: 0.4,
217-
// match_count: limit,
218-
// })
219-
// : null,
212+
isSimilaritySearchEnabled
213+
? supabase.rpc("match_package_embeddings", {
214+
query_embedding: await embed({
215+
value: query,
216+
model: google.textEmbeddingModel("text-embedding-004"),
217+
}).then((res) => res.embedding as unknown as string),
218+
match_threshold: 0.5,
219+
match_count: limit,
220+
})
221+
: null,
220222
{ data: [], error: null },
221223
isSimilaritySearchEnabled
222224
? supabase.rpc("find_closest_package_embeddings", {

web/app/modules/search.nav.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
} from "./search.hit";
2727
import { SearchInput } from "./search.input";
2828
import { ProvidedByLabel } from "./provided-by-label";
29+
import { RiProgress8Fill } from "@remixicon/react";
2930

3031
type Props = {
3132
searchContentRef: RefObject<HTMLDivElement>;
@@ -53,6 +54,8 @@ export function NavSearch(props: Props) {
5354
} = props;
5455

5556
const fetcher = useFetcher();
57+
const isBusy = fetcher.state === "loading" || fetcher.state === "submitting";
58+
5659
const actionData =
5760
(fetcher.data as SearchHitsResults | undefined) || fallbackSearchResults;
5861

@@ -64,7 +67,7 @@ export function NavSearch(props: Props) {
6467
action: "/api/search?index",
6568
});
6669
},
67-
150,
70+
300,
6871
{
6972
edges: ["trailing"],
7073
},
@@ -143,6 +146,12 @@ export function NavSearch(props: Props) {
143146
inputClassName={inputClassName}
144147
onChange={onChange}
145148
/>
149+
{isBusy ? (
150+
<div className="text-gray-ui absolute right-1 top-5 animate-fade">
151+
<RiProgress8Fill size={18} className="animate-pulse" />
152+
</div>
153+
) : null}
154+
146155
{isFocused && searchContentRef.current && actionData ? (
147156
<ClientOnly>
148157
{() =>
@@ -151,6 +160,7 @@ export function NavSearch(props: Props) {
151160
state={fetcher.state}
152161
data={actionData}
153162
isDataExpected={input.length > 0}
163+
isBusy={isBusy}
154164
onSelect={onSelect}
155165
/>,
156166
searchContentRef.current!,
@@ -167,10 +177,11 @@ export function SearchResults(
167177
state: "idle" | "loading" | "submitting";
168178
data: SearchHitsResults;
169179
isDataExpected?: boolean;
180+
isBusy?: boolean;
170181
onSelect: (item?: BaseSearchHit | PackageSemanticSearchHit) => void;
171182
}>,
172183
) {
173-
const { data, isDataExpected, onSelect, children } = props;
184+
const { data, isDataExpected, isBusy, onSelect, children } = props;
174185
const { combined } = data;
175186
const hasAnyHits = combined.length > 0;
176187

@@ -220,7 +231,7 @@ export function SearchResults(
220231
))}
221232
</ul>
222233
</div>
223-
) : (
234+
) : isBusy ? null : (
224235
<p className="text-gray-dim">No results found</p>
225236
)}
226237
</section>

web/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)