From 7e7c7f3a1ae4bf388d9220344fef1a2344be8e56 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 20 Mar 2026 23:43:00 +0800 Subject: [PATCH] feat: clarify admin model type labels --- .../settings/admin-settings-client.tsx | 48 +++++++++++++++---- lib/ai/model-classification.ts | 12 +++-- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/app/(admin)/settings/admin-settings-client.tsx b/app/(admin)/settings/admin-settings-client.tsx index b4a292286..7f7b52b81 100644 --- a/app/(admin)/settings/admin-settings-client.tsx +++ b/app/(admin)/settings/admin-settings-client.tsx @@ -105,6 +105,10 @@ import { getCanvasSkillIconComponent, } from "@/components/canvas/canvas-skill-icons"; import { fetchUploadWithRetry } from "@/lib/client/upload-with-retry"; +import { + isImageGenerationModelDescriptor, + isVideoModelDescriptor, +} from "@/lib/ai/model-classification"; import type { AgentWorkflowUiConfig } from "@/types/agent"; const fetcher = (url: string) => fetch(url).then((res) => res.json()); @@ -1556,14 +1560,24 @@ export function AdminSettingsClient() { const selectedModelProviderType = providersData?.providers?.find((p) => p.id === modelForm.providerId)?.type || ""; - const isVideoProviderForModelConfig = [ - "volcano-video", - "doubao-video", - "qianwen-video", - "fal-video", - "ruxa-video", - "runway", - ].includes(selectedModelProviderType); + const isVideoProviderForModelConfig = isVideoModelDescriptor({ + providerType: selectedModelProviderType, + modelId: modelForm.modelId, + supportsImageGen: modelForm.supportsImageGen, + }); + const isImageProviderForModelConfig = isImageGenerationModelDescriptor({ + providerType: selectedModelProviderType, + modelId: modelForm.modelId, + supportsImageGen: modelForm.supportsImageGen, + }); + const modelKindHint = + selectedModelProviderType === "runway" && !modelForm.modelId.trim() + ? "Runway 同时支持图片与视频模型,填写模型 ID 后系统会自动识别标签。" + : isVideoProviderForModelConfig + ? "当前识别为视频模型,将使用视频能力、视频积分和视频路由。" + : isImageProviderForModelConfig + ? "当前识别为图片模型,将使用生图能力、图片积分和生图路由。" + : "当前识别为对话/分析模型。"; // 存储配置状态 const [storageForm, setStorageForm] = useState({ @@ -7050,6 +7064,7 @@ export function AdminSettingsClient() { onChange={(e) => setModelForm({ ...modelForm, modelId: e.target.value })} placeholder="例如: qwen-turbo" /> +

{modelKindHint}

@@ -7233,7 +7248,7 @@ export function AdminSettingsClient() {
{/* 🆕 图片生成模型特性配置 */} - {(modelForm.supportsImageGen || isVideoProviderForModelConfig) && ( + {(isImageProviderForModelConfig || isVideoProviderForModelConfig) && (
生成配置
@@ -7448,6 +7463,18 @@ export function AdminSettingsClient() {
{modelsData?.models?.map((model) => { const provider = providersData?.providers?.find((p) => p.id === model.providerId); + const isVideoModel = isVideoModelDescriptor({ + providerType: provider?.type, + modelId: model.modelId, + capabilities: (model as any).capabilities, + supportsImageGen: model.supportsImageGen, + }); + const isImageModel = isImageGenerationModelDescriptor({ + providerType: provider?.type, + modelId: model.modelId, + capabilities: (model as any).capabilities, + supportsImageGen: model.supportsImageGen, + }); return (
@@ -7465,6 +7492,9 @@ export function AdminSettingsClient() { {model.displayName} {model.isDefault && 默认} {model.isAgentModel && Agent} + {isImageModel && 图片模型} + {isVideoModel && 视频模型} + {!isImageModel && !isVideoModel && 对话模型} {model.isMultimodal && 多模态} {model.isHidden && 前台隐藏} {(model as any).excludeFromFailover && 不参与故障迁移} diff --git a/lib/ai/model-classification.ts b/lib/ai/model-classification.ts index 7209fc26f..2a5e23f3f 100644 --- a/lib/ai/model-classification.ts +++ b/lib/ai/model-classification.ts @@ -98,17 +98,19 @@ export function isImageGenerationModelDescriptor(params: { }): boolean { const providerType = normalizeText(params.providerType); - if (params.supportsImageGen === true) { - return true; - } - if (providerType === "runway") { - return inferRunwayModelKind(params.modelId) === "image"; + const runwayModelKind = inferRunwayModelKind(params.modelId); + if (runwayModelKind === "image") return true; + if (runwayModelKind === "video") return false; } if (isVideoModelDescriptor(params)) { return false; } + if (params.supportsImageGen === true) { + return true; + } + return STATIC_IMAGE_PROVIDER_TYPES.has(providerType); }