Files
OmniRoute/tests/unit/embedding-rerank-provider-registry.test.ts
Ravi Tharuma 3d0ffb49a4 feat(providers): complete Jina + Gemini Embedding 2 multimodal via OmniRoute (#10581)
* feat(providers): complete Jina AI via OmniRoute including Omni multimodal

Dashboard and env keys share one Jina credential pool, native v5 Omni
{text}/{image}/{content} docs pass through /v1/embeddings intact, and
classify/segment/search are proxied without a third unused Jina card.

* chore(changelog): name Jina complete-provider fragment for #10581

* feat(providers): make Gemini Embedding 2 multimodal work via OmniRoute

Route gemini-embedding-2 through embedContent/batchEmbedContents so N
OpenAI input items become N vectors, pass through native multimodal
parts, and use dashboard Gemini keys (GEMINI_API_KEY only as fallback).

* fix(providers): resolve rebase fallout for Jina/Gemini embeddings

- narrow the two new no-explicit-any violations introduced by this PR
  (validateJinaFoundationProvider's params + catch, search.ts's
  normalizeJinaSearchResponse data param)
- cast credentials to Record<string, unknown> at the two quota-preflight
  call sites in src/sse/services/auth.ts so the new JinaEnvCredentials /
  GeminiEnvCredentials union members type-check without loosening the
  allRateLimited narrowing used elsewhere in the same function

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: Ravi Tharuma <RaviTharuma@users.noreply.github.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
2026-08-18 10:52:43 -03:00

124 lines
5.3 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import {
getAllEmbeddingModels,
getEmbeddingProvider,
parseEmbeddingModel,
} from "../../open-sse/config/embeddingRegistry.ts";
import {
getAllRerankModels,
getRerankProvider,
parseRerankModel,
} from "../../open-sse/config/rerankRegistry.ts";
test("voyage-ai embedding registry exposes current embedding models", () => {
const provider = getEmbeddingProvider("voyage-ai");
assert.ok(provider);
assert.equal(provider.baseUrl, "https://api.voyageai.com/v1/embeddings");
assert.ok(provider.models.some((model) => model.id === "voyage-4-large"));
assert.ok(provider.models.some((model) => model.id === "voyage-code-3"));
assert.ok(provider.models.some((model) => model.id === "voyage-4"));
const parsed = parseEmbeddingModel("voyage-ai/voyage-4-large");
assert.equal(parsed.provider, "voyage-ai");
assert.equal(parsed.model, "voyage-4-large");
const all = getAllEmbeddingModels().filter((model) => model.provider === "voyage-ai");
assert.ok(all.length >= 3);
});
// #7351: voyage-multilingual-3.5 does not exist in the Voyage AI API — it was
// added to the registry by mistake and caused HTTP 400 on every test/request.
// voyage-multilingual-2 is the real model and was missing from the registry.
test("#7351 voyage-ai registry does not list non-existent voyage-multilingual-3.5", () => {
const provider = getEmbeddingProvider("voyage-ai");
assert.ok(provider);
assert.ok(
!provider.models.some((model) => model.id === "voyage-multilingual-3.5"),
"voyage-multilingual-3.5 must not be in the registry — it does not exist in the Voyage AI API"
);
});
test("#7351 voyage-ai registry includes voyage-multilingual-2 (real model)", () => {
const provider = getEmbeddingProvider("voyage-ai");
assert.ok(provider);
assert.ok(provider.models.some((model) => model.id === "voyage-multilingual-2"));
});
test("#7351 voyage-ai registry includes voyage-3.5 and voyage-3.5-lite", () => {
const provider = getEmbeddingProvider("voyage-ai");
assert.ok(provider);
assert.ok(provider.models.some((model) => model.id === "voyage-3.5"));
assert.ok(provider.models.some((model) => model.id === "voyage-3.5-lite"));
});
test("voyage-ai and jina-ai rerank registries expose supported models", () => {
const voyage = getRerankProvider("voyage-ai");
const jina = getRerankProvider("jina-ai");
assert.ok(voyage);
assert.equal(voyage.baseUrl, "https://api.voyageai.com/v1/rerank");
assert.ok(voyage.models.some((model) => model.id === "rerank-2.5"));
assert.ok(voyage.models.some((model) => model.id === "rerank-2.5-lite"));
assert.ok(jina);
assert.equal(jina.baseUrl, "https://api.jina.ai/v1/rerank");
assert.ok(jina.models.some((model) => model.id === "jina-reranker-v3.5"));
assert.ok(jina.models.some((model) => model.id === "jina-reranker-v3"));
assert.ok(jina.models.some((model) => model.id === "jina-reranker-m0"));
const parsedVoyage = parseRerankModel("voyage-ai/rerank-2.5");
assert.equal(parsedVoyage.provider, "voyage-ai");
assert.equal(parsedVoyage.model, "rerank-2.5");
const parsedJina = parseRerankModel("jina-ai/jina-reranker-v3");
assert.equal(parsedJina.provider, "jina-ai");
assert.equal(parsedJina.model, "jina-reranker-v3");
const parsedJinaAlias = parseRerankModel("jina/jina-reranker-v3");
assert.equal(parsedJinaAlias.provider, "jina-ai");
assert.equal(parsedJinaAlias.model, "jina-reranker-v3");
const all = getAllRerankModels();
assert.ok(all.some((model) => model.id === "voyage-ai/rerank-2.5"));
assert.ok(all.some((model) => model.id === "jina-ai/jina-reranker-v3"));
});
test("upstage embedding registry exposes current embedding models", () => {
const provider = getEmbeddingProvider("upstage");
assert.ok(provider);
assert.equal(provider.baseUrl, "https://api.upstage.ai/v1/embeddings");
assert.ok(provider.models.some((model) => model.id === "embedding-query"));
assert.ok(provider.models.some((model) => model.id === "embedding-passage"));
const parsed = parseEmbeddingModel("upstage/embedding-query");
assert.equal(parsed.provider, "upstage");
assert.equal(parsed.model, "embedding-query");
const all = getAllEmbeddingModels().filter((model) => model.provider === "upstage");
assert.deepEqual(
all.map((model) => model.id),
["upstage/embedding-query", "upstage/embedding-passage"]
);
});
test("nvidia embedding and rerank parsing preserves provider-prefixed upstream model IDs", () => {
const parsedEmbedding = parseEmbeddingModel("nvidia/nv-embedqa-e5-v5");
assert.equal(parsedEmbedding.provider, "nvidia");
assert.equal(parsedEmbedding.model, "nvidia/nv-embedqa-e5-v5");
const parsedDoublePrefixedEmbedding = parseEmbeddingModel("nvidia/nvidia/nv-embedqa-e5-v5");
assert.equal(parsedDoublePrefixedEmbedding.provider, "nvidia");
assert.equal(parsedDoublePrefixedEmbedding.model, "nvidia/nv-embedqa-e5-v5");
const parsedRerank = parseRerankModel("nvidia/nv-rerankqa-mistral-4b-v3");
assert.equal(parsedRerank.provider, "nvidia");
assert.equal(parsedRerank.model, "nvidia/nv-rerankqa-mistral-4b-v3");
const parsedDoublePrefixedRerank = parseRerankModel("nvidia/nvidia/nv-rerankqa-mistral-4b-v3");
assert.equal(parsedDoublePrefixedRerank.provider, "nvidia");
assert.equal(parsedDoublePrefixedRerank.model, "nvidia/nv-rerankqa-mistral-4b-v3");
});