Files
cherry-studio/src/renderer/src/config/models.ts
T
亢奋猫 ebe2806467 feat: add cherryin provider (#9681)
* feat: add Zhipu logo and update related images

- Introduced a new Zhipu logo component in SVG format.
- Updated existing image assets for chatglm, zhipu, and zhipu_dark.
- Added a new zhipu image for search functionality.

* feat: integrate Cherryin signature generation

- Added a new integration for Cherryin, including a signature generation feature.
- Updated IPC channels to handle Cherryin requests.
- Introduced a new JavaScript file for Cherryin integration.
- Modified configuration files to include Cherryin client secrets and paths.
- Enhanced the ESLint and TypeScript configurations to accommodate the new integration.

* feat: add Zhipu search provider and logo integration

- Implemented a new ZhipuProvider for web search functionality.
- Added Zhipu logo to the WebSearchButton component.
- Updated WebSearchProviderFactory to include Zhipu as a search option.
- Enhanced error handling and logging for Zhipu search requests.

* feat: add cherryin provider

* fix: correct import path for CherryinAPIClient and update paintings state structure in migration

* chore: update version number to 1.5.8 in package.json

* feat: enhance model filtering in SelectModelPopup

- Added support for identifying free trial models in the model filtering logic.
- Updated the condition for determining free models to include both free and free trial models.

* refactor: update navigation to use query parameters for provider settings

- Modified navigation logic in FreeTrialModelTag and related utilities to use query parameters instead of state for provider identification.
- Removed unused useLocation hook in ProviderList component to streamline state management.

* fix: remove provider ID from search parameters on selection change in ProviderList

* refactor: remove free trial model references and update related logic

- Eliminated the FreeTrialTag component and its associated logic from ModelTagsWithLabel and SelectModelPopup.
- Updated model filtering to only consider free models without the free trial distinction.
- Removed translations and utility functions related to free trial models across multiple locales.

* fix: prevent mutation of read-only properties in web search provider

- Updated the addWebSearchProvider function to clone the provider object before pushing it to the state, preventing mutation of read-only properties.
- Enhanced the migration logic to update the apiKey for the zhipu web search provider if it exists.

* refactor: streamline provider selection and navigation logic

- Updated FreeTrialModelTag to directly navigate to provider settings using query parameters, removing unnecessary provider fetching.
- Simplified ProviderList by eliminating the EventEmitter for provider selection and ensuring search parameters are updated correctly.
2025-08-30 20:09:35 +08:00

3262 lines
89 KiB
TypeScript

import Ai360ModelLogo from '@renderer/assets/images/models/360.png'
import Ai360ModelLogoDark from '@renderer/assets/images/models/360_dark.png'
import AdeptModelLogo from '@renderer/assets/images/models/adept.png'
import AdeptModelLogoDark from '@renderer/assets/images/models/adept_dark.png'
import Ai21ModelLogo from '@renderer/assets/images/models/ai21.png'
import Ai21ModelLogoDark from '@renderer/assets/images/models/ai21_dark.png'
import AimassModelLogo from '@renderer/assets/images/models/aimass.png'
import AimassModelLogoDark from '@renderer/assets/images/models/aimass_dark.png'
import AisingaporeModelLogo from '@renderer/assets/images/models/aisingapore.png'
import AisingaporeModelLogoDark from '@renderer/assets/images/models/aisingapore_dark.png'
import BaichuanModelLogo from '@renderer/assets/images/models/baichuan.png'
import BaichuanModelLogoDark from '@renderer/assets/images/models/baichuan_dark.png'
import BgeModelLogo from '@renderer/assets/images/models/bge.webp'
import BigcodeModelLogo from '@renderer/assets/images/models/bigcode.webp'
import BigcodeModelLogoDark from '@renderer/assets/images/models/bigcode_dark.webp'
import ChatGLMModelLogo from '@renderer/assets/images/models/chatglm.png'
import ChatGLMModelLogoDark from '@renderer/assets/images/models/chatglm_dark.png'
import ChatGptModelLogo from '@renderer/assets/images/models/chatgpt.jpeg'
import ClaudeModelLogo from '@renderer/assets/images/models/claude.png'
import ClaudeModelLogoDark from '@renderer/assets/images/models/claude_dark.png'
import CodegeexModelLogo from '@renderer/assets/images/models/codegeex.png'
import CodegeexModelLogoDark from '@renderer/assets/images/models/codegeex_dark.png'
import CodestralModelLogo from '@renderer/assets/images/models/codestral.png'
import CohereModelLogo from '@renderer/assets/images/models/cohere.png'
import CohereModelLogoDark from '@renderer/assets/images/models/cohere_dark.png'
import CopilotModelLogo from '@renderer/assets/images/models/copilot.png'
import CopilotModelLogoDark from '@renderer/assets/images/models/copilot_dark.png'
import DalleModelLogo from '@renderer/assets/images/models/dalle.png'
import DalleModelLogoDark from '@renderer/assets/images/models/dalle_dark.png'
import DbrxModelLogo from '@renderer/assets/images/models/dbrx.png'
import DeepSeekModelLogo from '@renderer/assets/images/models/deepseek.png'
import DeepSeekModelLogoDark from '@renderer/assets/images/models/deepseek_dark.png'
import DianxinModelLogo from '@renderer/assets/images/models/dianxin.png'
import DianxinModelLogoDark from '@renderer/assets/images/models/dianxin_dark.png'
import DoubaoModelLogo from '@renderer/assets/images/models/doubao.png'
import DoubaoModelLogoDark from '@renderer/assets/images/models/doubao_dark.png'
import {
default as EmbeddingModelLogo,
default as EmbeddingModelLogoDark
} from '@renderer/assets/images/models/embedding.png'
import FlashaudioModelLogo from '@renderer/assets/images/models/flashaudio.png'
import FlashaudioModelLogoDark from '@renderer/assets/images/models/flashaudio_dark.png'
import FluxModelLogo from '@renderer/assets/images/models/flux.png'
import FluxModelLogoDark from '@renderer/assets/images/models/flux_dark.png'
import GeminiModelLogo from '@renderer/assets/images/models/gemini.png'
import GeminiModelLogoDark from '@renderer/assets/images/models/gemini_dark.png'
import GemmaModelLogo from '@renderer/assets/images/models/gemma.png'
import GemmaModelLogoDark from '@renderer/assets/images/models/gemma_dark.png'
import { default as GoogleModelLogo, default as GoogleModelLogoDark } from '@renderer/assets/images/models/google.png'
import ChatGPT35ModelLogo from '@renderer/assets/images/models/gpt_3.5.png'
import ChatGPT4ModelLogo from '@renderer/assets/images/models/gpt_4.png'
import {
default as ChatGPT4ModelLogoDark,
default as ChatGPT35ModelLogoDark,
default as ChatGptModelLogoDark,
default as ChatGPTo1ModelLogoDark
} from '@renderer/assets/images/models/gpt_dark.png'
import ChatGPTImageModelLogo from '@renderer/assets/images/models/gpt_image_1.png'
import ChatGPTo1ModelLogo from '@renderer/assets/images/models/gpt_o1.png'
import GPT5ModelLogo from '@renderer/assets/images/models/gpt-5.png'
import GPT5ChatModelLogo from '@renderer/assets/images/models/gpt-5-chat.png'
import GPT5MiniModelLogo from '@renderer/assets/images/models/gpt-5-mini.png'
import GPT5NanoModelLogo from '@renderer/assets/images/models/gpt-5-nano.png'
import GrokModelLogo from '@renderer/assets/images/models/grok.png'
import GrokModelLogoDark from '@renderer/assets/images/models/grok_dark.png'
import GrypheModelLogo from '@renderer/assets/images/models/gryphe.png'
import GrypheModelLogoDark from '@renderer/assets/images/models/gryphe_dark.png'
import HailuoModelLogo from '@renderer/assets/images/models/hailuo.png'
import HailuoModelLogoDark from '@renderer/assets/images/models/hailuo_dark.png'
import HuggingfaceModelLogo from '@renderer/assets/images/models/huggingface.png'
import HuggingfaceModelLogoDark from '@renderer/assets/images/models/huggingface_dark.png'
import HunyuanModelLogo from '@renderer/assets/images/models/hunyuan.png'
import HunyuanModelLogoDark from '@renderer/assets/images/models/hunyuan_dark.png'
import IbmModelLogo from '@renderer/assets/images/models/ibm.png'
import IbmModelLogoDark from '@renderer/assets/images/models/ibm_dark.png'
import InternlmModelLogo from '@renderer/assets/images/models/internlm.png'
import InternlmModelLogoDark from '@renderer/assets/images/models/internlm_dark.png'
import InternvlModelLogo from '@renderer/assets/images/models/internvl.png'
import JinaModelLogo from '@renderer/assets/images/models/jina.png'
import JinaModelLogoDark from '@renderer/assets/images/models/jina_dark.png'
import KeLingModelLogo from '@renderer/assets/images/models/keling.png'
import KeLingModelLogoDark from '@renderer/assets/images/models/keling_dark.png'
import LlamaModelLogo from '@renderer/assets/images/models/llama.png'
import LlamaModelLogoDark from '@renderer/assets/images/models/llama_dark.png'
import LLavaModelLogo from '@renderer/assets/images/models/llava.png'
import LLavaModelLogoDark from '@renderer/assets/images/models/llava_dark.png'
import LumaModelLogo from '@renderer/assets/images/models/luma.png'
import LumaModelLogoDark from '@renderer/assets/images/models/luma_dark.png'
import MagicModelLogo from '@renderer/assets/images/models/magic.png'
import MagicModelLogoDark from '@renderer/assets/images/models/magic_dark.png'
import MediatekModelLogo from '@renderer/assets/images/models/mediatek.png'
import MediatekModelLogoDark from '@renderer/assets/images/models/mediatek_dark.png'
import MicrosoftModelLogo from '@renderer/assets/images/models/microsoft.png'
import MicrosoftModelLogoDark from '@renderer/assets/images/models/microsoft_dark.png'
import MidjourneyModelLogo from '@renderer/assets/images/models/midjourney.png'
import MidjourneyModelLogoDark from '@renderer/assets/images/models/midjourney_dark.png'
import {
default as MinicpmModelLogo,
default as MinicpmModelLogoDark
} from '@renderer/assets/images/models/minicpm.webp'
import MinimaxModelLogo from '@renderer/assets/images/models/minimax.png'
import MinimaxModelLogoDark from '@renderer/assets/images/models/minimax_dark.png'
import MistralModelLogo from '@renderer/assets/images/models/mixtral.png'
import MistralModelLogoDark from '@renderer/assets/images/models/mixtral_dark.png'
import MoonshotModelLogo from '@renderer/assets/images/models/moonshot.png'
import MoonshotModelLogoDark from '@renderer/assets/images/models/moonshot_dark.png'
import {
default as NousResearchModelLogo,
default as NousResearchModelLogoDark
} from '@renderer/assets/images/models/nousresearch.png'
import NvidiaModelLogo from '@renderer/assets/images/models/nvidia.png'
import NvidiaModelLogoDark from '@renderer/assets/images/models/nvidia_dark.png'
import PalmModelLogo from '@renderer/assets/images/models/palm.png'
import PalmModelLogoDark from '@renderer/assets/images/models/palm_dark.png'
import PanguModelLogo from '@renderer/assets/images/models/pangu.svg'
import {
default as PerplexityModelLogo,
default as PerplexityModelLogoDark
} from '@renderer/assets/images/models/perplexity.png'
import PixtralModelLogo from '@renderer/assets/images/models/pixtral.png'
import PixtralModelLogoDark from '@renderer/assets/images/models/pixtral_dark.png'
import QwenModelLogo from '@renderer/assets/images/models/qwen.png'
import QwenModelLogoDark from '@renderer/assets/images/models/qwen_dark.png'
import RakutenaiModelLogo from '@renderer/assets/images/models/rakutenai.png'
import RakutenaiModelLogoDark from '@renderer/assets/images/models/rakutenai_dark.png'
import SparkDeskModelLogo from '@renderer/assets/images/models/sparkdesk.png'
import SparkDeskModelLogoDark from '@renderer/assets/images/models/sparkdesk_dark.png'
import StabilityModelLogo from '@renderer/assets/images/models/stability.png'
import StabilityModelLogoDark from '@renderer/assets/images/models/stability_dark.png'
import StepModelLogo from '@renderer/assets/images/models/step.png'
import StepModelLogoDark from '@renderer/assets/images/models/step_dark.png'
import SunoModelLogo from '@renderer/assets/images/models/suno.png'
import SunoModelLogoDark from '@renderer/assets/images/models/suno_dark.png'
import TeleModelLogo from '@renderer/assets/images/models/tele.png'
import TeleModelLogoDark from '@renderer/assets/images/models/tele_dark.png'
import TokenFluxModelLogo from '@renderer/assets/images/models/tokenflux.png'
import TokenFluxModelLogoDark from '@renderer/assets/images/models/tokenflux_dark.png'
import UpstageModelLogo from '@renderer/assets/images/models/upstage.png'
import UpstageModelLogoDark from '@renderer/assets/images/models/upstage_dark.png'
import ViduModelLogo from '@renderer/assets/images/models/vidu.png'
import ViduModelLogoDark from '@renderer/assets/images/models/vidu_dark.png'
import VoyageModelLogo from '@renderer/assets/images/models/voyageai.png'
import WenxinModelLogo from '@renderer/assets/images/models/wenxin.png'
import WenxinModelLogoDark from '@renderer/assets/images/models/wenxin_dark.png'
import XirangModelLogo from '@renderer/assets/images/models/xirang.png'
import XirangModelLogoDark from '@renderer/assets/images/models/xirang_dark.png'
import YiModelLogo from '@renderer/assets/images/models/yi.png'
import YiModelLogoDark from '@renderer/assets/images/models/yi_dark.png'
import ZhipuModelLogo from '@renderer/assets/images/models/zhipu.png'
import ZhipuModelLogoDark from '@renderer/assets/images/models/zhipu_dark.png'
import YoudaoLogo from '@renderer/assets/images/providers/netease-youdao.svg'
import NomicLogo from '@renderer/assets/images/providers/nomic.png'
import ZhipuProviderLogo from '@renderer/assets/images/providers/zhipu.png'
import { getProviderByModel } from '@renderer/services/AssistantService'
import {
isSystemProviderId,
Model,
ReasoningEffortConfig,
SystemProviderId,
ThinkingModelType,
ThinkingOptionConfig
} from '@renderer/types'
import { getLowerBaseModelName, isUserSelectedModelType } from '@renderer/utils'
import OpenAI from 'openai'
import { WEB_SEARCH_PROMPT_FOR_OPENROUTER } from './prompts'
import { getWebSearchTools } from './tools'
// Vision models
const visionAllowedModels = [
'llava',
'moondream',
'minicpm',
'gemini-1\\.5',
'gemini-2\\.0',
'gemini-2\\.5',
'gemini-exp',
'claude-3',
'claude-sonnet-4',
'claude-opus-4',
'vision',
'glm-4(?:\\.\\d+)?v(?:-[\\w-]+)?',
'qwen-vl',
'qwen2-vl',
'qwen2.5-vl',
'qwen2.5-omni',
'qvq',
'internvl2',
'grok-vision-beta',
'grok-4(?:-[\\w-]+)?',
'pixtral',
'gpt-4(?:-[\\w-]+)',
'gpt-4.1(?:-[\\w-]+)?',
'gpt-4o(?:-[\\w-]+)?',
'gpt-4.5(?:-[\\w-]+)',
'gpt-5(?:-[\\w-]+)?',
'chatgpt-4o(?:-[\\w-]+)?',
'o1(?:-[\\w-]+)?',
'o3(?:-[\\w-]+)?',
'o4(?:-[\\w-]+)?',
'deepseek-vl(?:[\\w-]+)?',
'kimi-latest',
'gemma-3(?:-[\\w-]+)',
'doubao-seed-1[.-]6(?:-[\\w-]+)?',
'kimi-thinking-preview',
`gemma3(?:[-:\\w]+)?`,
'kimi-vl-a3b-thinking(?:-[\\w-]+)?',
'llama-guard-4(?:-[\\w-]+)?',
'llama-4(?:-[\\w-]+)?',
'step-1o(?:.*vision)?',
'step-1v(?:-[\\w-]+)?'
]
const visionExcludedModels = [
'gpt-4-\\d+-preview',
'gpt-4-turbo-preview',
'gpt-4-32k',
'gpt-4-\\d+',
'o1-mini',
'o3-mini',
'o1-preview',
'AIDC-AI/Marco-o1'
]
export const VISION_REGEX = new RegExp(
`\\b(?!(?:${visionExcludedModels.join('|')})\\b)(${visionAllowedModels.join('|')})\\b`,
'i'
)
// For middleware to identify models that must use the dedicated Image API
export const DEDICATED_IMAGE_MODELS = ['grok-2-image', 'dall-e-3', 'dall-e-2', 'gpt-image-1']
export const isDedicatedImageGenerationModel = (model: Model): boolean => {
const modelId = getLowerBaseModelName(model.id)
return DEDICATED_IMAGE_MODELS.filter((m) => modelId.includes(m)).length > 0
}
// Text to image models
export const TEXT_TO_IMAGE_REGEX = /flux|diffusion|stabilityai|sd-|dall|cogview|janus|midjourney|mj-|image|gpt-image/i
// Reasoning models
export const REASONING_REGEX =
/^(o\d+(?:-[\w-]+)?|.*\b(?:reasoning|reasoner|thinking)\b.*|.*-[rR]\d+.*|.*\bqwq(?:-[\w-]+)?\b.*|.*\bhunyuan-t1(?:-[\w-]+)?\b.*|.*\bglm-zero-preview\b.*|.*\bgrok-(?:3-mini|4)(?:-[\w-]+)?\b.*)$/i
// Embedding models
export const EMBEDDING_REGEX =
/(?:^text-|embed|bge-|e5-|LLM2Vec|retrieval|uae-|gte-|jina-clip|jina-embeddings|voyage-)/i
// Rerank models
export const RERANKING_REGEX = /(?:rerank|re-rank|re-ranker|re-ranking|retrieval|retriever)/i
export const NOT_SUPPORTED_REGEX = /(?:^tts|whisper|speech)/i
// Tool calling models
export const FUNCTION_CALLING_MODELS = [
'gpt-4o',
'gpt-4o-mini',
'gpt-4',
'gpt-4.5',
'gpt-oss(?:-[\\w-]+)',
'gpt-5(?:-[0-9-]+)?',
'o(1|3|4)(?:-[\\w-]+)?',
'claude',
'qwen',
'qwen3',
'hunyuan',
'deepseek',
'glm-4(?:-[\\w-]+)?',
'glm-4.5(?:-[\\w-]+)?',
'learnlm(?:-[\\w-]+)?',
'gemini(?:-[\\w-]+)?', // 提前排除了gemini的嵌入模型
'grok-3(?:-[\\w-]+)?',
'doubao-seed-1[.-]6(?:-[\\w-]+)?',
'kimi-k2(?:-[\\w-]+)?'
]
const FUNCTION_CALLING_EXCLUDED_MODELS = [
'aqa(?:-[\\w-]+)?',
'imagen(?:-[\\w-]+)?',
'o1-mini',
'o1-preview',
'AIDC-AI/Marco-o1',
'gemini-1(?:\\.[\\w-]+)?',
'qwen-mt(?:-[\\w-]+)?',
'gpt-5-chat(?:-[\\w-]+)?',
'glm-4\\.5v'
]
export const FUNCTION_CALLING_REGEX = new RegExp(
`\\b(?!(?:${FUNCTION_CALLING_EXCLUDED_MODELS.join('|')})\\b)(?:${FUNCTION_CALLING_MODELS.join('|')})\\b`,
'i'
)
export const CLAUDE_SUPPORTED_WEBSEARCH_REGEX = new RegExp(
`\\b(?:claude-3(-|\\.)(7|5)-sonnet(?:-[\\w-]+)|claude-3(-|\\.)5-haiku(?:-[\\w-]+)|claude-sonnet-4(?:-[\\w-]+)?|claude-opus-4(?:-[\\w-]+)?)\\b`,
'i'
)
// 模型类型到支持的reasoning_effort的映射表
// TODO: refactor this. too many identical options
export const MODEL_SUPPORTED_REASONING_EFFORT: ReasoningEffortConfig = {
default: ['low', 'medium', 'high'] as const,
o: ['low', 'medium', 'high'] as const,
gpt5: ['minimal', 'low', 'medium', 'high'] as const,
grok: ['low', 'high'] as const,
gemini: ['low', 'medium', 'high', 'auto'] as const,
gemini_pro: ['low', 'medium', 'high', 'auto'] as const,
qwen: ['low', 'medium', 'high'] as const,
qwen_thinking: ['low', 'medium', 'high'] as const,
doubao: ['auto', 'high'] as const,
doubao_no_auto: ['high'] as const,
hunyuan: ['auto'] as const,
zhipu: ['auto'] as const,
perplexity: ['low', 'medium', 'high'] as const,
deepseek_hybrid: ['auto'] as const
} as const
// 模型类型到支持选项的映射表
export const MODEL_SUPPORTED_OPTIONS: ThinkingOptionConfig = {
default: ['off', ...MODEL_SUPPORTED_REASONING_EFFORT.default] as const,
o: MODEL_SUPPORTED_REASONING_EFFORT.o,
gpt5: [...MODEL_SUPPORTED_REASONING_EFFORT.gpt5] as const,
grok: MODEL_SUPPORTED_REASONING_EFFORT.grok,
gemini: ['off', ...MODEL_SUPPORTED_REASONING_EFFORT.gemini] as const,
gemini_pro: MODEL_SUPPORTED_REASONING_EFFORT.gemini_pro,
qwen: ['off', ...MODEL_SUPPORTED_REASONING_EFFORT.qwen] as const,
qwen_thinking: MODEL_SUPPORTED_REASONING_EFFORT.qwen_thinking,
doubao: ['off', ...MODEL_SUPPORTED_REASONING_EFFORT.doubao] as const,
doubao_no_auto: ['off', ...MODEL_SUPPORTED_REASONING_EFFORT.doubao_no_auto] as const,
hunyuan: ['off', ...MODEL_SUPPORTED_REASONING_EFFORT.hunyuan] as const,
zhipu: ['off', ...MODEL_SUPPORTED_REASONING_EFFORT.zhipu] as const,
perplexity: MODEL_SUPPORTED_REASONING_EFFORT.perplexity,
deepseek_hybrid: ['off', ...MODEL_SUPPORTED_REASONING_EFFORT.deepseek_hybrid] as const
} as const
export const getThinkModelType = (model: Model): ThinkingModelType => {
let thinkingModelType: ThinkingModelType = 'default'
if (isGPT5SeriesModel(model)) {
thinkingModelType = 'gpt5'
} else if (isSupportedReasoningEffortOpenAIModel(model)) {
thinkingModelType = 'o'
} else if (isSupportedThinkingTokenGeminiModel(model)) {
if (GEMINI_FLASH_MODEL_REGEX.test(model.id)) {
thinkingModelType = 'gemini'
} else {
thinkingModelType = 'gemini_pro'
}
} else if (isSupportedReasoningEffortGrokModel(model)) thinkingModelType = 'grok'
else if (isSupportedThinkingTokenQwenModel(model)) {
if (isQwenAlwaysThinkModel(model)) {
thinkingModelType = 'qwen_thinking'
}
thinkingModelType = 'qwen'
} else if (isSupportedThinkingTokenDoubaoModel(model)) {
if (isDoubaoThinkingAutoModel(model)) {
thinkingModelType = 'doubao'
} else {
thinkingModelType = 'doubao_no_auto'
}
} else if (isSupportedThinkingTokenHunyuanModel(model)) thinkingModelType = 'hunyuan'
else if (isSupportedReasoningEffortPerplexityModel(model)) thinkingModelType = 'perplexity'
else if (isSupportedThinkingTokenZhipuModel(model)) thinkingModelType = 'zhipu'
else if (isDeepSeekHybridInferenceModel(model)) thinkingModelType = 'deepseek_hybrid'
return thinkingModelType
}
export function isFunctionCallingModel(model?: Model): boolean {
if (!model || isEmbeddingModel(model) || isRerankModel(model) || isTextToImageModel(model)) {
return false
}
const modelId = getLowerBaseModelName(model.id)
if (isUserSelectedModelType(model, 'function_calling') !== undefined) {
return isUserSelectedModelType(model, 'function_calling')!
}
if (model.provider === 'qiniu') {
return ['deepseek-v3-tool', 'deepseek-v3-0324', 'qwq-32b', 'qwen2.5-72b-instruct'].includes(modelId)
}
if (model.provider === 'doubao' || modelId.includes('doubao')) {
return FUNCTION_CALLING_REGEX.test(modelId) || FUNCTION_CALLING_REGEX.test(model.name)
}
if (['deepseek', 'anthropic', 'kimi', 'moonshot'].includes(model.provider)) {
return true
}
// 2025/08/26 百炼与火山引擎均不支持 v3.1 函数调用
// 先默认支持
if (isDeepSeekHybridInferenceModel(model)) {
if (isSystemProviderId(model.provider)) {
switch (model.provider) {
case 'dashscope':
case 'doubao':
// case 'nvidia': // nvidia api 太烂了 测不了能不能用 先假设能用
return false
}
}
return true
}
return FUNCTION_CALLING_REGEX.test(modelId)
}
export function getModelLogo(modelId: string) {
const isLight = true
if (!modelId) {
return undefined
}
const logoMap = {
pixtral: isLight ? PixtralModelLogo : PixtralModelLogoDark,
jina: isLight ? JinaModelLogo : JinaModelLogoDark,
abab: isLight ? MinimaxModelLogo : MinimaxModelLogoDark,
minimax: isLight ? MinimaxModelLogo : MinimaxModelLogoDark,
veo: isLight ? GeminiModelLogo : GeminiModelLogoDark,
o1: isLight ? ChatGPTo1ModelLogo : ChatGPTo1ModelLogoDark,
o3: isLight ? ChatGPTo1ModelLogo : ChatGPTo1ModelLogoDark,
o4: isLight ? ChatGPTo1ModelLogo : ChatGPTo1ModelLogoDark,
'gpt-image': ChatGPTImageModelLogo,
'gpt-3': isLight ? ChatGPT35ModelLogo : ChatGPT35ModelLogoDark,
'gpt-4': isLight ? ChatGPT4ModelLogo : ChatGPT4ModelLogoDark,
'gpt-5-mini': GPT5MiniModelLogo,
'gpt-5-nano': GPT5NanoModelLogo,
'gpt-5-chat': GPT5ChatModelLogo,
'gpt-5': GPT5ModelLogo,
gpts: isLight ? ChatGPT4ModelLogo : ChatGPT4ModelLogoDark,
'gpt-oss(?:-[\\w-]+)': isLight ? ChatGptModelLogo : ChatGptModelLogoDark,
'text-moderation': isLight ? ChatGptModelLogo : ChatGptModelLogoDark,
'babbage-': isLight ? ChatGptModelLogo : ChatGptModelLogoDark,
'(sora-|sora_)': isLight ? ChatGptModelLogo : ChatGptModelLogoDark,
'(^|/)omni-': isLight ? ChatGptModelLogo : ChatGptModelLogoDark,
'Embedding-V1': isLight ? WenxinModelLogo : WenxinModelLogoDark,
'text-embedding-v': isLight ? QwenModelLogo : QwenModelLogoDark,
'text-embedding': isLight ? ChatGptModelLogo : ChatGptModelLogoDark,
'davinci-': isLight ? ChatGptModelLogo : ChatGptModelLogoDark,
glm: isLight ? ChatGLMModelLogo : ChatGLMModelLogoDark,
deepseek: isLight ? DeepSeekModelLogo : DeepSeekModelLogoDark,
'(qwen|qwq|qwq-|qvq-)': isLight ? QwenModelLogo : QwenModelLogoDark,
gemma: isLight ? GemmaModelLogo : GemmaModelLogoDark,
'yi-': isLight ? YiModelLogo : YiModelLogoDark,
llama: isLight ? LlamaModelLogo : LlamaModelLogoDark,
mixtral: isLight ? MistralModelLogo : MistralModelLogo,
mistral: isLight ? MistralModelLogo : MistralModelLogoDark,
codestral: CodestralModelLogo,
ministral: isLight ? MistralModelLogo : MistralModelLogoDark,
magistral: isLight ? MistralModelLogo : MistralModelLogoDark,
moonshot: isLight ? MoonshotModelLogo : MoonshotModelLogoDark,
kimi: isLight ? MoonshotModelLogo : MoonshotModelLogoDark,
phi: isLight ? MicrosoftModelLogo : MicrosoftModelLogoDark,
baichuan: isLight ? BaichuanModelLogo : BaichuanModelLogoDark,
claude: isLight ? ClaudeModelLogo : ClaudeModelLogoDark,
gemini: isLight ? GeminiModelLogo : GeminiModelLogoDark,
bison: isLight ? PalmModelLogo : PalmModelLogoDark,
palm: isLight ? PalmModelLogo : PalmModelLogoDark,
step: isLight ? StepModelLogo : StepModelLogoDark,
hailuo: isLight ? HailuoModelLogo : HailuoModelLogoDark,
doubao: isLight ? DoubaoModelLogo : DoubaoModelLogoDark,
seedream: isLight ? DoubaoModelLogo : DoubaoModelLogoDark,
'ep-202': isLight ? DoubaoModelLogo : DoubaoModelLogoDark,
cohere: isLight ? CohereModelLogo : CohereModelLogoDark,
command: isLight ? CohereModelLogo : CohereModelLogoDark,
minicpm: isLight ? MinicpmModelLogo : MinicpmModelLogoDark,
'360': isLight ? Ai360ModelLogo : Ai360ModelLogoDark,
aimass: isLight ? AimassModelLogo : AimassModelLogoDark,
codegeex: isLight ? CodegeexModelLogo : CodegeexModelLogoDark,
copilot: isLight ? CopilotModelLogo : CopilotModelLogoDark,
creative: isLight ? CopilotModelLogo : CopilotModelLogoDark,
balanced: isLight ? CopilotModelLogo : CopilotModelLogoDark,
precise: isLight ? CopilotModelLogo : CopilotModelLogoDark,
dalle: isLight ? DalleModelLogo : DalleModelLogoDark,
'dall-e': isLight ? DalleModelLogo : DalleModelLogoDark,
dbrx: isLight ? DbrxModelLogo : DbrxModelLogo,
flashaudio: isLight ? FlashaudioModelLogo : FlashaudioModelLogoDark,
flux: isLight ? FluxModelLogo : FluxModelLogoDark,
grok: isLight ? GrokModelLogo : GrokModelLogoDark,
hunyuan: isLight ? HunyuanModelLogo : HunyuanModelLogoDark,
internlm: isLight ? InternlmModelLogo : InternlmModelLogoDark,
internvl: InternvlModelLogo,
llava: isLight ? LLavaModelLogo : LLavaModelLogoDark,
magic: isLight ? MagicModelLogo : MagicModelLogoDark,
midjourney: isLight ? MidjourneyModelLogo : MidjourneyModelLogoDark,
'mj-': isLight ? MidjourneyModelLogo : MidjourneyModelLogoDark,
'tao-': isLight ? WenxinModelLogo : WenxinModelLogoDark,
'ernie-': isLight ? WenxinModelLogo : WenxinModelLogoDark,
voice: isLight ? FlashaudioModelLogo : FlashaudioModelLogoDark,
'tts-1': isLight ? ChatGptModelLogo : ChatGptModelLogoDark,
'whisper-': isLight ? ChatGptModelLogo : ChatGptModelLogoDark,
'stable-': isLight ? StabilityModelLogo : StabilityModelLogoDark,
sd2: isLight ? StabilityModelLogo : StabilityModelLogoDark,
sd3: isLight ? StabilityModelLogo : StabilityModelLogoDark,
sdxl: isLight ? StabilityModelLogo : StabilityModelLogoDark,
sparkdesk: isLight ? SparkDeskModelLogo : SparkDeskModelLogoDark,
generalv: isLight ? SparkDeskModelLogo : SparkDeskModelLogoDark,
wizardlm: isLight ? MicrosoftModelLogo : MicrosoftModelLogoDark,
microsoft: isLight ? MicrosoftModelLogo : MicrosoftModelLogoDark,
hermes: isLight ? NousResearchModelLogo : NousResearchModelLogoDark,
gryphe: isLight ? GrypheModelLogo : GrypheModelLogoDark,
suno: isLight ? SunoModelLogo : SunoModelLogoDark,
chirp: isLight ? SunoModelLogo : SunoModelLogoDark,
luma: isLight ? LumaModelLogo : LumaModelLogoDark,
keling: isLight ? KeLingModelLogo : KeLingModelLogoDark,
'vidu-': isLight ? ViduModelLogo : ViduModelLogoDark,
ai21: isLight ? Ai21ModelLogo : Ai21ModelLogoDark,
'jamba-': isLight ? Ai21ModelLogo : Ai21ModelLogoDark,
mythomax: isLight ? GrypheModelLogo : GrypheModelLogoDark,
nvidia: isLight ? NvidiaModelLogo : NvidiaModelLogoDark,
dianxin: isLight ? DianxinModelLogo : DianxinModelLogoDark,
tele: isLight ? TeleModelLogo : TeleModelLogoDark,
adept: isLight ? AdeptModelLogo : AdeptModelLogoDark,
aisingapore: isLight ? AisingaporeModelLogo : AisingaporeModelLogoDark,
bigcode: isLight ? BigcodeModelLogo : BigcodeModelLogoDark,
mediatek: isLight ? MediatekModelLogo : MediatekModelLogoDark,
upstage: isLight ? UpstageModelLogo : UpstageModelLogoDark,
rakutenai: isLight ? RakutenaiModelLogo : RakutenaiModelLogoDark,
ibm: isLight ? IbmModelLogo : IbmModelLogoDark,
'google/': isLight ? GoogleModelLogo : GoogleModelLogoDark,
xirang: isLight ? XirangModelLogo : XirangModelLogoDark,
hugging: isLight ? HuggingfaceModelLogo : HuggingfaceModelLogoDark,
youdao: YoudaoLogo,
'embedding-3': ZhipuProviderLogo,
embedding: isLight ? EmbeddingModelLogo : EmbeddingModelLogoDark,
perplexity: isLight ? PerplexityModelLogo : PerplexityModelLogoDark,
sonar: isLight ? PerplexityModelLogo : PerplexityModelLogoDark,
'bge-': BgeModelLogo,
'voyage-': VoyageModelLogo,
tokenflux: isLight ? TokenFluxModelLogo : TokenFluxModelLogoDark,
'nomic-': NomicLogo,
'pangu-': PanguModelLogo,
cogview: isLight ? ZhipuModelLogo : ZhipuModelLogoDark,
zhipu: isLight ? ZhipuModelLogo : ZhipuModelLogoDark
}
for (const key in logoMap) {
const regex = new RegExp(key, 'i')
if (regex.test(modelId)) {
return logoMap[key]
}
}
return undefined
}
export const glm45FlashModel: Model = {
id: 'glm-4.5-flash',
name: 'GLM-4.5-Flash',
provider: 'cherryin',
group: 'GLM-4.5'
}
export const qwen38bModel: Model = {
id: 'Qwen/Qwen3-8B',
name: 'Qwen3-8B',
provider: 'cherryin',
group: 'Qwen'
}
export const SYSTEM_MODELS: Record<SystemProviderId | 'defaultModel', Model[]> = {
defaultModel: [
// Default assistant model
glm45FlashModel,
// Default topic naming model
qwen38bModel,
// Default translation model
glm45FlashModel,
// Default quick assistant model
glm45FlashModel
],
cherryin: [
{
id: 'glm-4.5-flash',
name: 'GLM-4.5-Flash',
provider: 'cherryin',
group: 'GLM-4.5'
},
{
id: 'Qwen/Qwen3-8B',
name: 'Qwen3-8B',
provider: 'cherryin',
group: 'Qwen'
}
],
vertexai: [],
'302ai': [
{
id: 'deepseek-chat',
name: 'deepseek-chat',
provider: '302ai',
group: 'DeepSeek'
},
{
id: 'deepseek-reasoner',
name: 'deepseek-reasoner',
provider: '302ai',
group: 'DeepSeek'
},
{
id: 'chatgpt-4o-latest',
name: 'chatgpt-4o-latest',
provider: '302ai',
group: 'OpenAI'
},
{
id: 'gpt-4.1',
name: 'gpt-4.1',
provider: '302ai',
group: 'OpenAI'
},
{
id: 'o3',
name: 'o3',
provider: '302ai',
group: 'OpenAI'
},
{
id: 'o4-mini',
name: 'o4-mini',
provider: '302ai',
group: 'OpenAI'
},
{
id: 'qwen3-235b-a22b',
name: 'qwen3-235b-a22b',
provider: '302ai',
group: 'Qwen'
},
{
id: 'gemini-2.5-flash-preview-05-20',
name: 'gemini-2.5-flash-preview-05-20',
provider: '302ai',
group: 'Gemini'
},
{
id: 'gemini-2.5-pro-preview-06-05',
name: 'gemini-2.5-pro-preview-06-05',
provider: '302ai',
group: 'Gemini'
},
{
id: 'claude-sonnet-4-20250514',
provider: '302ai',
name: 'claude-sonnet-4-20250514',
group: 'Anthropic'
},
{
id: 'claude-opus-4-20250514',
provider: '302ai',
name: 'claude-opus-4-20250514',
group: 'Anthropic'
},
{
id: 'jina-clip-v2',
name: 'jina-clip-v2',
provider: '302ai',
group: 'Jina AI'
},
{
id: 'jina-reranker-m0',
name: 'jina-reranker-m0',
provider: '302ai',
group: 'Jina AI'
}
],
ph8: [
{
id: 'deepseek-v3-241226',
name: 'deepseek-v3-241226',
provider: 'ph8',
group: 'DeepSeek'
},
{
id: 'deepseek-r1-250120',
name: 'deepseek-r1-250120',
provider: 'ph8',
group: 'DeepSeek'
}
],
aihubmix: [
{
id: 'gpt-5',
provider: 'aihubmix',
name: 'gpt-5',
group: 'OpenAI'
},
{
id: 'gpt-5-mini',
provider: 'aihubmix',
name: 'gpt-5-mini',
group: 'OpenAI'
},
{
id: 'gpt-5-nano',
provider: 'aihubmix',
name: 'gpt-5-nano',
group: 'OpenAI'
},
{
id: 'gpt-5-chat-latest',
provider: 'aihubmix',
name: 'gpt-5-chat-latest',
group: 'OpenAI'
},
{
id: 'o3',
provider: 'aihubmix',
name: 'o3',
group: 'OpenAI'
},
{
id: 'o4-mini',
provider: 'aihubmix',
name: 'o4-mini',
group: 'OpenAI'
},
{
id: 'gpt-4.1',
provider: 'aihubmix',
name: 'gpt-4.1',
group: 'OpenAI'
},
{
id: 'gpt-4o',
provider: 'aihubmix',
name: 'gpt-4o',
group: 'OpenAI'
},
{
id: 'gpt-image-1',
provider: 'aihubmix',
name: 'gpt-image-1',
group: 'OpenAI'
},
{
id: 'DeepSeek-V3',
provider: 'aihubmix',
name: 'DeepSeek-V3',
group: 'DeepSeek'
},
{
id: 'DeepSeek-R1',
provider: 'aihubmix',
name: 'DeepSeek-R1',
group: 'DeepSeek'
},
{
id: 'claude-sonnet-4-20250514',
provider: 'aihubmix',
name: 'claude-sonnet-4-20250514',
group: 'Claude'
},
{
id: 'gemini-2.5-pro',
provider: 'aihubmix',
name: 'gemini-2.5-pro',
group: 'Gemini'
},
{
id: 'gemini-2.5-flash-nothink',
provider: 'aihubmix',
name: 'gemini-2.5-flash-nothink',
group: 'Gemini'
},
{
id: 'gemini-2.5-flash',
provider: 'aihubmix',
name: 'gemini-2.5-flash',
group: 'Gemini'
},
{
id: 'Qwen3-235B-A22B-Instruct-2507',
provider: 'aihubmix',
name: 'Qwen3-235B-A22B-Instruct-2507',
group: 'qwen'
},
{
id: 'kimi-k2-0711-preview',
provider: 'aihubmix',
name: 'kimi-k2-0711-preview',
group: 'moonshot'
},
{
id: 'Llama-4-Scout-17B-16E-Instruct',
provider: 'aihubmix',
name: 'Llama-4-Scout-17B-16E-Instruct',
group: 'llama'
},
{
id: 'Llama-4-Maverick-17B-128E-Instruct-FP8',
provider: 'aihubmix',
name: 'Llama-4-Maverick-17B-128E-Instruct-FP8',
group: 'llama'
}
],
burncloud: [
{ id: 'claude-3-7-sonnet-20250219-thinking', provider: 'burncloud', name: 'Claude 3.7 thinking', group: 'Claude' },
{ id: 'claude-3-7-sonnet-20250219', provider: 'burncloud', name: 'Claude 3.7 Sonnet', group: 'Claude 3.7' },
{ id: 'claude-3-5-sonnet-20241022', provider: 'burncloud', name: 'Claude 3.5 Sonnet', group: 'Claude 3.5' },
{ id: 'claude-3-5-haiku-20241022', provider: 'burncloud', name: 'Claude 3.5 Haiku', group: 'Claude 3.5' },
{ id: 'gpt-4.5-preview', provider: 'burncloud', name: 'gpt-4.5-preview', group: 'gpt-4.5' },
{ id: 'gpt-4o', provider: 'burncloud', name: 'GPT-4o', group: 'GPT 4o' },
{ id: 'gpt-4o-mini', provider: 'burncloud', name: 'GPT-4o-mini', group: 'GPT 4o' },
{ id: 'o3', provider: 'burncloud', name: 'GPT-o1-mini', group: 'o1' },
{ id: 'o3-mini', provider: 'burncloud', name: 'GPT-o1-preview', group: 'o1' },
{ id: 'o1-mini', provider: 'burncloud', name: 'GPT-o1-mini', group: 'o1' },
{ id: 'gemini-2.5-pro-preview-03-25', provider: 'burncloud', name: 'Gemini 2.5 Preview', group: 'Geminit 2.5' },
{ id: 'gemini-2.5-pro-exp-03-25', provider: 'burncloud', name: 'Gemini 2.5 Pro Exp', group: 'Geminit 2.5' },
{ id: 'gemini-2.0-flash-lite', provider: 'burncloud', name: 'Gemini 2.0 Flash Lite', group: 'Geminit 2.0' },
{ id: 'gemini-2.0-flash-exp', provider: 'burncloud', name: 'Gemini 2.0 Flash Exp', group: 'Geminit 2.0' },
{ id: 'gemini-2.0-flash', provider: 'burncloud', name: 'Gemini 2.0 Flash', group: 'Geminit 2.0' },
{ id: 'deepseek-r1', name: 'DeepSeek-R1', provider: 'burncloud', group: 'deepseek-ai' },
{ id: 'deepseek-v3', name: 'DeepSeek-V3', provider: 'burncloud', group: 'deepseek-ai' }
],
ollama: [],
lmstudio: [],
silicon: [
{
id: 'deepseek-ai/DeepSeek-R1',
name: 'deepseek-ai/DeepSeek-R1',
provider: 'silicon',
group: 'deepseek-ai'
},
{
id: 'deepseek-ai/DeepSeek-V3',
name: 'deepseek-ai/DeepSeek-V3',
provider: 'silicon',
group: 'deepseek-ai'
},
{
id: 'Qwen/Qwen2.5-7B-Instruct',
provider: 'silicon',
name: 'Qwen2.5-7B-Instruct',
group: 'Qwen'
},
{
id: 'BAAI/bge-m3',
name: 'BAAI/bge-m3',
provider: 'silicon',
group: 'BAAI'
},
{
id: 'Qwen/Qwen3-8B',
name: 'Qwen/Qwen3-8B',
provider: 'silicon',
group: 'Qwen'
}
],
ppio: [
{
id: 'deepseek/deepseek-r1-0528',
provider: 'ppio',
name: 'DeepSeek R1-0528',
group: 'deepseek'
},
{
id: 'deepseek/deepseek-v3-0324',
provider: 'ppio',
name: 'DeepSeek V3-0324',
group: 'deepseek'
},
{
id: 'deepseek/deepseek-r1-turbo',
provider: 'ppio',
name: 'DeepSeek R1 Turbo',
group: 'deepseek'
},
{
id: 'deepseek/deepseek-v3-turbo',
provider: 'ppio',
name: 'DeepSeek V3 Turbo',
group: 'deepseek'
},
{
id: 'deepseek/deepseek-r1/community',
name: 'DeepSeek: DeepSeek R1 (Community)',
provider: 'ppio',
group: 'deepseek'
},
{
id: 'deepseek/deepseek-v3/community',
name: 'DeepSeek: DeepSeek V3 (Community)',
provider: 'ppio',
group: 'deepseek'
},
{
id: 'minimaxai/minimax-m1-80k',
provider: 'ppio',
name: 'MiniMax M1-80K',
group: 'minimaxai'
},
{
id: 'qwen/qwen3-235b-a22b-fp8',
provider: 'ppio',
name: 'Qwen3 235B',
group: 'qwen'
},
{
id: 'qwen/qwen3-32b-fp8',
provider: 'ppio',
name: 'Qwen3 32B',
group: 'qwen'
},
{
id: 'qwen/qwen3-30b-a3b-fp8',
provider: 'ppio',
name: 'Qwen3 30B',
group: 'qwen'
},
{
id: 'qwen/qwen2.5-vl-72b-instruct',
provider: 'ppio',
name: 'Qwen2.5 VL 72B',
group: 'qwen'
},
{
id: 'qwen/qwen3-embedding-8b',
provider: 'ppio',
name: 'Qwen3 Embedding 8B',
group: 'qwen'
},
{
id: 'qwen/qwen3-reranker-8b',
provider: 'ppio',
name: 'Qwen3 Reranker 8B',
group: 'qwen'
}
],
alayanew: [],
openai: [
{ id: 'gpt-4.5-preview', provider: 'openai', name: ' gpt-4.5-preview', group: 'gpt-4.5' },
{ id: 'gpt-4o', provider: 'openai', name: ' GPT-4o', group: 'GPT 4o' },
{ id: 'gpt-4o-mini', provider: 'openai', name: ' GPT-4o-mini', group: 'GPT 4o' },
{ id: 'o1-mini', provider: 'openai', name: ' o1-mini', group: 'o1' },
{ id: 'o1-preview', provider: 'openai', name: ' o1-preview', group: 'o1' }
],
'azure-openai': [
{
id: 'gpt-4o',
provider: 'azure-openai',
name: ' GPT-4o',
group: 'GPT 4o'
},
{
id: 'gpt-4o-mini',
provider: 'azure-openai',
name: ' GPT-4o-mini',
group: 'GPT 4o'
}
],
gemini: [
{
id: 'gemini-1.5-flash',
provider: 'gemini',
name: 'Gemini 1.5 Flash',
group: 'Gemini 1.5'
},
{
id: 'gemini-1.5-flash-8b',
provider: 'gemini',
name: 'Gemini 1.5 Flash (8B)',
group: 'Gemini 1.5'
},
{
id: 'gemini-1.5-pro',
name: 'Gemini 1.5 Pro',
provider: 'gemini',
group: 'Gemini 1.5'
},
{
id: 'gemini-2.0-flash',
provider: 'gemini',
name: 'Gemini 2.0 Flash',
group: 'Gemini 2.0'
}
],
anthropic: [
{
id: 'claude-sonnet-4-20250514',
provider: 'anthropic',
name: 'Claude Sonnet 4',
group: 'Claude 4'
},
{
id: 'claude-opus-4-20250514',
provider: 'anthropic',
name: 'Claude Opus 4',
group: 'Claude 4'
},
{
id: 'claude-3-7-sonnet-20250219',
provider: 'anthropic',
name: 'Claude 3.7 Sonnet',
group: 'Claude 3.7'
},
{
id: 'claude-3-5-sonnet-20241022',
provider: 'anthropic',
name: 'Claude 3.5 Sonnet',
group: 'Claude 3.5'
},
{
id: 'claude-3-5-haiku-20241022',
provider: 'anthropic',
name: 'Claude 3.5 Haiku',
group: 'Claude 3.5'
},
{
id: 'claude-3-5-sonnet-20240620',
provider: 'anthropic',
name: 'Claude 3.5 Sonnet (Legacy)',
group: 'Claude 3.5'
},
{
id: 'claude-3-opus-20240229',
provider: 'anthropic',
name: 'Claude 3 Opus',
group: 'Claude 3'
},
{
id: 'claude-3-haiku-20240307',
provider: 'anthropic',
name: 'Claude 3 Haiku',
group: 'Claude 3'
}
],
deepseek: [
{
id: 'deepseek-chat',
provider: 'deepseek',
name: 'DeepSeek Chat',
group: 'DeepSeek Chat'
},
{
id: 'deepseek-reasoner',
provider: 'deepseek',
name: 'DeepSeek Reasoner',
group: 'DeepSeek Reasoner'
}
],
together: [
{
id: 'meta-llama/Llama-3.2-11B-Vision-Instruct-Turbo',
provider: 'together',
name: 'Llama-3.2-11B-Vision',
group: 'Llama-3.2'
},
{
id: 'meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo',
provider: 'together',
name: 'Llama-3.2-90B-Vision',
group: 'Llama-3.2'
},
{
id: 'google/gemma-2-27b-it',
provider: 'together',
name: 'gemma-2-27b-it',
group: 'Gemma'
},
{
id: 'google/gemma-2-9b-it',
provider: 'together',
name: 'gemma-2-9b-it',
group: 'Gemma'
}
],
ocoolai: [
{
id: 'deepseek-chat',
provider: 'ocoolai',
name: 'deepseek-chat',
group: 'DeepSeek'
},
{
id: 'deepseek-reasoner',
provider: 'ocoolai',
name: 'deepseek-reasoner',
group: 'DeepSeek'
},
{
id: 'deepseek-ai/DeepSeek-R1',
provider: 'ocoolai',
name: 'deepseek-ai/DeepSeek-R1',
group: 'DeepSeek'
},
{
id: 'HiSpeed/DeepSeek-R1',
provider: 'ocoolai',
name: 'HiSpeed/DeepSeek-R1',
group: 'DeepSeek'
},
{
id: 'ocoolAI/DeepSeek-R1',
provider: 'ocoolai',
name: 'ocoolAI/DeepSeek-R1',
group: 'DeepSeek'
},
{
id: 'Azure/DeepSeek-R1',
provider: 'ocoolai',
name: 'Azure/DeepSeek-R1',
group: 'DeepSeek'
},
{
id: 'gpt-4o',
provider: 'ocoolai',
name: 'gpt-4o',
group: 'OpenAI'
},
{
id: 'gpt-4o-all',
provider: 'ocoolai',
name: 'gpt-4o-all',
group: 'OpenAI'
},
{
id: 'gpt-4o-mini',
provider: 'ocoolai',
name: 'gpt-4o-mini',
group: 'OpenAI'
},
{
id: 'gpt-4',
provider: 'ocoolai',
name: 'gpt-4',
group: 'OpenAI'
},
{
id: 'o1-preview',
provider: 'ocoolai',
name: 'o1-preview',
group: 'OpenAI'
},
{
id: 'o1-mini',
provider: 'ocoolai',
name: 'o1-mini',
group: 'OpenAI'
},
{
id: 'claude-3-5-sonnet-20240620',
provider: 'ocoolai',
name: 'claude-3-5-sonnet-20240620',
group: 'Anthropic'
},
{
id: 'claude-3-5-haiku-20241022',
provider: 'ocoolai',
name: 'claude-3-5-haiku-20241022',
group: 'Anthropic'
},
{
id: 'gemini-pro',
provider: 'ocoolai',
name: 'gemini-pro',
group: 'Gemini'
},
{
id: 'gemini-1.5-pro',
provider: 'ocoolai',
name: 'gemini-1.5-pro',
group: 'Gemini'
},
{
id: 'meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo',
provider: 'ocoolai',
name: 'Llama-3.2-90B-Vision-Instruct-Turbo',
group: 'Llama-3.2'
},
{
id: 'meta-llama/Llama-3.2-11B-Vision-Instruct-Turbo',
provider: 'ocoolai',
name: 'Llama-3.2-11B-Vision-Instruct-Turbo',
group: 'Llama-3.2'
},
{
id: 'meta-llama/Llama-3.2-3B-Vision-Instruct-Turbo',
provider: 'ocoolai',
name: 'Llama-3.2-3B-Vision-Instruct-Turbo',
group: 'Llama-3.2'
},
{
id: 'google/gemma-2-27b-it',
provider: 'ocoolai',
name: 'gemma-2-27b-it',
group: 'Gemma'
},
{
id: 'google/gemma-2-9b-it',
provider: 'ocoolai',
name: 'gemma-2-9b-it',
group: 'Gemma'
},
{
id: 'Doubao-embedding',
provider: 'ocoolai',
name: 'Doubao-embedding',
group: 'Doubao'
},
{
id: 'text-embedding-3-large',
provider: 'ocoolai',
name: 'text-embedding-3-large',
group: 'Embedding'
},
{
id: 'text-embedding-3-small',
provider: 'ocoolai',
name: 'text-embedding-3-small',
group: 'Embedding'
},
{
id: 'text-embedding-v2',
provider: 'ocoolai',
name: 'text-embedding-v2',
group: 'Embedding'
}
],
github: [
{
id: 'gpt-4o',
provider: 'github',
name: 'OpenAI GPT-4o',
group: 'OpenAI'
}
],
copilot: [
{
id: 'gpt-4o-mini',
provider: 'copilot',
name: 'OpenAI GPT-4o-mini',
group: 'OpenAI'
}
],
yi: [
{ id: 'yi-lightning', name: 'Yi Lightning', provider: 'yi', group: 'yi-lightning', owned_by: '01.ai' },
{ id: 'yi-vision-v2', name: 'Yi Vision v2', provider: 'yi', group: 'yi-vision', owned_by: '01.ai' }
],
zhipu: [
{
id: 'glm-4.5-flash',
provider: 'zhipu',
name: 'GLM-4.5-Flash',
group: 'GLM-4.5'
},
{
id: 'glm-4.5',
provider: 'zhipu',
name: 'GLM-4.5',
group: 'GLM-4.5'
},
{
id: 'glm-4.5-air',
provider: 'zhipu',
name: 'GLM-4.5-Air',
group: 'GLM-4.5'
},
{
id: 'glm-4.5-airx',
provider: 'zhipu',
name: 'GLM-4.5-AirX',
group: 'GLM-4.5'
},
{
id: 'glm-4.5v',
provider: 'zhipu',
name: 'GLM-4.5V',
group: 'GLM-4.5V'
},
{
id: 'embedding-3',
provider: 'zhipu',
name: 'Embedding-3',
group: 'Embedding'
}
],
moonshot: [
{
id: 'moonshot-v1-auto',
name: 'moonshot-v1-auto',
provider: 'moonshot',
group: 'moonshot-v1',
owned_by: 'moonshot',
capabilities: [{ type: 'text' }, { type: 'function_calling' }]
},
{
id: 'kimi-k2-0711-preview',
name: 'kimi-k2-0711-preview',
provider: 'moonshot',
group: 'kimi-k2',
owned_by: 'moonshot',
capabilities: [{ type: 'text' }, { type: 'function_calling' }],
pricing: {
input_per_million_tokens: 0.6,
output_per_million_tokens: 2.5,
currencySymbol: 'USD'
}
}
],
baichuan: [
{
id: 'Baichuan4',
provider: 'baichuan',
name: 'Baichuan4',
group: 'Baichuan4'
},
{
id: 'Baichuan3-Turbo',
provider: 'baichuan',
name: 'Baichuan3 Turbo',
group: 'Baichuan3'
},
{
id: 'Baichuan3-Turbo-128k',
provider: 'baichuan',
name: 'Baichuan3 Turbo 128k',
group: 'Baichuan3'
}
],
modelscope: [
{
id: 'Qwen/Qwen2.5-72B-Instruct',
name: 'Qwen/Qwen2.5-72B-Instruct',
provider: 'modelscope',
group: 'Qwen'
},
{
id: 'Qwen/Qwen2.5-VL-72B-Instruct',
name: 'Qwen/Qwen2.5-VL-72B-Instruct',
provider: 'modelscope',
group: 'Qwen'
},
{
id: 'Qwen/Qwen2.5-Coder-32B-Instruct',
name: 'Qwen/Qwen2.5-Coder-32B-Instruct',
provider: 'modelscope',
group: 'Qwen'
},
{
id: 'deepseek-ai/DeepSeek-R1',
name: 'deepseek-ai/DeepSeek-R1',
provider: 'modelscope',
group: 'deepseek-ai'
},
{
id: 'deepseek-ai/DeepSeek-V3',
name: 'deepseek-ai/DeepSeek-V3',
provider: 'modelscope',
group: 'deepseek-ai'
}
],
dashscope: [
{ id: 'qwen-vl-plus', name: 'qwen-vl-plus', provider: 'dashscope', group: 'qwen-vl', owned_by: 'system' },
{ id: 'qwen-coder-plus', name: 'qwen-coder-plus', provider: 'dashscope', group: 'qwen-coder', owned_by: 'system' },
{ id: 'qwen-flash', name: 'qwen-flash', provider: 'dashscope', group: 'qwen-flash', owned_by: 'system' },
{ id: 'qwen-plus', name: 'qwen-plus', provider: 'dashscope', group: 'qwen-plus', owned_by: 'system' },
{ id: 'qwen-max', name: 'qwen-max', provider: 'dashscope', group: 'qwen-max', owned_by: 'system' }
],
stepfun: [
{
id: 'step-1-8k',
provider: 'stepfun',
name: 'Step 1 8K',
group: 'Step 1'
},
{
id: 'step-1-flash',
provider: 'stepfun',
name: 'Step 1 Flash',
group: 'Step 1'
}
],
doubao: [
{
id: 'doubao-1-5-vision-pro-32k-250115',
provider: 'doubao',
name: 'doubao-1.5-vision-pro',
group: 'Doubao-1.5-vision-pro'
},
{
id: 'doubao-1-5-pro-32k-250115',
provider: 'doubao',
name: 'doubao-1.5-pro-32k',
group: 'Doubao-1.5-pro'
},
{
id: 'doubao-1-5-pro-32k-character-250228',
provider: 'doubao',
name: 'doubao-1.5-pro-32k-character',
group: 'Doubao-1.5-pro'
},
{
id: 'doubao-1-5-pro-256k-250115',
provider: 'doubao',
name: 'Doubao-1.5-pro-256k',
group: 'Doubao-1.5-pro'
},
{
id: 'deepseek-r1-250120',
provider: 'doubao',
name: 'DeepSeek-R1',
group: 'DeepSeek'
},
{
id: 'deepseek-r1-distill-qwen-32b-250120',
provider: 'doubao',
name: 'DeepSeek-R1-Distill-Qwen-32B',
group: 'DeepSeek'
},
{
id: 'deepseek-r1-distill-qwen-7b-250120',
provider: 'doubao',
name: 'DeepSeek-R1-Distill-Qwen-7B',
group: 'DeepSeek'
},
{
id: 'deepseek-v3-250324',
provider: 'doubao',
name: 'DeepSeek-V3',
group: 'DeepSeek'
},
{
id: 'doubao-pro-32k-241215',
provider: 'doubao',
name: 'Doubao-pro-32k',
group: 'Doubao-pro'
},
{
id: 'doubao-pro-32k-functioncall-241028',
provider: 'doubao',
name: 'Doubao-pro-32k-functioncall-241028',
group: 'Doubao-pro'
},
{
id: 'doubao-pro-32k-character-241215',
provider: 'doubao',
name: 'Doubao-pro-32k-character-241215',
group: 'Doubao-pro'
},
{
id: 'doubao-pro-256k-241115',
provider: 'doubao',
name: 'Doubao-pro-256k',
group: 'Doubao-pro'
},
{
id: 'doubao-lite-4k-character-240828',
provider: 'doubao',
name: 'Doubao-lite-4k-character-240828',
group: 'Doubao-lite'
},
{
id: 'doubao-lite-32k-240828',
provider: 'doubao',
name: 'Doubao-lite-32k',
group: 'Doubao-lite'
},
{
id: 'doubao-lite-32k-character-241015',
provider: 'doubao',
name: 'Doubao-lite-32k-character-241015',
group: 'Doubao-lite'
},
{
id: 'doubao-lite-128k-240828',
provider: 'doubao',
name: 'Doubao-lite-128k',
group: 'Doubao-lite'
},
{
id: 'doubao-1-5-lite-32k-250115',
provider: 'doubao',
name: 'Doubao-1.5-lite-32k',
group: 'Doubao-lite'
},
{
id: 'doubao-embedding-large-text-240915',
provider: 'doubao',
name: 'Doubao-embedding-large',
group: 'Doubao-embedding'
},
{
id: 'doubao-embedding-text-240715',
provider: 'doubao',
name: 'Doubao-embedding',
group: 'Doubao-embedding'
},
{
id: 'doubao-embedding-vision-241215',
provider: 'doubao',
name: 'Doubao-embedding-vision',
group: 'Doubao-embedding'
},
{
id: 'doubao-vision-lite-32k-241015',
provider: 'doubao',
name: 'Doubao-vision-lite-32k',
group: 'Doubao-vision-lite-32k'
}
],
minimax: [
{
id: 'abab6.5s-chat',
provider: 'minimax',
name: 'abab6.5s',
group: 'abab6'
},
{
id: 'abab6.5g-chat',
provider: 'minimax',
name: 'abab6.5g',
group: 'abab6'
},
{
id: 'abab6.5t-chat',
provider: 'minimax',
name: 'abab6.5t',
group: 'abab6'
},
{
id: 'abab5.5s-chat',
provider: 'minimax',
name: 'abab5.5s',
group: 'abab5'
},
{
id: 'minimax-text-01',
provider: 'minimax',
name: 'minimax-01',
group: 'minimax-01'
}
],
hyperbolic: [
{
id: 'Qwen/Qwen2-VL-72B-Instruct',
provider: 'hyperbolic',
name: 'Qwen2-VL-72B-Instruct',
group: 'Qwen2-VL'
},
{
id: 'Qwen/Qwen2-VL-7B-Instruct',
provider: 'hyperbolic',
name: 'Qwen2-VL-7B-Instruct',
group: 'Qwen2-VL'
},
{
id: 'mistralai/Pixtral-12B-2409',
provider: 'hyperbolic',
name: 'Pixtral-12B-2409',
group: 'Pixtral'
},
{
id: 'meta-llama/Meta-Llama-3.1-405B',
provider: 'hyperbolic',
name: 'Meta-Llama-3.1-405B',
group: 'Meta-Llama-3.1'
}
],
grok: [
{
id: 'grok-4',
provider: 'grok',
name: 'Grok 4',
group: 'Grok'
},
{
id: 'grok-3',
provider: 'grok',
name: 'Grok 3',
group: 'Grok'
},
{
id: 'grok-3-fast',
provider: 'grok',
name: 'Grok 3 Fast',
group: 'Grok'
},
{
id: 'grok-3-mini',
provider: 'grok',
name: 'Grok 3 Mini',
group: 'Grok'
},
{
id: 'grok-3-mini-fast',
provider: 'grok',
name: 'Grok 3 Mini Fast',
group: 'Grok'
},
{
id: 'grok-2-vision-1212',
provider: 'grok',
name: 'Grok 2 Vision 1212',
group: 'Grok'
},
{
id: 'grok-2-1212',
provider: 'grok',
name: 'Grok 2 1212',
group: 'Grok'
}
],
mistral: [
{
id: 'pixtral-12b-2409',
provider: 'mistral',
name: 'Pixtral 12B [Free]',
group: 'Pixtral'
},
{
id: 'pixtral-large-latest',
provider: 'mistral',
name: 'Pixtral Large',
group: 'Pixtral'
},
{
id: 'ministral-3b-latest',
provider: 'mistral',
name: 'Mistral 3B [Free]',
group: 'Mistral Mini'
},
{
id: 'ministral-8b-latest',
provider: 'mistral',
name: 'Mistral 8B [Free]',
group: 'Mistral Mini'
},
{
id: 'codestral-latest',
provider: 'mistral',
name: 'Mistral Codestral',
group: 'Mistral Code'
},
{
id: 'mistral-large-latest',
provider: 'mistral',
name: 'Mistral Large',
group: 'Mistral Chat'
},
{
id: 'mistral-small-latest',
provider: 'mistral',
name: 'Mistral Small',
group: 'Mistral Chat'
},
{
id: 'open-mistral-nemo',
provider: 'mistral',
name: 'Mistral Nemo',
group: 'Mistral Chat'
},
{
id: 'mistral-embed',
provider: 'mistral',
name: 'Mistral Embedding',
group: 'Mistral Embed'
}
],
jina: [
{
id: 'jina-clip-v1',
provider: 'jina',
name: 'jina-clip-v1',
group: 'Jina Clip'
},
{
id: 'jina-clip-v2',
provider: 'jina',
name: 'jina-clip-v2',
group: 'Jina Clip'
},
{
id: 'jina-embeddings-v2-base-en',
provider: 'jina',
name: 'jina-embeddings-v2-base-en',
group: 'Jina Embeddings V2'
},
{
id: 'jina-embeddings-v2-base-es',
provider: 'jina',
name: 'jina-embeddings-v2-base-es',
group: 'Jina Embeddings V2'
},
{
id: 'jina-embeddings-v2-base-de',
provider: 'jina',
name: 'jina-embeddings-v2-base-de',
group: 'Jina Embeddings V2'
},
{
id: 'jina-embeddings-v2-base-zh',
provider: 'jina',
name: 'jina-embeddings-v2-base-zh',
group: 'Jina Embeddings V2'
},
{
id: 'jina-embeddings-v2-base-code',
provider: 'jina',
name: 'jina-embeddings-v2-base-code',
group: 'Jina Embeddings V2'
},
{
id: 'jina-embeddings-v3',
provider: 'jina',
name: 'jina-embeddings-v3',
group: 'Jina Embeddings V3'
}
],
fireworks: [
{
id: 'accounts/fireworks/models/mythomax-l2-13b',
provider: 'fireworks',
name: 'mythomax-l2-13b',
group: 'Gryphe'
},
{
id: 'accounts/fireworks/models/llama-v3-70b-instruct',
provider: 'fireworks',
name: 'Llama-3-70B-Instruct',
group: 'Llama3'
}
],
hunyuan: [
{
id: 'hunyuan-pro',
provider: 'hunyuan',
name: 'hunyuan-pro',
group: 'Hunyuan'
},
{
id: 'hunyuan-standard',
provider: 'hunyuan',
name: 'hunyuan-standard',
group: 'Hunyuan'
},
{
id: 'hunyuan-lite',
provider: 'hunyuan',
name: 'hunyuan-lite',
group: 'Hunyuan'
},
{
id: 'hunyuan-standard-256k',
provider: 'hunyuan',
name: 'hunyuan-standard-256k',
group: 'Hunyuan'
},
{
id: 'hunyuan-vision',
provider: 'hunyuan',
name: 'hunyuan-vision',
group: 'Hunyuan'
},
{
id: 'hunyuan-code',
provider: 'hunyuan',
name: 'hunyuan-code',
group: 'Hunyuan'
},
{
id: 'hunyuan-role',
provider: 'hunyuan',
name: 'hunyuan-role',
group: 'Hunyuan'
},
{
id: 'hunyuan-turbo',
provider: 'hunyuan',
name: 'hunyuan-turbo',
group: 'Hunyuan'
},
{
id: 'hunyuan-turbos-latest',
provider: 'hunyuan',
name: 'hunyuan-turbos-latest',
group: 'Hunyuan'
},
{
id: 'hunyuan-embedding',
provider: 'hunyuan',
name: 'hunyuan-embedding',
group: 'Embedding'
}
],
nvidia: [
{
id: '01-ai/yi-large',
provider: 'nvidia',
name: 'yi-large',
group: 'Yi'
},
{
id: 'meta/llama-3.1-405b-instruct',
provider: 'nvidia',
name: 'llama-3.1-405b-instruct',
group: 'llama-3.1'
}
],
openrouter: [
{
id: 'google/gemini-2.5-flash-preview',
provider: 'openrouter',
name: 'Google: Gemini 2.5 Flash Preview',
group: 'google'
},
{
id: 'qwen/qwen-2.5-7b-instruct:free',
provider: 'openrouter',
name: 'Qwen: Qwen-2.5-7B Instruct',
group: 'qwen'
},
{
id: 'deepseek/deepseek-chat',
provider: 'openrouter',
name: 'DeepSeek: V3',
group: 'deepseek'
},
{
id: 'mistralai/mistral-7b-instruct:free',
provider: 'openrouter',
name: 'Mistral: Mistral 7B Instruct',
group: 'mistralai'
}
],
groq: [
{
id: 'llama3-8b-8192',
provider: 'groq',
name: 'LLaMA3 8B',
group: 'Llama3'
},
{
id: 'llama3-70b-8192',
provider: 'groq',
name: 'LLaMA3 70B',
group: 'Llama3'
},
{
id: 'mistral-saba-24b',
provider: 'groq',
name: 'Mistral Saba 24B',
group: 'Mistral'
},
{
id: 'gemma-9b-it',
provider: 'groq',
name: 'Gemma 9B',
group: 'Gemma'
}
],
'baidu-cloud': [
{
id: 'deepseek-r1',
provider: 'baidu-cloud',
name: 'DeepSeek R1',
group: 'DeepSeek'
},
{
id: 'deepseek-v3',
provider: 'baidu-cloud',
name: 'DeepSeek V3',
group: 'DeepSeek'
},
{
id: 'ernie-4.0-8k-latest',
provider: 'baidu-cloud',
name: 'ERNIE-4.0',
group: 'ERNIE'
},
{
id: 'ernie-4.0-turbo-8k-latest',
provider: 'baidu-cloud',
name: 'ERNIE 4.0 Trubo',
group: 'ERNIE'
},
{
id: 'ernie-speed-8k',
provider: 'baidu-cloud',
name: 'ERNIE Speed',
group: 'ERNIE'
},
{
id: 'ernie-lite-8k',
provider: 'baidu-cloud',
name: 'ERNIE Lite',
group: 'ERNIE'
},
{
id: 'bge-large-zh',
provider: 'baidu-cloud',
name: 'BGE Large ZH',
group: 'Embedding'
},
{
id: 'bge-large-en',
provider: 'baidu-cloud',
name: 'BGE Large EN',
group: 'Embedding'
}
],
dmxapi: [
{
id: 'Qwen/Qwen2.5-7B-Instruct',
provider: 'dmxapi',
name: 'Qwen/Qwen2.5-7B-Instruct',
group: '免费模型'
},
{
id: 'ERNIE-Speed-128K',
provider: 'dmxapi',
name: 'ERNIE-Speed-128K',
group: '免费模型'
},
{
id: 'gpt-4o',
provider: 'dmxapi',
name: 'gpt-4o',
group: 'OpenAI'
},
{
id: 'gpt-4o-mini',
provider: 'dmxapi',
name: 'gpt-4o-mini',
group: 'OpenAI'
},
{
id: 'DMXAPI-DeepSeek-R1',
provider: 'dmxapi',
name: 'DMXAPI-DeepSeek-R1',
group: 'DeepSeek'
},
{
id: 'DMXAPI-DeepSeek-V3',
provider: 'dmxapi',
name: 'DMXAPI-DeepSeek-V3',
group: 'DeepSeek'
},
{
id: 'claude-3-5-sonnet-20241022',
provider: 'dmxapi',
name: 'claude-3-5-sonnet-20241022',
group: 'Claude'
},
{
id: 'gemini-2.0-flash',
provider: 'dmxapi',
name: 'gemini-2.0-flash',
group: 'Gemini'
}
],
perplexity: [
{
id: 'sonar-reasoning-pro',
provider: 'perplexity',
name: 'sonar-reasoning-pro',
group: 'Sonar'
},
{
id: 'sonar-reasoning',
provider: 'perplexity',
name: 'sonar-reasoning',
group: 'Sonar'
},
{
id: 'sonar-pro',
provider: 'perplexity',
name: 'sonar-pro',
group: 'Sonar'
},
{
id: 'sonar',
provider: 'perplexity',
name: 'sonar',
group: 'Sonar'
},
{
id: 'sonar-deep-research',
provider: 'perplexity',
name: 'sonar-deep-research',
group: 'Sonar'
}
],
infini: [
{
id: 'deepseek-r1',
provider: 'infini',
name: 'deepseek-r1',
group: 'DeepSeek'
},
{
id: 'deepseek-r1-distill-qwen-32b',
provider: 'infini',
name: 'deepseek-r1-distill-qwen-32b',
group: 'DeepSeek'
},
{
id: 'deepseek-v3',
provider: 'infini',
name: 'deepseek-v3',
group: 'DeepSeek'
},
{
id: 'qwen2.5-72b-instruct',
provider: 'infini',
name: 'qwen2.5-72b-instruct',
group: 'Qwen'
},
{
id: 'qwen2.5-32b-instruct',
provider: 'infini',
name: 'qwen2.5-32b-instruct',
group: 'Qwen'
},
{
id: 'qwen2.5-14b-instruct',
provider: 'infini',
name: 'qwen2.5-14b-instruct',
group: 'Qwen'
},
{
id: 'qwen2.5-7b-instruct',
provider: 'infini',
name: 'qwen2.5-7b-instruct',
group: 'Qwen'
},
{
id: 'qwen2-72b-instruct',
provider: 'infini',
name: 'qwen2-72b-instruct',
group: 'Qwen'
},
{
id: 'qwq-32b-preview',
provider: 'infini',
name: 'qwq-32b-preview',
group: 'Qwen'
},
{
id: 'qwen2.5-coder-32b-instruct',
provider: 'infini',
name: 'qwen2.5-coder-32b-instruct',
group: 'Qwen'
},
{
id: 'llama-3.3-70b-instruct',
provider: 'infini',
name: 'llama-3.3-70b-instruct',
group: 'Llama'
},
{
id: 'bge-m3',
provider: 'infini',
name: 'bge-m3',
group: 'BAAI'
},
{
id: 'gemma-2-27b-it',
provider: 'infini',
name: 'gemma-2-27b-it',
group: 'Gemma'
},
{
id: 'jina-embeddings-v2-base-zh',
provider: 'infini',
name: 'jina-embeddings-v2-base-zh',
group: 'Jina'
},
{
id: 'jina-embeddings-v2-base-code',
provider: 'infini',
name: 'jina-embeddings-v2-base-code',
group: 'Jina'
}
],
xirang: [],
'tencent-cloud-ti': [
{
id: 'deepseek-r1',
provider: 'tencent-cloud-ti',
name: 'DeepSeek R1',
group: 'DeepSeek'
},
{
id: 'deepseek-v3',
provider: 'tencent-cloud-ti',
name: 'DeepSeek V3',
group: 'DeepSeek'
}
],
gpustack: [],
voyageai: [
{
id: 'voyage-3-large',
provider: 'voyageai',
name: 'voyage-3-large',
group: 'Voyage Embeddings V3'
},
{
id: 'voyage-3',
provider: 'voyageai',
name: 'voyage-3',
group: 'Voyage Embeddings V3'
},
{
id: 'voyage-3-lite',
provider: 'voyageai',
name: 'voyage-3-lite',
group: 'Voyage Embeddings V3'
},
{
id: 'voyage-code-3',
provider: 'voyageai',
name: 'voyage-code-3',
group: 'Voyage Embeddings V3'
},
{
id: 'voyage-finance-3',
provider: 'voyageai',
name: 'voyage-finance-3',
group: 'Voyage Embeddings V2'
},
{
id: 'voyage-law-2',
provider: 'voyageai',
name: 'voyage-law-2',
group: 'Voyage Embeddings V2'
},
{
id: 'voyage-code-2',
provider: 'voyageai',
name: 'voyage-code-2',
group: 'Voyage Embeddings V2'
},
{
id: 'rerank-2',
provider: 'voyageai',
name: 'rerank-2',
group: 'Voyage Rerank V2'
},
{
id: 'rerank-2-lite',
provider: 'voyageai',
name: 'rerank-2-lite',
group: 'Voyage Rerank V2'
}
],
qiniu: [
{
id: 'deepseek-r1',
provider: 'qiniu',
name: 'DeepSeek R1',
group: 'DeepSeek'
},
{
id: 'deepseek-r1-search',
provider: 'qiniu',
name: 'DeepSeek R1 Search',
group: 'DeepSeek'
},
{
id: 'deepseek-r1-32b',
provider: 'qiniu',
name: 'DeepSeek R1 32B',
group: 'DeepSeek'
},
{
id: 'deepseek-v3',
provider: 'qiniu',
name: 'DeepSeek V3',
group: 'DeepSeek'
},
{
id: 'deepseek-v3-search',
provider: 'qiniu',
name: 'DeepSeek V3 Search',
group: 'DeepSeek'
},
{
id: 'deepseek-v3-tool',
provider: 'qiniu',
name: 'DeepSeek V3 Tool',
group: 'DeepSeek'
},
{
id: 'qwq-32b',
provider: 'qiniu',
name: 'QWQ 32B',
group: 'Qwen'
},
{
id: 'qwen2.5-72b-instruct',
provider: 'qiniu',
name: 'Qwen2.5 72B Instruct',
group: 'Qwen'
}
],
tokenflux: [
{
id: 'gpt-4.1',
provider: 'tokenflux',
name: 'GPT-4.1',
group: 'GPT-4.1'
},
{
id: 'gpt-4.1-mini',
provider: 'tokenflux',
name: 'GPT-4.1 Mini',
group: 'GPT-4.1'
},
{
id: 'claude-sonnet-4',
provider: 'tokenflux',
name: 'Claude Sonnet 4',
group: 'Claude'
},
{
id: 'claude-3-7-sonnet',
provider: 'tokenflux',
name: 'Claude 3.7 Sonnet',
group: 'Claude'
},
{
id: 'gemini-2.5-pro',
provider: 'tokenflux',
name: 'Gemini 2.5 Pro',
group: 'Gemini'
},
{
id: 'gemini-2.5-flash',
provider: 'tokenflux',
name: 'Gemini 2.5 Flash',
group: 'Gemini'
},
{
id: 'deepseek-r1',
provider: 'tokenflux',
name: 'DeepSeek R1',
group: 'DeepSeek'
},
{
id: 'deepseek-v3',
provider: 'tokenflux',
name: 'DeepSeek V3',
group: 'DeepSeek'
},
{
id: 'qwen-max',
provider: 'tokenflux',
name: 'Qwen Max',
group: 'Qwen'
},
{
id: 'qwen-plus',
provider: 'tokenflux',
name: 'Qwen Plus',
group: 'Qwen'
}
],
cephalon: [
{
id: 'DeepSeek-R1',
provider: 'cephalon',
name: 'DeepSeek-R1满血版',
group: 'DeepSeek'
}
],
lanyun: [
{
id: '/maas/deepseek-ai/DeepSeek-R1-0528',
name: 'deepseek-ai/DeepSeek-R1',
provider: 'lanyun',
group: 'deepseek-ai'
},
{
id: '/maas/deepseek-ai/DeepSeek-V3-0324',
name: 'deepseek-ai/DeepSeek-V3',
provider: 'lanyun',
group: 'deepseek-ai'
},
{
id: '/maas/qwen/Qwen2.5-72B-Instruct',
provider: 'lanyun',
name: 'Qwen2.5-72B-Instruct',
group: 'Qwen'
},
{
id: '/maas/qwen/Qwen3-235B-A22B',
name: 'Qwen/Qwen3-235B',
provider: 'lanyun',
group: 'Qwen'
},
{
id: '/maas/minimax/MiniMax-M1-80k',
name: 'MiniMax-M1-80k',
provider: 'lanyun',
group: 'MiniMax'
},
{
id: '/maas/google/Gemma3-27B',
name: 'Gemma3-27B',
provider: 'lanyun',
group: 'google'
}
],
'new-api': [],
'aws-bedrock': [],
poe: [
{
id: 'gpt-4o',
name: 'GPT-4o',
provider: 'poe',
group: 'poe'
}
]
}
export const TEXT_TO_IMAGES_MODELS = [
{
id: 'Kwai-Kolors/Kolors',
provider: 'silicon',
name: 'Kolors',
group: 'Kwai-Kolors'
}
// {
// id: 'black-forest-labs/FLUX.1-schnell',
// provider: 'silicon',
// name: 'FLUX.1 Schnell',
// group: 'FLUX'
// },
// {
// id: 'black-forest-labs/FLUX.1-dev',
// provider: 'silicon',
// name: 'FLUX.1 Dev',
// group: 'FLUX'
// },
// {
// id: 'black-forest-labs/FLUX.1-pro',
// provider: 'silicon',
// name: 'FLUX.1 Pro',
// group: 'FLUX'
// },
// {
// id: 'Pro/black-forest-labs/FLUX.1-schnell',
// provider: 'silicon',
// name: 'FLUX.1 Schnell Pro',
// group: 'FLUX'
// },
// {
// id: 'LoRA/black-forest-labs/FLUX.1-dev',
// provider: 'silicon',
// name: 'FLUX.1 Dev LoRA',
// group: 'FLUX'
// },
// {
// id: 'deepseek-ai/Janus-Pro-7B',
// provider: 'silicon',
// name: 'Janus-Pro-7B',
// group: 'deepseek-ai'
// },
// {
// id: 'stabilityai/stable-diffusion-3-5-large',
// provider: 'silicon',
// name: 'Stable Diffusion 3.5 Large',
// group: 'Stable Diffusion'
// },
// {
// id: 'stabilityai/stable-diffusion-3-5-large-turbo',
// provider: 'silicon',
// name: 'Stable Diffusion 3.5 Large Turbo',
// group: 'Stable Diffusion'
// },
// {
// id: 'stabilityai/stable-diffusion-3-medium',
// provider: 'silicon',
// name: 'Stable Diffusion 3 Medium',
// group: 'Stable Diffusion'
// },
// {
// id: 'stabilityai/stable-diffusion-2-1',
// provider: 'silicon',
// name: 'Stable Diffusion 2.1',
// group: 'Stable Diffusion'
// },
// {
// id: 'stabilityai/stable-diffusion-xl-base-1.0',
// provider: 'silicon',
// name: 'Stable Diffusion XL Base 1.0',
// group: 'Stable Diffusion'
// }
]
export const TEXT_TO_IMAGES_MODELS_SUPPORT_IMAGE_ENHANCEMENT = [
'stabilityai/stable-diffusion-2-1',
'stabilityai/stable-diffusion-xl-base-1.0'
]
export const SUPPORTED_DISABLE_GENERATION_MODELS = [
'gemini-2.0-flash-exp',
'gpt-4o',
'gpt-4o-mini',
'gpt-4.1',
'gpt-4.1-mini',
'gpt-4.1-nano',
'o3'
]
export const GENERATE_IMAGE_MODELS = [
'gemini-2.0-flash-exp-image-generation',
'gemini-2.0-flash-preview-image-generation',
'gemini-2.5-flash-image-preview',
'grok-2-image-1212',
'grok-2-image',
'grok-2-image-latest',
'gpt-image-1',
...SUPPORTED_DISABLE_GENERATION_MODELS
]
export const GEMINI_SEARCH_REGEX = new RegExp('gemini-2\\..*', 'i')
export const OPENAI_NO_SUPPORT_DEV_ROLE_MODELS = ['o1-preview', 'o1-mini']
export const PERPLEXITY_SEARCH_MODELS = [
'sonar-pro',
'sonar',
'sonar-reasoning',
'sonar-reasoning-pro',
'sonar-deep-research'
]
export function isTextToImageModel(model: Model): boolean {
const modelId = getLowerBaseModelName(model.id)
return TEXT_TO_IMAGE_REGEX.test(modelId)
}
export function isEmbeddingModel(model: Model): boolean {
if (!model || isRerankModel(model)) {
return false
}
const modelId = getLowerBaseModelName(model.id)
if (isUserSelectedModelType(model, 'embedding') !== undefined) {
return isUserSelectedModelType(model, 'embedding')!
}
if (['anthropic'].includes(model?.provider)) {
return false
}
if (model.provider === 'doubao' || modelId.includes('doubao')) {
return EMBEDDING_REGEX.test(model.name)
}
return EMBEDDING_REGEX.test(modelId) || false
}
export function isRerankModel(model: Model): boolean {
if (isUserSelectedModelType(model, 'rerank') !== undefined) {
return isUserSelectedModelType(model, 'rerank')!
}
const modelId = getLowerBaseModelName(model.id)
return model ? RERANKING_REGEX.test(modelId) || false : false
}
export function isVisionModel(model: Model): boolean {
if (!model || isEmbeddingModel(model) || isRerankModel(model)) {
return false
}
// 新添字段 copilot-vision-request 后可使用 vision
// if (model.provider === 'copilot') {
// return false
// }
if (isUserSelectedModelType(model, 'vision') !== undefined) {
return isUserSelectedModelType(model, 'vision')!
}
const modelId = getLowerBaseModelName(model.id)
if (model.provider === 'doubao' || modelId.includes('doubao')) {
return VISION_REGEX.test(model.name) || VISION_REGEX.test(modelId) || false
}
return VISION_REGEX.test(modelId) || false
}
export function isOpenAIReasoningModel(model: Model): boolean {
const modelId = getLowerBaseModelName(model.id, '/')
return isSupportedReasoningEffortOpenAIModel(model) || modelId.includes('o1')
}
export function isOpenAILLMModel(model: Model): boolean {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id)
if (modelId.includes('gpt-4o-image')) {
return false
}
if (isOpenAIReasoningModel(model)) {
return true
}
if (modelId.includes('gpt')) {
return true
}
return false
}
export function isOpenAIModel(model: Model): boolean {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id)
return modelId.includes('gpt') || isOpenAIReasoningModel(model)
}
export function isSupportFlexServiceTierModel(model: Model): boolean {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id)
return (
(modelId.includes('o3') && !modelId.includes('o3-mini')) || modelId.includes('o4-mini') || modelId.includes('gpt-5')
)
}
export function isSupportVerbosityModel(model: Model): boolean {
const modelId = getLowerBaseModelName(model.id)
return isGPT5SeriesModel(model) && !modelId.includes('chat')
}
export function isSupportedReasoningEffortOpenAIModel(model: Model): boolean {
const modelId = getLowerBaseModelName(model.id)
return (
(modelId.includes('o1') && !(modelId.includes('o1-preview') || modelId.includes('o1-mini'))) ||
modelId.includes('o3') ||
modelId.includes('o4') ||
modelId.includes('gpt-oss') ||
(isGPT5SeriesModel(model) && !modelId.includes('chat'))
)
}
export function isOpenAIChatCompletionOnlyModel(model: Model): boolean {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id)
return (
modelId.includes('gpt-4o-search-preview') ||
modelId.includes('gpt-4o-mini-search-preview') ||
modelId.includes('o1-mini') ||
modelId.includes('o1-preview')
)
}
export function isOpenAIWebSearchChatCompletionOnlyModel(model: Model): boolean {
const modelId = getLowerBaseModelName(model.id)
return modelId.includes('gpt-4o-search-preview') || modelId.includes('gpt-4o-mini-search-preview')
}
export function isOpenAIWebSearchModel(model: Model): boolean {
const modelId = getLowerBaseModelName(model.id)
return (
modelId.includes('gpt-4o-search-preview') ||
modelId.includes('gpt-4o-mini-search-preview') ||
(modelId.includes('gpt-4.1') && !modelId.includes('gpt-4.1-nano')) ||
(modelId.includes('gpt-4o') && !modelId.includes('gpt-4o-image')) ||
modelId.includes('o3') ||
modelId.includes('o4') ||
(modelId.includes('gpt-5') && !modelId.includes('chat'))
)
}
/** 用于判断是否支持控制思考,但不一定以reasoning_effort的方式 */
export function isSupportedThinkingTokenModel(model?: Model): boolean {
if (!model) {
return false
}
// Specifically for DeepSeek V3.1. White list for now
if (isDeepSeekHybridInferenceModel(model)) {
return (['openrouter', 'dashscope', 'doubao', 'silicon', 'nvidia'] satisfies SystemProviderId[]).some(
(id) => id === model.provider
)
}
return (
isSupportedThinkingTokenGeminiModel(model) ||
isSupportedThinkingTokenQwenModel(model) ||
isSupportedThinkingTokenClaudeModel(model) ||
isSupportedThinkingTokenDoubaoModel(model) ||
isSupportedThinkingTokenHunyuanModel(model) ||
isSupportedThinkingTokenZhipuModel(model)
)
}
export function isSupportedReasoningEffortModel(model?: Model): boolean {
if (!model) {
return false
}
return (
isSupportedReasoningEffortOpenAIModel(model) ||
isSupportedReasoningEffortGrokModel(model) ||
isSupportedReasoningEffortPerplexityModel(model)
)
}
export function isGrokModel(model?: Model): boolean {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id)
return modelId.includes('grok')
}
export function isSupportedReasoningEffortGrokModel(model?: Model): boolean {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id)
if (modelId.includes('grok-3-mini')) {
return true
}
return false
}
export function isGrokReasoningModel(model?: Model): boolean {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id)
if (isSupportedReasoningEffortGrokModel(model) || modelId.includes('grok-4')) {
return true
}
return false
}
export function isGeminiReasoningModel(model?: Model): boolean {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id)
if (modelId.startsWith('gemini') && modelId.includes('thinking')) {
return true
}
if (isSupportedThinkingTokenGeminiModel(model)) {
return true
}
return false
}
export const isSupportedThinkingTokenGeminiModel = (model: Model): boolean => {
const modelId = getLowerBaseModelName(model.id, '/')
if (modelId.includes('gemini-2.5')) {
if (modelId.includes('image') || modelId.includes('tts')) {
return false
}
return true
} else {
return false
}
}
/** 是否为Qwen推理模型 */
export function isQwenReasoningModel(model?: Model): boolean {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id, '/')
if (modelId.startsWith('qwen3')) {
if (modelId.includes('thinking')) {
return true
} else if (modelId.includes('instruct')) {
return false
}
return true
}
if (isSupportedThinkingTokenQwenModel(model)) {
return true
}
if (modelId.includes('qwq') || modelId.includes('qvq')) {
return true
}
return false
}
/** 是否为支持思考控制的Qwen3推理模型 */
export function isSupportedThinkingTokenQwenModel(model?: Model): boolean {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id, '/')
if (modelId.includes('coder')) {
return false
}
if (modelId.startsWith('qwen3')) {
// instruct 是非思考模型 thinking 是思考模型,二者都不能控制思考
if (modelId.includes('instruct') || modelId.includes('thinking')) {
return false
}
return true
}
return [
'qwen-plus',
'qwen-plus-latest',
'qwen-plus-0428',
'qwen-plus-2025-04-28',
'qwen-plus-0714',
'qwen-plus-2025-07-14',
'qwen-turbo',
'qwen-turbo-latest',
'qwen-turbo-0428',
'qwen-turbo-2025-04-28',
'qwen-turbo-0715',
'qwen-turbo-2025-07-15',
'qwen-flash',
'qwen-flash-2025-07-28'
].includes(modelId)
}
/** 是否为不支持思考控制的Qwen推理模型 */
export function isQwenAlwaysThinkModel(model?: Model): boolean {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id, '/')
return modelId.startsWith('qwen3') && modelId.includes('thinking')
}
export function isSupportedThinkingTokenDoubaoModel(model?: Model): boolean {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id, '/')
return DOUBAO_THINKING_MODEL_REGEX.test(modelId) || DOUBAO_THINKING_MODEL_REGEX.test(model.name)
}
export function isClaudeReasoningModel(model?: Model): boolean {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id, '/')
return (
modelId.includes('claude-3-7-sonnet') ||
modelId.includes('claude-3.7-sonnet') ||
modelId.includes('claude-sonnet-4') ||
modelId.includes('claude-opus-4')
)
}
export const isSupportedThinkingTokenClaudeModel = isClaudeReasoningModel
export const isSupportedThinkingTokenHunyuanModel = (model?: Model): boolean => {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id, '/')
return modelId.includes('hunyuan-a13b')
}
export const isHunyuanReasoningModel = (model?: Model): boolean => {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id, '/')
return isSupportedThinkingTokenHunyuanModel(model) || modelId.includes('hunyuan-t1')
}
export const isPerplexityReasoningModel = (model?: Model): boolean => {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id, '/')
return isSupportedReasoningEffortPerplexityModel(model) || modelId.includes('reasoning')
}
export const isSupportedReasoningEffortPerplexityModel = (model: Model): boolean => {
const modelId = getLowerBaseModelName(model.id, '/')
return modelId.includes('sonar-deep-research')
}
export const isSupportedThinkingTokenZhipuModel = (model: Model): boolean => {
const modelId = getLowerBaseModelName(model.id, '/')
return modelId.includes('glm-4.5')
}
export const isDeepSeekHybridInferenceModel = (model: Model) => {
const modelId = getLowerBaseModelName(model.id)
// deepseek官方使用chat和reasoner做推理控制,其他provider需要单独判断,id可能会有所差别
// openrouter: deepseek/deepseek-chat-v3.1 不知道会不会有其他provider仿照ds官方分出一个同id的作为非思考模式的模型,这里有风险
return /deepseek-v3(?:\.1|-1-\d+)?/.test(modelId) || modelId === 'deepseek-chat-v3.1'
}
export const isSupportedThinkingTokenDeepSeekModel = isDeepSeekHybridInferenceModel
export const isZhipuReasoningModel = (model?: Model): boolean => {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id, '/')
return isSupportedThinkingTokenZhipuModel(model) || modelId.includes('glm-z1')
}
export const isStepReasoningModel = (model?: Model): boolean => {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id, '/')
return modelId.includes('step-3') || modelId.includes('step-r1-v-mini')
}
export function isReasoningModel(model?: Model): boolean {
if (!model || isEmbeddingModel(model) || isRerankModel(model) || isTextToImageModel(model)) {
return false
}
if (isUserSelectedModelType(model, 'reasoning') !== undefined) {
return isUserSelectedModelType(model, 'reasoning')!
}
const modelId = getLowerBaseModelName(model.id)
if (model.provider === 'doubao' || modelId.includes('doubao')) {
return (
REASONING_REGEX.test(modelId) ||
REASONING_REGEX.test(model.name) ||
isSupportedThinkingTokenDoubaoModel(model) ||
isDeepSeekHybridInferenceModel(model) ||
isDeepSeekHybridInferenceModel({ ...model, id: model.name }) ||
false
)
}
if (
isClaudeReasoningModel(model) ||
isOpenAIReasoningModel(model) ||
isGeminiReasoningModel(model) ||
isQwenReasoningModel(model) ||
isGrokReasoningModel(model) ||
isHunyuanReasoningModel(model) ||
isPerplexityReasoningModel(model) ||
isZhipuReasoningModel(model) ||
isStepReasoningModel(model) ||
isDeepSeekHybridInferenceModel(model) ||
modelId.includes('magistral') ||
modelId.includes('minimax-m1') ||
modelId.includes('pangu-pro-moe')
) {
return true
}
return REASONING_REGEX.test(modelId) || false
}
export function isSupportedModel(model: OpenAI.Models.Model): boolean {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id)
return !NOT_SUPPORTED_REGEX.test(modelId)
}
export function isNotSupportTemperatureAndTopP(model: Model): boolean {
if (!model) {
return true
}
if (
(isOpenAIReasoningModel(model) && !isOpenAIOpenWeightModel(model)) ||
isOpenAIChatCompletionOnlyModel(model) ||
isQwenMTModel(model)
) {
return true
}
return false
}
export function isWebSearchModel(model: Model): boolean {
if (!model || isEmbeddingModel(model) || isRerankModel(model) || isTextToImageModel(model)) {
return false
}
if (isUserSelectedModelType(model, 'web_search') !== undefined) {
return isUserSelectedModelType(model, 'web_search')!
}
const provider = getProviderByModel(model)
if (!provider) {
return false
}
const isEmbedding = isEmbeddingModel(model)
if (isEmbedding) {
return false
}
const modelId = getLowerBaseModelName(model.id, '/')
// 不管哪个供应商都判断了
if (isAnthropicModel(model)) {
return CLAUDE_SUPPORTED_WEBSEARCH_REGEX.test(modelId)
}
if (provider.type === 'openai-response') {
if (isOpenAIWebSearchModel(model)) {
return true
}
return false
}
if (provider.id === 'perplexity') {
return PERPLEXITY_SEARCH_MODELS.includes(modelId)
}
if (provider.id === 'aihubmix') {
// modelId 不以-search结尾
if (!modelId.endsWith('-search') && GEMINI_SEARCH_REGEX.test(modelId)) {
return true
}
if (isOpenAIWebSearchModel(model)) {
return true
}
return false
}
if (provider?.type === 'openai') {
if (GEMINI_SEARCH_REGEX.test(modelId) || isOpenAIWebSearchModel(model)) {
return true
}
}
if (provider.id === 'gemini' || provider?.type === 'gemini' || provider.type === 'vertexai') {
return GEMINI_SEARCH_REGEX.test(modelId)
}
if (provider.id === 'hunyuan') {
return modelId !== 'hunyuan-lite'
}
if (provider.id === 'zhipu') {
return modelId?.startsWith('glm-4-')
}
if (provider.id === 'dashscope') {
const models = ['qwen-turbo', 'qwen-max', 'qwen-plus', 'qwq', 'qwen-flash']
// matches id like qwen-max-0919, qwen-max-latest
return models.some((i) => modelId.startsWith(i))
}
if (provider.id === 'openrouter') {
return true
}
if (provider.id === 'grok') {
return true
}
return false
}
export function isMandatoryWebSearchModel(model: Model): boolean {
if (!model) {
return false
}
const provider = getProviderByModel(model)
if (!provider) {
return false
}
const modelId = getLowerBaseModelName(model.id)
if (provider.id === 'perplexity' || provider.id === 'openrouter') {
return PERPLEXITY_SEARCH_MODELS.includes(modelId)
}
return false
}
export function isOpenRouterBuiltInWebSearchModel(model: Model): boolean {
if (!model) {
return false
}
const provider = getProviderByModel(model)
if (provider.id !== 'openrouter') {
return false
}
const modelId = getLowerBaseModelName(model.id)
return isOpenAIWebSearchChatCompletionOnlyModel(model) || modelId.includes('sonar')
}
export function isGenerateImageModel(model: Model): boolean {
if (!model) {
return false
}
const provider = getProviderByModel(model)
if (!provider) {
return false
}
const isEmbedding = isEmbeddingModel(model)
if (isEmbedding) {
return false
}
const modelId = getLowerBaseModelName(model.id, '/')
if (GENERATE_IMAGE_MODELS.includes(modelId)) {
return true
}
return false
}
export function isSupportedDisableGenerationModel(model: Model): boolean {
if (!model) {
return false
}
return SUPPORTED_DISABLE_GENERATION_MODELS.includes(getLowerBaseModelName(model.id))
}
export function getOpenAIWebSearchParams(model: Model, isEnableWebSearch?: boolean): Record<string, any> {
if (!isEnableWebSearch) {
return {}
}
const webSearchTools = getWebSearchTools(model)
if (model.provider === 'grok') {
return {
search_parameters: {
mode: 'auto',
return_citations: true,
sources: [{ type: 'web' }, { type: 'x' }, { type: 'news' }]
}
}
}
if (model.provider === 'hunyuan') {
return { enable_enhancement: true, citation: true, search_info: true }
}
if (model.provider === 'dashscope') {
return {
enable_search: true,
search_options: {
forced_search: true
}
}
}
if (isOpenAIWebSearchChatCompletionOnlyModel(model)) {
return {
web_search_options: {}
}
}
if (model.provider === 'openrouter') {
return {
plugins: [{ id: 'web', search_prompts: WEB_SEARCH_PROMPT_FOR_OPENROUTER }]
}
}
return {
tools: webSearchTools
}
return {}
}
export function isGemmaModel(model?: Model): boolean {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id)
return modelId.includes('gemma-') || model.group === 'Gemma'
}
export function isZhipuModel(model?: Model): boolean {
if (!model) {
return false
}
return model.provider === 'zhipu'
}
export function isHunyuanSearchModel(model?: Model): boolean {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id)
if (model.provider === 'hunyuan') {
return modelId !== 'hunyuan-lite'
}
return false
}
/**
* 按 Qwen 系列模型分组
* @param models 模型列表
* @returns 分组后的模型
*/
export function groupQwenModels(models: Model[]): Record<string, Model[]> {
return models.reduce(
(groups, model) => {
const modelId = getLowerBaseModelName(model.id)
// 匹配 Qwen 系列模型的前缀
const prefixMatch = modelId.match(/^(qwen(?:\d+\.\d+|2(?:\.\d+)?|-\d+b|-(?:max|coder|vl)))/i)
// 匹配 qwen2.5、qwen2、qwen-7b、qwen-max、qwen-coder 等
const groupKey = prefixMatch ? prefixMatch[1] : model.group || '其他'
if (!groups[groupKey]) {
groups[groupKey] = []
}
groups[groupKey].push(model)
return groups
},
{} as Record<string, Model[]>
)
}
export const THINKING_TOKEN_MAP: Record<string, { min: number; max: number }> = {
// Gemini models
'gemini-2\\.5-flash-lite.*$': { min: 512, max: 24576 },
'gemini-.*-flash.*$': { min: 0, max: 24576 },
'gemini-.*-pro.*$': { min: 128, max: 32768 },
// Qwen models
'qwen3-235b-a22b-thinking-2507$': { min: 0, max: 81_920 },
'qwen3-30b-a3b-thinking-2507$': { min: 0, max: 81_920 },
'qwen-plus-2025-07-28$': { min: 0, max: 81_920 },
'qwen-plus-latest$': { min: 0, max: 81_920 },
'qwen3-1\\.7b$': { min: 0, max: 30_720 },
'qwen3-0\\.6b$': { min: 0, max: 30_720 },
'qwen-plus.*$': { min: 0, max: 38_912 },
'qwen-turbo.*$': { min: 0, max: 38_912 },
'qwen-flash.*$': { min: 0, max: 81_920 },
'qwen3-.*$': { min: 1024, max: 38_912 },
// Claude models
'claude-3[.-]7.*sonnet.*$': { min: 1024, max: 64000 },
'claude-(:?sonnet|opus)-4.*$': { min: 1024, max: 32000 }
}
export const findTokenLimit = (modelId: string): { min: number; max: number } | undefined => {
for (const [pattern, limits] of Object.entries(THINKING_TOKEN_MAP)) {
if (new RegExp(pattern, 'i').test(modelId)) {
return limits
}
}
return undefined
}
// Doubao 支持思考模式的模型正则
export const DOUBAO_THINKING_MODEL_REGEX =
/doubao-(?:1[.-]5-thinking-vision-pro|1[.-]5-thinking-pro-m|seed-1[.-]6(?:-flash)?(?!-(?:thinking)(?:-|$)))(?:-[\w-]+)*/i
// 支持 auto 的 Doubao 模型 doubao-seed-1.6-xxx doubao-seed-1-6-xxx doubao-1-5-thinking-pro-m-xxx
export const DOUBAO_THINKING_AUTO_MODEL_REGEX =
/doubao-(1-5-thinking-pro-m|seed-1[.-]6)(?!-(?:flash|thinking)(?:-|$))(?:-[\w-]+)*/i
export function isDoubaoThinkingAutoModel(model: Model): boolean {
const modelId = getLowerBaseModelName(model.id)
return DOUBAO_THINKING_AUTO_MODEL_REGEX.test(modelId) || DOUBAO_THINKING_AUTO_MODEL_REGEX.test(model.name)
}
export const GEMINI_FLASH_MODEL_REGEX = new RegExp('gemini-.*-flash.*$')
// 模型集合功能测试
export const isVisionModels = (models: Model[]) => {
return models.every((model) => isVisionModel(model))
}
export const isGenerateImageModels = (models: Model[]) => {
return models.every((model) => isGenerateImageModel(model))
}
export const isAnthropicModel = (model?: Model): boolean => {
if (!model) {
return false
}
const modelId = getLowerBaseModelName(model.id)
return modelId.startsWith('claude')
}
export const isQwenMTModel = (model: Model): boolean => {
const modelId = getLowerBaseModelName(model.id)
return modelId.includes('qwen-mt')
}
export const isNotSupportedTextDelta = (model: Model): boolean => {
return isQwenMTModel(model)
}
export const isNotSupportSystemMessageModel = (model: Model): boolean => {
return isQwenMTModel(model) || isGemmaModel(model)
}
export const isGPT5SeriesModel = (model: Model) => {
const modelId = getLowerBaseModelName(model.id)
return modelId.includes('gpt-5')
}
export const isGeminiModel = (model: Model) => {
const modelId = getLowerBaseModelName(model.id)
return modelId.includes('gemini')
}
export const isOpenAIOpenWeightModel = (model: Model) => {
const modelId = getLowerBaseModelName(model.id)
return modelId.includes('gpt-oss')
}
// zhipu 视觉推理模型用这组 special token 标记推理结果
export const ZHIPU_RESULT_TOKENS = ['<|begin_of_box|>', '<|end_of_box|>'] as const