mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-04 17:09:40 +00:00
Updated model capabilities across all providers (#940)
This commit is contained in:
1 parent
c9b7f224cc
commit
edbb75dd9f
10 files changed
+275
-256
No files matched your search
@@ -47,6 +47,43 @@ public static partial class ProviderExtensions
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// Check for the Qwen 3.8 family:
|
||||
if(modelName.StartsWith("qwen3.8"))
|
||||
{
|
||||
// Flash thinks by default, but thinking can be turned off:
|
||||
if(modelName.StartsWith("qwen3.8-flash"))
|
||||
return
|
||||
[
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT, Capability.VIDEO_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
|
||||
Capability.REASONING_BY_DEFAULT, Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// Unlike the open-weight checkpoint, the Max model keeps its vision
|
||||
// capabilities when used through Alibaba Cloud:
|
||||
if(modelName.StartsWith("qwen3.8-max"))
|
||||
return
|
||||
[
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT, Capability.VIDEO_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
|
||||
Capability.ALWAYS_REASONING, Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// All other 3.8 models, such as the 27B one:
|
||||
return
|
||||
[
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
|
||||
Capability.REASONING_BY_DEFAULT, Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
}
|
||||
|
||||
// Check for the 3.0 VL models:
|
||||
if(modelName.IndexOf("-vl-") is not -1)
|
||||
return
|
||||
|
||||
@@ -18,6 +18,26 @@ public static partial class ProviderExtensions
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// Claude Opus 5 and Sonnet 5 think adaptively unless thinking is turned off:
|
||||
if(modelName.StartsWith("claude-opus-5") || modelName.StartsWith("claude-sonnet-5"))
|
||||
return [
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
|
||||
Capability.REASONING_BY_DEFAULT, Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// Claude Haiku 4.5 needs an explicit thinking budget to reason:
|
||||
if(modelName.StartsWith("claude-haiku-4-5"))
|
||||
return [
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
|
||||
Capability.OPTIONAL_REASONING, Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// Claude 4.x models:
|
||||
if(modelName.StartsWith("claude-opus-4") || modelName.StartsWith("claude-sonnet-4"))
|
||||
return [
|
||||
@@ -48,9 +68,10 @@ public static partial class ProviderExtensions
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// Any other model is able to process text only:
|
||||
// Any other model. Every current Claude model accepts images, so we assume the
|
||||
// same for models we do not know yet:
|
||||
return [
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
|
||||
@@ -8,21 +8,31 @@ public static partial class ProviderExtensions
|
||||
{
|
||||
var modelName = model.Id.ToLowerInvariant().AsSpan();
|
||||
|
||||
// The reasoner alias points to the thinking mode of the current flash model:
|
||||
if(modelName.IndexOf("reasoner") is not -1)
|
||||
return
|
||||
[
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
|
||||
Capability.ALWAYS_REASONING,
|
||||
|
||||
Capability.ALWAYS_REASONING, Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
return
|
||||
[
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// The chat alias points to the non-thinking mode of the same model:
|
||||
if(modelName.IndexOf("chat") is not -1)
|
||||
return
|
||||
[
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
|
||||
Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// DeepSeek publishes its models as open weights and offers them under the same
|
||||
// names here. Instead of maintaining a second copy of those rules, we reuse the
|
||||
// ones for open source models:
|
||||
return GetModelCapabilitiesOpenSource(model);
|
||||
}
|
||||
}
|
||||
@@ -10,14 +10,13 @@ public static partial class ProviderExtensions
|
||||
|
||||
if (modelName.IndexOf("gemini-") is not -1)
|
||||
{
|
||||
// Chat-compatible Gemini 3.x reasoning models:
|
||||
if (modelName is "gemini-3.5-flash" ||
|
||||
// Chat-compatible Gemini 3.x reasoning models. We match the entire 3.x line
|
||||
// so that new releases are covered as well: they all reason, and the
|
||||
// thinking level can only be lowered, never turned off. The two rolling
|
||||
// aliases carry no version number and are listed separately:
|
||||
if (modelName.IndexOf("gemini-3") is not -1 ||
|
||||
modelName is "gemini-flash-latest" ||
|
||||
modelName is "gemini-3.1-flash-lite" ||
|
||||
modelName is "gemini-3-flash-preview" ||
|
||||
modelName is "gemini-pro-latest" ||
|
||||
modelName is "gemini-3.1-pro-preview" ||
|
||||
modelName is "gemini-3.1-pro-preview-customtools")
|
||||
modelName is "gemini-pro-latest")
|
||||
return
|
||||
[
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT, Capability.AUDIO_INPUT,
|
||||
|
||||
@@ -182,7 +182,7 @@ public static partial class ProviderExtensions
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT,
|
||||
Capability.TEXT_OUTPUT, Capability.IMAGE_OUTPUT,
|
||||
|
||||
Capability.FUNCTION_CALLING, Capability.OPTIONAL_REASONING, Capability.REASONING_BY_DEFAULT,
|
||||
Capability.FUNCTION_CALLING, Capability.REASONING_BY_DEFAULT,
|
||||
Capability.WEB_SEARCH,
|
||||
Capability.RESPONSES_API, Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
@@ -193,7 +193,7 @@ public static partial class ProviderExtensions
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
|
||||
Capability.FUNCTION_CALLING, Capability.OPTIONAL_REASONING, Capability.REASONING_BY_DEFAULT,
|
||||
Capability.FUNCTION_CALLING, Capability.REASONING_BY_DEFAULT,
|
||||
Capability.WEB_SEARCH,
|
||||
Capability.RESPONSES_API, Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
@@ -6,244 +6,66 @@ public static partial class ProviderExtensions
|
||||
{
|
||||
private static List<Capability> GetModelCapabilitiesOpenRouter(Model model)
|
||||
{
|
||||
var modelName = model.Id.ToLowerInvariant().AsSpan();
|
||||
//
|
||||
// OpenRouter model IDs follow the pattern "vendor/model-name". Examples:
|
||||
// - openai/gpt-5.6
|
||||
// - anthropic/claude-opus-5
|
||||
// - google/gemini-3.7-flash
|
||||
// - qwen/qwen3.8-flash-next
|
||||
//
|
||||
// OpenRouter offers the models of all the other providers. Instead of keeping a
|
||||
// second set of rules here, which would always lag behind, we hand the model
|
||||
// over to the provider implementation which already knows it. The vendor prefix
|
||||
// has to be removed first: some of those implementations match the beginning of
|
||||
// the model name and would not recognize a prefixed ID.
|
||||
//
|
||||
var separatorIndex = model.Id.IndexOf('/');
|
||||
var vendor = separatorIndex is -1 ? string.Empty : model.Id[..separatorIndex].ToLowerInvariant();
|
||||
var bareModel = separatorIndex is -1 ? model : model with { Id = model.Id[(separatorIndex + 1)..] };
|
||||
var bareModelName = bareModel.Id.ToLowerInvariant().AsSpan();
|
||||
|
||||
//
|
||||
// OpenRouter model IDs follow the pattern: "provider/model-name"
|
||||
// Examples:
|
||||
// - openai/gpt-4o
|
||||
// - anthropic/claude-3-5-sonnet
|
||||
// - google/gemini-pro-1.5
|
||||
// - meta-llama/llama-3.1-405b-instruct
|
||||
//
|
||||
// We need to detect capabilities based on both provider and model name.
|
||||
//
|
||||
|
||||
//
|
||||
// OpenAI models via OpenRouter:
|
||||
//
|
||||
if (modelName.IndexOf("openai/") is not -1)
|
||||
var capabilities = vendor switch
|
||||
{
|
||||
// Reasoning models (o1, o3, o4 series)
|
||||
if (modelName.IndexOf("/o1") is not -1 ||
|
||||
modelName.IndexOf("/o3") is not -1 ||
|
||||
modelName.IndexOf("/o4") is not -1)
|
||||
return [
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.ALWAYS_REASONING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
// The gpt-oss models are open weights. The OpenAI implementation does not
|
||||
// know them, because they are not part of the OpenAI cloud offering:
|
||||
"openai" when bareModelName.IndexOf("gpt-oss") is not -1 => GetModelCapabilitiesOpenSource(bareModel),
|
||||
"openai" => GetModelCapabilitiesOpenAI(bareModel),
|
||||
|
||||
// GPT-4o and GPT-5 series with multimodal
|
||||
if (modelName.IndexOf("/gpt-4o") is not -1 ||
|
||||
modelName.IndexOf("/gpt-5") is not -1 ||
|
||||
modelName.IndexOf("/chatgpt-4o") is not -1)
|
||||
return [
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
"anthropic" => GetModelCapabilitiesAnthropic(bareModel),
|
||||
|
||||
// Standard GPT-4
|
||||
if (modelName.IndexOf("/gpt-4") is not -1)
|
||||
return [
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
// Gemma is open weights, Gemini is not:
|
||||
"google" when bareModelName.IndexOf("gemma") is not -1 => GetModelCapabilitiesOpenSource(bareModel),
|
||||
"google" => GetModelCapabilitiesGoogle(bareModel),
|
||||
|
||||
// GPT-3.5
|
||||
if (modelName.IndexOf("/gpt-3.5") is not -1 ||
|
||||
modelName.IndexOf("/gpt-3") is not -1)
|
||||
return [
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
}
|
||||
"mistralai" => GetModelCapabilitiesMistral(bareModel),
|
||||
"perplexity" => GetModelCapabilitiesPerplexity(bareModel),
|
||||
|
||||
//
|
||||
// Anthropic models via OpenRouter:
|
||||
//
|
||||
if (modelName.IndexOf("anthropic/") is not -1)
|
||||
{
|
||||
// Claude 3.5 and newer with vision
|
||||
if (modelName.IndexOf("/claude-3.5") is not -1 ||
|
||||
modelName.IndexOf("/claude-3-5") is not -1)
|
||||
return [
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
// Everything else is open source: Qwen, Llama, GLM, Kimi, Muse, Hunyuan,
|
||||
// Nemotron, Grok, and whatever OpenRouter adds next. DeepSeek belongs here
|
||||
// as well: its own implementation covers the aliases of the DeepSeek
|
||||
// platform, while OpenRouter uses the names of the open weights.
|
||||
_ => GetModelCapabilitiesOpenSource(bareModel),
|
||||
};
|
||||
|
||||
// Claude 3 Opus/Sonnet with vision
|
||||
if (modelName.IndexOf("/claude-3-opus") is not -1 ||
|
||||
modelName.IndexOf("/claude-3-sonnet") is not -1)
|
||||
return [
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// Other Claude 3 models
|
||||
if (modelName.IndexOf("/claude-3") is not -1)
|
||||
return [
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
}
|
||||
|
||||
//
|
||||
// Google models via OpenRouter:
|
||||
//
|
||||
if (modelName.IndexOf("google/") is not -1)
|
||||
{
|
||||
// Gemini models with multimodal
|
||||
if (modelName.IndexOf("/gemini") is not -1)
|
||||
return [
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
}
|
||||
|
||||
//
|
||||
// xAI Grok models via OpenRouter:
|
||||
//
|
||||
if (modelName.IndexOf("x-ai/") is not -1 || modelName.IndexOf("/grok") is not -1)
|
||||
{
|
||||
if (modelName.IndexOf("-vision") is not -1)
|
||||
return [
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
return [
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
}
|
||||
|
||||
//
|
||||
// DeepSeek models via OpenRouter:
|
||||
//
|
||||
if (modelName.IndexOf("/deepseek") is not -1)
|
||||
{
|
||||
if (modelName.IndexOf("-r1") is not -1 || modelName.IndexOf(" r1") is not -1)
|
||||
return [
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.ALWAYS_REASONING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
return [
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
}
|
||||
|
||||
//
|
||||
// Mistral models via OpenRouter:
|
||||
//
|
||||
if (modelName.IndexOf("/mistral") is not -1 || modelName.IndexOf("/pixtral") is not -1)
|
||||
{
|
||||
if (modelName.IndexOf("/pixtral") is not -1)
|
||||
return [
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
return [
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
}
|
||||
|
||||
//
|
||||
// Meta Llama models via OpenRouter:
|
||||
//
|
||||
if (modelName.IndexOf("/llama") is not -1)
|
||||
{
|
||||
// Llama 4 with vision
|
||||
if (modelName.IndexOf("/llama-4") is not -1 ||
|
||||
modelName.IndexOf("/llama4") is not -1)
|
||||
return [
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// Vision models
|
||||
if (modelName.IndexOf("-vision") is not -1)
|
||||
return [
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// Llama 3.1+ with function calling
|
||||
if (modelName.IndexOf("/llama-3.") is not -1 ||
|
||||
modelName.IndexOf("/llama3.") is not -1)
|
||||
return [
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// Default Llama
|
||||
return [
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
}
|
||||
|
||||
//
|
||||
// Qwen models via OpenRouter:
|
||||
//
|
||||
if (modelName.IndexOf("/qwen") is not -1 || modelName.IndexOf("/qwq") is not -1)
|
||||
{
|
||||
if (modelName.IndexOf("/qwq") is not -1)
|
||||
return [
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.ALWAYS_REASONING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
return [
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
}
|
||||
|
||||
//
|
||||
// Default for unknown models:
|
||||
// Assume basic text input/output with chat completion
|
||||
//
|
||||
return [
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
return NormalizeForOpenRouter(capabilities);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjusts the capabilities reported by another provider for use through OpenRouter.
|
||||
/// </summary>
|
||||
/// <param name="capabilities">The capabilities as reported by the provider implementation.</param>
|
||||
/// <returns>The capabilities as they apply when using the model through OpenRouter.</returns>
|
||||
/// <remarks>
|
||||
/// OpenRouter serves every model through its OpenAI-compatible chat completion API.
|
||||
/// The Responses API is not available there, no matter which API the original
|
||||
/// provider offers.
|
||||
/// </remarks>
|
||||
private static List<Capability> NormalizeForOpenRouter(List<Capability> capabilities)
|
||||
{
|
||||
capabilities.Remove(Capability.RESPONSES_API);
|
||||
if(!capabilities.Contains(Capability.CHAT_COMPLETION_API))
|
||||
capabilities.Add(Capability.CHAT_COMPLETION_API);
|
||||
|
||||
return capabilities;
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,21 @@ public static partial class ProviderExtensions
|
||||
];
|
||||
}
|
||||
|
||||
//
|
||||
// Meta Muse models. They need their own block because their names do not
|
||||
// contain "llama". Muse Glimmer always reasons: its chat template opens the
|
||||
// thinking channel unconditionally, only the reasoning strength can be lowered.
|
||||
//
|
||||
if (modelName.IndexOf("muse-glimmer") is not -1)
|
||||
return
|
||||
[
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
|
||||
Capability.ALWAYS_REASONING, Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
//
|
||||
// DeepSeek models:
|
||||
//
|
||||
@@ -122,6 +137,19 @@ public static partial class ProviderExtensions
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// Check for the Qwen 3.8 Flash models. The open weights are published as
|
||||
// Flash-Next, while Flash without the suffix is the production model. Both
|
||||
// share the same capabilities, so one check covers them:
|
||||
if(modelName.IndexOf("qwen3.8-flash") is not -1)
|
||||
return
|
||||
[
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT, Capability.VIDEO_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
|
||||
Capability.REASONING_BY_DEFAULT, Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// Check for the multimodal Qwen 3.8 27B checkpoint:
|
||||
if(modelName.IndexOf("qwen3.8-27b") is not -1)
|
||||
return
|
||||
@@ -193,6 +221,23 @@ public static partial class ProviderExtensions
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
//
|
||||
// Tencent Hunyuan models. Hy3 answers directly by default: its reasoning_effort
|
||||
// parameter defaults to no_think, low and high must be requested. We also match
|
||||
// the short name because providers offer the model as tencent/hy3, so checking
|
||||
// the start of the name is not enough.
|
||||
//
|
||||
if (modelName.IndexOf("hunyuan") is not -1 ||
|
||||
modelName.IndexOf("hy3") is not -1)
|
||||
return
|
||||
[
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
|
||||
Capability.OPTIONAL_REASONING, Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
//
|
||||
// Mistral models:
|
||||
//
|
||||
@@ -335,6 +380,18 @@ public static partial class ProviderExtensions
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// Grok 4 models take text, images, and video natively. Reasoning is always
|
||||
// on, only the reasoning effort can be configured:
|
||||
if(modelName.IndexOf("grok-4") is not -1)
|
||||
return
|
||||
[
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT, Capability.VIDEO_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
|
||||
Capability.ALWAYS_REASONING, Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
if(modelName.StartsWith("grok-3-mini"))
|
||||
return
|
||||
[
|
||||
@@ -346,14 +403,25 @@ public static partial class ProviderExtensions
|
||||
];
|
||||
|
||||
if(modelName.StartsWith("grok-3"))
|
||||
return
|
||||
return
|
||||
[
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
|
||||
|
||||
Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
// Any other Grok model. Without this, unknown Grok versions would fall
|
||||
// through to the global default and would lose function calling:
|
||||
return
|
||||
[
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
|
||||
Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
}
|
||||
|
||||
//
|
||||
@@ -383,11 +451,41 @@ public static partial class ProviderExtensions
|
||||
];
|
||||
}
|
||||
|
||||
//
|
||||
// NVIDIA Nemotron models. They are built for agentic workloads and are text
|
||||
// only. Reasoning has to be requested through enable_thinking, so it is
|
||||
// optional. The check also covers the quantized checkpoints such as
|
||||
// NVIDIA-Nemotron-3.5-Lightning-30B-A3B-NVFP4.
|
||||
//
|
||||
if (modelName.IndexOf("nemotron") is not -1)
|
||||
return
|
||||
[
|
||||
Capability.TEXT_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
|
||||
Capability.OPTIONAL_REASONING, Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
//
|
||||
// Z AI / GLM models:
|
||||
//
|
||||
if (modelName.IndexOf("glm") is not -1)
|
||||
{
|
||||
// GLM 5.3 uses forced thinking: the reasoning effort can be lowered, but
|
||||
// reasoning cannot be turned off. This check must stay in front of the
|
||||
// vision check below, because quantized builds such as GLM-5.3-Flash-NVFP4
|
||||
// contain a "v" and would be misread as a vision model:
|
||||
if (modelName.IndexOf("glm-5.3") is not -1)
|
||||
return
|
||||
[
|
||||
Capability.TEXT_INPUT, Capability.MULTIPLE_IMAGE_INPUT,
|
||||
Capability.TEXT_OUTPUT,
|
||||
|
||||
Capability.ALWAYS_REASONING, Capability.FUNCTION_CALLING,
|
||||
Capability.CHAT_COMPLETION_API,
|
||||
];
|
||||
|
||||
if (modelName.IndexOf("glm-5.2") is not -1)
|
||||
return
|
||||
[
|
||||
|
||||
Reference in new issue
Block a user