neural-sync/frontend/src/components/ExperimentBoard.vue

152 lines
4.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<n-space vertical>
<n-card title="进行中的实验" size="medium">
<template #header-extra>
<n-button type="primary" @click="fetchExperiments">刷新</n-button>
<n-button @click="openModal" style="margin-left: 12px;">新建实验</n-button>
</template>
<n-grid :x-gap="12" :y-gap="12" :cols="3">
<n-grid-item v-for="exp in experiments" :key="exp.id">
<n-card :title="exp.title" hoverable>
<template #header-extra>
<n-tag :type="getStatusType(exp.status)">{{ getStatusLabel(exp.status) }}</n-tag>
</template>
<p class="hypothesis-text">{{ exp.hypothesis }}</p>
<n-space vertical>
<n-statistic label="当前评分" :value="exp.current_score || '暂无数据'" />
<n-text depth="3" v-if="exp.linked_context_nodes && exp.linked_context_nodes.length">
关联认知节点: {{ exp.linked_context_nodes.length }} 个
</n-text>
</n-space>
</n-card>
</n-grid-item>
</n-grid>
</n-card>
<n-modal v-model:show="showModal">
<n-card style="width: 600px" title="设计新实验" :bordered="false" size="huge" role="dialog" aria-modal="true">
<n-form ref="formRef" :model="formValue">
<n-form-item label="标题" path="title">
<n-input v-model:value="formValue.title" placeholder="例如: 测试 DeepSeek-V3 的 SQL 生成能力" />
</n-form-item>
<n-form-item label="假设 (Hypothesis)" path="hypothesis">
<n-input v-model:value="formValue.hypothesis" type="textarea" placeholder="如果我们切换到 DeepSeek-V3,准确率预计提升 5%..." />
</n-form-item>
<n-form-item label="目标指标" path="target_metric">
<n-input v-model:value="formValue.target_metric" placeholder="例如: accuracy, latency" />
</n-form-item>
<n-form-item label="关联认知节点 (Context)" path="linked_context_nodes">
<n-select
v-model:value="formValue.linked_context_nodes"
multiple
:options="contextNodeOptions"
placeholder="选择此实验试图挑战或验证的认知..."
/>
</n-form-item>
</n-form>
<template #footer>
<n-button type="primary" block @click="createExperiment">启动实验</n-button>
</template>
</n-card>
</n-modal>
</n-space>
</template>
<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import { NSpace, NCard, NButton, NGrid, NGridItem, NTag, NStatistic, NModal, NForm, NFormItem, NInput, useMessage, NSelect, NText } from 'naive-ui'
import axios from 'axios'
const message = useMessage()
const experiments = ref<any[]>([])
const contextNodes = ref<any[]>([])
const showModal = ref(false)
const formValue = ref({
title: '',
hypothesis: '',
target_metric: 'accuracy',
linked_context_nodes: []
})
const contextNodeOptions = computed(() => {
return contextNodes.value.map(node => ({
label: `${node.content.substring(0, 50)}...`,
value: node.id
}))
})
const getStatusType = (status: string) => {
switch (status) {
case 'success': return 'success'
case 'failed': return 'error'
case 'running': return 'info'
default: return 'default'
}
}
const getStatusLabel = (status: string) => {
switch (status) {
case 'success': return '成功'
case 'failed': return '失败'
case 'running': return '进行中'
case 'draft': return '草稿'
default: return status
}
}
const fetchExperiments = async () => {
try {
const res = await axios.get('http://127.0.0.1:8000/experiments/')
experiments.value = res.data
} catch (error) {
message.error('获取实验列表失败')
}
}
const fetchContextNodes = async () => {
try {
const res = await axios.get('http://127.0.0.1:8000/context_nodes/')
contextNodes.value = res.data
} catch (error) {
console.error('Failed to fetch context nodes')
}
}
const openModal = () => {
fetchContextNodes()
showModal.value = true
}
const createExperiment = async () => {
try {
const res = await axios.post('http://127.0.0.1:8000/experiments/', formValue.value)
message.success('实验已启动!')
experiments.value.push(res.data)
showModal.value = false
// Reset form
formValue.value = {
title: '',
hypothesis: '',
target_metric: 'accuracy',
linked_context_nodes: []
}
} catch (error) {
message.error('创建实验失败')
}
}
onMounted(() => {
fetchExperiments()
fetchContextNodes()
})
</script>
<style scoped>
.hypothesis-text {
min-height: 3em;
color: #aaa;
font-size: 0.9em;
}
</style>