|
103 | 103 | <div style="font-size:11px;color:#909399;margin-top:4px">运行页中显示为快捷按钮,点击即填入补充说明,方便常用提问一键发起。</div> |
104 | 104 | </div> |
105 | 105 | </el-form-item> |
| 106 | + <el-form-item label="模型参数"> |
| 107 | + <div style="width:100%"> |
| 108 | + <div style="display:flex;gap:8px;align-items:center;margin-bottom:6px"> |
| 109 | + <span style="width:64px;font-size:12px;color:#666;flex-shrink:0">默认模型</span> |
| 110 | + <el-select v-model="form.providerId" size="small" style="flex:1" clearable placeholder="供应商(空=第一个启用)" @change="onAssistantProviderChange"> |
| 111 | + <el-option v-for="p in aiProviders" :key="p.id" :label="p.providerName" :value="p.id" /> |
| 112 | + </el-select> |
| 113 | + <el-select v-model="form.model" size="small" style="flex:1" clearable filterable allow-create default-first-option placeholder="模型(空=供应商默认)"> |
| 114 | + <el-option v-for="m in assistantModelOptions" :key="m" :label="m" :value="m" /> |
| 115 | + </el-select> |
| 116 | + </div> |
| 117 | + <div style="display:flex;align-items:center;gap:8px;margin-bottom:6px"> |
| 118 | + <span style="width:64px;font-size:12px;color:#666;flex-shrink:0">深度思考</span> |
| 119 | + <el-switch v-model="form.enableThinking" size="small" /> |
| 120 | + <span style="font-size:11px;color:#909399">推理模型(deepseek-reasoner / Qwen 思考模式)生效</span> |
| 121 | + </div> |
| 122 | + <div style="display:flex;align-items:center;gap:8px;margin-bottom:6px"> |
| 123 | + <span style="width:64px;font-size:12px;color:#666;flex-shrink:0">温度</span> |
| 124 | + <el-slider v-model="form.temperature" size="small" style="flex:1" :min="0" :max="2" :step="0.1" :format-tooltip="tempFormat" /> |
| 125 | + <span style="width:36px;font-size:12px;color:#666;text-align:right;flex-shrink:0">{{ (form.temperature || 0).toFixed(1) }}</span> |
| 126 | + </div> |
| 127 | + <div style="display:flex;align-items:center;gap:8px;margin-bottom:6px"> |
| 128 | + <span style="width:64px;font-size:12px;color:#666;flex-shrink:0">最大输出</span> |
| 129 | + <el-input-number v-model="form.maxTokens" size="small" style="flex:1" :min="0" :step="100" controls-position="right" /> |
| 130 | + <span style="font-size:11px;color:#909399;flex-shrink:0">0=不限制</span> |
| 131 | + </div> |
| 132 | + <div style="display:flex;align-items:center;gap:8px"> |
| 133 | + <span style="width:64px;font-size:12px;color:#666;flex-shrink:0">随机种子</span> |
| 134 | + <el-input-number v-model="form.seed" size="small" style="flex:1" :min="0" :step="1" controls-position="right" /> |
| 135 | + <span style="font-size:11px;color:#909399;flex-shrink:0">0=随机</span> |
| 136 | + </div> |
| 137 | + </div> |
| 138 | + </el-form-item> |
106 | 139 | <el-form-item label="支持的能力"> |
107 | 140 | <div style="width:100%"> |
108 | 141 | <div style="display:flex;gap:8px;align-items:center;margin-bottom:6px"> |
|
151 | 184 | </template> |
152 | 185 |
|
153 | 186 | <script setup lang="ts"> |
154 | | -import { ref, onMounted } from 'vue' |
| 187 | +import { ref, computed, onMounted } from 'vue' |
155 | 188 | import { ElMessage, ElMessageBox } from 'element-plus' |
156 | 189 | import request from '../../utils/request' |
157 | 190 | import MarketPublishDialog from '../../components/MarketPublishDialog.vue' |
@@ -210,6 +243,28 @@ const skillOptions = ref<any[]>([]) |
210 | 243 | const apiOptions = ref<any[]>([]) |
211 | 244 | const flowOptions = ref<any[]>([]) |
212 | 245 |
|
| 246 | +// 模型参数(默认供应商/模型/深度思考/温度/最大输出/随机种子) |
| 247 | +const aiProviders = ref<any[]>([]) |
| 248 | +const assistantModelOptions = computed(() => { |
| 249 | + const p = aiProviders.value.find((x: any) => x.id === form.value.providerId) |
| 250 | + const list = String(p?.models || '').split(',').map((s: string) => s.trim()).filter(Boolean) |
| 251 | + if (p?.model && !list.includes(p.model)) list.unshift(p.model) |
| 252 | + return list.filter(Boolean) |
| 253 | +}) |
| 254 | +function onAssistantProviderChange() { |
| 255 | + const p = aiProviders.value.find((x: any) => x.id === form.value.providerId) |
| 256 | + if (p) form.value.model = p.model || '' |
| 257 | +} |
| 258 | +function tempFormat(v: number) { return v.toFixed(1) } |
| 259 | +
|
| 260 | +/** 加载启用的供应商(默认模型选择用) */ |
| 261 | +async function loadAiProviders() { |
| 262 | + try { |
| 263 | + const res: any = await request.get('/ai/providers/enabled') |
| 264 | + aiProviders.value = res.data || [] |
| 265 | + } catch { /* 未配置供应商 */ } |
| 266 | +} |
| 267 | +
|
213 | 268 | /** 加载能力选项(技能/接口/流程) */ |
214 | 269 | async function loadCapabilityOptions() { |
215 | 270 | try { |
@@ -261,22 +316,36 @@ function countParams(json: string): number { |
261 | 316 | } |
262 | 317 |
|
263 | 318 | function openAdd() { |
264 | | - form.value = { id: 0, assistantName: '', description: '', systemPrompt: '', icon: '', enabled: true } |
| 319 | + form.value = { |
| 320 | + id: 0, assistantName: '', description: '', systemPrompt: '', icon: '', enabled: true, |
| 321 | + providerId: 0, model: '', enableThinking: false, temperature: 0.7, maxTokens: 0, seed: 0 |
| 322 | + } |
265 | 323 | inputParams.value = [] |
266 | 324 | outputParams.value = [] |
267 | 325 | quickPrompts.value = [] |
268 | 326 | parseCapabilities('') |
269 | 327 | dialogVisible.value = true |
270 | 328 | loadCapabilityOptions() |
| 329 | + loadAiProviders() |
271 | 330 | } |
272 | 331 | function openEdit(row: any) { |
273 | | - form.value = { ...row, enabled: row.enabled === 1 } |
| 332 | + form.value = { |
| 333 | + ...row, |
| 334 | + enabled: row.enabled === 1, |
| 335 | + enableThinking: row.enableThinking === 1, |
| 336 | + temperature: row.temperature ?? 0.7, |
| 337 | + maxTokens: row.maxTokens || 0, |
| 338 | + seed: row.seed || 0, |
| 339 | + providerId: row.providerId || 0, |
| 340 | + model: row.model || '' |
| 341 | + } |
274 | 342 | try { inputParams.value = JSON.parse(row.inputParams || '[]') } catch { inputParams.value = [] } |
275 | 343 | try { outputParams.value = JSON.parse(row.outputParams || '[]') } catch { outputParams.value = [] } |
276 | 344 | try { quickPrompts.value = JSON.parse(row.quickPrompts || '[]') } catch { quickPrompts.value = [] } |
277 | 345 | parseCapabilities(row.capabilities || '') |
278 | 346 | dialogVisible.value = true |
279 | 347 | loadCapabilityOptions() |
| 348 | + loadAiProviders() |
280 | 349 | } |
281 | 350 |
|
282 | 351 | function isImageIcon(icon: string): boolean { |
|
0 commit comments