You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
5.6 KiB
129 lines
5.6 KiB
<template>
|
|
<div class="node-config">
|
|
<el-divider content-position="left">模型配置</el-divider>
|
|
|
|
<el-form-item label="选择模型">
|
|
<el-select :model-value="modelValue.model || ''" @change="onModelSelect" placeholder="从模型管理中选择或手动输入" filterable clearable allow-create>
|
|
<template #header>
|
|
<div style="padding: 4px 0; color: #909399; font-size: 12px;">
|
|
仅显示已启用的 LLM 模型(来自模型管理)
|
|
</div>
|
|
</template>
|
|
<el-option-group label="大语言模型 (LLM)">
|
|
<el-option
|
|
v-for="m in llmModels"
|
|
:key="m.id"
|
|
:label="`${m.display_name || m.model_name} (${getProviderName(m.provider_id)})`"
|
|
:value="m.model_name"
|
|
>
|
|
<span style="display: flex; justify-content: space-between; align-items: center;">
|
|
<span>{{ m.display_name || m.model_name }}</span>
|
|
<el-tag size="small" type="info" style="margin-left: 8px;">{{ getProviderName(m.provider_id) }}</el-tag>
|
|
</span>
|
|
</el-option>
|
|
</el-option-group>
|
|
</el-select>
|
|
</el-form-item>
|
|
|
|
<!-- 选中模型后显示其默认参数提示 -->
|
|
<div v-if="selectedModelInfo" style="margin-bottom: 12px; padding: 8px 12px; background: #f0f9ff; border-radius: 6px; font-size: 12px; color: #606266;">
|
|
<span v-if="(selectedModelInfo.default_params || {}).temperature !== undefined">
|
|
Temperature={{ selectedModelInfo.default_params.temperature }}
|
|
</span>
|
|
<span v-if="(selectedModelInfo.default_params || {}).max_tokens" style="margin-left: 8px;">
|
|
MaxTokens={{ selectedModelInfo.default_params.max_tokens }}
|
|
</span>
|
|
<el-tag v-if="(selectedModelInfo.capabilities || {}).vision" size="small" type="primary" effect="plain" style="margin-left: 8px;">Vision</el-tag>
|
|
<el-tag v-if="(selectedModelInfo.capabilities || {}).function_calling" size="small" type="primary" effect="plain" style="margin-left: 4px;">FC</el-tag>
|
|
</div>
|
|
|
|
<el-form-item label="系统提示词">
|
|
<el-input :model-value="modelValue.system_prompt" type="textarea" :rows="4" @input="(e: any) => update('system_prompt', e)" placeholder="输入系统提示词,定义AI角色和行为" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="温度">
|
|
<el-slider :model-value="modelValue.temperature ?? 0.7" :min="0" :max="2" :step="0.1" @change="update('temperature', $event)" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="最大Token数">
|
|
<el-input-number :model-value="modelValue.max_tokens ?? 2000" :min="1" :max="200000" :step="256" @change="update('max_tokens', $event)" />
|
|
</el-form-item>
|
|
|
|
<el-divider content-position="left">记忆配置</el-divider>
|
|
|
|
<el-form-item label="上下文长度">
|
|
<el-input-number :model-value="modelValue.context_length ?? 5" :min="1" :max="20" :step="1" @change="update('context_length', $event)" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="记忆模式">
|
|
<el-select :model-value="modelValue.memory_mode || 'short_term'" @change="update('memory_mode', $event)">
|
|
<el-option label="无记忆" value="none" />
|
|
<el-option label="短期记忆" value="short_term" />
|
|
<el-option label="长期记忆" value="long_term" />
|
|
</el-select>
|
|
</el-form-item>
|
|
|
|
<el-divider content-position="left">高级选项</el-divider>
|
|
|
|
<el-form-item label="流式输出">
|
|
<el-switch :model-value="modelValue.stream ?? true" @change="update('stream', $event)" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="函数调用">
|
|
<el-switch :model-value="modelValue.tool_call ?? false" @change="update('tool_call', $event)" />
|
|
</el-form-item>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
|
|
const props = defineProps<{
|
|
modelValue: any
|
|
modelList: any[]
|
|
}>()
|
|
|
|
const emit = defineEmits(['change', 'update:modelValue'])
|
|
|
|
function update(key: string, val: any) {
|
|
emit('change')
|
|
emit('update:modelValue', { ...props.modelValue, [key]: val })
|
|
}
|
|
|
|
// 过滤出 LLM 类型的模型
|
|
const llmModels = computed(() => {
|
|
return (props.modelList || []).filter((m: any) => m.model_type === 'llm' && m.is_active !== false)
|
|
})
|
|
|
|
// 当前选中的模型信息
|
|
const selectedModelInfo = computed(() => {
|
|
const modelName = props.modelValue?.model
|
|
if (!modelName) return null
|
|
return llmModels.value.find((m: any) => m.model_name === modelName)
|
|
})
|
|
|
|
function getProviderName(providerId: string): string {
|
|
// providerId 可能是 UUID 字符串,这里无法直接查供应商名
|
|
// 显示 ID 前缀作为标识
|
|
return providerId ? String(providerId).slice(0, 8) + '...' : '-'
|
|
}
|
|
|
|
function onModelSelect(val: string) {
|
|
// 如果选择了已管理的模型,同时保存 model_name 和 model_instance_id
|
|
const model = val ? llmModels.value.find((m: any) => m.model_name === val) : null
|
|
if (model) {
|
|
// 从模型管理选择:保存 model + model_instance_id
|
|
const updated = { ...props.modelValue, model: val, model_instance_id: model.id }
|
|
// 自动填入默认参数
|
|
const params = model.default_params || {}
|
|
if (params.temperature !== undefined && !updated.temperature) updated.temperature = params.temperature
|
|
if (params.max_tokens && !updated.max_tokens) updated.max_tokens = params.max_tokens
|
|
if ((model.capabilities || {}).function_calling && updated.tool_call === false) updated.tool_call = true
|
|
emit('update:modelValue', updated)
|
|
} else {
|
|
// 手动输入或清空:只保存 model,清除 model_instance_id
|
|
const updated = { ...props.modelValue, model: val, model_instance_id: undefined }
|
|
emit('update:modelValue', updated)
|
|
}
|
|
}
|
|
</script>
|
|
|