2026-07-10 16:45:55 +08:00
|
|
|
|
<script setup lang="ts">
|
2026-07-12 15:39:59 +08:00
|
|
|
|
import { ref, reactive, computed, onMounted } from 'vue'
|
2026-07-10 16:45:55 +08:00
|
|
|
|
import { useRoute, useRouter } from 'vue-router'
|
|
|
|
|
|
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
|
|
|
|
|
|
import PageCard from '@/components/PageCard.vue'
|
2026-07-12 15:39:59 +08:00
|
|
|
|
import DimensionFormFields, { type DimensionFormDraft } from './create/DimensionFormFields.vue'
|
2026-07-10 16:45:55 +08:00
|
|
|
|
import {
|
|
|
|
|
|
createDimension,
|
|
|
|
|
|
updateDimension,
|
|
|
|
|
|
getDimension,
|
|
|
|
|
|
} from '@/api/modules/eval'
|
|
|
|
|
|
import { getModelList } from '@/api/modules/model'
|
2026-07-12 15:39:59 +08:00
|
|
|
|
import { EVAL_METHODS } from '@/constants/dimension'
|
|
|
|
|
|
import type { ModelItem } from '@/types'
|
2026-07-10 16:45:55 +08:00
|
|
|
|
|
|
|
|
|
|
const route = useRoute()
|
|
|
|
|
|
const router = useRouter()
|
|
|
|
|
|
const formRef = ref<FormInstance>()
|
|
|
|
|
|
const submitting = ref(false)
|
|
|
|
|
|
const isEdit = computed(() => !!route.params.id)
|
|
|
|
|
|
const editId = computed(() => route.params.id as string | undefined)
|
|
|
|
|
|
|
|
|
|
|
|
const evalModels = ref<ModelItem[]>([])
|
|
|
|
|
|
|
2026-07-12 22:49:05 +08:00
|
|
|
|
const form = reactive<DimensionFormDraft & { name: string }>({
|
2026-07-10 16:45:55 +08:00
|
|
|
|
name: '',
|
2026-07-12 15:39:59 +08:00
|
|
|
|
type: '',
|
2026-07-10 16:45:55 +08:00
|
|
|
|
description: '',
|
|
|
|
|
|
eval_model: '',
|
|
|
|
|
|
eval_method: '' as string | string[],
|
|
|
|
|
|
eval_prompt: '',
|
|
|
|
|
|
is_active: true,
|
|
|
|
|
|
is_default: false,
|
|
|
|
|
|
// text_similarity
|
|
|
|
|
|
bleu_n: 1,
|
|
|
|
|
|
output_precision: 3,
|
|
|
|
|
|
// metric
|
|
|
|
|
|
score_min: 0,
|
|
|
|
|
|
score_max: 5,
|
|
|
|
|
|
pass_threshold: 3,
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const rules: FormRules = {
|
|
|
|
|
|
name: [
|
|
|
|
|
|
{ required: true, message: '请输入维度名称', trigger: 'blur' },
|
|
|
|
|
|
{ max: 50, message: '不超过 50 字符', trigger: 'blur' },
|
|
|
|
|
|
],
|
|
|
|
|
|
type: [{ required: true, message: '请选择指标类型', trigger: 'change' }],
|
|
|
|
|
|
eval_model: [{ required: true, message: '请选择大模型', trigger: 'change' }],
|
2026-07-12 15:39:59 +08:00
|
|
|
|
eval_method: [{ required: true, message: '请选择评估方式', trigger: 'change' }],
|
2026-07-10 16:45:55 +08:00
|
|
|
|
eval_prompt: [{ required: true, message: '请填写评估 Prompt', trigger: 'blur' }],
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function loadEditData() {
|
|
|
|
|
|
if (!editId.value) return
|
|
|
|
|
|
try {
|
|
|
|
|
|
const dim: any = await getDimension(editId.value)
|
|
|
|
|
|
// 补全所有字段回填(修复原项目回填不完整 bug)
|
|
|
|
|
|
Object.assign(form, {
|
|
|
|
|
|
name: dim.name || '',
|
|
|
|
|
|
type: dim.type || '',
|
|
|
|
|
|
description: dim.description || '',
|
|
|
|
|
|
eval_model: dim.eval_model || '',
|
|
|
|
|
|
eval_method: dim.eval_method || (dim.type ? EVAL_METHODS[dim.type]?.[0]?.value : ''),
|
|
|
|
|
|
eval_prompt: dim.eval_prompt || '',
|
|
|
|
|
|
is_active: dim.is_active !== false,
|
|
|
|
|
|
is_default: !!dim.is_default,
|
|
|
|
|
|
bleu_n: dim.bleu_n ?? 1,
|
|
|
|
|
|
output_precision: dim.output_precision ?? 3,
|
|
|
|
|
|
score_min: dim.score_min ?? 0,
|
|
|
|
|
|
score_max: dim.score_max ?? 5,
|
|
|
|
|
|
pass_threshold: dim.pass_threshold ?? 3,
|
|
|
|
|
|
})
|
|
|
|
|
|
} catch {
|
|
|
|
|
|
// ignore
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function loadModels() {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const all = (await getModelList()) || []
|
2026-07-28 19:34:41 +08:00
|
|
|
|
evalModels.value = all.filter(
|
|
|
|
|
|
(m) => m.purpose === 'evaluation' || (m.model_source === 'api' && !!m.api_url),
|
|
|
|
|
|
)
|
2026-07-10 16:45:55 +08:00
|
|
|
|
} catch {
|
|
|
|
|
|
evalModels.value = []
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function handleSubmit() {
|
|
|
|
|
|
if (!formRef.value) return
|
|
|
|
|
|
await formRef.value.validate(async (valid) => {
|
|
|
|
|
|
if (!valid) return
|
|
|
|
|
|
submitting.value = true
|
|
|
|
|
|
try {
|
|
|
|
|
|
const data: any = {
|
|
|
|
|
|
name: form.name,
|
|
|
|
|
|
type: form.type,
|
|
|
|
|
|
description: form.description,
|
|
|
|
|
|
eval_model: form.type === 'text_similarity' ? null : form.eval_model,
|
|
|
|
|
|
eval_method: form.eval_method,
|
|
|
|
|
|
eval_prompt: form.type === 'text_similarity' ? null : form.eval_prompt,
|
|
|
|
|
|
is_active: form.is_active,
|
|
|
|
|
|
is_default: form.is_default,
|
|
|
|
|
|
create_time: new Date().toISOString(),
|
|
|
|
|
|
}
|
|
|
|
|
|
if (form.type === 'text_similarity') {
|
|
|
|
|
|
data.bleu_n = form.bleu_n
|
|
|
|
|
|
data.output_precision = form.output_precision
|
|
|
|
|
|
}
|
|
|
|
|
|
if (form.type === 'metric') {
|
|
|
|
|
|
data.score_min = form.score_min
|
|
|
|
|
|
data.score_max = form.score_max
|
|
|
|
|
|
data.pass_threshold = form.pass_threshold
|
|
|
|
|
|
}
|
|
|
|
|
|
if (isEdit.value && editId.value) {
|
|
|
|
|
|
await updateDimension(editId.value, data)
|
|
|
|
|
|
ElMessage.success('更新成功')
|
|
|
|
|
|
} else {
|
|
|
|
|
|
await createDimension(data)
|
|
|
|
|
|
ElMessage.success('创建成功')
|
|
|
|
|
|
}
|
|
|
|
|
|
router.push('/model-eval')
|
|
|
|
|
|
} catch {
|
|
|
|
|
|
// ignore
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
submitting.value = false
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function handleCancel() {
|
|
|
|
|
|
router.back()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
loadModels()
|
|
|
|
|
|
loadEditData()
|
|
|
|
|
|
})
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
|
<PageCard :title="isEdit ? '编辑评测维度' : '添加评测维度'">
|
|
|
|
|
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="130px" style="max-width: 760px">
|
2026-07-12 22:49:05 +08:00
|
|
|
|
<el-form-item label="维度名称" prop="name">
|
|
|
|
|
|
<el-input v-model="form.name" placeholder="请输入维度名称" maxlength="50" show-word-limit />
|
|
|
|
|
|
</el-form-item>
|
2026-07-12 15:39:59 +08:00
|
|
|
|
<DimensionFormFields v-model="form" :eval-models="evalModels" />
|
2026-07-10 16:45:55 +08:00
|
|
|
|
|
|
|
|
|
|
<el-form-item>
|
|
|
|
|
|
<el-button type="primary" :loading="submitting" @click="handleSubmit">
|
|
|
|
|
|
{{ isEdit ? '保存' : '创建' }}
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
<el-button @click="handleCancel">取消</el-button>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
</PageCard>
|
|
|
|
|
|
</template>
|