Skip to content

Commit 132727b

Browse files
committed
chore: ensure that extra parameters are discarded
Voyage will reject all requests with extra parameters
1 parent d42ec2f commit 132727b

File tree

4 files changed

+29
-6
lines changed

4 files changed

+29
-6
lines changed

src/common/search/embeddingsProvider.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,33 @@ export const zVoyageModels = z
2727
.enum(["voyage-3-large", "voyage-3.5", "voyage-3.5-lite", "voyage-code-3"])
2828
.default("voyage-3-large");
2929

30+
// Zod does not undestand JS boxed numbers (like Int32) as integer literals,
31+
// so we preprocess them to unwrap them so Zod understands them.
32+
function unboxNumber(v: unknown): number {
33+
if (v && typeof v === "object" && typeof v.valueOf === "function") {
34+
const n = Number(v.valueOf());
35+
if (!Number.isNaN(n)) return n;
36+
}
37+
return v as number;
38+
}
39+
3040
export const zVoyageEmbeddingParameters = z.object({
3141
outputDimension: z
32-
.union([z.literal(256), z.literal(512), z.literal(1024), z.literal(2048), z.literal(4096)])
42+
.preprocess(
43+
unboxNumber,
44+
z.union([z.literal(256), z.literal(512), z.literal(1024), z.literal(2048), z.literal(4096)])
45+
)
3346
.optional()
3447
.default(1024),
35-
outputDType: z.enum(["float", "int8", "uint8", "binary", "ubinary"]).optional().default("float"),
48+
outputDtype: z.enum(["float", "int8", "uint8", "binary", "ubinary"]).optional().default("float"),
3649
});
3750

51+
const zVoyageAPIParameters = zVoyageEmbeddingParameters
52+
.extend({
53+
inputType: z.enum(["query", "document"]),
54+
})
55+
.strip();
56+
3857
type VoyageModels = z.infer<typeof zVoyageModels>;
3958
type VoyageEmbeddingParameters = z.infer<typeof zVoyageEmbeddingParameters> & EmbeddingParameters;
4059

@@ -62,11 +81,15 @@ class VoyageEmbeddingsProvider implements EmbeddingsProvider<VoyageModels, Voyag
6281
content: EmbeddingsInput[],
6382
parameters: VoyageEmbeddingParameters
6483
): Promise<Embeddings[]> {
84+
// This ensures that if we receive any random parameter from the outside (agent or us)
85+
// it's stripped before sending it to Voyage, as Voyage will reject the request on
86+
// a single unknown parameter.
87+
const voyage = zVoyageAPIParameters.parse(parameters);
6588
const model = this.voyage.textEmbeddingModel(modelId);
6689
const { embeddings } = await embedMany({
6790
model,
6891
values: content,
69-
providerOptions: { voyage: parameters },
92+
providerOptions: { voyage },
7093
});
7194

7295
return embeddings;

src/tools/mongodb/read/aggregate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export const AggregateArgs = {
6565
### Usage Rules for \`$vectorSearch\`
6666
- **Unset embeddings:**
6767
Unless the user explicitly requests the embeddings, add an \`$unset\` stage **at the end of the pipeline** to remove the embedding field and avoid context limits. **The $unset stage in this situation is mandatory**.
68-
- **Prefiltering:**
68+
- **Pre-filtering:**
6969
If the user requests additional filtering, include filters in \`$vectorSearch.filter\` only for pre-filter fields in the vector index.
7070
NEVER include fields in $vectorSearch.filter that are not part of the vector index.
7171
- **Post-filtering:**

tests/integration/tools/mongodb/read/aggregate.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ describeWithMongoDB("aggregate tool", (integration) => {
3232
### Usage Rules for \`$vectorSearch\`
3333
- **Unset embeddings:**
3434
Unless the user explicitly requests the embeddings, add an \`$unset\` stage **at the end of the pipeline** to remove the embedding field and avoid context limits. **The $unset stage in this situation is mandatory**.
35-
- **Prefiltering:**
35+
- **Pre-filtering:**
3636
If the user requests additional filtering, include filters in \`$vectorSearch.filter\` only for pre-filter fields in the vector index.
3737
NEVER include fields in $vectorSearch.filter that are not part of the vector index.
3838
- **Post-filtering:**

tests/unit/common/search/vectorSearchEmbeddingsManager.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ describe("VectorSearchEmbeddingsManager", () => {
396396
collection: "mycoll",
397397
path: "embedding_field",
398398
rawValues: ["oops"],
399-
embeddingParameters: { model: "voyage-3-large", outputDimension: 1024, outputDType: "float" } as const,
399+
embeddingParameters: { model: "voyage-3-large", outputDimension: 1024, outputDtype: "float" } as const,
400400
inputType: "query" as const,
401401
};
402402

0 commit comments

Comments
 (0)