fix: simplify workflow prompt composition
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-04-03 20:40:11 +08:00
parent 2eb8d7ad67
commit 9b0f762654
5 changed files with 90 additions and 32 deletions

View File

@ -4320,6 +4320,7 @@ export async function POST(request: Request) {
selectedVisibilityType,
composerMode,
hiddenPrompt,
workflowPromptOptimizationEnabled,
autoContext,
contextPayload,
agentModePayload,
@ -4333,6 +4334,7 @@ export async function POST(request: Request) {
selectedVisibilityType: VisibilityType;
composerMode?: "agent" | "image" | "video" | "detail";
hiddenPrompt?: string;
workflowPromptOptimizationEnabled?: boolean;
autoContext?: string;
contextPayload?: PostRequestBody["contextPayload"];
agentModePayload?: PostRequestBody["agentModePayload"];
@ -7478,7 +7480,9 @@ export async function POST(request: Request) {
})
: "";
const optimizedSceneWorkflowResult =
hiddenPromptText && sceneOptimizationImageUrls.primaryImageUrl
workflowPromptOptimizationEnabled !== false &&
hiddenPromptText &&
sceneOptimizationImageUrls.primaryImageUrl
? await optimizeAgentSceneWorkflowPrompt({
workflowPrompt: hiddenPromptText,
slotPrompt: dedupedSceneSlotPrompt || null,
@ -7508,6 +7512,12 @@ export async function POST(request: Request) {
negativeConstraints: optimizedSceneWorkflowResult.negativeConstraints,
conflicts: optimizedSceneWorkflowResult.conflicts,
});
} else if (hiddenPromptText && workflowPromptOptimizationEnabled === false) {
console.info("[Chat API] Agent scene workflow prompt optimization skipped:", {
chatId: id,
agentPresetId: selectedAgentPreset.id,
reason: "workflow_prompt_optimization_disabled",
});
}
const scenePrompt =
buildAgentSceneWorkflowPrompt({

View File

@ -98,6 +98,7 @@ export const postRequestBodySchema = z.object({
parts: z.array(partSchema),
}),
hiddenPrompt: z.string().max(4000).optional(),
workflowPromptOptimizationEnabled: z.boolean().optional(),
autoContext: z.string().max(4000).optional(),
agentPresetId: z.string().uuid().optional(),
// 支持预定义模型名称或数据库中的模型 UUID

View File

@ -2587,6 +2587,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
selectedAgentPresetId={isAgentWorkspaceEnabled ? selectedAgentPresetId : null}
selectedBrandModel={selectedBrandModel}
workflowContext={workflowContext}
workflowPromptOptimizationEnabled={appearanceRecognitionEnabled}
getLatestWorkflowContext={getLatestWorkflowContext}
agentModeState={agentModeState}
onAgentModeStateChange={setAgentModeState}

View File

@ -117,6 +117,7 @@ interface AgentGenerationWorkspaceDarkV2Props {
selectedAgentPresetId?: string | null;
selectedBrandModel?: AgentWorkflowSelectedBrandModel | null;
workflowContext?: AgentWorkflowComposerContext | null;
workflowPromptOptimizationEnabled?: boolean;
getLatestWorkflowContext?: () => AgentWorkflowComposerContext | null;
onBack?: () => void;
presetPanel?: ReactNode;
@ -955,6 +956,7 @@ export function AgentGenerationWorkspaceDarkV2({
selectedAgentPresetId,
selectedBrandModel = null,
workflowContext = null,
workflowPromptOptimizationEnabled = true,
getLatestWorkflowContext,
onBack,
presetPanel,
@ -1625,6 +1627,7 @@ export function AgentGenerationWorkspaceDarkV2({
"",
MAX_CHAT_HIDDEN_PROMPT_LENGTH
) || undefined,
workflowPromptOptimizationEnabled,
agentPresetId: isValidChatUuid(resolvedAgentPresetId)
? resolvedAgentPresetId
: undefined,

View File

@ -41,8 +41,65 @@ const WORKFLOW_FRAGMENT_INLINE_LABELS = [
"模特",
];
const BUSINESS_METADATA_NOISE_PATTERNS = [
/官方旗舰店/gi,
/旗舰店/gi,
/专卖店/gi,
/专营店/gi,
/企业店/gi,
/品牌馆/gi,
/拼多多/gi,
/天猫/gi,
/淘宝/gi,
/京东/gi,
];
function escapeRegExp(value: string) {
return String(value || "").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function sanitizePromptBusinessMetadata(params: {
value: string;
inputs: AgentWorkflowInputsValue;
}) {
const metadataTerms = [
params.inputs.brand,
params.inputs.store,
params.inputs.thirdCategory,
params.inputs.fourthCategory,
params.inputs.fifthCategory,
params.inputs.priceBand,
]
.map((item) => normalizeWorkflowText(item || ""))
.filter(Boolean)
.sort((left, right) => right.length - left.length);
let nextValue = normalizeWorkflowText(params.value || "");
if (!nextValue) {
return "";
}
metadataTerms.forEach((term) => {
nextValue = nextValue.replace(new RegExp(escapeRegExp(term), "gi"), " ");
});
BUSINESS_METADATA_NOISE_PATTERNS.forEach((pattern) => {
nextValue = nextValue.replace(pattern, " ");
});
nextValue = nextValue
.replace(/[()()【】[\]「」『』]/g, " ")
.replace(/[::]/g, " ")
.replace(/\s*[/-]\s*/g, " ")
.replace(/\s+/g, " ")
.trim();
return nextValue;
}
function buildGoodsInfoPromptLine(params: {
label: string;
inputs: AgentWorkflowInputsValue;
result?: AgentWorkflowMaterialSelections["primary"]["result"] | null;
}) {
const goodsInfo = params.result?.goodsInfo;
@ -50,8 +107,12 @@ function buildGoodsInfoPromptLine(params: {
return "";
}
const cleanedProductName = sanitizePromptBusinessMetadata({
value: goodsInfo.productName || "",
inputs: params.inputs,
});
const parts = [
goodsInfo.productName ? `商品名称:${goodsInfo.productName}` : "",
cleanedProductName ? `商品名称:${cleanedProductName}` : "",
goodsInfo.sizeInfo ? `尺寸信息:${goodsInfo.sizeInfo}` : "",
goodsInfo.materialInfo ? `材质信息:${goodsInfo.materialInfo}` : "",
goodsInfo.boardType ? `板材类型:${goodsInfo.boardType}` : "",
@ -110,6 +171,7 @@ function buildGoodsInfoAppearanceConstraintLine(params: {
function buildGoodsInfoSummaryLine(params: {
label: string;
inputs: AgentWorkflowInputsValue;
result?: AgentWorkflowMaterialSelections["primary"]["result"] | null;
}) {
const goodsInfo = params.result?.goodsInfo;
@ -117,8 +179,12 @@ function buildGoodsInfoSummaryLine(params: {
return "";
}
const cleanedProductName = sanitizePromptBusinessMetadata({
value: goodsInfo.productName || "",
inputs: params.inputs,
});
const parts = [
goodsInfo.productName || "",
cleanedProductName || "",
goodsInfo.sizeInfo || "",
goodsInfo.materialInfo || "",
].filter(Boolean);
@ -374,6 +440,7 @@ export function buildAgentWorkflowComposerContext(params: {
}
const primaryGoodsInfoSummary = buildGoodsInfoSummaryLine({
label: "主SKU商品信息",
inputs: params.inputs,
result: params.materials?.primary?.result || null,
});
if (primaryGoodsInfoSummary) {
@ -381,6 +448,7 @@ export function buildAgentWorkflowComposerContext(params: {
}
const secondaryGoodsInfoSummary = buildGoodsInfoSummaryLine({
label: "搭配SKU商品信息",
inputs: params.inputs,
result: params.materials?.secondary?.result || null,
});
if (secondaryGoodsInfoSummary) {
@ -398,7 +466,7 @@ export function buildAgentWorkflowComposerContext(params: {
}
if (referenceImages.some((item) => item.source === "brandModel")) {
summaryParts.push(
`品牌模特图:${referenceImages.filter((item) => item.source === "brandModel").length}张`
`模特参考图:${referenceImages.filter((item) => item.source === "brandModel").length}张`
);
}
summaryParts.push(
@ -413,35 +481,10 @@ export function buildAgentWorkflowComposerContext(params: {
return null;
}
const basicContextLines: string[] = [];
if (params.inputs.primarySku.trim()) {
basicContextLines.push(`主SKU:${params.inputs.primarySku.trim()}`);
}
if (params.inputs.secondarySku.trim()) {
basicContextLines.push(`搭配SKU:${params.inputs.secondarySku.trim()}`);
}
if (params.inputs.brand.trim()) {
basicContextLines.push(`品牌:${params.inputs.brand.trim()}`);
}
if (params.inputs.store.trim()) {
basicContextLines.push(`店铺:${params.inputs.store.trim()}`);
}
if (params.inputs.thirdCategory.trim()) {
basicContextLines.push(`三级分类:${params.inputs.thirdCategory.trim()}`);
}
if (params.inputs.fourthCategory.trim()) {
basicContextLines.push(`四级分类:${params.inputs.fourthCategory.trim()}`);
}
if (params.inputs.fifthCategory.trim()) {
basicContextLines.push(`五级分类:${params.inputs.fifthCategory.trim()}`);
}
if (params.inputs.priceBand.trim()) {
basicContextLines.push(`价格带:${params.inputs.priceBand.trim()}`);
}
const primaryLockLines: string[] = [];
const primaryGoodsInfoPrompt = buildGoodsInfoPromptLine({
label: "主SKU商品信息",
inputs: params.inputs,
result: params.materials?.primary?.result || null,
});
if (primaryGoodsInfoPrompt) {
@ -466,6 +509,7 @@ export function buildAgentWorkflowComposerContext(params: {
const secondaryLockLines: string[] = [];
const secondaryGoodsInfoPrompt = buildGoodsInfoPromptLine({
label: "搭配SKU商品信息",
inputs: params.inputs,
result: params.materials?.secondary?.result || null,
});
if (secondaryGoodsInfoPrompt) {
@ -519,7 +563,7 @@ export function buildAgentWorkflowComposerContext(params: {
.filter(Boolean)
.slice(0, 8);
referenceLines.push(
`品牌模特图:已选${referenceImages.filter((item) => item.source === "brandModel").length}张${
`模特参考图:已选${referenceImages.filter((item) => item.source === "brandModel").length}张${
labels.length > 0 ? `(${labels.join("、")})` : ""
}`
);
@ -530,7 +574,6 @@ export function buildAgentWorkflowComposerContext(params: {
}
const promptSections = [
buildPromptSection("项目背景", basicContextLines),
buildPromptSection("主SKU锁定", primaryLockLines),
buildPromptSection("搭配SKU锁定", secondaryLockLines),
buildPromptSection("参考图", referenceLines),