Skip to content

Commit 8d3df6f

Browse files
authored
test(client-s3vectors): add e2e test (#7487)
1 parent ba1aeb6 commit 8d3df6f

File tree

3 files changed

+132
-1
lines changed

3 files changed

+132
-1
lines changed

clients/client-s3vectors/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
"build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4",
1212
"clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0",
1313
"extract:docs": "api-extractor run --local",
14-
"generate:client": "node ../../scripts/generate-clients/single-service --solo s3vectors"
14+
"generate:client": "node ../../scripts/generate-clients/single-service --solo s3vectors",
15+
"test:e2e": "yarn g:vitest run -c vitest.config.e2e.mts",
16+
"test:e2e:watch": "yarn g:vitest watch -c vitest.config.e2e.mts"
1517
},
1618
"main": "./dist-cjs/index.js",
1719
"types": "./dist-types/index.d.ts",
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { BedrockRuntime } from "@aws-sdk/client-bedrock-runtime";
2+
import { S3Vectors } from "@aws-sdk/client-s3vectors";
3+
import { beforeEach, describe, expect, test as it } from "vitest";
4+
5+
describe(
6+
S3Vectors.name,
7+
() => {
8+
const s3v = new S3Vectors({
9+
region: "us-west-2",
10+
});
11+
const rock = new BedrockRuntime({
12+
region: "us-west-2",
13+
});
14+
15+
const VECTOR_BUCKET_NAME = "jsv3-e2e-vector";
16+
17+
beforeEach(async () => {
18+
async function checkForBucket() {
19+
const buckets = await s3v.listVectorBuckets({
20+
prefix: VECTOR_BUCKET_NAME,
21+
});
22+
23+
return buckets.vectorBuckets?.some((bucket) => bucket.vectorBucketName === VECTOR_BUCKET_NAME);
24+
}
25+
26+
const testBucket = await checkForBucket();
27+
28+
if (!testBucket) {
29+
await s3v.createVectorBucket({
30+
vectorBucketName: VECTOR_BUCKET_NAME,
31+
});
32+
await s3v.createIndex({
33+
vectorBucketName: VECTOR_BUCKET_NAME,
34+
indexName: "characters",
35+
dataType: "float32",
36+
dimension: 1024,
37+
distanceMetric: "cosine",
38+
});
39+
}
40+
41+
while (true) {
42+
const testBucket = await checkForBucket();
43+
if (!testBucket) {
44+
await new Promise((r) => setTimeout(r, 5000));
45+
} else {
46+
break;
47+
}
48+
}
49+
});
50+
51+
it("can put vectors", async () => {
52+
const texts = [
53+
"Santa Bear is a bear who wears a Santa outfit.",
54+
"Saucey is a tiger who is rotund.",
55+
`Tigey is a tiger who likes to say "woof".`,
56+
];
57+
58+
const embeddings: number[][] = [];
59+
for (const text of texts) {
60+
const invoke = await rock.invokeModel({
61+
modelId: "amazon.titan-embed-text-v2:0",
62+
body: JSON.stringify({
63+
inputText: text,
64+
}),
65+
});
66+
embeddings.push([...invoke.body].slice(0, 1024));
67+
}
68+
69+
await s3v.putVectors({
70+
vectorBucketName: VECTOR_BUCKET_NAME,
71+
indexName: "characters",
72+
vectors: [
73+
{
74+
key: "Santa Bear",
75+
data: { float32: embeddings[0] },
76+
metadata: { source_text: texts[0], genre: "bear" },
77+
},
78+
{
79+
key: "Saucey",
80+
data: { float32: embeddings[1] },
81+
metadata: { source_text: texts[1], genre: "tiger" },
82+
},
83+
{
84+
key: "Tigey",
85+
data: { float32: embeddings[2] },
86+
metadata: { source_text: texts[2], genre: "tiger" },
87+
},
88+
],
89+
});
90+
});
91+
92+
it("can query vectors", async () => {
93+
const invoke = await rock.invokeModel({
94+
modelId: "amazon.titan-embed-text-v2:0",
95+
body: JSON.stringify({
96+
inputText: "characters who are tigers or bears",
97+
}),
98+
});
99+
100+
const embedding = invoke.body;
101+
102+
const query = await s3v.queryVectors({
103+
vectorBucketName: VECTOR_BUCKET_NAME,
104+
indexName: "characters",
105+
queryVector: {
106+
float32: [...embedding].slice(0, 1024),
107+
},
108+
topK: 3,
109+
returnDistance: true,
110+
returnMetadata: true,
111+
});
112+
113+
expect(query.vectors?.some((v) => v.key === "Tigey")).toBeDefined();
114+
expect(query.vectors?.some((v) => v.key === "Santa Bear")).toBeDefined();
115+
expect(query.vectors?.some((v) => v.key === "Saucey")).toBeDefined();
116+
});
117+
},
118+
120_000
119+
);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { defineConfig } from "vitest/config";
2+
3+
export default defineConfig({
4+
test: {
5+
exclude: ["**/*.browser.e2e.spec.ts"],
6+
include: ["**/*.e2e.spec.ts"],
7+
environment: "node",
8+
},
9+
mode: "development",
10+
});

0 commit comments

Comments
 (0)