diff --git a/constant/model.js b/constant/model.js index 67f9187a..f6f77a92 100644 --- a/constant/model.js +++ b/constant/model.js @@ -68,6 +68,12 @@ export const MODEL_PROVIDERS = [ 'microsoft/phi-3-mini-128k-instruct:free' ] }, + { + id: 'requesty', + name: 'Requesty', + defaultEndpoint: 'https://router.requesty.ai/v1', + defaultModels: ['openai/gpt-4o-mini', 'openai/gpt-4o', 'anthropic/claude-sonnet-4-5', 'google/gemini-2.5-flash'] + }, { id: 'alibailian', name: '阿里云百炼', diff --git a/lib/db/llm-providers.js b/lib/db/llm-providers.js index 39719f71..ced09b6c 100644 --- a/lib/db/llm-providers.js +++ b/lib/db/llm-providers.js @@ -59,6 +59,11 @@ export async function getLlmProviders() { name: 'OpenRouter', apiUrl: 'https://openrouter.ai/api/v1/' }, + { + id: 'requesty', + name: 'Requesty', + apiUrl: 'https://router.requesty.ai/v1' + }, { id: 'alibailian', name: '阿里云百炼', diff --git a/lib/llm/core/index.js b/lib/llm/core/index.js index 4495f39a..d436726b 100644 --- a/lib/llm/core/index.js +++ b/lib/llm/core/index.js @@ -10,6 +10,7 @@ const OllamaClient = require('./providers/ollama'); // 导入 OllamaClient const OpenAIClient = require('./providers/openai'); // 导入 OpenAIClient const ZhiPuClient = require('./providers/zhipu'); // 导入 ZhiPuClient const OpenRouterClient = require('./providers/openrouter'); +const RequestyClient = require('./providers/requesty'); const AlibailianClient = require('./providers/alibailian'); // 导入 AlibailianClient const MiniMaxClient = require('./providers/minimax'); // 导入 MiniMaxClient @@ -123,6 +124,7 @@ class LLMClient { deepseek: OpenAIClient, zhipu: ZhiPuClient, openrouter: OpenRouterClient, + requesty: RequestyClient, alibailian: AlibailianClient, minimax: MiniMaxClient }; diff --git a/lib/llm/core/providers/requesty.js b/lib/llm/core/providers/requesty.js new file mode 100644 index 00000000..c2a18412 --- /dev/null +++ b/lib/llm/core/providers/requesty.js @@ -0,0 +1,28 @@ +import { createOpenAICompatible } from '@ai-sdk/openai-compatible'; + +import BaseClient from './base.js'; + +// Requesty is an OpenAI-compatible LLM router (https://requesty.ai). +// Base URL: https://router.requesty.ai/v1 (EU: https://router.eu.requesty.ai/v1) +// Auth: Authorization: Bearer . Models use the provider/model +// naming convention (e.g. openai/gpt-4o-mini), same as OpenRouter. +class RequestyClient extends BaseClient { + constructor(config) { + super(config); + this.requesty = createOpenAICompatible({ + name: 'requesty', + baseURL: this.endpoint, + apiKey: this.apiKey, + headers: { + 'HTTP-Referer': 'https://github.com/ConardLi/easy-dataset', + 'X-Title': 'Easy Dataset' + } + }); + } + + _getModel() { + return this.requesty(this.model); + } +} + +module.exports = RequestyClient; diff --git a/lib/util/providerLogo.js b/lib/util/providerLogo.js index b1f15c60..f641c6f1 100644 --- a/lib/util/providerLogo.js +++ b/lib/util/providerLogo.js @@ -1,5 +1,6 @@ const PROVIDER_LOGO_MAP = { openrouter: '/imgs/providers/openrouter.ico', + requesty: '/imgs/providers/requesty.ico', ollama: '/imgs/providers/ollama.png', openai: '/imgs/providers/openai.png', siliconcloud: '/imgs/providers/siliconflow.ico', @@ -23,6 +24,7 @@ export function normalizeProviderId(providerId = '', providerName = '') { const normalized = raw.replace(/[\s_-]/g, ''); if (normalized === 'openrouter' || normalized === 'openrouterai') return 'openrouter'; + if (normalized === 'requesty' || normalized === 'requestyai') return 'requesty'; if (normalized === 'openai') return 'openai'; if (normalized === 'siliconflow' || normalized === 'siliconcloud') return 'siliconcloud'; if (normalized === 'zhipuai' || normalized === 'zhipu') return 'zhipu'; diff --git a/public/imgs/providers/requesty.ico b/public/imgs/providers/requesty.ico new file mode 100644 index 00000000..eac20d8b Binary files /dev/null and b/public/imgs/providers/requesty.ico differ