Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/site/docs/en/model-common-config.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ MIDSCENE_INSIGHT_MODEL_FAMILY="xiaomi-mimo"

| Model version | Commonly used model names | `MIDSCENE_MODEL_FAMILY` | Notes |
| --- | --- | --- | --- |
| GLM-5.3 series | `glm-5.3-flash` | `glm-v` | Always-thinking: `thinking.type` cannot be disabled, so disabling reasoning sends `reasoning_effort: low` instead. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Document GLM-5.3 reasoning-effort support

The adapter now consumes MIDSCENE_MODEL_REASONING_EFFORT for GLM-5.3-Flash, but the authoritative supported-family list in apps/site/docs/{en,zh}/model-config.mdx still omits GLM and says only the listed families support this setting. Users therefore cannot discover the knob that the implementation and this new row rely on; add GLM-5.3-Flash to both language versions of that list. apps/site/agents.mdL5-L5

Useful? React with 👍 / 👎.

| GLM-5V series | `glm-5v-turbo` | `glm-v` | — |
| GLM-4.6 series | `glm-4.6v` | `glm-v` | `glm-4.6v` is open-source. |

Expand Down
1 change: 1 addition & 0 deletions apps/site/docs/en/model-config.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ The following model families currently support `MIDSCENE_MODEL_REASONING_ENABLED
- Gemini: Maps to `thinking_config.thinking_level`.
- GPT-5: Maps to `reasoning_effort`.
- Kimi K3 series: Maps to `reasoning_effort`.
- Zhipu GLM: Maps to `reasoning_effort` (glm-5.3-flash only).

Provider support and accepted values vary. See each provider's official documentation for supported model versions and values. If the current model does not support an explicit setting, Midscene ignores it instead of guessing a provider-specific private parameter.

Expand Down
1 change: 1 addition & 0 deletions apps/site/docs/zh/model-common-config.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ MIDSCENE_INSIGHT_MODEL_FAMILY="xiaomi-mimo"

| 模型版本 | 常用模型名称 | `MIDSCENE_MODEL_FAMILY` | 备注 |
| --- | --- | --- | --- |
| GLM-5.3 系列 | `glm-5.3-flash` | `glm-v` | 始终思考:不支持关闭 `thinking.type`,关闭推理时会改发 `reasoning_effort: low`。 |
| GLM-5V 系列 | `glm-5v-turbo` | `glm-v` | — |
| GLM-4.6 系列 | `glm-4.6v` | `glm-v` | `glm-4.6v` 是开源模型。 |

Expand Down
1 change: 1 addition & 0 deletions apps/site/docs/zh/model-config.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ Midscene 默认关闭模型原生思考,以获得更好的执行速度和稳
- Gemini:对应 `thinking_config.thinking_level`。
- GPT-5:对应 `reasoning_effort`。
- Kimi K3 系列:对应 `reasoning_effort`。
- 智谱 GLM:对应 `reasoning_effort`(仅 glm-5.3-flash)。

不同模型服务商支持的参数和值不同。具体取值和适用模型版本请参考对应服务商的官方文档。如果当前模型不支持某项显式配置,Midscene 会忽略该配置,不会猜测服务商的私有参数。

Expand Down
10 changes: 10 additions & 0 deletions packages/core/src/ai-model/model-adapter/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ export type ChatCompletionUnsupportedUserConfig =

export interface ChatCompletionCallInput {
intent?: TIntent;
/**
* Model name resolved for this call. Adapters may use it to branch within a
* family when a specific model requires different request parameters (for
* example, always-thinking variants).
*/
modelName?: string;
userConfig?: ChatCompletionCallUserConfig;
/**
* Number of preceding semantic parsing failures for this request.
Expand All @@ -83,6 +89,10 @@ export interface ChatCompletionCallInput {

export interface ChatCompletionCallContext {
intent?: TIntent;
/**
* Model name resolved for this call; see ChatCompletionCallInput.
*/
modelName?: string;
userConfig: ChatCompletionCallUserConfig;
semanticRetryAttempt?: number;
requiresOriginalImageDetail?: boolean;
Expand Down
45 changes: 42 additions & 3 deletions packages/core/src/ai-model/models/glm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,31 @@ import type {
ModelAdapterDefinition,
} from '../model-adapter/types';

const ALWAYS_THINKING_GLM_MODEL_PATTERN = /^glm-5\.3-flash\b/;

const buildGlmChatCompletionParams = (
input: ChatCompletionCallContext,
): ChatCompletionParamsResult => {
const { midsceneDefaults, userConfig } = input;
const { midsceneDefaults, userConfig, modelName } = input;
const { reasoningEnabled } = userConfig;
const commonOverrideConfig: Record<string, unknown> = {};

if (userConfig.temperature !== undefined) {
// GLM models that cannot turn thinking off. GLM-5.3-Flash rejects
// `thinking.type: 'disabled'` with error 1210 ("该模型始终思考,不支持关闭
// 思考"), so for these models the adapter keeps thinking enabled and steers
// its depth with `reasoning_effort` instead. Field-tested against the
// Zhipu Coding Plan endpoint in KSL-49 (2026-08-26).
const alwaysThinking = ALWAYS_THINKING_GLM_MODEL_PATTERN.test(
modelName ?? '',
);

if (alwaysThinking) {
// Officially recommended sampling parameters for GLM-5.3-Flash
// (https://docs.bigmodel.cn/cn/guide/models/vlm/glm-5.3-flash), and the
// values its vision integration was field-tested with.
commonOverrideConfig.temperature = userConfig.temperature ?? 1;
commonOverrideConfig.top_p = 0.95;
} else if (userConfig.temperature !== undefined) {
commonOverrideConfig.temperature = userConfig.temperature;
}

Expand All @@ -27,7 +44,27 @@ const buildGlmChatCompletionParams = (

const modelSpecificConfig: Record<string, unknown> = {};

if (reasoningEnabled !== 'default') {
if (alwaysThinking) {
if (reasoningEnabled !== 'default') {
modelSpecificConfig.thinking = {
type: 'enabled',
clear_thinking: false,
};
if (reasoningEnabled !== true) {
// Thinking cannot be disabled, so a "no reasoning" intent (explicit
// false or unset) maps to the cheapest effort level. `low` was
// sufficient for the KSL-49 vision probes; users can raise it via
// the reasoning-effort config.
modelSpecificConfig.reasoning_effort =
userConfig.reasoningEffort ?? 'low';
} else if (userConfig.reasoningEffort) {
modelSpecificConfig.reasoning_effort = userConfig.reasoningEffort;
}
}
// reasoningEnabled='default' sends no thinking or effort override, per
// the documented contract in docs/model-config.mdx: default follows the
// provider behavior and ignores explicit effort settings.
} else if (reasoningEnabled !== 'default') {
modelSpecificConfig.thinking = {
type: (reasoningEnabled ?? false) ? 'enabled' : 'disabled',
};
Expand All @@ -45,6 +82,8 @@ const buildGlmChatCompletionParams = (
export const glmAdapters = {
'glm-v': {
chatCompletion: {
// reasoningEffort is honored only by the always-thinking GLM models
// (see above); reasoningBudget is not supported by the family at all.
unsupportedUserConfig: ['reasoningEffort', 'reasoningBudget'],
buildChatCompletionParams: buildGlmChatCompletionParams,
useReasoningAsContentFallback: true,
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/ai-model/service-caller/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ export async function callAI(
: undefined;
const chatCompletionInput = {
intent: modelConfig.intent,
modelName: modelConfig.modelName,
userConfig: {
temperature: modelConfig.temperature,
reasoningEnabled: modelConfig.reasoningEnabled,
Expand Down
115 changes: 115 additions & 0 deletions packages/core/tests/unit-test/model-adapter/glm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,118 @@ describe('glm model adapter', () => {
expect(result.config.response_format).toBeUndefined();
});
});

describe('glm-5.3-flash always-thinking contract', () => {
it('never sends thinking.type=disabled for glm-5.3-flash', () => {
const result = glmAdapter.chatCompletion.buildChatCompletionParams({
modelName: 'glm-5.3-flash',
userConfig: {},
});
expect(result.config).toEqual({
temperature: 1,
top_p: 0.95,
thinking: { type: 'enabled', clear_thinking: false },
reasoning_effort: 'low',
});
});

it('maps a reasoning-disable intent to effort=low for glm-5.3-flash', () => {
const result = glmAdapter.chatCompletion.buildChatCompletionParams({
modelName: 'glm-5.3-flash',
userConfig: { reasoningEnabled: false },
});
expect(result.config).toEqual({
temperature: 1,
top_p: 0.95,
thinking: { type: 'enabled', clear_thinking: false },
reasoning_effort: 'low',
});
});

it('forwards an explicit reasoning effort for glm-5.3-flash', () => {
const result = glmAdapter.chatCompletion.buildChatCompletionParams({
modelName: 'glm-5.3-flash',
userConfig: { reasoningEnabled: true, reasoningEffort: 'high' },
});
expect(result.config).toEqual({
temperature: 1,
top_p: 0.95,
thinking: { type: 'enabled', clear_thinking: false },
reasoning_effort: 'high',
});
});

it('keeps the provider effort default when reasoning is explicitly enabled without effort', () => {
const result = glmAdapter.chatCompletion.buildChatCompletionParams({
modelName: 'glm-5.3-flash',
userConfig: { reasoningEnabled: true },
});
expect(result.config).toEqual({
temperature: 1,
top_p: 0.95,
thinking: { type: 'enabled', clear_thinking: false },
});
expect(result.config.reasoning_effort).toBeUndefined();
});

it('ignores an explicit effort in default reasoning mode for glm-5.3-flash', () => {
const result = glmAdapter.chatCompletion.buildChatCompletionParams({
modelName: 'glm-5.3-flash',
userConfig: { reasoningEnabled: 'default', reasoningEffort: 'high' },
});
expect(result.config).toEqual({
temperature: 1,
top_p: 0.95,
});
});

it('follows provider default for glm-5.3-flash when reasoningEnabled=default', () => {
const result = glmAdapter.chatCompletion.buildChatCompletionParams({
modelName: 'glm-5.3-flash',
userConfig: { reasoningEnabled: 'default' },
});
expect(result.config).toEqual({
temperature: 1,
top_p: 0.95,
});
});

it('keeps an explicit user temperature for glm-5.3-flash', () => {
const result = glmAdapter.chatCompletion.buildChatCompletionParams({
modelName: 'glm-5.3-flash',
userConfig: { temperature: 0 },
});
expect(result.config).toEqual({
temperature: 0,
top_p: 0.95,
thinking: { type: 'enabled', clear_thinking: false },
reasoning_effort: 'low',
});
});

it('combines json_object response format with always-thinking params', () => {
const result = glmAdapter.chatCompletion.buildChatCompletionParams({
modelName: 'glm-5.3-flash',
expectedJsonObjectResponse: true,
userConfig: {},
});
expect(result.config).toEqual({
temperature: 1,
top_p: 0.95,
response_format: { type: 'json_object' },
thinking: { type: 'enabled', clear_thinking: false },
reasoning_effort: 'low',
});
});

it('keeps toggleable thinking for non-flash glm-v models', () => {
const result = glmAdapter.chatCompletion.buildChatCompletionParams({
modelName: 'glm-5v-turbo',
userConfig: {},
});
expect(result.config).toEqual({
temperature: 0,
thinking: { type: 'disabled' },
});
});
});