Add quick LLM provider setup
This commit is contained in:
@@ -43,7 +43,7 @@ const knowledgeForm = reactive({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const modelForm = reactive({
|
const modelForm = reactive({
|
||||||
provider: "openai",
|
provider: "openai-compatible",
|
||||||
displayName: "",
|
displayName: "",
|
||||||
apiType: "openai_compatible",
|
apiType: "openai_compatible",
|
||||||
modelName: "",
|
modelName: "",
|
||||||
@@ -66,58 +66,65 @@ const modelForm = reactive({
|
|||||||
timeoutSecond: 30,
|
timeoutSecond: 30,
|
||||||
});
|
});
|
||||||
|
|
||||||
const modelPresets = [
|
const quickModelForm = reactive({
|
||||||
|
provider: "deepseek",
|
||||||
|
modelName: "deepseek-v4-pro",
|
||||||
|
apiKey: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const quickModelProviders = [
|
||||||
{
|
{
|
||||||
label: "OpenAI",
|
label: "DeepSeek",
|
||||||
provider: "openai",
|
provider: "deepseek",
|
||||||
|
apiType: "openai_compatible",
|
||||||
|
baseUrl: "https://api.deepseek.com",
|
||||||
|
authType: "bearer",
|
||||||
|
apiVersion: "",
|
||||||
|
temperature: 0.2,
|
||||||
|
topP: null,
|
||||||
|
maxToken: 1024,
|
||||||
|
contextWindow: 128000,
|
||||||
|
models: [
|
||||||
|
{ label: "deepseek-v4-pro", value: "deepseek-v4-pro" },
|
||||||
|
{ label: "deepseek-v4-flash", value: "deepseek-v4-flash" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "MiniMax",
|
||||||
|
provider: "minimax",
|
||||||
|
apiType: "anthropic_messages",
|
||||||
|
baseUrl: "https://api.minimax.io/anthropic",
|
||||||
|
authType: "bearer",
|
||||||
|
apiVersion: "",
|
||||||
|
temperature: null,
|
||||||
|
topP: null,
|
||||||
|
maxToken: 1024,
|
||||||
|
contextWindow: 1000000,
|
||||||
|
models: [
|
||||||
|
{ label: "MiniMax-M3", value: "MiniMax-M3" },
|
||||||
|
{ label: "MiniMax-M2.7", value: "MiniMax-M2.7" },
|
||||||
|
{ label: "MiniMax-M2.7-highspeed", value: "MiniMax-M2.7-highspeed" },
|
||||||
|
{ label: "MiniMax-M2.5", value: "MiniMax-M2.5" },
|
||||||
|
{ label: "MiniMax-M2.5-highspeed", value: "MiniMax-M2.5-highspeed" },
|
||||||
|
{ label: "MiniMax-M2.1", value: "MiniMax-M2.1" },
|
||||||
|
{ label: "MiniMax-M2.1-highspeed", value: "MiniMax-M2.1-highspeed" },
|
||||||
|
{ label: "MiniMax-M2", value: "MiniMax-M2" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
const protocolPresets = [
|
||||||
|
{
|
||||||
|
label: "OpenAI 兼容协议",
|
||||||
|
provider: "openai-compatible",
|
||||||
apiType: "openai_compatible",
|
apiType: "openai_compatible",
|
||||||
baseUrl: "https://api.openai.com/v1",
|
baseUrl: "https://api.openai.com/v1",
|
||||||
apiUrl: "",
|
apiUrl: "",
|
||||||
authType: "bearer",
|
authType: "bearer",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "DeepSeek",
|
label: "Anthropic Messages 协议",
|
||||||
provider: "deepseek",
|
provider: "anthropic-compatible",
|
||||||
apiType: "openai_compatible",
|
|
||||||
baseUrl: "https://api.deepseek.com/v1",
|
|
||||||
apiUrl: "",
|
|
||||||
authType: "bearer",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "通义千问 DashScope",
|
|
||||||
provider: "qwen",
|
|
||||||
apiType: "openai_compatible",
|
|
||||||
baseUrl: "https://dashscope.aliyuncs.com/compatible-mode/v1",
|
|
||||||
apiUrl: "",
|
|
||||||
authType: "bearer",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Kimi / Moonshot",
|
|
||||||
provider: "moonshot",
|
|
||||||
apiType: "openai_compatible",
|
|
||||||
baseUrl: "https://api.moonshot.cn/v1",
|
|
||||||
apiUrl: "",
|
|
||||||
authType: "bearer",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "硅基流动 SiliconFlow",
|
|
||||||
provider: "siliconflow",
|
|
||||||
apiType: "openai_compatible",
|
|
||||||
baseUrl: "https://api.siliconflow.cn/v1",
|
|
||||||
apiUrl: "",
|
|
||||||
authType: "bearer",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "火山方舟 Ark",
|
|
||||||
provider: "volcengine-ark",
|
|
||||||
apiType: "openai_compatible",
|
|
||||||
baseUrl: "https://ark.cn-beijing.volces.com/api/v3",
|
|
||||||
apiUrl: "",
|
|
||||||
authType: "bearer",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Anthropic Claude",
|
|
||||||
provider: "anthropic",
|
|
||||||
apiType: "anthropic_messages",
|
apiType: "anthropic_messages",
|
||||||
baseUrl: "https://api.anthropic.com",
|
baseUrl: "https://api.anthropic.com",
|
||||||
apiUrl: "",
|
apiUrl: "",
|
||||||
@@ -127,17 +134,6 @@ const modelPresets = [
|
|||||||
topP: null,
|
topP: null,
|
||||||
topK: null,
|
topK: null,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: "Google Gemini",
|
|
||||||
provider: "gemini",
|
|
||||||
apiType: "gemini_generate_content",
|
|
||||||
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
|
||||||
apiUrl: "",
|
|
||||||
authType: "api_key",
|
|
||||||
temperature: null,
|
|
||||||
topP: null,
|
|
||||||
topK: null,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const nullableModelFields = [
|
const nullableModelFields = [
|
||||||
@@ -267,6 +263,52 @@ function buildModelPayload() {
|
|||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function quickAddModel() {
|
||||||
|
const provider = selectedQuickProvider();
|
||||||
|
if (!provider) return;
|
||||||
|
if (!quickModelForm.apiKey) {
|
||||||
|
ElMessage.error("请填写 API Key");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await api.createModel({
|
||||||
|
provider: provider.provider,
|
||||||
|
displayName: `${provider.label} ${quickModelForm.modelName}`,
|
||||||
|
apiType: provider.apiType,
|
||||||
|
modelName: quickModelForm.modelName,
|
||||||
|
baseUrl: provider.baseUrl,
|
||||||
|
apiUrl: "",
|
||||||
|
apiKey: quickModelForm.apiKey,
|
||||||
|
authType: provider.authType,
|
||||||
|
apiVersion: provider.apiVersion,
|
||||||
|
temperature: provider.temperature,
|
||||||
|
topP: provider.topP,
|
||||||
|
topK: null,
|
||||||
|
presencePenalty: null,
|
||||||
|
frequencyPenalty: null,
|
||||||
|
maxToken: provider.maxToken,
|
||||||
|
contextWindow: provider.contextWindow,
|
||||||
|
streamEnabled: 1,
|
||||||
|
responseFormat: null,
|
||||||
|
extraParams: null,
|
||||||
|
remark: "快速添加",
|
||||||
|
timeoutSecond: 30,
|
||||||
|
});
|
||||||
|
ElMessage.success(`${provider.label} 模型已新增`);
|
||||||
|
quickModelForm.apiKey = "";
|
||||||
|
await loadCurrentMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectedQuickProvider() {
|
||||||
|
return quickModelProviders.find((item) => item.provider === quickModelForm.provider) ?? quickModelProviders[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyQuickProvider(provider: string) {
|
||||||
|
const target = quickModelProviders.find((item) => item.provider === provider);
|
||||||
|
if (!target) return;
|
||||||
|
quickModelForm.modelName = target.models[0]?.value ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
async function enableModel(id: number) {
|
async function enableModel(id: number) {
|
||||||
await api.enableModel(id);
|
await api.enableModel(id);
|
||||||
ElMessage.success("模型已启用");
|
ElMessage.success("模型已启用");
|
||||||
@@ -283,7 +325,7 @@ async function testModel(id: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function applyModelPreset(label: string) {
|
function applyModelPreset(label: string) {
|
||||||
const preset = modelPresets.find((item) => item.label === label);
|
const preset = protocolPresets.find((item) => item.label === label);
|
||||||
if (!preset) return;
|
if (!preset) return;
|
||||||
Object.assign(
|
Object.assign(
|
||||||
modelForm,
|
modelForm,
|
||||||
@@ -332,7 +374,7 @@ function editModel(row: ModelItem) {
|
|||||||
function resetModelForm() {
|
function resetModelForm() {
|
||||||
editingModelId.value = null;
|
editingModelId.value = null;
|
||||||
Object.assign(modelForm, {
|
Object.assign(modelForm, {
|
||||||
provider: "openai",
|
provider: "openai-compatible",
|
||||||
displayName: "",
|
displayName: "",
|
||||||
apiType: "openai_compatible",
|
apiType: "openai_compatible",
|
||||||
modelName: "",
|
modelName: "",
|
||||||
@@ -516,27 +558,64 @@ function buildChatQuery() {
|
|||||||
|
|
||||||
<template v-if="activeMenu === 'models'">
|
<template v-if="activeMenu === 'models'">
|
||||||
<div class="page-head inline">
|
<div class="page-head inline">
|
||||||
<div><h2>模型管理</h2><p>支持 OpenAI 兼容、Anthropic Messages、Gemini generateContent 和常见第三方 LLM。</p></div>
|
<div><h2>模型管理</h2><p>DeepSeek、MiniMax 可快速添加;其他供应商按 OpenAI 兼容或 Anthropic Messages 协议添加。</p></div>
|
||||||
<el-button @click="resetModelForm">清空表单</el-button>
|
<el-button @click="resetModelForm">清空表单</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<section class="quick-model-panel">
|
||||||
|
<div class="quick-model-head">
|
||||||
|
<div>
|
||||||
|
<h3>快速添加</h3>
|
||||||
|
<p>适用于 DeepSeek 和 MiniMax,只需要填写 API Key 并选择模型。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="quick-model-grid">
|
||||||
|
<el-form-item label="厂商">
|
||||||
|
<el-select v-model="quickModelForm.provider" @change="applyQuickProvider">
|
||||||
|
<el-option
|
||||||
|
v-for="provider in quickModelProviders"
|
||||||
|
:key="provider.provider"
|
||||||
|
:label="provider.label"
|
||||||
|
:value="provider.provider"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="模型">
|
||||||
|
<el-select v-model="quickModelForm.modelName">
|
||||||
|
<el-option
|
||||||
|
v-for="model in selectedQuickProvider()?.models"
|
||||||
|
:key="model.value"
|
||||||
|
:label="model.label"
|
||||||
|
:value="model.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="API Key">
|
||||||
|
<el-input v-model="quickModelForm.apiKey" placeholder="填写后保存,列表中只展示掩码" show-password />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label=" ">
|
||||||
|
<el-button type="primary" class="full-btn" @click="quickAddModel">快速新增</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<el-form class="model-config-panel" label-position="top" :model="modelForm">
|
<el-form class="model-config-panel" label-position="top" :model="modelForm">
|
||||||
<div class="model-config-grid">
|
<div class="model-config-grid">
|
||||||
<el-form-item label="供应商预设">
|
<el-form-item label="协议模板">
|
||||||
<el-select placeholder="选择预设" clearable @change="applyModelPreset">
|
<el-select placeholder="选择协议模板" clearable @change="applyModelPreset">
|
||||||
<el-option v-for="preset in modelPresets" :key="preset.label" :label="preset.label" :value="preset.label" />
|
<el-option v-for="preset in protocolPresets" :key="preset.label" :label="preset.label" :value="preset.label" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="供应商标识">
|
<el-form-item label="供应商标识">
|
||||||
<el-input v-model="modelForm.provider" placeholder="openai / deepseek / qwen" />
|
<el-input v-model="modelForm.provider" placeholder="custom-openai / custom-anthropic" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="显示名称">
|
<el-form-item label="显示名称">
|
||||||
<el-input v-model="modelForm.displayName" placeholder="例如:DeepSeek V3 生产" />
|
<el-input v-model="modelForm.displayName" placeholder="例如:自建网关生产模型" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="协议类型">
|
<el-form-item label="协议类型">
|
||||||
<el-select v-model="modelForm.apiType">
|
<el-select v-model="modelForm.apiType">
|
||||||
<el-option label="OpenAI 兼容" value="openai_compatible" />
|
<el-option label="OpenAI 兼容" value="openai_compatible" />
|
||||||
<el-option label="Anthropic Messages" value="anthropic_messages" />
|
<el-option label="Anthropic Messages" value="anthropic_messages" />
|
||||||
<el-option label="Gemini generateContent" value="gemini_generate_content" />
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="模型名">
|
<el-form-item label="模型名">
|
||||||
|
|||||||
@@ -193,16 +193,48 @@ textarea {
|
|||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quick-model-panel {
|
||||||
|
margin-bottom: 18px;
|
||||||
|
padding: 18px;
|
||||||
|
border: 1px solid #cde7df;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #f8fcfb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-model-head {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-model-head h3 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-model-head p {
|
||||||
|
margin: 6px 0 0;
|
||||||
|
color: #667a73;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-model-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 180px 240px minmax(280px, 1fr) 130px;
|
||||||
|
gap: 12px;
|
||||||
|
align-items: end;
|
||||||
|
}
|
||||||
|
|
||||||
.model-config-grid {
|
.model-config-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(4, minmax(180px, 1fr));
|
grid-template-columns: repeat(4, minmax(180px, 1fr));
|
||||||
gap: 12px 14px;
|
gap: 12px 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quick-model-panel .el-form-item,
|
||||||
.model-config-panel .el-form-item {
|
.model-config-panel .el-form-item {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quick-model-panel .el-select,
|
||||||
|
.quick-model-panel .el-input,
|
||||||
.model-config-panel .el-select,
|
.model-config-panel .el-select,
|
||||||
.model-config-panel .el-input-number,
|
.model-config-panel .el-input-number,
|
||||||
.model-config-panel .el-input {
|
.model-config-panel .el-input {
|
||||||
|
|||||||
@@ -138,11 +138,7 @@ def _call_anthropic_messages(model: ModelConfig, rag_result: RagResult) -> str:
|
|||||||
_put_if_not_none(payload, "top_k", model.top_k)
|
_put_if_not_none(payload, "top_k", model.top_k)
|
||||||
payload.update(_load_extra_params(model.extra_params))
|
payload.update(_load_extra_params(model.extra_params))
|
||||||
|
|
||||||
headers = {
|
headers = _anthropic_headers(model)
|
||||||
"x-api-key": model.api_key,
|
|
||||||
"anthropic-version": model.api_version or "2023-06-01",
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
}
|
|
||||||
try:
|
try:
|
||||||
response = httpx.post(
|
response = httpx.post(
|
||||||
_resolve_anthropic_endpoint(model),
|
_resolve_anthropic_endpoint(model),
|
||||||
@@ -263,6 +259,19 @@ def _auth_headers(model: ModelConfig) -> dict[str, str]:
|
|||||||
return headers
|
return headers
|
||||||
|
|
||||||
|
|
||||||
|
def _anthropic_headers(model: ModelConfig) -> dict[str, str]:
|
||||||
|
headers = {"Content-Type": "application/json"}
|
||||||
|
if model.auth_type == "bearer":
|
||||||
|
headers["Authorization"] = f"Bearer {model.api_key}"
|
||||||
|
else:
|
||||||
|
headers["x-api-key"] = model.api_key
|
||||||
|
if model.api_version:
|
||||||
|
headers["anthropic-version"] = model.api_version
|
||||||
|
elif model.provider == "anthropic":
|
||||||
|
headers["anthropic-version"] = "2023-06-01"
|
||||||
|
return headers
|
||||||
|
|
||||||
|
|
||||||
def _decimal_to_float(value: Any) -> float | None:
|
def _decimal_to_float(value: Any) -> float | None:
|
||||||
return float(value) if value is not None else None
|
return float(value) if value is not None else None
|
||||||
|
|
||||||
|
|||||||
@@ -35,11 +35,12 @@
|
|||||||
| D-012 | 大模型真实调用先按 OpenAI 兼容 `chat/completions` 非流式响应接入。 | 默认采用 | 先打通配置化真实模型调用和失败日志,后续再升级为模型原生流式透传。 |
|
| D-012 | 大模型真实调用先按 OpenAI 兼容 `chat/completions` 非流式响应接入。 | 默认采用 | 先打通配置化真实模型调用和失败日志,后续再升级为模型原生流式透传。 |
|
||||||
| D-013 | 管理后台开发阶段支持首次登录自动创建默认管理员。 | 默认采用 | 降低本地初始化成本;生产环境必须修改默认账号密码。 |
|
| D-013 | 管理后台开发阶段支持首次登录自动创建默认管理员。 | 默认采用 | 降低本地初始化成本;生产环境必须修改默认账号密码。 |
|
||||||
| D-014 | 管理后台 Element Plus 先整体引入,后续再做按需导入优化。 | 已调整 | 阶段五优先保证后台功能闭环和交付速度;已在 D-019 调整为按需注册。 |
|
| D-014 | 管理后台 Element Plus 先整体引入,后续再做按需导入优化。 | 已调整 | 阶段五优先保证后台功能闭环和交付速度;已在 D-019 调整为按需注册。 |
|
||||||
| D-015 | 模型管理按“OpenAI 兼容协议 + 原生协议”两类补全。 | 默认采用 | DeepSeek、通义千问兼容模式、Kimi、硅基流动、火山方舟优先走 OpenAI 兼容;Anthropic Messages、Gemini generateContent 保留原生协议适配。 |
|
| D-015 | 模型管理按“快速厂商 + 协议通用配置”补全。 | 已调整 | DeepSeek 和 MiniMax 提供快速添加;其他供应商按 OpenAI 兼容协议或 Anthropic Messages 协议添加。 |
|
||||||
| D-016 | 模型配置支持 `baseUrl` 自动拼接接口,同时保留 `apiUrl` 覆盖能力。 | 默认采用 | 降低普通配置成本,同时给特殊代理网关、私有化模型和供应商非标准路径保留出口。 |
|
| D-016 | 模型配置支持 `baseUrl` 自动拼接接口,同时保留 `apiUrl` 覆盖能力。 | 默认采用 | 降低普通配置成本,同时给特殊代理网关、私有化模型和供应商非标准路径保留出口。 |
|
||||||
| D-017 | 编辑模型时 API Key 留空表示保留旧密钥。 | 默认采用 | 减少密钥重复暴露,避免后台人员只改参数时误覆盖密钥。 |
|
| D-017 | 编辑模型时 API Key 留空表示保留旧密钥。 | 默认采用 | 减少密钥重复暴露,避免后台人员只改参数时误覆盖密钥。 |
|
||||||
| D-018 | 模型高级参数用 JSON 对象透传。 | 默认采用 | 用较低成本兼容供应商差异,避免数据库字段无限膨胀。 |
|
| D-018 | 模型高级参数用 JSON 对象透传。 | 默认采用 | 用较低成本兼容供应商差异,避免数据库字段无限膨胀。 |
|
||||||
| D-019 | 管理后台 Element Plus 改为按需注册,并拆分表格和基础 vendor chunk。 | 默认采用 | 解决后台构建单 chunk 过大的提示,降低首屏主入口体积,同时不引入额外构建插件。 |
|
| D-019 | 管理后台 Element Plus 改为按需注册,并拆分表格和基础 vendor chunk。 | 默认采用 | 解决后台构建单 chunk 过大的提示,降低首屏主入口体积,同时不引入额外构建插件。 |
|
||||||
|
| D-020 | MiniMax 快速添加默认使用 Anthropic Messages 兼容协议。 | 默认采用 | MiniMax 文本生成指南推荐 Anthropic-compatible 路径;后端按 `auth_type` 兼容 Bearer 和 x-api-key 两种鉴权。 |
|
||||||
|
|
||||||
## 待确认决策
|
## 待确认决策
|
||||||
|
|
||||||
|
|||||||
@@ -4,16 +4,16 @@
|
|||||||
|
|
||||||
## 本次目标
|
## 本次目标
|
||||||
|
|
||||||
把管理后台的模型管理从“只保存一个 OpenAI 兼容地址”补全为可维护的第三方 LLM 配置能力,后续可以支持 OpenAI、DeepSeek、通义千问兼容模式、Kimi、硅基流动、火山方舟、Anthropic Claude、Google Gemini 等供应商。
|
把管理后台的模型管理从“只保存一个 OpenAI 兼容地址”补全为可维护的第三方 LLM 配置能力。当前交互收敛为两个常用厂商快速添加,以及两种协议级通用添加。
|
||||||
|
|
||||||
## 参考口径
|
## 参考口径
|
||||||
|
|
||||||
本次以各供应商公开接口文档的共同配置项为基础,不绑定某一个供应商 SDK:
|
本次以各供应商公开接口文档的共同配置项为基础,不绑定某一个供应商 SDK:
|
||||||
|
|
||||||
- OpenAI 兼容类:统一使用 `chat/completions` 风格,支持 `model`、`messages`、`temperature`、`top_p`、`max_tokens`、`stream`、`response_format` 等常见参数。
|
- OpenAI 兼容类:统一使用 `chat/completions` 风格,支持 `model`、`messages`、`temperature`、`top_p`、`max_tokens`、`stream`、`response_format` 等常见参数。
|
||||||
- DeepSeek、硅基流动、通义千问兼容模式、Kimi、火山方舟:优先作为 OpenAI 兼容协议接入,通过不同 `Base URL` 和 `modelName` 区分。
|
- Anthropic Messages 类:统一使用 `/v1/messages` 风格,支持 `model`、`messages`、`system`、`max_tokens` 等常见参数。
|
||||||
- Anthropic Claude:使用 Messages API 原生协议,鉴权使用 `x-api-key`,并支持 `anthropic-version`。
|
- DeepSeek:作为快速添加厂商,默认走 OpenAI 兼容协议。
|
||||||
- Google Gemini:使用 `generateContent` 原生协议,生成参数放在 `generationConfig` 下。
|
- MiniMax:作为快速添加厂商,默认走 Anthropic Messages 兼容协议。
|
||||||
|
|
||||||
## 已完成
|
## 已完成
|
||||||
|
|
||||||
@@ -50,16 +50,13 @@
|
|||||||
|
|
||||||
### 管理后台
|
### 管理后台
|
||||||
|
|
||||||
- 模型管理表单改为完整配置面板。
|
- 模型管理表单改为“快速添加 + 按协议添加”两段。
|
||||||
- 新增供应商预设:
|
- 新增快速添加:
|
||||||
- OpenAI
|
- DeepSeek:填写 API Key,选择 `deepseek-v4-pro` 或 `deepseek-v4-flash`。
|
||||||
- DeepSeek
|
- MiniMax:填写 API Key,选择 MiniMax-M3、MiniMax-M2.7、MiniMax-M2.5 等模型。
|
||||||
- 通义千问 DashScope
|
- 通用添加只保留协议模板:
|
||||||
- Kimi / Moonshot
|
- OpenAI 兼容协议。
|
||||||
- 硅基流动 SiliconFlow
|
- Anthropic Messages 协议。
|
||||||
- 火山方舟 Ark
|
|
||||||
- Anthropic Claude
|
|
||||||
- Google Gemini
|
|
||||||
- 新增参数配置:
|
- 新增参数配置:
|
||||||
- 协议类型
|
- 协议类型
|
||||||
- Base URL
|
- Base URL
|
||||||
@@ -88,12 +85,13 @@
|
|||||||
|
|
||||||
| 编号 | 决策 | 原因 |
|
| 编号 | 决策 | 原因 |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| M-001 | 第三方 LLM 分为 OpenAI 兼容协议和原生协议两类。 | 国内多数供应商提供 OpenAI 兼容模式,用统一协议可以减少重复代码;Anthropic、Gemini 保留原生协议以避免参数结构不匹配。 |
|
| M-001 | 第三方 LLM 分为 OpenAI 兼容协议和 Anthropic Messages 协议两类。 | 这两类是当前 Agent/LLM 配置中最常见的接入形态,后台不再为每个供应商堆大量预设。 |
|
||||||
| M-002 | `apiUrl` 可以为空,优先由 `baseUrl + apiType` 自动拼接。 | 后台人员更容易配置,只要填供应商 Base URL 和模型名即可;高级场景仍可用 API URL 覆盖。 |
|
| M-002 | `apiUrl` 可以为空,优先由 `baseUrl + apiType` 自动拼接。 | 后台人员更容易配置,只要填供应商 Base URL 和模型名即可;高级场景仍可用 API URL 覆盖。 |
|
||||||
| M-003 | 编辑模型时 API Key 留空表示不修改。 | 避免密钥频繁暴露和重复粘贴,降低误改风险。 |
|
| M-003 | 编辑模型时 API Key 留空表示不修改。 | 避免密钥频繁暴露和重复粘贴,降低误改风险。 |
|
||||||
| M-004 | 高级参数使用 JSON 对象透传。 | 保留不同供应商的扩展能力,同时避免每个小参数都单独改数据库结构。 |
|
| M-004 | 高级参数使用 JSON 对象透传。 | 保留不同供应商的扩展能力,同时避免每个小参数都单独改数据库结构。 |
|
||||||
| M-005 | Anthropic、Gemini 预设默认不强行填采样参数。 | 部分模型对非默认采样参数较敏感,预设应先保证能通,再由后台人员按需调整。 |
|
| M-005 | Anthropic Messages 协议模板默认不强行填采样参数。 | 部分模型对非默认采样参数较敏感,协议模板应先保证能通,再由后台人员按需调整。 |
|
||||||
| M-006 | 模型测试接口直接调用真实供应商。 | 这是后台配置验收动作,应该真实发现 Key、URL、模型名和参数错误。 |
|
| M-006 | 模型测试接口直接调用真实供应商。 | 这是后台配置验收动作,应该真实发现 Key、URL、模型名和参数错误。 |
|
||||||
|
| M-007 | DeepSeek 和 MiniMax 作为快速添加厂商。 | 一期高频模型供应商不需要后台人员理解协议细节,只填 API Key 和模型即可。 |
|
||||||
|
|
||||||
## 当前边界
|
## 当前边界
|
||||||
|
|
||||||
@@ -101,6 +99,7 @@
|
|||||||
- 流式输出字段已保存,但当前真实模型调用仍以非流式方式完成,用户端 SSE 分块由后端模拟输出。
|
- 流式输出字段已保存,但当前真实模型调用仍以非流式方式完成,用户端 SSE 分块由后端模拟输出。
|
||||||
- 不同供应商的费用、限流、区域和模型上下文窗口仍需要运营配置时自行确认。
|
- 不同供应商的费用、限流、区域和模型上下文窗口仍需要运营配置时自行确认。
|
||||||
- `extra_params` 由后台人员自行维护,系统只校验 JSON 对象格式,不校验供应商语义。
|
- `extra_params` 由后台人员自行维护,系统只校验 JSON 对象格式,不校验供应商语义。
|
||||||
|
- 后端仍保留 Gemini generateContent 适配代码,但当前后台入口不再暴露 Gemini 协议模板;如后续确认为高频供应商,再单独设计快速入口。
|
||||||
|
|
||||||
## 本次验证
|
## 本次验证
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user