fix(ai): add qwen-chat-template compat mode closes #2020
This commit is contained in:
@@ -392,9 +392,12 @@ function buildParams(model: Model<"openai-completions">, context: Context, optio
|
|||||||
params.tool_choice = options.toolChoice;
|
params.tool_choice = options.toolChoice;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((compat.thinkingFormat === "zai" || compat.thinkingFormat === "qwen") && model.reasoning) {
|
if (compat.thinkingFormat === "zai" && model.reasoning) {
|
||||||
// Both Z.ai and Qwen use enable_thinking: boolean
|
|
||||||
(params as any).enable_thinking = !!options?.reasoningEffort;
|
(params as any).enable_thinking = !!options?.reasoningEffort;
|
||||||
|
} else if (compat.thinkingFormat === "qwen" && model.reasoning) {
|
||||||
|
(params as any).enable_thinking = !!options?.reasoningEffort;
|
||||||
|
} else if (compat.thinkingFormat === "qwen-chat-template" && model.reasoning) {
|
||||||
|
(params as any).chat_template_kwargs = { enable_thinking: !!options?.reasoningEffort };
|
||||||
} else if (options?.reasoningEffort && model.reasoning && compat.supportsReasoningEffort) {
|
} else if (options?.reasoningEffort && model.reasoning && compat.supportsReasoningEffort) {
|
||||||
// OpenAI-style reasoning_effort
|
// OpenAI-style reasoning_effort
|
||||||
(params as any).reasoning_effort = mapReasoningEffort(options.reasoningEffort, compat.reasoningEffortMap);
|
(params as any).reasoning_effort = mapReasoningEffort(options.reasoningEffort, compat.reasoningEffortMap);
|
||||||
|
|||||||
@@ -270,8 +270,8 @@ export interface OpenAICompletionsCompat {
|
|||||||
requiresAssistantAfterToolResult?: boolean;
|
requiresAssistantAfterToolResult?: boolean;
|
||||||
/** Whether thinking blocks must be converted to text blocks with <thinking> delimiters. Default: auto-detected from URL. */
|
/** Whether thinking blocks must be converted to text blocks with <thinking> delimiters. Default: auto-detected from URL. */
|
||||||
requiresThinkingAsText?: boolean;
|
requiresThinkingAsText?: boolean;
|
||||||
/** Format for reasoning/thinking parameter. "openai" uses reasoning_effort, "zai" uses thinking: { type: "enabled" }, "qwen" uses enable_thinking: boolean. Default: "openai". */
|
/** Format for reasoning/thinking parameter. "openai" uses reasoning_effort, "zai" uses top-level enable_thinking: boolean, "qwen" uses top-level enable_thinking: boolean, and "qwen-chat-template" uses chat_template_kwargs.enable_thinking. Default: "openai". */
|
||||||
thinkingFormat?: "openai" | "zai" | "qwen";
|
thinkingFormat?: "openai" | "zai" | "qwen" | "qwen-chat-template";
|
||||||
/** OpenRouter-specific routing preferences. Only used when baseUrl points to OpenRouter. */
|
/** OpenRouter-specific routing preferences. Only used when baseUrl points to OpenRouter. */
|
||||||
openRouterRouting?: OpenRouterRouting;
|
openRouterRouting?: OpenRouterRouting;
|
||||||
/** Vercel AI Gateway routing preferences. Only used when baseUrl points to Vercel AI Gateway. */
|
/** Vercel AI Gateway routing preferences. Only used when baseUrl points to Vercel AI Gateway. */
|
||||||
|
|||||||
@@ -183,11 +183,13 @@ models: [{
|
|||||||
},
|
},
|
||||||
maxTokensField: "max_tokens", // instead of "max_completion_tokens"
|
maxTokensField: "max_tokens", // instead of "max_completion_tokens"
|
||||||
requiresToolResultName: true, // tool results need name field
|
requiresToolResultName: true, // tool results need name field
|
||||||
thinkingFormat: "qwen" // uses enable_thinking: true
|
thinkingFormat: "qwen" // top-level enable_thinking: true
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Use `qwen-chat-template` instead for local Qwen-compatible servers that read `chat_template_kwargs.enable_thinking`.
|
||||||
|
|
||||||
> Migration note: Mistral moved from `openai-completions` to `mistral-conversations`.
|
> Migration note: Mistral moved from `openai-completions` to `mistral-conversations`.
|
||||||
> Use `mistral-conversations` for native Mistral models.
|
> Use `mistral-conversations` for native Mistral models.
|
||||||
> If you intentionally route Mistral-compatible/custom endpoints through `openai-completions`, set `compat` flags explicitly as needed.
|
> If you intentionally route Mistral-compatible/custom endpoints through `openai-completions`, set `compat` flags explicitly as needed.
|
||||||
@@ -586,7 +588,9 @@ interface ProviderModelConfig {
|
|||||||
requiresToolResultName?: boolean;
|
requiresToolResultName?: boolean;
|
||||||
requiresAssistantAfterToolResult?: boolean;
|
requiresAssistantAfterToolResult?: boolean;
|
||||||
requiresThinkingAsText?: boolean;
|
requiresThinkingAsText?: boolean;
|
||||||
thinkingFormat?: "openai" | "zai" | "qwen";
|
thinkingFormat?: "openai" | "zai" | "qwen" | "qwen-chat-template";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`qwen` is for DashScope-style top-level `enable_thinking`. Use `qwen-chat-template` for local Qwen-compatible servers that read `chat_template_kwargs.enable_thinking`.
|
||||||
|
|||||||
@@ -244,11 +244,13 @@ For providers with partial OpenAI compatibility, use the `compat` field.
|
|||||||
| `requiresToolResultName` | Include `name` on tool result messages |
|
| `requiresToolResultName` | Include `name` on tool result messages |
|
||||||
| `requiresAssistantAfterToolResult` | Insert an assistant message before a user message after tool results |
|
| `requiresAssistantAfterToolResult` | Insert an assistant message before a user message after tool results |
|
||||||
| `requiresThinkingAsText` | Convert thinking blocks to plain text |
|
| `requiresThinkingAsText` | Convert thinking blocks to plain text |
|
||||||
| `thinkingFormat` | Use `reasoning_effort`, `zai`, or `qwen` thinking parameters |
|
| `thinkingFormat` | Use `reasoning_effort`, `zai`, `qwen`, or `qwen-chat-template` thinking parameters |
|
||||||
| `supportsStrictMode` | Include the `strict` field in tool definitions |
|
| `supportsStrictMode` | Include the `strict` field in tool definitions |
|
||||||
| `openRouterRouting` | OpenRouter routing config passed to OpenRouter for model/provider selection |
|
| `openRouterRouting` | OpenRouter routing config passed to OpenRouter for model/provider selection |
|
||||||
| `vercelGatewayRouting` | Vercel AI Gateway routing config for provider selection (`only`, `order`) |
|
| `vercelGatewayRouting` | Vercel AI Gateway routing config for provider selection (`only`, `order`) |
|
||||||
|
|
||||||
|
`qwen` uses top-level `enable_thinking`. Use `qwen-chat-template` for local Qwen-compatible servers that require `chat_template_kwargs.enable_thinking`.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
|||||||
@@ -60,7 +60,14 @@ const OpenAICompletionsCompatSchema = Type.Object({
|
|||||||
requiresToolResultName: Type.Optional(Type.Boolean()),
|
requiresToolResultName: Type.Optional(Type.Boolean()),
|
||||||
requiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),
|
requiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),
|
||||||
requiresThinkingAsText: Type.Optional(Type.Boolean()),
|
requiresThinkingAsText: Type.Optional(Type.Boolean()),
|
||||||
thinkingFormat: Type.Optional(Type.Union([Type.Literal("openai"), Type.Literal("zai"), Type.Literal("qwen")])),
|
thinkingFormat: Type.Optional(
|
||||||
|
Type.Union([
|
||||||
|
Type.Literal("openai"),
|
||||||
|
Type.Literal("zai"),
|
||||||
|
Type.Literal("qwen"),
|
||||||
|
Type.Literal("qwen-chat-template"),
|
||||||
|
]),
|
||||||
|
),
|
||||||
openRouterRouting: Type.Optional(OpenRouterRoutingSchema),
|
openRouterRouting: Type.Optional(OpenRouterRoutingSchema),
|
||||||
vercelGatewayRouting: Type.Optional(VercelGatewayRoutingSchema),
|
vercelGatewayRouting: Type.Optional(VercelGatewayRoutingSchema),
|
||||||
supportsStrictMode: Type.Optional(Type.Boolean()),
|
supportsStrictMode: Type.Optional(Type.Boolean()),
|
||||||
|
|||||||
Reference in New Issue
Block a user