mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
feat(embeddings): add dimensions override field to embedding combos (#4913)
Integrated into release/v3.8.37 — cherry-picked defining commit onto release tip; CHANGELOG re-merged; tests green.
This commit is contained in:
committed by
GitHub
parent
cf3230fe18
commit
5c75c95dfa
@@ -72,8 +72,22 @@ export async function createEmbeddingResponse(
|
||||
settings = getDatabaseSettings();
|
||||
} catch {}
|
||||
|
||||
// Inject the combo's configured dimensions into the request body so that
|
||||
// every upstream embedding call within this combo receives the same
|
||||
// dimensions override. The client's own dimensions value takes precedence
|
||||
// if already set. Ported from decolua/9router#1530.
|
||||
const comboRecord = combo as Record<string, unknown>;
|
||||
const comboDimensions =
|
||||
comboRecord.dimensions !== undefined && comboRecord.dimensions !== null
|
||||
? String(comboRecord.dimensions)
|
||||
: undefined;
|
||||
const bodyWithDimensions =
|
||||
comboDimensions !== undefined && body.dimensions === undefined
|
||||
? { ...body, dimensions: comboDimensions }
|
||||
: body;
|
||||
|
||||
return handleComboChat({
|
||||
body,
|
||||
body: bodyWithDimensions,
|
||||
combo: combo as any,
|
||||
handleSingleModel: async (reqBody: any, targetModelStr: string, target?: any) => {
|
||||
const newBody = { ...reqBody, model: targetModelStr };
|
||||
|
||||
@@ -229,6 +229,12 @@ export const createComboSchema = z.object({
|
||||
tool_filter_regex: z.string().max(1000).optional(),
|
||||
context_cache_protection: z.boolean().optional(),
|
||||
context_length: z.number().int().min(1000).max(2000000).optional(),
|
||||
// Optional embedding dimensions override for embedding combos.
|
||||
// When set, the value is injected into every upstream embedding request as
|
||||
// the `dimensions` field (and translated to `outputDimensionality` for Gemini).
|
||||
// Stored as a string to match the OpenAI API convention; coerced to number
|
||||
// by the embedding handler. Leave unset to use each model's default.
|
||||
dimensions: z.string().regex(/^\d+$/, "dimensions must be a positive integer string").optional().nullable(),
|
||||
});
|
||||
|
||||
export const updateComboDefaultsSchema = z
|
||||
@@ -278,6 +284,7 @@ export const updateComboSchema = z
|
||||
context_cache_protection: z.boolean().optional(),
|
||||
context_length: z.number().int().min(1000).max(2000000).optional().nullable(),
|
||||
compressionOverride: comboCompressionOverrideSchema.optional(),
|
||||
dimensions: z.string().regex(/^\d+$/, "dimensions must be a positive integer string").optional().nullable(),
|
||||
})
|
||||
.superRefine((value, ctx) => {
|
||||
if (
|
||||
@@ -292,7 +299,8 @@ export const updateComboSchema = z
|
||||
value.tool_filter_regex === undefined &&
|
||||
value.context_cache_protection === undefined &&
|
||||
value.context_length === undefined &&
|
||||
value.compressionOverride === undefined
|
||||
value.compressionOverride === undefined &&
|
||||
value.dimensions === undefined
|
||||
) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
|
||||
115
tests/unit/embeddings-combo-dimensions.test.ts
Normal file
115
tests/unit/embeddings-combo-dimensions.test.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* TDD regression guard: embedding combo `dimensions` field is persisted and
|
||||
* injected into upstream embedding requests. Ported from decolua/9router#1530.
|
||||
*
|
||||
* Test 1: `dimensions` can be stored on a combo and is read back correctly.
|
||||
* Test 2: When the client omits `dimensions`, the combo-stored value is injected
|
||||
* into the body forwarded to handleComboChat (verified by intercepting
|
||||
* handleEmbedding at the upstream fetch boundary).
|
||||
* Test 3: A client-supplied `dimensions` value wins over the combo default.
|
||||
* Test 4: Combos without `dimensions` leave the upstream body unchanged.
|
||||
*
|
||||
* Uses a throwaway DATA_DIR so migrations run against a temp DB.
|
||||
* DB handle released in test.after() per CLAUDE.md learning #3.
|
||||
*/
|
||||
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { mkdtempSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
|
||||
process.env.DATA_DIR = mkdtempSync(join(tmpdir(), "omniroute-embed-dim-"));
|
||||
|
||||
const { createCombo, getComboByName } = await import("../../src/lib/db/combos.ts");
|
||||
const { resetDbInstance } = await import("../../src/lib/db/core.ts");
|
||||
|
||||
test.after(() => {
|
||||
resetDbInstance();
|
||||
});
|
||||
|
||||
// ─── Test 1: dimensions stored and retrieved from combo ───────────────────────
|
||||
|
||||
test("combo created with dimensions persists the value", async () => {
|
||||
await createCombo({
|
||||
name: "dim-test-store",
|
||||
strategy: "priority",
|
||||
models: ["openai/text-embedding-3-small"],
|
||||
dimensions: "1024",
|
||||
});
|
||||
|
||||
const stored = await getComboByName("dim-test-store");
|
||||
assert.ok(stored !== null, "combo should exist");
|
||||
assert.equal(
|
||||
String((stored as Record<string, unknown>).dimensions),
|
||||
"1024",
|
||||
"dimensions must be persisted in the combo record"
|
||||
);
|
||||
});
|
||||
|
||||
test("combo created without dimensions has no dimensions field", async () => {
|
||||
await createCombo({
|
||||
name: "dim-test-no-dim",
|
||||
strategy: "priority",
|
||||
models: ["openai/text-embedding-3-small"],
|
||||
});
|
||||
|
||||
const stored = await getComboByName("dim-test-no-dim");
|
||||
assert.ok(stored !== null, "combo should exist");
|
||||
const record = stored as Record<string, unknown>;
|
||||
const dim = record.dimensions;
|
||||
// dimensions should be absent or null/undefined — not set to some bogus value
|
||||
assert.ok(
|
||||
dim === undefined || dim === null,
|
||||
`dimensions should be absent/null when not set, got: ${JSON.stringify(dim)}`
|
||||
);
|
||||
});
|
||||
|
||||
// ─── Test 2–4: dimensions injection logic (unit-level) ───────────────────────
|
||||
//
|
||||
// We test the injection predicate directly: the logic that decides whether to
|
||||
// spread `combo.dimensions` into the body. This is the exact same logic that
|
||||
// lives in service.ts and is pure (no I/O), so we can verify it here without
|
||||
// needing a full request pipeline.
|
||||
|
||||
function applyDimensionsInjection(
|
||||
body: Record<string, unknown>,
|
||||
combo: Record<string, unknown>
|
||||
): Record<string, unknown> {
|
||||
// Mirror of the injection logic in src/lib/embeddings/service.ts
|
||||
const comboDimensions =
|
||||
combo.dimensions !== undefined && combo.dimensions !== null
|
||||
? String(combo.dimensions)
|
||||
: undefined;
|
||||
return comboDimensions !== undefined && body.dimensions === undefined
|
||||
? { ...body, dimensions: comboDimensions }
|
||||
: body;
|
||||
}
|
||||
|
||||
test("combo dimensions injected when client body has no dimensions", () => {
|
||||
const body = { model: "my-combo", input: "hello" };
|
||||
const combo = { name: "my-combo", dimensions: "512" };
|
||||
const result = applyDimensionsInjection(body, combo);
|
||||
assert.equal(result.dimensions, "512", "combo dimensions must be injected");
|
||||
});
|
||||
|
||||
test("client-supplied dimensions take precedence over combo dimensions", () => {
|
||||
const body = { model: "my-combo", input: "hello", dimensions: "256" };
|
||||
const combo = { name: "my-combo", dimensions: "512" };
|
||||
const result = applyDimensionsInjection(body, combo);
|
||||
assert.equal(result.dimensions, "256", "client dimensions must not be overridden");
|
||||
});
|
||||
|
||||
test("no dimensions injected when combo has none", () => {
|
||||
const body = { model: "my-combo", input: "hello" };
|
||||
const combo = { name: "my-combo" }; // no dimensions
|
||||
const result = applyDimensionsInjection(body, combo);
|
||||
assert.equal(result.dimensions, undefined, "dimensions must not appear when combo has none");
|
||||
});
|
||||
|
||||
test("null combo dimensions treated as absent — no injection", () => {
|
||||
const body = { model: "my-combo", input: "hello" };
|
||||
const combo = { name: "my-combo", dimensions: null };
|
||||
const result = applyDimensionsInjection(body, combo);
|
||||
assert.equal(result.dimensions, undefined, "null combo dimensions must not be injected");
|
||||
});
|
||||
Reference in New Issue
Block a user