优化模型问题和调优问题
This commit is contained in:
parent
dde2895f13
commit
30e63d9598
@ -29,7 +29,8 @@
|
||||
<el-icon><Monitor /></el-icon>
|
||||
<span>大模型与AI治理</span>
|
||||
</template>
|
||||
<el-menu-item index="ai-models">模型参数调优</el-menu-item>
|
||||
<el-menu-item index="ai-model-config">模型配置管理</el-menu-item>
|
||||
<el-menu-item index="ai-model-tuning">模型参数调优</el-menu-item>
|
||||
<el-menu-item index="ai-logs">聊天日志审计</el-menu-item>
|
||||
<el-menu-item index="ai-content">内容审查</el-menu-item>
|
||||
</el-sub-menu>
|
||||
@ -105,11 +106,16 @@
|
||||
<SceneBinding />
|
||||
</div>
|
||||
|
||||
<!-- 模型参数调优 -->
|
||||
<div v-show="activeMenu === 'ai-models'" class="page-content">
|
||||
<!-- 模型配置管理 -->
|
||||
<div v-show="activeMenu === 'ai-model-config'" class="page-content">
|
||||
<ModelConfig />
|
||||
</div>
|
||||
|
||||
<!-- 模型参数调优 -->
|
||||
<div v-show="activeMenu === 'ai-model-tuning'" class="page-content">
|
||||
<ModelTuning />
|
||||
</div>
|
||||
|
||||
<!-- 聊天日志审计 -->
|
||||
<div v-show="activeMenu === 'ai-logs'" class="page-content">
|
||||
<ChatLogs />
|
||||
@ -184,6 +190,7 @@ import BackgroundManager from './components/admin/BackgroundManager.vue'
|
||||
import PetManager from './components/admin/PetManager.vue'
|
||||
import SceneBinding from './components/admin/SceneBinding.vue'
|
||||
import ModelConfig from './components/admin/ModelConfig.vue'
|
||||
import ModelTuning from './components/admin/ModelTuning.vue'
|
||||
import ChatLogs from './components/admin/ChatLogs.vue'
|
||||
import ContentAudit from './components/admin/ContentAudit.vue'
|
||||
import UserList from './components/admin/UserList.vue'
|
||||
@ -211,6 +218,7 @@ export default {
|
||||
PetManager,
|
||||
SceneBinding,
|
||||
ModelConfig,
|
||||
ModelTuning,
|
||||
ChatLogs,
|
||||
ContentAudit,
|
||||
UserList,
|
||||
@ -225,7 +233,7 @@ export default {
|
||||
setup() {
|
||||
const router = useRouter()
|
||||
const userStore = useUserStore()
|
||||
const activeMenu = ref('scene-backgrounds')
|
||||
const activeMenu = ref('ai-model-config')
|
||||
const loading = ref(false)
|
||||
|
||||
// 页面标题映射
|
||||
@ -233,7 +241,8 @@ export default {
|
||||
'scene-backgrounds': '背景资源管理',
|
||||
'scene-pets': '智能体库',
|
||||
'scene-binding': '背景绑定配置',
|
||||
'ai-models': '模型参数调优',
|
||||
'ai-model-config': '模型配置管理',
|
||||
'ai-model-tuning': '模型参数调优',
|
||||
'ai-logs': '聊天日志审计',
|
||||
'ai-content': '内容审查',
|
||||
'users-list': '用户列表',
|
||||
|
||||
283
frontend/src/views/components/admin/ModelTuning.vue
Normal file
283
frontend/src/views/components/admin/ModelTuning.vue
Normal file
@ -0,0 +1,283 @@
|
||||
<template>
|
||||
<div class="model-tuning">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<h3>模型参数调优</h3>
|
||||
<el-button @click="loadModels" :loading="loading">
|
||||
<el-icon><Refresh /></el-icon>
|
||||
刷新
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-alert
|
||||
type="info"
|
||||
show-icon
|
||||
:closable="false"
|
||||
title="在这里按模型维度调优推理参数,不修改模型接入信息(如 API Key / Base URL)。"
|
||||
style="margin-bottom: 16px"
|
||||
/>
|
||||
|
||||
<el-table :data="modelList" v-loading="loading" row-key="id">
|
||||
<el-table-column prop="name" label="模型名称" min-width="160" />
|
||||
<el-table-column prop="model_key" label="模型键" min-width="180" />
|
||||
<el-table-column prop="provider" label="提供商" width="120" />
|
||||
<el-table-column prop="temperature" label="Temperature" width="130" />
|
||||
<el-table-column prop="top_p" label="Top P" width="110" />
|
||||
<el-table-column prop="max_tokens" label="最大Token" width="120" />
|
||||
<el-table-column prop="enabled" label="状态" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.enabled ? 'success' : 'danger'">
|
||||
{{ row.enabled ? '启用' : '禁用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="240">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" type="primary" @click="openTuningDialog(row)">参数调优</el-button>
|
||||
<el-button size="small" @click="openTestDialog(row)">调优测试</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-dialog v-model="dialogVisible" title="模型参数调优" width="620px">
|
||||
<el-form :model="tuningForm" label-width="130px">
|
||||
<el-form-item label="模型名称">
|
||||
<el-input v-model="tuningForm.name" disabled />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Temperature">
|
||||
<el-slider
|
||||
v-model="tuningForm.temperature"
|
||||
:min="0"
|
||||
:max="2"
|
||||
:step="0.01"
|
||||
show-input
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Top P">
|
||||
<el-slider
|
||||
v-model="tuningForm.top_p"
|
||||
:min="0"
|
||||
:max="1"
|
||||
:step="0.01"
|
||||
show-input
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="最大Token">
|
||||
<el-input-number v-model="tuningForm.max_tokens" :min="1" :max="1000000" style="width: 100%" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="上下文长度">
|
||||
<el-input-number v-model="tuningForm.context_length" :min="1" :max="1000000" style="width: 100%" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="启用状态">
|
||||
<el-switch v-model="tuningForm.enabled" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="saving" @click="saveTuning">保存调优</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="testDialogVisible" title="调优参数测试" width="640px">
|
||||
<el-form :model="testForm" label-width="100px">
|
||||
<el-form-item label="模型">
|
||||
<el-input v-model="testForm.model_name" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="测试消息">
|
||||
<el-input
|
||||
v-model="testForm.test_message"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
placeholder="请输入测试消息"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-divider>测试结果</el-divider>
|
||||
<div v-if="testResult">
|
||||
<el-alert
|
||||
:type="testResult.success ? 'success' : 'error'"
|
||||
:title="testResult.message"
|
||||
show-icon
|
||||
/>
|
||||
<div v-if="testResult.response" class="response-content">
|
||||
<h4>响应内容:</h4>
|
||||
<p>{{ testResult.response }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="testDialogVisible = false">关闭</el-button>
|
||||
<el-button type="primary" :loading="testing" @click="submitTest">开始测试</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { Refresh } from '@element-plus/icons-vue'
|
||||
import axios from '@/api/index.js'
|
||||
|
||||
export default {
|
||||
name: 'ModelTuning',
|
||||
components: { Refresh },
|
||||
setup() {
|
||||
const loading = ref(false)
|
||||
const saving = ref(false)
|
||||
const testing = ref(false)
|
||||
const dialogVisible = ref(false)
|
||||
const testDialogVisible = ref(false)
|
||||
|
||||
const modelList = ref([])
|
||||
const testResult = ref(null)
|
||||
|
||||
const tuningForm = reactive({
|
||||
id: null,
|
||||
name: '',
|
||||
model_key: '',
|
||||
temperature: 0.7,
|
||||
top_p: 1,
|
||||
max_tokens: 4096,
|
||||
context_length: 8192,
|
||||
enabled: true
|
||||
})
|
||||
|
||||
const testForm = reactive({
|
||||
model_key: '',
|
||||
model_name: '',
|
||||
test_message: '请用一句话介绍你当前参数下的回答风格。'
|
||||
})
|
||||
|
||||
const loadModels = async () => {
|
||||
try {
|
||||
loading.value = true
|
||||
const response = await axios.get('/api/v1/model-config/', {
|
||||
params: { skip: 0, limit: 1000 }
|
||||
})
|
||||
modelList.value = response.data.data || []
|
||||
} catch (error) {
|
||||
console.error('加载模型列表失败:', error)
|
||||
ElMessage.error('加载模型列表失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const openTuningDialog = (row) => {
|
||||
Object.assign(tuningForm, {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
model_key: row.model_key,
|
||||
temperature: row.temperature ?? 0.7,
|
||||
top_p: row.top_p ?? 1,
|
||||
max_tokens: row.max_tokens ?? 4096,
|
||||
context_length: row.context_length ?? 8192,
|
||||
enabled: row.enabled ?? true
|
||||
})
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
const saveTuning = async () => {
|
||||
try {
|
||||
saving.value = true
|
||||
await axios.put(`/api/v1/model-config/${tuningForm.id}`, {
|
||||
temperature: tuningForm.temperature,
|
||||
top_p: tuningForm.top_p,
|
||||
max_tokens: tuningForm.max_tokens,
|
||||
context_length: tuningForm.context_length,
|
||||
enabled: tuningForm.enabled
|
||||
})
|
||||
ElMessage.success('调优参数保存成功')
|
||||
dialogVisible.value = false
|
||||
await loadModels()
|
||||
} catch (error) {
|
||||
console.error('保存调优参数失败:', error)
|
||||
ElMessage.error(error.response?.data?.detail || '保存调优参数失败')
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const openTestDialog = (row) => {
|
||||
testForm.model_key = row.model_key
|
||||
testForm.model_name = row.name
|
||||
testResult.value = null
|
||||
testDialogVisible.value = true
|
||||
}
|
||||
|
||||
const submitTest = async () => {
|
||||
try {
|
||||
testing.value = true
|
||||
const response = await axios.post('/api/v1/model-config/test-connection', {
|
||||
model_key: testForm.model_key,
|
||||
test_message: testForm.test_message
|
||||
})
|
||||
testResult.value = response.data
|
||||
} catch (error) {
|
||||
console.error('测试失败:', error)
|
||||
testResult.value = {
|
||||
success: false,
|
||||
message: error.response?.data?.detail || '测试失败'
|
||||
}
|
||||
} finally {
|
||||
testing.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadModels()
|
||||
})
|
||||
|
||||
return {
|
||||
loading,
|
||||
saving,
|
||||
testing,
|
||||
dialogVisible,
|
||||
testDialogVisible,
|
||||
modelList,
|
||||
tuningForm,
|
||||
testForm,
|
||||
testResult,
|
||||
loadModels,
|
||||
openTuningDialog,
|
||||
saveTuning,
|
||||
openTestDialog,
|
||||
submitTest
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.model-tuning {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.response-content {
|
||||
margin-top: 12px;
|
||||
padding: 10px;
|
||||
border-radius: 6px;
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
.response-content h4 {
|
||||
margin: 0 0 8px;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue
Block a user