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);
}