Skip to content

Commit 194a537

Browse files
committed
VS-284: Enable query by id via Wrangler
1 parent ef3af25 commit 194a537

File tree

4 files changed

+142
-117
lines changed

4 files changed

+142
-117
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wrangler": minor
3+
---
4+
5+
feat: [VS-284] Enable Vectorize query by id via Wrangler

packages/wrangler/src/__tests__/vectorize/vectorize.test.ts

Lines changed: 80 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ describe("vectorize help", () => {
170170
-v, --version Show version number [boolean]
171171
172172
OPTIONS
173-
--vector Vector to query the Vectorize Index [array] [required]
173+
--vector Vector to query the Vectorize Index [array]
174+
--vector-id Identifier for a vector in the index against which the index should be queried [string]
174175
--top-k The number of results (nearest neighbors) to return [number] [default: 5]
175176
--return-values Specify if the vector values should be included in the results [boolean] [default: false]
176177
--return-metadata Specify if the vector metadata should be included in the results [string] [choices: \\"all\\", \\"indexed\\", \\"none\\"] [default: \\"none\\"]
@@ -514,87 +515,25 @@ describe("vectorize commands", () => {
514515
await runWrangler(
515516
"vectorize query test-index --vector 1 2 3 '4' 1.5 '2.6' a 'b' null 7 abc 8 undefined"
516517
);
517-
expect(std.out).toMatchInlineSnapshot(`
518-
"📋 Searching for relevant vectors...
519-
{
520-
\\"count\\": 2,
521-
\\"matches\\": [
522-
{
523-
\\"id\\": \\"a\\",
524-
\\"score\\": 0.5,
525-
\\"values\\": [
526-
1,
527-
2,
528-
3,
529-
4
530-
],
531-
\\"namespace\\": \\"abcd\\",
532-
\\"metadata\\": {
533-
\\"a\\": true,
534-
\\"b\\": 123
535-
}
536-
},
537-
{
538-
\\"id\\": \\"b\\",
539-
\\"score\\": 0.75,
540-
\\"values\\": [
541-
5,
542-
6,
543-
7,
544-
8
545-
],
546-
\\"metadata\\": {
547-
\\"c\\": false,
548-
\\"b\\": \\"123\\"
549-
}
550-
}
551-
]
552-
}"
553-
`);
518+
expect(std.out).toMatchInlineSnapshot(querySnapshot);
519+
});
520+
521+
it("should handle a query with a vector-id", async () => {
522+
mockVectorizeV2Request();
523+
await runWrangler("vectorize query test-index --vector-id some-vector-id");
524+
expect(std.out).toMatchInlineSnapshot(querySnapshot);
525+
526+
// No warning or error
527+
expect(std.warn).toMatchInlineSnapshot(`""`);
528+
expect(std.err).toMatchInlineSnapshot(`""`);
554529
});
555530

556531
it("should handle a query on a vectorize index with all options", async () => {
557532
mockVectorizeV2Request();
558533
await runWrangler(
559534
`vectorize query test-index --vector 1 2 3 '4' --top-k=2 --return-values=true --return-metadata=indexed --namespace=abc --filter '{ "p1": "abc", "p2": { "$ne": true }, "p3": 10, "p4": false, "nested.p5": "abcd" }'`
560535
);
561-
expect(std.out).toMatchInlineSnapshot(`
562-
"📋 Searching for relevant vectors...
563-
{
564-
\\"count\\": 2,
565-
\\"matches\\": [
566-
{
567-
\\"id\\": \\"a\\",
568-
\\"score\\": 0.5,
569-
\\"values\\": [
570-
1,
571-
2,
572-
3,
573-
4
574-
],
575-
\\"namespace\\": \\"abcd\\",
576-
\\"metadata\\": {
577-
\\"a\\": true,
578-
\\"b\\": 123
579-
}
580-
},
581-
{
582-
\\"id\\": \\"b\\",
583-
\\"score\\": 0.75,
584-
\\"values\\": [
585-
5,
586-
6,
587-
7,
588-
8
589-
],
590-
\\"metadata\\": {
591-
\\"c\\": false,
592-
\\"b\\": \\"123\\"
593-
}
594-
}
595-
]
596-
}"
597-
`);
536+
expect(std.out).toMatchInlineSnapshot(querySnapshot);
598537

599538
// No warning > Valid filter
600539
expect(std.warn).toMatchInlineSnapshot(`""`);
@@ -605,43 +544,7 @@ describe("vectorize commands", () => {
605544
await runWrangler(
606545
"vectorize query test-index --vector 1 2 3 '4' --filter='{ 'p1': [1,2,3] }'"
607546
);
608-
expect(std.out).toMatchInlineSnapshot(`
609-
"📋 Searching for relevant vectors...
610-
{
611-
\\"count\\": 2,
612-
\\"matches\\": [
613-
{
614-
\\"id\\": \\"a\\",
615-
\\"score\\": 0.5,
616-
\\"values\\": [
617-
1,
618-
2,
619-
3,
620-
4
621-
],
622-
\\"namespace\\": \\"abcd\\",
623-
\\"metadata\\": {
624-
\\"a\\": true,
625-
\\"b\\": 123
626-
}
627-
},
628-
{
629-
\\"id\\": \\"b\\",
630-
\\"score\\": 0.75,
631-
\\"values\\": [
632-
5,
633-
6,
634-
7,
635-
8
636-
],
637-
\\"metadata\\": {
638-
\\"c\\": false,
639-
\\"b\\": \\"123\\"
640-
}
641-
}
642-
]
643-
}"
644-
`);
547+
expect(std.out).toMatchInlineSnapshot(querySnapshot);
645548

646549
expect(std.warn).toMatchInlineSnapshot(`
647550
"▲ [WARNING] 🚨 Invalid query filter. Please use the recommended format.
@@ -660,6 +563,34 @@ describe("vectorize commands", () => {
660563
expect(std.warn).toMatchInlineSnapshot(`
661564
"▲ [WARNING] Could not find any relevant vectors
662565
566+
"
567+
`);
568+
});
569+
570+
it("should fail query when neither vector nor vector-id is provided", async () => {
571+
mockVectorizeV2RequestError();
572+
await runWrangler(
573+
"vectorize query test-index --top-k=2 --return-values=true"
574+
);
575+
expect(std.out).toMatchInlineSnapshot(`""`);
576+
577+
expect(std.err).toMatchInlineSnapshot(`
578+
"X [ERROR] 🚨 Either vector or vector-id param must be provided, but not both.
579+
580+
"
581+
`);
582+
});
583+
584+
it("should fail query when both vector and vector-id are provided", async () => {
585+
mockVectorizeV2RequestError();
586+
await runWrangler(
587+
"vectorize query test-index --vector 1 2 3 '4' --vector-id some-vector-id"
588+
);
589+
expect(std.out).toMatchInlineSnapshot(`""`);
590+
591+
expect(std.err).toMatchInlineSnapshot(`
592+
"X [ERROR] 🚨 Either vector or vector-id param must be provided, but not both.
593+
663594
"
664595
`);
665596
});
@@ -857,6 +788,43 @@ describe("vectorize query filter", () => {
857788
});
858789
});
859790

791+
const querySnapshot = `
792+
"📋 Searching for relevant vectors...
793+
{
794+
\\"count\\": 2,
795+
\\"matches\\": [
796+
{
797+
\\"id\\": \\"a\\",
798+
\\"score\\": 0.5,
799+
\\"values\\": [
800+
1,
801+
2,
802+
3,
803+
4
804+
],
805+
\\"namespace\\": \\"abcd\\",
806+
\\"metadata\\": {
807+
\\"a\\": true,
808+
\\"b\\": 123
809+
}
810+
},
811+
{
812+
\\"id\\": \\"b\\",
813+
\\"score\\": 0.75,
814+
\\"values\\": [
815+
5,
816+
6,
817+
7,
818+
8
819+
],
820+
\\"metadata\\": {
821+
\\"c\\": false,
822+
\\"b\\": \\"123\\"
823+
}
824+
}
825+
]
826+
}"`;
827+
860828
/** Create a mock handler for the Vectorize API */
861829
function mockVectorizeRequest() {
862830
msw.use(

packages/wrangler/src/vectorize/client.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export async function upsertIntoIndex(
131131
);
132132
}
133133

134-
export async function queryIndex(
134+
export async function queryIndexByVector(
135135
config: Config,
136136
indexName: string,
137137
vector: VectorFloatArray | number[],
@@ -153,6 +153,28 @@ export async function queryIndex(
153153
);
154154
}
155155

156+
export async function queryIndexByVectorId(
157+
config: Config,
158+
indexName: string,
159+
vectorId: string,
160+
options: VectorizeQueryOptions
161+
): Promise<VectorizeMatches> {
162+
const accountId = await requireAuth(config);
163+
return await fetchResult(
164+
`/accounts/${accountId}/vectorize/v2/indexes/${indexName}/query`,
165+
{
166+
method: "POST",
167+
headers: {
168+
"content-type": jsonContentType,
169+
},
170+
body: JSON.stringify({
171+
...options,
172+
vectorId,
173+
}),
174+
}
175+
);
176+
}
177+
156178
export async function getByIds(
157179
config: Config,
158180
indexName: string,

packages/wrangler/src/vectorize/query.ts

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { readConfig } from "../config";
22
import { logger } from "../logger";
3-
import { queryIndex } from "./client";
3+
import { queryIndexByVector, queryIndexByVectorId } from "./client";
44
import { vectorizeBetaWarning } from "./common";
55
import type {
66
CommonYargsArgv,
77
StrictYargsOptionsToInterface,
88
} from "../yargs-types";
99
import type {
10+
VectorizeMatches,
1011
VectorizeMetadataFilterInnerValue,
1112
VectorizeMetadataFilterValue,
1213
VectorizeMetadataRetrievalLevel,
@@ -26,7 +27,6 @@ export function options(yargs: CommonYargsArgv) {
2627
.options({
2728
vector: {
2829
type: "array",
29-
demandOption: true,
3030
describe: "Vector to query the Vectorize Index",
3131
coerce: (arg: unknown[]) =>
3232
arg
@@ -38,6 +38,11 @@ export function options(yargs: CommonYargsArgv) {
3838
typeof value === "number" && !isNaN(value)
3939
),
4040
},
41+
"vector-id": {
42+
type: "string",
43+
describe:
44+
"Identifier for a vector in the index against which the index should be queried",
45+
},
4146
"top-k": {
4247
type: "number",
4348
default: 5,
@@ -114,10 +119,35 @@ export async function handler(
114119
}
115120
}
116121

122+
if (
123+
(args.vector === undefined && args.vectorId === undefined) ||
124+
(args.vector !== undefined && args.vectorId !== undefined)
125+
) {
126+
logger.error(
127+
"🚨 Either vector or vector-id param must be provided, but not both."
128+
);
129+
return;
130+
}
131+
117132
logger.log(`📋 Searching for relevant vectors...`);
118-
const res = await queryIndex(config, args.name, args.vector, queryOptions);
133+
let res: VectorizeMatches | undefined;
134+
if (args.vector !== undefined) {
135+
res = await queryIndexByVector(
136+
config,
137+
args.name,
138+
args.vector,
139+
queryOptions
140+
);
141+
} else if (args.vectorId !== undefined) {
142+
res = await queryIndexByVectorId(
143+
config,
144+
args.name,
145+
args.vectorId,
146+
queryOptions
147+
);
148+
}
119149

120-
if (res.count === 0) {
150+
if (res === undefined || res.count === 0) {
121151
logger.warn(`Could not find any relevant vectors`);
122152
return;
123153
}

0 commit comments

Comments
 (0)