feat(llm): 华为云 MaaS 思考强度实例级配置 + 管理台 select 字段类型 (#3446)

- openai provider: THINKING_DISABLED_DOMAINS 补 modelarts-maas.com
- openai provider: 实例配置支持可选 thinking 字段(off/low/medium/high/keep),
  实例值优先于域名默认表; keep=完全直通(适配强制思考且拒绝该参数的模型, 如 MaaS glm-5.3)
- manager-web: 模型配置表单渲染器支持 select 字段类型(el-select + field.options)
  (ModelEditDialog / AddModelDialog 两处渲染点与类型映射)

Co-authored-by: SecInsight <secinsight@users.noreply.github.com>
Co-authored-by: Sakura-RanChen <1908198662@qq.com>
This commit is contained in:
authored and GitHub committed 2026-10-28 15:20:28 +08:00
1 parent d9c2e8c5d9
commit 2cb0562ade
3 files changed
+33 -4

No files matched your search

@@ -77,7 +77,11 @@
<el-form :model="formData.configJson" label-width="auto" label-position="left" class="custom-form">
<div v-for="(row, rowIndex) in chunkedCallInfoFields" :key="rowIndex" class="form-row">
<el-form-item v-for="field in row" :key="field.prop" :label="field.label" :prop="field.prop" style="flex: 1;">
<el-input v-if="field.type === 'json-textarea'" v-model="formData.configJson[field.prop]" type="textarea"
<el-select v-if="field.type === 'select'" v-model="formData.configJson[field.prop]"
:placeholder="field.placeholder" class="custom-input-bg" style="width: 100%">
<el-option v-for="opt in field.options" :key="opt" :label="opt" :value="opt"></el-option>
</el-select>
<el-input v-else-if="field.type === 'json-textarea'" v-model="formData.configJson[field.prop]" type="textarea"
:rows="3" :placeholder="field.placeholder" class="custom-input-bg">
</el-input>
<el-input v-else v-model="formData.configJson[field.prop]" :placeholder="field.placeholder"
@@ -164,7 +168,8 @@ export default {
fields: JSON.parse(item.fields || '[]').map(f => ({
label: f.label,
prop: f.key,
type: f.type === 'dict' ? 'json-textarea' : f.type === 'password' ? 'password' : 'text',
type: f.type === 'dict' ? 'json-textarea' : f.type === 'password' ? 'password' : (f.type === 'select' ? 'select' : 'text'),
options: f.options || [],
placeholder: `请输入${f.key}`
}))
}))
@@ -81,6 +81,11 @@
"></el-input>
</template>
<el-select v-else-if="field.type === 'select'" v-model="form.configJson[field.prop]"
:placeholder="field.placeholder" style="width: 100%">
<el-option v-for="opt in field.options" :key="opt" :label="opt" :value="opt"></el-option>
</el-select>
<el-input v-else v-model="form.configJson[field.prop]" :placeholder="field.placeholder" :type="field.type"
:show-password="field.type === 'password'" @focus="
isSensitiveField(field.prop)
@@ -312,7 +317,10 @@ export default {
? "json-textarea"
: f.type === "password"
? "password"
: "text",
: f.type === "select"
? "select"
: "text",
options: f.options || [],
placeholder: `请输入${f.key}`,
}));
@@ -16,12 +16,15 @@ THINKING_DISABLED_DOMAINS = {
"bigmodel.cn": {"thinking": {"type": "disabled"}},
"moonshot.cn": {"thinking": {"type": "disabled"}},
"volces.com": {"thinking": {"type": "disabled"}},
"modelarts-maas.com": {"thinking": {"type": "disabled"}},
}
class LLMProvider(LLMProviderBase):
def __init__(self, config):
self.model_name = config.get("model_name")
# 可选实例级思考强度: off/disabled/none/disable | low/medium/high | 空/其他=按域名默认
self.thinking_mode = str(config.get("thinking") or "").strip().lower()
self.api_key = config.get("api_key")
if "base_url" in config:
self.base_url = config.get("base_url")
@@ -80,7 +83,20 @@ class LLMProvider(LLMProviderBase):
return dialogue
def _apply_thinking_disabled(self, request_params: dict):
"""根据域名自动禁用思考模式"""
"""思考模式控制: 实例配置(thinking)优先, 否则按域名默认表"""
mode = getattr(self, "thinking_mode", "")
if mode in ("keep", "passthrough", "default"):
# 不干预: 既不发 thinking 参数也不查域名表(适用于强制思考/拒绝该参数的模型, 如 MaaS glm-5.3)
return
if mode in ("off", "disabled", "none", "disable"):
request_params.setdefault("extra_body", {}).update({"thinking": {"type": "disabled"}})
logger.bind(tag=TAG).info("思考强度=off: 已禁用思考模式(实例配置)")
return
if mode in ("low", "medium", "high"):
request_params.setdefault("extra_body", {}).update(
{"reasoning_effort": mode, "thinking": {"type": "enabled"}})
logger.bind(tag=TAG).info(f"思考强度={mode}: reasoning_effort 已设置(实例配置)")
return
parsed_url = urlparse(self.base_url)
domain = parsed_url.netloc
for disabled_domain, params in THINKING_DISABLED_DOMAINS.items():