feat: 增加对新模型提供商的支持,包括智谱、MiniMax 和 Moonshot,更新相关配置和 UI

This commit is contained in:
锦麟 王
2026-02-06 10:59:27 +08:00
parent 427ea6ae8d
commit f919487506
4 changed files with 326 additions and 51 deletions

View File

@@ -428,17 +428,30 @@ async def test_llm_with_config(request: LLMTestRequest) -> dict[str, Any]:
# 根据提供商进行测试
start = time.time()
if provider in ["openai-compatible", "openai", "deepseek"]:
if provider in ["openai-compatible", "openai", "deepseek", "zhipu", "minimax", "moonshot"]:
# OpenAI 兼容接口
import httpx
url = base_url or "https://api.openai.com/v1"
model_name = model or "gpt-3.5-turbo"
# 获取代理设置
# 设置各提供商默认 URL
if provider == "deepseek" and not base_url:
url = "https://api.deepseek.com/v1"
elif provider == "zhipu" and not base_url:
url = "https://open.bigmodel.cn/api/paas/v4"
model_name = model or "glm-4-flash"
elif provider == "minimax" and not base_url:
url = "https://api.minimax.chat/v1"
model_name = model or "abab6.5s-chat"
elif provider == "moonshot" and not base_url:
url = "https://api.moonshot.cn/v1"
model_name = model or "moonshot-v1-8k"
# 国内 API 不需要代理
settings = get_settings()
proxy_url = None
if settings.proxy.enabled and provider not in ["deepseek"]:
if settings.proxy.enabled and provider not in ["deepseek", "zhipu", "minimax", "moonshot"]:
proxy_url = settings.proxy.http or settings.proxy.https
async with httpx.AsyncClient(

View File

@@ -458,99 +458,277 @@ body {
}
}
/* 亮色主题额外样式覆盖 */
/* ========== 亮色主题全面覆盖 ========== */
/* 全局背景 & 文字 */
.theme-light,
.theme-light body {
background-color: #f0f2f5 !important;
color: #303133 !important;
}
.theme-light .app-container {
background-color: #f0f2f5;
}
/* 侧边栏 */
.theme-light .sidebar {
background-color: #fff !important;
border-right-color: #e4e7ed !important;
}
.theme-light .logo {
border-bottom-color: #e4e7ed !important;
}
.theme-light .el-menu {
background-color: var(--bg-primary) !important;
background-color: #fff !important;
}
.theme-light .el-menu-item,
.theme-light .el-sub-menu__title {
color: var(--text-primary) !important;
color: #303133 !important;
}
.theme-light .el-menu-item.is-active {
background-color: var(--bg-secondary) !important;
color: var(--accent-primary) !important;
background-color: #ecf5ff !important;
color: #409eff !important;
}
.theme-light .el-menu-item:hover,
.theme-light .el-sub-menu__title:hover {
background-color: var(--bg-tertiary) !important;
background-color: #f5f7fa !important;
}
/* 头部 */
.theme-light .header {
background-color: #fff !important;
border-bottom-color: #e4e7ed !important;
color: #303133 !important;
}
.theme-light .header h3,
.theme-light .header span {
color: #303133 !important;
}
/* 主内容区 */
.theme-light .main-content {
background-color: #f0f2f5 !important;
}
/* 卡片 */
.theme-light .el-card {
background-color: var(--bg-secondary);
border-color: var(--border-color);
background-color: #fff !important;
border-color: #e4e7ed !important;
color: #303133 !important;
--el-card-bg-color: #fff;
}
.theme-light .el-card__header {
background-color: #fafbfc !important;
border-bottom-color: #e4e7ed !important;
color: #303133 !important;
}
.theme-light .el-card__body {
color: #303133 !important;
}
.theme-light .config-card {
background-color: #fff !important;
}
.theme-light .config-card .el-card__header {
background-color: #fafbfc !important;
border-bottom-color: #e4e7ed !important;
}
.theme-light .provider-card {
background-color: #fafbfc !important;
border-color: #e4e7ed !important;
}
.theme-light .stat-card {
background-color: #fff !important;
border-color: #e4e7ed !important;
}
/* 表单 */
.theme-light .el-form-item__label {
color: #606266 !important;
}
.theme-light .el-input__inner,
.theme-light .el-textarea__inner {
background-color: var(--bg-primary) !important;
border-color: var(--border-color) !important;
color: var(--text-primary) !important;
background-color: #fff !important;
border-color: #dcdfe6 !important;
color: #303133 !important;
}
.theme-light .el-input__wrapper {
background-color: #fff !important;
box-shadow: 0 0 0 1px #dcdfe6 inset !important;
}
.theme-light .el-input__wrapper:hover {
box-shadow: 0 0 0 1px #c0c4cc inset !important;
}
.theme-light .el-input__wrapper.is-focus {
box-shadow: 0 0 0 1px #409eff inset !important;
}
.theme-light .el-select-dropdown {
background-color: var(--bg-primary) !important;
background-color: #fff !important;
}
.theme-light .el-select-dropdown__item {
color: var(--text-primary) !important;
color: #303133 !important;
}
.theme-light .config-card {
background-color: var(--bg-secondary);
/* 按钮 */
.theme-light .el-button--default {
--el-button-bg-color: #fff;
--el-button-border-color: #dcdfe6;
--el-button-text-color: #606266;
--el-button-hover-bg-color: #ecf5ff;
--el-button-hover-border-color: #c6e2ff;
--el-button-hover-text-color: #409eff;
}
.theme-light .provider-card {
background-color: var(--bg-primary);
.theme-light .el-button--primary {
--el-button-bg-color: #409eff;
--el-button-border-color: #409eff;
--el-button-hover-bg-color: #66b1ff;
--el-button-hover-border-color: #66b1ff;
}
.theme-light .stat-card {
background-color: var(--bg-secondary);
/* 分割线 */
.theme-light .el-divider {
border-color: #e4e7ed !important;
}
/* 标签 */
.theme-light .el-tag {
--el-tag-bg-color: #ecf5ff;
--el-tag-border-color: #d9ecff;
--el-tag-text-color: #409eff;
}
/* Alert */
.theme-light .el-alert--info {
background-color: #f4f4f5 !important;
color: #909399 !important;
}
.theme-light .el-alert--info .el-alert__title {
color: #606266 !important;
}
/* 表格 */
.theme-light .el-table {
--el-table-bg-color: #fff;
--el-table-header-bg-color: #fafbfc;
--el-table-tr-bg-color: #fff;
--el-table-row-hover-bg-color: #f5f7fa;
--el-table-text-color: #303133;
--el-table-header-text-color: #909399;
--el-table-border-color: #ebeef5;
}
/* Tabs */
.theme-light .el-tabs__item {
color: #909399 !important;
}
.theme-light .el-tabs__item.is-active {
color: #409eff !important;
}
.theme-light .el-tabs--border-card {
background-color: #fff !important;
border-color: #dcdfe6 !important;
}
.theme-light .el-tabs__header {
background-color: #f5f7fa !important;
border-bottom-color: #e4e7ed !important;
}
/* Switch */
.theme-light .el-switch__label {
color: #606266 !important;
}
/* 对话框 */
.theme-light .el-dialog {
--el-dialog-bg-color: #fff;
}
.theme-light .el-dialog__title {
color: #303133 !important;
}
.theme-light .el-breadcrumb__inner {
color: #303133 !important;
}
/* 终端 & 日志 */
.theme-light .terminal-container,
.theme-light .logs-container {
background-color: var(--bg-primary);
background-color: #fff !important;
border-color: #e4e7ed !important;
}
.theme-light .terminal-header,
.theme-light .logs-header {
background-color: var(--bg-secondary);
background-color: #fafbfc !important;
border-bottom-color: #e4e7ed !important;
}
.theme-light .el-breadcrumb__inner {
color: var(--text-primary) !important;
}
.theme-light .el-dialog {
--el-dialog-bg-color: var(--bg-primary);
}
.theme-light .el-table {
--el-table-bg-color: var(--bg-secondary);
--el-table-header-bg-color: var(--bg-tertiary);
--el-table-tr-bg-color: var(--bg-secondary);
--el-table-row-hover-bg-color: var(--bg-tertiary);
--el-table-text-color: var(--text-primary);
--el-table-header-text-color: var(--text-secondary);
--el-table-border-color: var(--border-color);
.theme-light .log-entry {
border-bottom-color: #ebeef5 !important;
}
/* LLM 配置状态卡片 */
.theme-light .status-chip {
background-color: var(--bg-primary);
background-color: #fff !important;
border-color: #e4e7ed !important;
}
.theme-light .status-chip:hover,
.theme-light .status-chip.selected {
background-color: rgba(64, 158, 255, 0.1);
background-color: #ecf5ff !important;
border-color: #409eff !important;
}
.theme-light .test-result.success {
background-color: rgba(103, 194, 58, 0.15);
color: #67c23a;
background-color: rgba(103, 194, 58, 0.1);
}
.theme-light .test-result.error {
background-color: rgba(245, 108, 108, 0.15);
color: #f56c6c;
background-color: rgba(245, 108, 108, 0.1);
}
/* 文字颜色确保 */
.theme-light span,
.theme-light p,
.theme-light div,
.theme-light label {
color: inherit;
}
.theme-light .provider-name,
.theme-light .status-name,
.theme-light .stat-card-title,
.theme-light .log-message {
color: #303133;
}
.theme-light .stat-card-sub,
.theme-light .log-time {
color: #909399;
}

View File

@@ -72,7 +72,8 @@ app.component('channels-config-page', {
<li>登录企业微信管理后台 → 应用管理 → 创建应用</li>
<li>获取 CorpID、AgentID、Secret</li>
<li>在「接收消息」中配置 URL、Token、EncodingAESKey</li>
<li>Webhook URL: <code>https://your-domain.com/webhook/wework</code></li>
<li>回调地址指向 <b>Gateway 服务</b>(默认端口 8000</li>
<li>Webhook URL: <code>http://你的服务器IP:8000/webhook/wework</code></li>
</ol>
</template>
</el-alert>
@@ -125,7 +126,8 @@ app.component('channels-config-page', {
<li>登录飞书开放平台 → 创建企业自建应用</li>
<li>获取 App ID 和 App Secret</li>
<li>在「事件订阅」中配置请求地址和 Token</li>
<li>Webhook URL: <code>https://your-domain.com/webhook/feishu</code></li>
<li>事件请求地址指向 <b>Gateway 服务</b>(默认端口 8000</li>
<li>Webhook URL: <code>http://你的服务器IP:8000/webhook/feishu</code></li>
</ol>
</template>
</el-alert>

View File

@@ -26,7 +26,7 @@ app.component('llm-config-page', {
// 保存状态
const saving = ref(false);
// 表单数据 - 简化为通用的 OpenAI 兼容格式
// 表单数据
const form = reactive({
// 当前使用的配置
provider: 'openai-compatible',
@@ -62,6 +62,28 @@ app.component('llm-config-page', {
base_url: '',
model: 'gemini-2.5-flash-preview-05-20',
configured: false
},
'zhipu': {
name: '智谱 GLM',
api_key: '',
base_url: 'https://open.bigmodel.cn/api/paas/v4',
model: 'glm-4-flash',
configured: false
},
'minimax': {
name: 'MiniMax',
api_key: '',
base_url: 'https://api.minimax.chat/v1',
model: 'abab6.5s-chat',
group_id: '',
configured: false
},
'moonshot': {
name: 'Moonshot (Kimi)',
api_key: '',
base_url: 'https://api.moonshot.cn/v1',
model: 'moonshot-v1-8k',
configured: false
}
}
});
@@ -107,6 +129,37 @@ app.component('llm-config-page', {
defaultModel: 'gemini-2.5-flash-preview-05-20',
keyPlaceholder: 'AIzaSy-xxx',
domestic: false
},
{
id: 'zhipu',
name: '智谱 GLM',
icon: '🧠',
description: '智谱 AI 大模型,国内直连',
defaultUrl: 'https://open.bigmodel.cn/api/paas/v4',
defaultModel: 'glm-4-flash',
keyPlaceholder: 'xxx.xxx',
domestic: true
},
{
id: 'minimax',
name: 'MiniMax',
icon: '🎯',
description: 'MiniMax 大模型,国内直连(需 Group ID',
defaultUrl: 'https://api.minimax.chat/v1',
defaultModel: 'abab6.5s-chat',
keyPlaceholder: 'eyJhbGci-xxx',
domestic: true,
extraFields: ['group_id']
},
{
id: 'moonshot',
name: 'Moonshot (Kimi)',
icon: '🌙',
description: 'Moonshot/Kimi 大模型,国内直连',
defaultUrl: 'https://api.moonshot.cn/v1',
defaultModel: 'moonshot-v1-8k',
keyPlaceholder: 'sk-xxx',
domestic: true
}
];
@@ -137,6 +190,13 @@ app.component('llm-config-page', {
migrateConfig('anthropic', newVal.anthropic_api_key, newVal.anthropic_base_url);
migrateConfig('deepseek', newVal.deepseek_api_key, newVal.deepseek_base_url);
migrateConfig('gemini', newVal.gemini_api_key, newVal.gemini_base_url);
migrateConfig('zhipu', newVal.zhipu_api_key, newVal.zhipu_base_url);
migrateConfig('minimax', newVal.minimax_api_key, newVal.minimax_base_url);
migrateConfig('moonshot', newVal.moonshot_api_key, newVal.moonshot_base_url);
// MiniMax group_id
if (newVal.minimax_group_id) {
form.configs['minimax'].group_id = newVal.minimax_group_id;
}
}
}, { immediate: true, deep: true });
@@ -147,9 +207,9 @@ app.component('llm-config-page', {
'anthropic': 'anthropic',
'deepseek': 'deepseek',
'gemini': 'gemini',
'zhipu': 'openai-compatible',
'minimax': 'openai-compatible',
'moonshot': 'openai-compatible'
'zhipu': 'zhipu',
'minimax': 'minimax',
'moonshot': 'moonshot'
};
return map[name] || 'openai-compatible';
}
@@ -263,7 +323,17 @@ app.component('llm-config-page', {
deepseek_base_url: form.configs['deepseek'].base_url,
// Gemini
gemini_api_key: form.configs['gemini'].api_key,
gemini_base_url: form.configs['gemini'].base_url
gemini_base_url: form.configs['gemini'].base_url,
// 智谱
zhipu_api_key: form.configs['zhipu'].api_key,
zhipu_base_url: form.configs['zhipu'].base_url,
// MiniMax
minimax_api_key: form.configs['minimax'].api_key,
minimax_base_url: form.configs['minimax'].base_url,
minimax_group_id: form.configs['minimax'].group_id || '',
// Moonshot
moonshot_api_key: form.configs['moonshot'].api_key,
moonshot_base_url: form.configs['moonshot'].base_url
};
emit('save', saveData);
@@ -406,6 +476,18 @@ app.component('llm-config-page', {
留空将使用默认模型:{{ currentProvider.defaultModel }}
</div>
</el-form-item>
<!-- MiniMax 额外的 Group ID 字段 -->
<el-form-item v-if="activeProvider === 'minimax'" label="Group ID" required>
<el-input
v-model="form.configs['minimax'].group_id"
placeholder="MiniMax Group ID"
size="large"
/>
<div style="margin-top: 4px; font-size: 12px; color: var(--text-secondary);">
在 MiniMax 控制台获取,用于 API 调用
</div>
</el-form-item>
</el-form>
<!-- 测试区域 -->