fix(canvas): 生成任务 - 校验视频提示词长度并修复工作流产物ID与供应商错误识别
This commit is contained in:
@@ -101,6 +101,19 @@ export function modelCompatibilityError(config: AiConfig, model: string, require
|
||||
return input.imageCount > 0 || input.videoCount > 0 || input.audioCount > 0 ? "音频模型只接受文本或单个角色卡输入" : "";
|
||||
}
|
||||
|
||||
export function modelPromptLengthError(config: AiConfig, model: string, capability: ModelCapability, prompt: string) {
|
||||
const channel = resolveModelChannel(config, model);
|
||||
const configuredProfile = channel.modelCosts?.find((item) => item.model === modelOptionName(model))?.capabilityConfig;
|
||||
if (!configuredProfile) return "";
|
||||
const profile = modelCapabilityConfigFor(config, model);
|
||||
const maxChars = capability === "text" ? profile.text?.references.promptMaxChars : capability === "image" ? profile.image?.references.promptMaxChars : capability === "video" ? profile.video?.references.promptMaxChars : undefined;
|
||||
if (!maxChars || maxChars <= 0) return "";
|
||||
const actualChars = Array.from(prompt).length;
|
||||
if (actualChars <= maxChars) return "";
|
||||
const label = capability === "text" ? "文本" : capability === "image" ? "图片" : "视频";
|
||||
return `当前${label}模型提示词最多 ${maxChars} 个字符,完整提示词为 ${actualChars} 个字符。系统不会自动截断,请精简当前输入、连线内容或技能上下文后重试`;
|
||||
}
|
||||
|
||||
export function modelRequestOptions(config: AiConfig, capability: ModelCapability) {
|
||||
switch (capability) {
|
||||
case "image":
|
||||
|
||||
@@ -9,7 +9,7 @@ import { isGenerationTaskCapacityError } from "@/lib/canvas/canvas-generation-ba
|
||||
import { buildPortraitTexturePrompt } from "@/lib/canvas/canvas-portrait-texture";
|
||||
import { resolveCanvasStyleExecution } from "@/lib/canvas/canvas-style-execution";
|
||||
import { generationErrorMessage, generationFailureMetadata } from "@/lib/generation-error";
|
||||
import { modelCompatibilityError, modelGroupReferenceLimits, modelRequestOptions, type ModelRequirements } from "@/lib/model-selection";
|
||||
import { modelCompatibilityError, modelGroupReferenceLimits, modelPromptLengthError, modelRequestOptions, type ModelRequirements } from "@/lib/model-selection";
|
||||
import { navigateToSettings } from "@/lib/settings-navigation";
|
||||
import type { Skill } from "@/services/api/skills";
|
||||
import { skillRuntime } from "@/services/skill-runtime";
|
||||
@@ -185,6 +185,11 @@ export function useCanvasGenerationExecutor({
|
||||
return;
|
||||
}
|
||||
}
|
||||
const promptLengthError = mode === "video" ? modelPromptLengthError(generationConfig, generationConfig.model, mode, effectivePrompt) : "";
|
||||
if (promptLengthError) {
|
||||
message.error(promptLengthError);
|
||||
return;
|
||||
}
|
||||
const generationContext = { ...rawGenerationContext, prompt: effectivePrompt };
|
||||
if (mode === "audio" && generationContext.characterReferences.length) {
|
||||
if (generationContext.characterReferences.length !== 1) {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { describe, expect, test } from "bun:test";
|
||||
import { canvasConnectionError } from "../src/lib/canvas/canvas-connection-policy";
|
||||
import { assertCanvasImageReferenceLimit, buildGenerationConfig, canvasImageReferenceLimitError, resolveCanvasGenerationModel } from "../src/lib/canvas/canvas-project-generation";
|
||||
import { defaultModelCapabilityConfig } from "../src/lib/model-capabilities";
|
||||
import { groupModelsByDisplayName, inferVideoOperation, modelCompatibilityError, modelGroupReferenceLimits, resolveCompatibleModel, resolveModelGenerationDefaults } from "../src/lib/model-selection";
|
||||
import { groupModelsByDisplayName, inferVideoOperation, modelCompatibilityError, modelGroupReferenceLimits, modelPromptLengthError, resolveCompatibleModel, resolveModelGenerationDefaults } from "../src/lib/model-selection";
|
||||
import { defaultConfig, normalizeModelOptionValue, type AiConfig, type ModelChannel } from "../src/stores/use-config-store";
|
||||
import { CanvasNodeType, type CanvasConnection, type CanvasNodeData } from "../src/types/canvas";
|
||||
|
||||
@@ -53,6 +53,18 @@ function node(id: string, type: CanvasNodeType, generationMode?: "image" | "vide
|
||||
}
|
||||
|
||||
describe("逻辑模型选择", () => {
|
||||
test("技能上下文展开后按最终视频模型字符上限拒绝提交", () => {
|
||||
const config = policyConfig();
|
||||
const model = config.videoModels[0]!;
|
||||
config.channels[0]!.modelCosts![0]!.capabilityConfig!.video!.references.promptMaxChars = 10_000;
|
||||
|
||||
const error = modelPromptLengthError(config, model, "video", "镜".repeat(23_142));
|
||||
|
||||
expect(error).toContain("最多 10000 个字符");
|
||||
expect(error).toContain("完整提示词为 23142 个字符");
|
||||
expect(error).toContain("不会自动截断");
|
||||
});
|
||||
|
||||
test("图片逻辑模型忽略全局视频时长,不应显示为不支持当前时长", () => {
|
||||
const model = "platform::gpt-image-2";
|
||||
const channel: ModelChannel = {
|
||||
|
||||
Reference in New Issue
Block a user