1.0.0初始化源代码
This commit is contained in:
275
frontend/src/views/AIModels.vue
Normal file
275
frontend/src/views/AIModels.vue
Normal file
@@ -0,0 +1,275 @@
|
||||
<template>
|
||||
<div class="ai-models">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>AI 模型配置</span>
|
||||
<el-button type="primary" @click="showAddDialog = true">
|
||||
<el-icon><Plus /></el-icon>
|
||||
添加模型
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table :data="modelList" v-loading="loading">
|
||||
<el-table-column prop="id" label="ID" width="80" />
|
||||
<el-table-column prop="display_name" label="名称" width="150" />
|
||||
<el-table-column prop="model_name" label="模型" width="150" />
|
||||
<el-table-column prop="provider" label="提供商" width="120">
|
||||
<template #default="{ row }">
|
||||
<el-tag size="small">{{ getProviderLabel(row.provider) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="temperature" label="温度" width="100" />
|
||||
<el-table-column prop="max_tokens" label="最大 Token" width="100" />
|
||||
<el-table-column prop="is_default" label="默认" width="80">
|
||||
<template #default="{ row }">
|
||||
<el-tag size="small" :type="row.is_default ? 'success' : 'info'">
|
||||
{{ row.is_default ? '是' : '否' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="is_active" label="状态" width="80">
|
||||
<template #default="{ row }">
|
||||
<el-tag size="small" :type="row.is_active ? 'success' : 'info'">
|
||||
{{ row.is_active ? '启用' : '禁用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" fixed="right" width="250">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" @click="handleTest(row)">测试</el-button>
|
||||
<el-button size="small" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button size="small" type="danger" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<!-- 添加/编辑对话框 -->
|
||||
<el-dialog
|
||||
v-model="showModelDialog"
|
||||
:title="isEdit ? '编辑模型' : '添加模型'"
|
||||
width="600px"
|
||||
>
|
||||
<el-form :model="modelForm" label-width="120px">
|
||||
<el-form-item label="显示名称">
|
||||
<el-input v-model="modelForm.display_name" placeholder="如:GPT-3.5" />
|
||||
</el-form-item>
|
||||
<el-form-item label="模型名称">
|
||||
<el-input v-model="modelForm.model_name" placeholder="如:gpt-3.5-turbo" :disabled="isEdit" />
|
||||
</el-form-item>
|
||||
<el-form-item label="提供商">
|
||||
<el-select v-model="modelForm.provider" placeholder="请选择" :disabled="isEdit">
|
||||
<el-option label="OpenAI" value="openai" />
|
||||
<el-option label="智谱 AI" value="zhipu" />
|
||||
<el-option label="百度文心" value="baidu" />
|
||||
<el-option label="阿里通义" value="aliyun" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="API 地址">
|
||||
<el-input v-model="modelForm.api_url" placeholder="https://api.openai.com/v1" />
|
||||
</el-form-item>
|
||||
<el-form-item label="API Key">
|
||||
<el-input v-model="modelForm.api_key" type="password" show-password placeholder="sk-..." />
|
||||
</el-form-item>
|
||||
<el-form-item label="温度">
|
||||
<el-slider v-model="modelForm.temperature" :min="0" :max="1" :step="0.1" />
|
||||
</el-form-item>
|
||||
<el-form-item label="最大 Token 数">
|
||||
<el-input-number v-model="modelForm.max_tokens" :min="1" :max="4096" />
|
||||
</el-form-item>
|
||||
<el-form-item label="设为默认">
|
||||
<el-switch v-model="modelForm.is_default" />
|
||||
</el-form-item>
|
||||
<el-form-item label="启用">
|
||||
<el-switch v-model="modelForm.is_active" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="showModelDialog = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit" :loading="saving">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 测试对话框 -->
|
||||
<el-dialog
|
||||
v-model="showTestDialog"
|
||||
title="测试模型"
|
||||
width="500px"
|
||||
>
|
||||
<el-form>
|
||||
<el-form-item label="测试提示词">
|
||||
<el-input
|
||||
v-model="testPrompt"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
placeholder="请输入测试内容,如:请写一条关于春天的评论"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="showTestDialog = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleRunTest" :loading="testing">测试</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { aiModelApi } from '@/api'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
||||
const loading = ref(false)
|
||||
const saving = ref(false)
|
||||
const testing = ref(false)
|
||||
const modelList = ref([])
|
||||
const showAddDialog = ref(false)
|
||||
const showModelDialog = ref(false)
|
||||
const showTestDialog = ref(false)
|
||||
const isEdit = ref(false)
|
||||
const currentModelId = ref(null)
|
||||
const testPrompt = ref('')
|
||||
|
||||
const modelForm = ref({
|
||||
display_name: '',
|
||||
model_name: '',
|
||||
provider: '',
|
||||
api_url: '',
|
||||
api_key: '',
|
||||
temperature: 0.7,
|
||||
max_tokens: 1000,
|
||||
is_default: false,
|
||||
is_active: true
|
||||
})
|
||||
|
||||
const testData = ref({})
|
||||
|
||||
// 加载数据
|
||||
const loadData = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await aiModelApi.getList()
|
||||
modelList.value = res || []
|
||||
} catch (error) {
|
||||
console.error('Load AI models error:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 添加/编辑
|
||||
const handleAdd = () => {
|
||||
isEdit.value = false
|
||||
modelForm.value = {
|
||||
display_name: '',
|
||||
model_name: '',
|
||||
provider: '',
|
||||
api_url: '',
|
||||
api_key: '',
|
||||
temperature: 0.7,
|
||||
max_tokens: 1000,
|
||||
is_default: false,
|
||||
is_active: true
|
||||
}
|
||||
showModelDialog.value = true
|
||||
}
|
||||
|
||||
const handleEdit = (row) => {
|
||||
isEdit.value = true
|
||||
currentModelId.value = row.id
|
||||
modelForm.value = { ...row }
|
||||
showModelDialog.value = true
|
||||
}
|
||||
|
||||
// 提交
|
||||
const handleSubmit = async () => {
|
||||
saving.value = true
|
||||
try {
|
||||
if (isEdit.value) {
|
||||
await aiModelApi.update(currentModelId.value, modelForm.value)
|
||||
ElMessage.success('更新成功')
|
||||
} else {
|
||||
await aiModelApi.create(modelForm.value)
|
||||
ElMessage.success('创建成功')
|
||||
}
|
||||
showModelDialog.value = false
|
||||
loadData()
|
||||
} catch (error) {
|
||||
console.error('Save model error:', error)
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 删除
|
||||
const handleDelete = (row) => {
|
||||
ElMessageBox.confirm('确定要删除此模型配置吗?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
try {
|
||||
await aiModelApi.delete(row.id)
|
||||
ElMessage.success('删除成功')
|
||||
loadData()
|
||||
} catch (error) {
|
||||
console.error('Delete model error:', error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 测试
|
||||
const handleTest = (row) => {
|
||||
currentModelId.value = row.id
|
||||
testPrompt.value = '请写一条简短的评论'
|
||||
showTestDialog.value = true
|
||||
}
|
||||
|
||||
const handleRunTest = async () => {
|
||||
testing.value = true
|
||||
try {
|
||||
const res = await aiModelApi.test({
|
||||
model_id: currentModelId.value,
|
||||
test_prompt: testPrompt.value
|
||||
})
|
||||
|
||||
testData.value = res
|
||||
|
||||
if (res.success) {
|
||||
ElMessage.success(`测试成功!消耗 ${res.tokens_used} tokens`)
|
||||
console.log('Test result:', res.content)
|
||||
} else {
|
||||
ElMessage.error(`测试失败:${res.error_message}`)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Test model error:', error)
|
||||
} finally {
|
||||
testing.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const getProviderLabel = (provider) => {
|
||||
const map = { openai: 'OpenAI', zhipu: '智谱 AI', baidu: '百度文心', aliyun: '阿里通义' }
|
||||
return map[provider] || provider
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.ai-models {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user