Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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/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
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
39 changes: 36 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,21 @@ const buildGlmChatCompletionParams = (

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

if (reasoningEnabled !== 'default') {
if (alwaysThinking) {
if (reasoningEnabled !== 'default') {
modelSpecificConfig.thinking = {
type: 'enabled',
clear_thinking: false,
};
// Thinking cannot be disabled, so a "no reasoning" intent 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';

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 Preserve normal effort when reasoning is enabled

When reasoningEnabled is explicitly true and no effort is supplied, this expression assigns low, just as it does for the disable case. The intended substitution described above is specifically for a no-reasoning request on an always-thinking model; applying it to users who force-enable reasoning silently minimizes reasoning and can reduce task accuracy. Use low only for the disabled/unset path and preserve the provider's effort default when reasoning is explicitly enabled.

Useful? React with 👍 / 👎.

} else if (userConfig.reasoningEffort) {
modelSpecificConfig.reasoning_effort = userConfig.reasoningEffort;

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 Avoid overriding effort in default reasoning mode

When a GLM-5.3 user sets MIDSCENE_MODEL_REASONING_ENABLED=default together with MIDSCENE_MODEL_REASONING_EFFORT, this branch still emits reasoning_effort. This violates the unified contract documented in apps/site/docs/en/model-config.mdx:88, where default follows provider behavior and ignores explicit effort settings, so users selecting that mode unexpectedly continue overriding the provider default.

Useful? React with 👍 / 👎.

}
} else if (reasoningEnabled !== 'default') {
modelSpecificConfig.thinking = {
type: (reasoningEnabled ?? false) ? 'enabled' : 'disabled',
};
Expand All @@ -45,6 +76,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
91 changes: 91 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,94 @@ 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('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' },
});
});
});