diff --git a/src/core/ai/recipes/dashscope-rerank.ts b/src/core/ai/recipes/dashscope-rerank.ts deleted file mode 100644 index 155c20b56..000000000 --- a/src/core/ai/recipes/dashscope-rerank.ts +++ /dev/null @@ -1,61 +0,0 @@ -import type { Recipe } from '../types.ts'; - -/** - * Alibaba DashScope (灵积) reranker. DashScope's OpenAI-compatible surface - * splits by capability: embeddings live under `/compatible-mode/v1` (see the - * sibling `dashscope` recipe) while rerank lives under `/compatible-api/v1` - * with a PLURAL leaf — `POST {base}/reranks`. Wire shape matches ZeroEntropy: - * request `{model, query, documents, top_n?}`, response - * `{results: [{index, relevance_score}]}` — so it rides gateway.rerank()'s - * native path with only the recipe-pluggable `path` override (v0.40.6.1). - * - * This is a SEPARATE recipe rather than a reranker touchpoint on `dashscope` - * because the two capabilities need different base URLs (`compatible-mode` - * vs `compatible-api`) and `provider_base_urls` is keyed by recipe id — one - * recipe can't point embeddings and rerank at different prefixes. Same - * topology precedent as llama-server vs llama-server-reranker. - * - * Live-verified against the China endpoint (2026-07): `/reranks` with - * `qwen3-rerank` → 200 `results[].relevance_score`; `/rerank` (singular) - * → 404; `gte-rerank-v2` → 404 "Unsupported model for OpenAI compatibility - * mode" (native-API only, so it is deliberately NOT listed here). - * - * Note: the international endpoint requires a region-aware DASHSCOPE_API_KEY. - * China-region users point at https://dashscope.aliyuncs.com/compatible-api/v1 - * via `provider_base_urls['dashscope-rerank']`, mirroring the embedding - * recipe's convention. - */ -export const dashscopeRerank: Recipe = { - id: 'dashscope-rerank', - name: 'Alibaba DashScope (灵积, reranker)', - tier: 'openai-compat', - implementation: 'openai-compatible', - base_url_default: 'https://dashscope-intl.aliyuncs.com/compatible-api/v1', - auth_env: { - required: ['DASHSCOPE_API_KEY'], - setup_url: 'https://help.aliyun.com/zh/model-studio/getting-started/', - }, - touchpoints: { - reranker: { - // Only the model verified live on the OpenAI-compat /reranks surface. - // gte-rerank-v2 exists on DashScope's native API but the compat path - // rejects it ("Unsupported model for OpenAI compatibility mode"). - models: ['qwen3-rerank'], - default_model: 'qwen3-rerank', - // Mirror ZE's defensive per-request ceiling; gateway.rerank() - // pre-flights body size and fails open. - max_payload_bytes: 5_000_000, - // PLURAL leaf under compatible-api — the whole reason this recipe - // exists. `${base_url}${path}` → `…/compatible-api/v1/reranks`. - path: '/reranks', - // Hosted API: no local warmup, but cross-region latency can exceed - // the 5s gateway default (same rationale as llama-server-reranker). - default_timeout_ms: 30_000, - }, - }, - setup_hint: - 'Get an API key at https://help.aliyun.com/zh/model-studio/getting-started/, then ' + - '`export DASHSCOPE_API_KEY=...` and `gbrain config set search.reranker.model ' + - 'dashscope-rerank:qwen3-rerank`. China-region accounts: `gbrain config set ' + - 'provider_base_urls.dashscope-rerank https://dashscope.aliyuncs.com/compatible-api/v1`.', -}; diff --git a/src/core/ai/recipes/index.ts b/src/core/ai/recipes/index.ts index 5cba83749..eb751ec61 100644 --- a/src/core/ai/recipes/index.ts +++ b/src/core/ai/recipes/index.ts @@ -19,7 +19,6 @@ import { together } from './together.ts'; import { llamaServer } from './llama-server.ts'; import { minimax } from './minimax.ts'; import { dashscope } from './dashscope.ts'; -import { dashscopeRerank } from './dashscope-rerank.ts'; import { zhipu } from './zhipu.ts'; import { azureOpenAI } from './azure-openai.ts'; import { zeroentropyai } from './zeroentropyai.ts'; @@ -43,7 +42,6 @@ const ALL: Recipe[] = [ llamaServerReranker, minimax, dashscope, - dashscopeRerank, zhipu, azureOpenAI, zeroentropyai, diff --git a/test/ai/recipe-dashscope-rerank.test.ts b/test/ai/recipe-dashscope-rerank.test.ts deleted file mode 100644 index ef009064b..000000000 --- a/test/ai/recipe-dashscope-rerank.test.ts +++ /dev/null @@ -1,79 +0,0 @@ -/** - * dashscope-rerank recipe smoke. - * - * Sibling of recipe-llama-server-reranker.test.ts. Pins the recipe shape so: - * - id + tier + implementation + base_url stay byte-stable - * - reranker touchpoint declares the PLURAL `/reranks` leaf (the whole - * reason this recipe exists — DashScope's compatible-api surface 404s - * on singular `/rerank`) + `default_timeout_ms` - * - only live-verified models are listed (gte-rerank-v2 is native-API only - * and rejected by the OpenAI-compat surface) - */ - -import { describe, expect, test } from 'bun:test'; -import { getRecipe } from '../../src/core/ai/recipes/index.ts'; -import { defaultResolveAuth } from '../../src/core/ai/gateway.ts'; -import { AIConfigError } from '../../src/core/ai/errors.ts'; - -describe('recipe: dashscope-rerank', () => { - test('registered with expected shape', () => { - const r = getRecipe('dashscope-rerank'); - expect(r).toBeDefined(); - expect(r!.id).toBe('dashscope-rerank'); - expect(r!.tier).toBe('openai-compat'); - expect(r!.implementation).toBe('openai-compatible'); - expect(r!.base_url_default).toBe( - 'https://dashscope-intl.aliyuncs.com/compatible-api/v1', - ); - expect(r!.auth_env?.required).toEqual(['DASHSCOPE_API_KEY']); - }); - - test('declares reranker touchpoint with PLURAL /reranks path + timeout', () => { - const r = getRecipe('dashscope-rerank')!; - const tp = r.touchpoints.reranker; - expect(tp).toBeDefined(); - expect(tp!.path).toBe('/reranks'); - expect(tp!.default_timeout_ms).toBe(30_000); - expect(tp!.max_payload_bytes).toBe(5_000_000); - }); - - test('base_url + path concatenation produces /v1/reranks, NOT /v1/v1/…', () => { - const r = getRecipe('dashscope-rerank')!; - const combined = - r.base_url_default!.replace(/\/$/, '') + (r.touchpoints.reranker!.path ?? '/models/rerank'); - expect(combined).toBe('https://dashscope-intl.aliyuncs.com/compatible-api/v1/reranks'); - expect(combined).not.toContain('/v1/v1/'); - expect(combined.endsWith('/reranks')).toBe(true); - }); - - test('lists only the live-verified compat-surface model', () => { - const r = getRecipe('dashscope-rerank')!; - const tp = r.touchpoints.reranker!; - expect(tp.models).toEqual(['qwen3-rerank']); - expect(tp.default_model).toBe('qwen3-rerank'); - // gte-rerank-v2 is native-API only; the compat surface rejects it. - expect(tp.models).not.toContain('gte-rerank-v2'); - }); - - test('default auth: DASHSCOPE_API_KEY set → Bearer token', () => { - const r = getRecipe('dashscope-rerank')!; - const auth = defaultResolveAuth( - r, - { DASHSCOPE_API_KEY: 'sk-dashscope-fake' }, - 'reranker', - ); - expect(auth.headerName).toBe('Authorization'); - expect(auth.token).toBe('Bearer sk-dashscope-fake'); - }); - - test('default auth: missing DASHSCOPE_API_KEY → AIConfigError', () => { - const r = getRecipe('dashscope-rerank')!; - expect(() => defaultResolveAuth(r, {}, 'reranker')).toThrow(AIConfigError); - }); - - test('does not perturb the sibling dashscope embedding recipe', () => { - const emb = getRecipe('dashscope')!; - expect(emb.base_url_default).toBe('https://dashscope-intl.aliyuncs.com/compatible-mode/v1'); - expect(emb.touchpoints.reranker).toBeUndefined(); - }); -});