feat: refine agent workflow flow
This commit is contained in:
parent
fbbc63f865
commit
64cb485dfa
@ -171,6 +171,57 @@ export function AgentWorkflowSettingsClient() {
|
||||
</Card>
|
||||
) : (
|
||||
<div className="space-y-5">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>基础下拉配置</CardTitle>
|
||||
<CardDescription>
|
||||
工作流左侧“品牌 / 店铺”采用后台配置的候选列表,前台支持输入关键字匹配下拉选择。
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div className="space-y-2">
|
||||
<Label>品牌列表</Label>
|
||||
<Textarea
|
||||
value={(config.inputOptions?.brands || []).join("\n")}
|
||||
onChange={(event) =>
|
||||
setConfig((prev) => ({
|
||||
...prev,
|
||||
inputOptions: {
|
||||
brands: event.target.value
|
||||
.split("\n")
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean),
|
||||
stores: prev.inputOptions?.stores || [],
|
||||
},
|
||||
}))
|
||||
}
|
||||
rows={10}
|
||||
placeholder={"例如:\n宜家\n顾家家居\n林氏家居"}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label>店铺列表</Label>
|
||||
<Textarea
|
||||
value={(config.inputOptions?.stores || []).join("\n")}
|
||||
onChange={(event) =>
|
||||
setConfig((prev) => ({
|
||||
...prev,
|
||||
inputOptions: {
|
||||
brands: prev.inputOptions?.brands || [],
|
||||
stores: event.target.value
|
||||
.split("\n")
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean),
|
||||
},
|
||||
}))
|
||||
}
|
||||
rows={10}
|
||||
placeholder={"例如:\n天猫旗舰店\n京东自营店\n抖音官方店"}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{sortedSteps.map((step) => (
|
||||
<Card key={step.key}>
|
||||
<CardHeader>
|
||||
|
||||
@ -517,6 +517,12 @@ const updateSchema = z.object({
|
||||
.optional(),
|
||||
agentWorkflowUiConfig: z
|
||||
.object({
|
||||
inputOptions: z
|
||||
.object({
|
||||
brands: z.array(z.string().trim().min(1).max(64)).max(300).optional(),
|
||||
stores: z.array(z.string().trim().min(1).max(64)).max(300).optional(),
|
||||
})
|
||||
.optional(),
|
||||
steps: z
|
||||
.array(
|
||||
z.object({
|
||||
|
||||
@ -5,6 +5,7 @@ import { useRouter, useParams, useSearchParams } from "next/navigation";
|
||||
import useSWR from "swr";
|
||||
import {
|
||||
AlertCircle,
|
||||
ArrowLeft,
|
||||
Save,
|
||||
Undo2,
|
||||
Redo2,
|
||||
@ -73,7 +74,10 @@ import {
|
||||
defaultAgentWorkflowUiConfig,
|
||||
normalizeAgentWorkflowUiConfig,
|
||||
} from "@/lib/agents/workflow-ui-config";
|
||||
import { buildAgentWorkflowComposerContext } from "@/lib/agents/workflow-composer";
|
||||
import {
|
||||
buildAgentWorkflowComposerContext,
|
||||
getAgentWorkflowProgress,
|
||||
} from "@/lib/agents/workflow-composer";
|
||||
import type {
|
||||
AgentWorkflowComposerContext,
|
||||
AgentWorkflowPersistedState,
|
||||
@ -161,6 +165,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
Partial<Record<AgentWorkflowStepKey, string>>
|
||||
>({});
|
||||
const [selectedAgentPresetId, setSelectedAgentPresetId] = useState<string | null>(null);
|
||||
const [currentAgentStage, setCurrentAgentStage] = useState<"workflow" | "mode">("workflow");
|
||||
const [workflowHydrationSource, setWorkflowHydrationSource] = useState<
|
||||
"pending" | "project" | "local" | "empty"
|
||||
>("pending");
|
||||
@ -286,6 +291,9 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
setSelectedAgentPresetId(
|
||||
String(persistedWorkflow.selectedAgentPresetId || "").trim() || null
|
||||
);
|
||||
setCurrentAgentStage(
|
||||
persistedWorkflow.currentStage === "mode" ? "mode" : "workflow"
|
||||
);
|
||||
setWorkflowHydrationSource("project");
|
||||
} else {
|
||||
setWorkflowHydrationSource("empty");
|
||||
@ -336,6 +344,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
},
|
||||
selections: workflowSelections,
|
||||
selectedAgentPresetId: selectedAgentPresetId || null,
|
||||
currentStage: currentAgentStage,
|
||||
};
|
||||
|
||||
return {
|
||||
@ -364,6 +373,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
});
|
||||
setWorkflowSelections(parsed.selections || {});
|
||||
setSelectedAgentPresetId(String(parsed.selectedAgentPresetId || "").trim() || null);
|
||||
setCurrentAgentStage(parsed.currentStage === "mode" ? "mode" : "workflow");
|
||||
} catch (error) {
|
||||
console.warn("[Canvas] Failed to hydrate workflow state from localStorage:", error);
|
||||
} finally {
|
||||
@ -381,6 +391,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
inputs: workflowInputs,
|
||||
selections: workflowSelections,
|
||||
selectedAgentPresetId,
|
||||
currentAgentStage,
|
||||
})
|
||||
);
|
||||
} catch (error) {
|
||||
@ -392,6 +403,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
workflowSelections,
|
||||
workflowStorageKey,
|
||||
selectedAgentPresetId,
|
||||
currentAgentStage,
|
||||
]);
|
||||
|
||||
const persistCanvasState = useCallback(
|
||||
@ -827,6 +839,14 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
selections: workflowSelections,
|
||||
});
|
||||
}, [resolvedWorkflowUiConfig, workflowInputs, workflowSelections]);
|
||||
const workflowProgress = useMemo(
|
||||
() =>
|
||||
getAgentWorkflowProgress({
|
||||
config: resolvedWorkflowUiConfig || defaultAgentWorkflowUiConfig,
|
||||
selections: workflowSelections,
|
||||
}),
|
||||
[resolvedWorkflowUiConfig, workflowSelections]
|
||||
);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
@ -883,8 +903,8 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
|
||||
<div className="absolute inset-0 flex pt-[72px]">
|
||||
<div className="min-w-0 flex-1 border-r bg-white dark:bg-zinc-950">
|
||||
<div className="grid h-full grid-rows-[minmax(0,1fr)_minmax(0,1fr)]">
|
||||
<div className="min-h-0 border-b">
|
||||
{currentAgentStage === "workflow" ? (
|
||||
<div className="h-full">
|
||||
<AgentWorkflowPanel
|
||||
embedded
|
||||
config={resolvedWorkflowUiConfig}
|
||||
@ -892,6 +912,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
onInputsChange={setWorkflowInputs}
|
||||
selections={workflowSelections}
|
||||
onSelectionsChange={setWorkflowSelections}
|
||||
onNextStep={() => setCurrentAgentStage("mode")}
|
||||
onReset={() => {
|
||||
setWorkflowInputs({
|
||||
primarySku: "",
|
||||
@ -901,17 +922,56 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
});
|
||||
setWorkflowSelections({});
|
||||
setSelectedAgentPresetId(null);
|
||||
setCurrentAgentStage("workflow");
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="min-h-0">
|
||||
) : (
|
||||
<div className="flex h-full flex-col">
|
||||
<div className="border-b p-4">
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div>
|
||||
<div className="flex items-center gap-2 text-sm font-semibold">
|
||||
<Wand2 className="h-4 w-4 text-amber-500" />
|
||||
生图模式
|
||||
</div>
|
||||
<div className="mt-1 text-xs text-muted-foreground">
|
||||
先完成第一步工作流,再选择具体的生图模式模板。
|
||||
</div>
|
||||
<div className="mt-2 inline-flex items-center rounded-full bg-muted px-2.5 py-1 text-[11px] text-muted-foreground">
|
||||
第 2 步 / 2 步
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => setCurrentAgentStage("workflow")}
|
||||
>
|
||||
<ArrowLeft className="mr-1 h-4 w-4" />
|
||||
返回上一步
|
||||
</Button>
|
||||
</div>
|
||||
{!workflowProgress.isComplete ? (
|
||||
<div className="mt-3 rounded-xl border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-800">
|
||||
第一步尚未完成,请先返回补全工作流环节。
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="min-h-0 flex-1">
|
||||
<AgentPresetPanel
|
||||
embedded
|
||||
selectedPresetId={selectedAgentPresetId}
|
||||
onSelectPreset={setSelectedAgentPresetId}
|
||||
title="生图模式"
|
||||
description="选择生图模式后,右侧对话框会按其要求显示上传槽位"
|
||||
searchPlaceholder="搜索生图模式"
|
||||
publicTitle="公共生图模式"
|
||||
privateTitle="我的生图模式"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
||||
@ -25,12 +25,22 @@ interface AgentPresetPanelProps {
|
||||
selectedPresetId?: string | null;
|
||||
onSelectPreset: (presetId: string | null) => void;
|
||||
embedded?: boolean;
|
||||
title?: string;
|
||||
description?: string;
|
||||
searchPlaceholder?: string;
|
||||
publicTitle?: string;
|
||||
privateTitle?: string;
|
||||
}
|
||||
|
||||
export function AgentPresetPanel({
|
||||
selectedPresetId,
|
||||
onSelectPreset,
|
||||
embedded = false,
|
||||
title = "智能体",
|
||||
description = "选择智能体后,右侧对话框会按其要求显示上传槽位",
|
||||
searchPlaceholder = "搜索智能体",
|
||||
publicTitle = "公共智能体",
|
||||
privateTitle = "我的智能体",
|
||||
}: AgentPresetPanelProps) {
|
||||
const [keyword, setKeyword] = useState("");
|
||||
const [categoryFilters, setCategoryFilters] = useState({
|
||||
@ -163,10 +173,10 @@ export function AgentPresetPanel({
|
||||
<div>
|
||||
<div className="flex items-center gap-2 text-sm font-semibold">
|
||||
<Sparkles className="h-4 w-4 text-amber-500" />
|
||||
智能体
|
||||
{title}
|
||||
</div>
|
||||
<div className="mt-1 text-xs text-muted-foreground">
|
||||
选择智能体后,右侧对话框会按其要求显示上传槽位
|
||||
{description}
|
||||
</div>
|
||||
</div>
|
||||
<Button size="sm" onClick={() => setShowCreateDialog(true)}>
|
||||
@ -175,7 +185,7 @@ export function AgentPresetPanel({
|
||||
</Button>
|
||||
</div>
|
||||
<Input
|
||||
placeholder="搜索智能体"
|
||||
placeholder={searchPlaceholder}
|
||||
value={keyword}
|
||||
onChange={(event) => setKeyword(event.target.value)}
|
||||
/>
|
||||
@ -185,7 +195,7 @@ export function AgentPresetPanel({
|
||||
<div className="space-y-5 p-4">
|
||||
<section className="space-y-3">
|
||||
<div className="space-y-3">
|
||||
<div className="text-sm font-medium">公共智能体</div>
|
||||
<div className="text-sm font-medium">{publicTitle}</div>
|
||||
<div className="grid grid-cols-1 gap-2 md:grid-cols-2">
|
||||
<Select
|
||||
value={categoryFilters.productCategory || "__none__"}
|
||||
@ -299,7 +309,7 @@ export function AgentPresetPanel({
|
||||
</section>
|
||||
|
||||
<section className="space-y-3">
|
||||
<div className="text-sm font-medium">我的智能体</div>
|
||||
<div className="text-sm font-medium">{privateTitle}</div>
|
||||
{isLoading ? null : filteredPrivatePresets.length > 0 ? (
|
||||
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-3">
|
||||
{filteredPrivatePresets.map((preset) => (
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useMemo } from "react";
|
||||
import { Copy, RotateCcw, Sparkles } from "lucide-react";
|
||||
import { ArrowRight, Copy, RotateCcw, Sparkles } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
@ -34,6 +34,7 @@ interface AgentWorkflowPanelProps {
|
||||
onSelectionsChange: (next: Partial<Record<AgentWorkflowStepKey, string>>) => void;
|
||||
onReset?: () => void;
|
||||
embedded?: boolean;
|
||||
onNextStep?: () => void;
|
||||
}
|
||||
|
||||
function buildSelectionSummary(params: {
|
||||
@ -69,7 +70,16 @@ export function AgentWorkflowPanel({
|
||||
onSelectionsChange,
|
||||
onReset,
|
||||
embedded = false,
|
||||
onNextStep,
|
||||
}: AgentWorkflowPanelProps) {
|
||||
const brandOptions = useMemo(
|
||||
() => config?.inputOptions?.brands || defaultAgentWorkflowUiConfig.inputOptions?.brands || [],
|
||||
[config?.inputOptions?.brands]
|
||||
);
|
||||
const storeOptions = useMemo(
|
||||
() => config?.inputOptions?.stores || defaultAgentWorkflowUiConfig.inputOptions?.stores || [],
|
||||
[config?.inputOptions?.stores]
|
||||
);
|
||||
const resolvedConfig = useMemo(() => {
|
||||
const source = config?.steps?.length ? config : defaultAgentWorkflowUiConfig;
|
||||
return {
|
||||
@ -181,15 +191,32 @@ export function AgentWorkflowPanel({
|
||||
onInputsChange({ ...inputs, brand: event.target.value })
|
||||
}
|
||||
placeholder="品牌"
|
||||
list="agent-workflow-brand-options"
|
||||
/>
|
||||
<datalist id="agent-workflow-brand-options">
|
||||
{brandOptions.map((item) => (
|
||||
<option key={item} value={item} />
|
||||
))}
|
||||
</datalist>
|
||||
<Input
|
||||
value={inputs.store}
|
||||
onChange={(event) =>
|
||||
onInputsChange({ ...inputs, store: event.target.value })
|
||||
}
|
||||
placeholder="店铺"
|
||||
list="agent-workflow-store-options"
|
||||
/>
|
||||
<datalist id="agent-workflow-store-options">
|
||||
{storeOptions.map((item) => (
|
||||
<option key={item} value={item} />
|
||||
))}
|
||||
</datalist>
|
||||
</div>
|
||||
{(brandOptions.length > 0 || storeOptions.length > 0) && (
|
||||
<div className="text-xs text-muted-foreground">
|
||||
品牌和店铺支持输入关键字匹配下拉选择,候选列表由系统设置配置。
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
{resolvedConfig.steps.map((step) => (
|
||||
@ -307,6 +334,14 @@ export function AgentWorkflowPanel({
|
||||
placeholder="选择左侧工作流后,这里会自动生成结构化 Prompt。"
|
||||
className="resize-none bg-background"
|
||||
/>
|
||||
{onNextStep ? (
|
||||
<div className="flex justify-end">
|
||||
<Button type="button" onClick={onNextStep} disabled={!progress.isComplete}>
|
||||
下一步:选择生图模式
|
||||
<ArrowRight className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
) : null}
|
||||
</section>
|
||||
</div>
|
||||
</ScrollArea>
|
||||
|
||||
@ -1361,6 +1361,55 @@ function extractFontWeight(value: string, fallback = "600"): string {
|
||||
return matched[1] || fallback;
|
||||
}
|
||||
|
||||
function sanitizeDetailImageModelPrompt(prompt: string): string {
|
||||
const filteredLines = String(prompt || "")
|
||||
.split(/\n+/)
|
||||
.map((line) => line.trim())
|
||||
.filter(Boolean)
|
||||
.map((line) => {
|
||||
if (
|
||||
/^(字体规范|标题规范|副标题规范|正文规范|版式规范|安全区|留白节奏|Typography|Layout|Palette|固定字体锁定|固定副标题锁定|固定正文锁定|固定排版安全区|固定留白节奏)/i.test(
|
||||
line
|
||||
)
|
||||
) {
|
||||
return "";
|
||||
}
|
||||
return line;
|
||||
})
|
||||
.filter(Boolean);
|
||||
|
||||
let result = filteredLines.join("\n");
|
||||
|
||||
const literalReplacements: Array<[RegExp, string]> = [
|
||||
[/画布固定(?:竖版)?\s*\d+\s*x\s*\d+\s*(?:像素|pixels?)。?/gi, "画布为竖版详情页构图。"],
|
||||
[/尺寸固定\s*\d+\s*x\s*\d+\s*(?:像素|pixels?)。?/gi, "尺寸为竖版详情页比例。"],
|
||||
[/输出为竖版电商详情图,尺寸固定\s*\d+\s*x\s*\d+\s*(?:像素|pixels?)。?/gi, "输出为竖版电商详情图。"],
|
||||
[/y\s*=\s*\d+\s*[-~~]\s*\d+/gi, "顶部标题安全区"],
|
||||
[/左右边距\s*\d+\s*px/gi, "左右留白充足"],
|
||||
[/模块间距\s*\d+\s*px/gi, "模块间距均匀"],
|
||||
[/标题和副标题间距\s*\d+\s*px/gi, "标题与副标题间距清晰"],
|
||||
[/主标题\s*\d+\s*px[^,。;\n]*/gi, "主标题醒目突出"],
|
||||
[/副标题\s*\d+\s*px[^,。;\n]*/gi, "副标题层级清晰"],
|
||||
[/正文\s*\d+\s*px[^,。;\n]*/gi, "正文精简易读"],
|
||||
[/商业摄影质感,留出清晰文案排版区,不要水印。?/gi, "商业摄影质感,留出清晰文字区域,不要水印。"],
|
||||
];
|
||||
|
||||
for (const [pattern, replacement] of literalReplacements) {
|
||||
result = result.replace(pattern, replacement);
|
||||
}
|
||||
|
||||
result = result
|
||||
.replace(/\b\d+\s*px\b/gi, "")
|
||||
.replace(/[((]\s*顶部标题安全区\s*[))]/g, "顶部标题安全区")
|
||||
.replace(/;{2,}/g, ";")
|
||||
.replace(/。{2,}/g, "。")
|
||||
.replace(/\s{2,}/g, " ")
|
||||
.replace(/\n{3,}/g, "\n\n")
|
||||
.trim();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function splitDetailKeywords(value: string, limit = 3): string[] {
|
||||
const raw = String(value || "")
|
||||
.split(/[\n,,、;;|]/)
|
||||
@ -5928,7 +5977,7 @@ export function CanvasChatPanel({
|
||||
),
|
||||
);
|
||||
|
||||
const generationPrompt = [
|
||||
const generationPrompt = sanitizeDetailImageModelPrompt([
|
||||
promptText,
|
||||
styleDirective ? `全局样式约束:${styleDirective}` : "",
|
||||
screen?.screenType
|
||||
@ -5963,7 +6012,7 @@ export function CanvasChatPanel({
|
||||
: "要求:整套详情图风格统一,产品外观严格一致,主标题/副标题/正文字体与层级全套一致,商业摄影质感,排版区域清晰,标题不得包含“第X屏”。",
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join("\n\n");
|
||||
.join("\n\n"));
|
||||
const styleAnchorUrl =
|
||||
index > 0 ? generatedImages[0]?.originalUrl || generatedImages[0]?.thumbnailUrl : null;
|
||||
const generationReferenceImagesBase = [
|
||||
@ -5976,12 +6025,13 @@ export function CanvasChatPanel({
|
||||
promptOverride: string,
|
||||
extraReferenceImages: string[] = []
|
||||
): Promise<{ originalUrl: string; thumbnailUrl: string }> => {
|
||||
const sanitizedPrompt = sanitizeDetailImageModelPrompt(promptOverride);
|
||||
const generationReferenceImages = [
|
||||
...generationReferenceImagesBase,
|
||||
...extraReferenceImages,
|
||||
].filter(Boolean);
|
||||
const result = await requestCanvasImageGeneration({
|
||||
prompt: promptOverride,
|
||||
prompt: sanitizedPrompt,
|
||||
model: modelForGeneration,
|
||||
aspectRatio: "9:16",
|
||||
imageSize: imageParams.imageSize,
|
||||
@ -6092,7 +6142,9 @@ export function CanvasChatPanel({
|
||||
|
||||
for (let retry = 0; retry < DETAIL_SCREEN_REVIEW_MAX_ATTEMPTS; retry += 1) {
|
||||
try {
|
||||
const revisedPrompt = String(screenReviewResult?.revisedPrompt || "").trim();
|
||||
const revisedPrompt = sanitizeDetailImageModelPrompt(
|
||||
String(screenReviewResult?.revisedPrompt || "").trim()
|
||||
);
|
||||
const regenerated = await generateDetailFrame(revisedPrompt, [
|
||||
firstPassImage.originalUrl || firstPassImage.thumbnailUrl,
|
||||
]);
|
||||
|
||||
@ -1,523 +1,528 @@
|
||||
# AI详情生成(AGENT + 生图模型 + 可编程渲染)开发文档
|
||||
# AI详情生成开发文档(当前实现版)
|
||||
|
||||
## 1. 文档目的
|
||||
## 1. 文档定位
|
||||
|
||||
本文档用于落地一套稳定的 AI 详情生成系统:
|
||||
本文档不再描述理想中的完整目标架构,而是基于当前仓库代码与前端交互,整理出一份可直接用于开发、联调、排查和运营说明的“当前实现版”文档。
|
||||
|
||||
- 保留现有传统生图模式(快速产图路线)
|
||||
- 保留生图模型能力(画面创作、质感、场景)
|
||||
- 用 AGENT 负责策划、文案、结构和审稿
|
||||
- 用编程渲染保证版式统一和可编辑
|
||||
- 支持用户切换两种模式(传统生图 / AGENT排版)
|
||||
- 最终结果直接进入无限画布,支持手动改字、拖拽图标、单屏重生
|
||||
适用范围:
|
||||
|
||||
目标是解决当前主要问题:生图模型理解偏差、全套风格不统一、失败不可控、返工成本高。
|
||||
- 无限画布中的 `AI详情生成工作台`
|
||||
- 前端入口与交互流程
|
||||
- 当前已接入的后端 API
|
||||
- `classic` 与 `agent_layout` 两种模式的真实差异
|
||||
- 已上线能力、未上线能力、已知限制
|
||||
|
||||
如果后续要继续推进“项目化管理 / Layout QA / 14屏严格状态机 / 项目级 API”,请在本文件基础上新增“规划版”文档,不要再把目标方案和当前实现混写。
|
||||
|
||||
---
|
||||
|
||||
## 2. 核心结论与原则
|
||||
## 2. 状态说明
|
||||
|
||||
### 2.1 核心结论
|
||||
本文档中的状态标签含义如下:
|
||||
|
||||
不能只靠生图模型“整页一次生成”。推荐架构是:
|
||||
|
||||
`AGENT 策划 -> 分屏生成 -> 程序化合成 -> 画布可编辑 -> 审核回路`
|
||||
|
||||
同时保留现有传统生图链路,采用双路线并行:
|
||||
|
||||
- 路线 A:`传统生图模式`(保持现状,快速出图)
|
||||
- 路线 B:`AGENT排版模式`(生图只负责画面,文字与排版交给程序)
|
||||
|
||||
### 2.2 设计原则
|
||||
|
||||
1. **模型出画面,代码定版式**
|
||||
2. **背景锁定,前景可生**(避免模型重画结构)
|
||||
3. **每屏可独立重试**(不整套重跑)
|
||||
4. **所有输入输出可追溯**(项目、版本、日志、成本)
|
||||
5. **画布内可编辑优先**(文字和图标非烤图)
|
||||
6. **双模式可切换且互不影响**(老链路稳定,新链路增量上线)
|
||||
- `已实现`:仓库中已有入口和主要逻辑,当前系统可走通
|
||||
- `部分实现`:已有部分链路,但与原设计稿不完全一致
|
||||
- `未实现`:文档中仅保留为后续规划,不应视为当前能力
|
||||
|
||||
---
|
||||
|
||||
## 3. 业务范围
|
||||
## 3. 当前能力总览
|
||||
|
||||
## 3.1 本期范围
|
||||
### 3.1 功能入口 `已实现`
|
||||
|
||||
- AI详情模式固定 14 屏流程(可配置)
|
||||
- 每屏固定尺寸 `790x1300`
|
||||
- 用户上传:
|
||||
- 5 张产品图(必填)
|
||||
- 1 张模特图(可用于卖家视角场景)
|
||||
- 3 张搭配图(可选,触发关联销售屏)
|
||||
- 输入业务信息:人群、场景、核心需求、SPU 等
|
||||
- 自动生成详情文案与视觉版式
|
||||
- 结果进入画布后可修改文字、拖拽图标、替换素材
|
||||
- 自动存档、历史恢复、继续生成
|
||||
- 入口位置:无限画布右侧聊天工作台中的 `AI详情生成`
|
||||
- 前端主文件:`components/canvas/CanvasChatPanel.tsx`
|
||||
- 用户可以选择两种模式:
|
||||
- `classic`:传统生图
|
||||
- `agent_layout`:AGENT排版
|
||||
|
||||
## 3.2 非本期范围
|
||||
### 3.2 当前真实输入约束 `已实现`
|
||||
|
||||
- 移动端编辑体验优化
|
||||
- 多人协同编辑冲突合并
|
||||
- 自动电商平台一键上架
|
||||
必填业务字段:
|
||||
|
||||
## 3.3 模式策略(新增)
|
||||
- `targetAudience`
|
||||
- `usageScenario`
|
||||
- `coreNeed`
|
||||
|
||||
- `传统生图模式(classic)`
|
||||
- 使用现有生图流程
|
||||
- 保留当前用户习惯与响应节奏
|
||||
- 适合快速尝试和低编辑需求场景
|
||||
- `AGENT排版模式(agent_layout)`
|
||||
- 生图模型只产出画面素材层,不产出文字排版
|
||||
- AGENT + 程序完成文案结构、版式和 UI 统一
|
||||
- 适合稳定量产、可编辑和可复用场景
|
||||
- 前端必须提供模式切换,并把模式写入任务上下文,后端按模式分流 pipeline
|
||||
当前前端强制素材要求:
|
||||
|
||||
- `5` 张产品图:必填
|
||||
- `1` 张模特图:当前实现中必填
|
||||
- `0-3` 张搭配图:可选
|
||||
|
||||
说明:
|
||||
|
||||
- 文档层面原本把模特图写成“可用于卖家视角场景”,但当前前端实现里它实际上是必填项。
|
||||
- 如果没有模特图,前端会直接拦截,不会进入 AI 详情规划。
|
||||
|
||||
### 3.3 当前真实输出结构 `已实现`
|
||||
|
||||
当前 AI 详情一次生成的输出由两部分组成:
|
||||
|
||||
1. `详情主图分镜`
|
||||
- 通过 `/api/canvas/detail-plan` 先规划
|
||||
- 再逐屏调用生图接口
|
||||
|
||||
2. `买家评价与晒单`
|
||||
- 在主图全部完成后由前端追加生成
|
||||
- 不属于 `detail-plan` 主分镜返回本体
|
||||
|
||||
---
|
||||
|
||||
## 4. 技术架构
|
||||
## 4. 当前系统里的真实流程
|
||||
|
||||
### 4.1 主流程概览 `已实现`
|
||||
|
||||
当前系统实际流程如下:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["用户输入(图片+业务信息)"] --> B["AGENT 规划器"]
|
||||
B --> C["ScreenSpec 14屏结构化脚本"]
|
||||
C --> D["生图编排器(逐屏调用模型)"]
|
||||
D --> E["程序化合成器(背景/文案/图标)"]
|
||||
E --> F["双总监审稿(设计+营销)"]
|
||||
F -->|通过| G["写入S3/MinIO + DB版本"]
|
||||
F -->|不通过| D
|
||||
G --> H["画布落地(垂直排版)"]
|
||||
H --> I["手动编辑(改字/拖拽/重生单屏)"]
|
||||
A["用户填写brief并上传素材"] --> B["前端校验必填字段和素材"]
|
||||
B --> C["POST /api/canvas/detail-plan"]
|
||||
C --> D["返回 screens/prompts/globalStyle/preflight"]
|
||||
D --> E["前端逐屏调用生图"]
|
||||
E --> F{"generation_mode"}
|
||||
F -->|classic| G["逐屏 detail-review 质检 + 可选二次修图"]
|
||||
F -->|agent_layout| H["前端叠加可编辑文字层"]
|
||||
G --> I["主图完成后追加评价晒图"]
|
||||
H --> I
|
||||
I --> J["写入画布节点 + 更新本地/数据库存档"]
|
||||
```
|
||||
|
||||
双路线分流(逻辑):
|
||||
### 4.2 关键特点
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
U["用户选择模式"] --> M{"generation_mode"}
|
||||
M -->|classic| C1["传统生图Pipeline"]
|
||||
M -->|agent_layout| C2["AGENT排版Pipeline"]
|
||||
C1 --> R["统一写入画布与历史记录"]
|
||||
C2 --> R
|
||||
```
|
||||
- 当前没有“项目级任务状态机 API”
|
||||
- 当前没有后端统一的 `/detail-projects/:projectId/generate`
|
||||
- 当前没有 SSE 进度接口
|
||||
- 进度条、占位图、逐屏生成状态全部在前端本地维护
|
||||
|
||||
---
|
||||
|
||||
## 5. 推荐开源技术选型
|
||||
## 5. 两种模式的真实差异
|
||||
|
||||
## 5.1 画布编辑层
|
||||
## 5.1 `classic` 传统生图模式 `已实现`
|
||||
|
||||
- `react-konva + konva`:用于画布图层编辑、拖拽、缩放、导出
|
||||
- `Moveable` 或 `interact.js`:吸附对齐、参考线、间距控制
|
||||
特点:
|
||||
|
||||
## 5.2 渲染层
|
||||
- 生图模型直接生成整页详情图
|
||||
- 提示词中会带标题、副标题、正文、FABE、排版说明
|
||||
- 每屏生成后会调用 `/api/canvas/detail-review`
|
||||
- 如果质检不通过,会基于 `revisedPrompt` 二次修图一次
|
||||
|
||||
- 主方案:HTML/CSS 模板 + Playwright 截图(最接近设计稿控制)
|
||||
- 备选:`Satori + resvg-js`(高一致性服务端矢量渲染)
|
||||
优点:
|
||||
|
||||
## 5.3 模型编排层
|
||||
- 成图速度快
|
||||
- 页面信息一次成型
|
||||
|
||||
- 继续使用当前生图供应商体系(支持路由和故障迁移)
|
||||
- AGENT 负责:
|
||||
- 详情策略规划
|
||||
- Prompt 生成与优化
|
||||
- 结果审稿和重试建议
|
||||
限制:
|
||||
|
||||
## 5.4 可选参考(不直接引入)
|
||||
- 文生图模型对文字和排版控制不稳定
|
||||
- 容易出现文字失真、布局漂移、参数被画出来等问题
|
||||
|
||||
- Excalidraw:交互/白板体验参考
|
||||
- Penpot:组件化设计体系参考
|
||||
- tldraw:能力强,但许可证需谨慎评估
|
||||
## 5.2 `agent_layout` AGENT排版模式 `已实现`
|
||||
|
||||
特点:
|
||||
|
||||
- 生图模型只生成画面层
|
||||
- 明确禁止模型输出可见文字、数字、Logo、水印
|
||||
- 画面生成完成后,前端在图片节点上叠加 3 个可编辑文字节点:
|
||||
- 标题
|
||||
- 副标题
|
||||
- 正文
|
||||
|
||||
当前文字层位置:
|
||||
|
||||
- 标题:`y + 72`
|
||||
- 副标题:`y + 214`
|
||||
- 正文:`y + 304`
|
||||
- 左边距:约画面宽度的 `7%`
|
||||
|
||||
优点:
|
||||
|
||||
- 文字可编辑
|
||||
- 文案层级更统一
|
||||
- 避免模型把整页文字烤死
|
||||
|
||||
限制:
|
||||
|
||||
- 当前文字层位置是前端固定模板,不是后端程序化版式引擎
|
||||
- 当前 `agent_layout` 不走 `/api/canvas/detail-review`
|
||||
- 当前没有“文字遮挡主体”的自动检测
|
||||
|
||||
---
|
||||
|
||||
## 6. 数据模型设计(数据库)
|
||||
## 6. 屏数与完成条件
|
||||
|
||||
建议新增或扩展以下表(命名可按现有规范调整):
|
||||
### 6.1 当前真实规则 `已实现`
|
||||
|
||||
## 6.1 `detail_projects`
|
||||
当前主图分镜数不是固定 14 屏,而是动态值:
|
||||
|
||||
- `id`
|
||||
- `user_id`
|
||||
- `canvas_id`
|
||||
- `spu`
|
||||
- `demand_type`
|
||||
- `project_name`(默认 `SPU+需求类型`)
|
||||
- `status`(draft/planning/generating/reviewing/completed/failed)
|
||||
- `generation_mode`(classic/agent_layout,默认 classic)
|
||||
- `created_at` / `updated_at`
|
||||
- 前端会从用户输入文本里解析 `X张 / X屏 / X页`
|
||||
- 如果没解析到,默认 `14` 屏
|
||||
- 后端会把数量限制在 `5-20`
|
||||
- 如果上传了搭配图,会额外加 `1` 屏搭配展示
|
||||
|
||||
## 6.2 `detail_project_inputs`
|
||||
### 6.2 当前真实完成条件 `已实现`
|
||||
|
||||
- `id`
|
||||
- `project_id`
|
||||
- `core_audience`
|
||||
- `usage_scenarios`
|
||||
- `core_needs`
|
||||
- `selling_points`
|
||||
- `tone_style`
|
||||
- `extra_requirements`
|
||||
- `raw_form_json`
|
||||
当前“完成”并不是“必须满 14 屏”,而是:
|
||||
|
||||
## 6.3 `detail_assets`
|
||||
- 本次 `detail-plan` 返回了多少条 `prompts`
|
||||
- 前端就按多少屏去生成
|
||||
- 当 `generatedImages.length === prompts.length` 时,主图阶段视为完成
|
||||
|
||||
- `id`
|
||||
- `project_id`
|
||||
- `asset_type`(product/model/combo/reference)
|
||||
- `source_url`
|
||||
- `storage_url`
|
||||
- `width` / `height`
|
||||
- `meta_json`
|
||||
### 6.3 评价晒图的关系 `已实现`
|
||||
|
||||
## 6.4 `detail_screen_specs`
|
||||
买家评价与晒单是主图完成后的追加产物:
|
||||
|
||||
- `id`
|
||||
- `project_id`
|
||||
- `screen_index`(1..14)
|
||||
- `screen_type`
|
||||
- `spec_json`(可编辑图层结构)
|
||||
- `prompt_json`
|
||||
- `status`
|
||||
|
||||
## 6.5 `detail_screen_renders`
|
||||
|
||||
- `id`
|
||||
- `project_id`
|
||||
- `screen_index`
|
||||
- `version_no`
|
||||
- `image_url`
|
||||
- `thumb_url`
|
||||
- `model_provider`
|
||||
- `model_name`
|
||||
- `cost_credits`
|
||||
- `latency_ms`
|
||||
- `review_score_design`
|
||||
- `review_score_marketing`
|
||||
- `review_notes`
|
||||
|
||||
## 6.6 `detail_generation_jobs`
|
||||
|
||||
- `id`
|
||||
- `project_id`
|
||||
- `job_type`(plan/generate/review/retry)
|
||||
- `generation_mode`(classic/agent_layout)
|
||||
- `progress`(0~100)
|
||||
- `stage`(规划中/生成中/审稿中/完成)
|
||||
- `error_code`
|
||||
- `error_message`
|
||||
- `started_at` / `finished_at`
|
||||
|
||||
## 6.7 现有聊天/消息表扩展(建议)
|
||||
|
||||
- 在会话或任务表增加 `generation_mode`
|
||||
- 在消息元数据增加 `mode_snapshot`(防止切换模式导致历史重放错乱)
|
||||
- 在生成记录增加 `resolved_pipeline`(最终实际执行链路)
|
||||
- 默认追加 `3` 条评价方案
|
||||
- 每条评价生成 `3` 张晒单图
|
||||
- 不计入主图 `prompts.length`
|
||||
|
||||
---
|
||||
|
||||
## 7. ScreenSpec(核心协议)
|
||||
## 7. 当前接口清单
|
||||
|
||||
AGENT 和渲染器之间只通过结构化协议通信,不直接拼字符串 UI。
|
||||
## 7.1 已上线接口
|
||||
|
||||
```json
|
||||
{
|
||||
"projectId": "dp_xxx",
|
||||
"canvasId": "cv_xxx",
|
||||
"size": { "width": 790, "height": 1300 },
|
||||
"globalStyle": {
|
||||
"fontFamily": "PingFang SC",
|
||||
"titleSize": 68,
|
||||
"subtitleSize": 36,
|
||||
"bodySize": 28,
|
||||
"lineHeight": 1.35,
|
||||
"palette": { "primary": "#5B4DFF", "text": "#111111" }
|
||||
},
|
||||
"screen": {
|
||||
"index": 1,
|
||||
"type": "hero_poster",
|
||||
"copy": {
|
||||
"name": "安敏裤",
|
||||
"title": "安敏裤 | 敏宝整夜安睡不红屁屁",
|
||||
"subtitle": "过敏体质宝宝专研,夜用安心不反渗"
|
||||
},
|
||||
"layers": [
|
||||
{ "id": "bg", "kind": "backgroundImage", "editable": false, "src": "https://..." },
|
||||
{ "id": "title", "kind": "text", "editable": true, "x": 56, "y": 120, "w": 678, "h": 180 },
|
||||
{ "id": "badge", "kind": "icon", "editable": true, "x": 56, "y": 340, "w": 160, "h": 52 }
|
||||
],
|
||||
"gen": {
|
||||
"needModelImage": true,
|
||||
"prompt": "只生成产品前景和光效,不生成文字,不改背景结构",
|
||||
"negativePrompt": "杂乱文字, 水印, logo"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
### 1. `POST /api/canvas/detail-plan` `已实现`
|
||||
|
||||
---
|
||||
作用:
|
||||
|
||||
## 8. 14屏生产流程(标准)
|
||||
- 生成 AI 详情规划结果
|
||||
- 返回:
|
||||
- `summary`
|
||||
- `prompts`
|
||||
- `globalStyle`
|
||||
- `skillFlow`
|
||||
- `qualityChecks`
|
||||
- `preflight`
|
||||
- `screens`
|
||||
- `generationMode`
|
||||
|
||||
1. 首屏海报(命名+核心需求一句话)
|
||||
2. 用户痛点
|
||||
3. 核心卖点机制
|
||||
4. 卖点证据/参数
|
||||
5. 场景 1(日常)
|
||||
6. 场景 2(高频痛点)
|
||||
7. 细节特写
|
||||
8. 对比页
|
||||
9. 使用方法
|
||||
10. 搭配销售(用户上传搭配图时启用)
|
||||
11. 买家评价 1(自动生成评价+3图)
|
||||
12. 买家评价 2(可再次生成新2条)
|
||||
13. 品牌背书/服务承诺
|
||||
14. 收口 CTA
|
||||
输入重点:
|
||||
|
||||
约束:必须完整到第 14 屏才能标记 `completed`。
|
||||
- `prompt`
|
||||
- `count`
|
||||
- `generationMode`
|
||||
- `referenceImages`
|
||||
- `referenceImageNotes`
|
||||
- `modelImageUrl`
|
||||
- `bundleImageUrls`
|
||||
- `brief`
|
||||
|
||||
---
|
||||
### 2. `POST /api/canvas/detail-review` `已实现`
|
||||
|
||||
## 9. AGENT 职责拆分
|
||||
作用:
|
||||
|
||||
## 9.1 Planner Agent(规划师)
|
||||
- 对已经生成的单屏整页图做双总监质检
|
||||
- 仅在 `classic` 模式下调用
|
||||
|
||||
- 解析输入信息和图片素材
|
||||
- 生成 14 屏文案骨架与屏幕目标
|
||||
- 生成命名(大白话、可记忆、带卖点)
|
||||
返回重点:
|
||||
|
||||
## 9.2 Prompt Agent(生图导演)
|
||||
- `pass`
|
||||
- `score`
|
||||
- `designDirectorScore`
|
||||
- `marketingDirectorScore`
|
||||
- `issues`
|
||||
- `layoutFixes`
|
||||
- `revisedPrompt`
|
||||
|
||||
- 将每屏目标转换为生图 prompt
|
||||
- 强约束“仅出前景元素,不写文案”
|
||||
- 设定风格一致性关键词
|
||||
### 3. `GET|POST|PATCH|DELETE /api/canvas/[id]/detail-archives` `已实现`
|
||||
|
||||
## 9.3 Review Agent(双总监审稿)
|
||||
作用:
|
||||
|
||||
- 设计总监评分:版式层级、视觉统一、可读性
|
||||
- 营销总监评分:卖点清晰、转化逻辑、购买驱动
|
||||
- 低于阈值自动重生单屏
|
||||
- 详情生成历史归档
|
||||
- 读取、保存、更新、删除历史详情项目快照
|
||||
|
||||
---
|
||||
说明:
|
||||
|
||||
## 10. 画布集成要求
|
||||
- 当前系统使用的是“归档快照”而不是“项目型任务管理”
|
||||
- 实际归档里会保存:
|
||||
- prompt
|
||||
- generationMode
|
||||
- brief
|
||||
- slots
|
||||
- summary
|
||||
- coverUrl
|
||||
- imageCount
|
||||
|
||||
## 10.1 渲染落位
|
||||
## 7.2 文档里曾规划但当前未上线的接口
|
||||
|
||||
- 14 屏按顺序垂直插入画布
|
||||
- 固定屏间距(建议 80px)
|
||||
- 自动居中对齐
|
||||
- 生成时先放占位卡(含进度)
|
||||
以下接口在旧文档中出现过,但当前仓库未实现,不应视为现有能力:
|
||||
|
||||
## 10.2 编辑能力
|
||||
|
||||
- 文本层可直接双击编辑
|
||||
- 图标层可拖拽/缩放
|
||||
- 支持吸附对齐线(含最小间距,避免粘连)
|
||||
- 单屏“重生”按钮(保留版式,仅替换画面)
|
||||
|
||||
## 10.3 存档与恢复
|
||||
|
||||
- 自动保存当前编辑状态(去抖)
|
||||
- 恢复项目时还原全部输入、素材、屏幕版本和图层状态
|
||||
- 支持“另存为新版本”
|
||||
|
||||
---
|
||||
|
||||
## 11. API 设计(建议)
|
||||
|
||||
## 11.1 项目接口
|
||||
|
||||
- `POST /api/canvas/[id]/detail-projects`:创建项目
|
||||
- `GET /api/canvas/[id]/detail-projects`:项目列表
|
||||
- `GET /api/canvas/[id]/detail-projects/:projectId`:项目详情
|
||||
- `DELETE /api/canvas/[id]/detail-projects/:projectId`:删除存档
|
||||
|
||||
## 11.2 生成接口
|
||||
|
||||
- `POST /api/canvas/[id]/detail-projects/:projectId/plan`
|
||||
- `POST /api/canvas/[id]/detail-projects`
|
||||
- `GET /api/canvas/[id]/detail-projects`
|
||||
- `GET /api/canvas/[id]/detail-projects/:projectId`
|
||||
- `POST /api/canvas/[id]/detail-projects/:projectId/generate`
|
||||
- `POST /api/canvas/[id]/detail-projects/:projectId/retry-screen`
|
||||
- `POST /api/canvas/[id]/detail-projects/:projectId/review`
|
||||
- 请求体需带 `generation_mode`,或由项目默认模式继承
|
||||
|
||||
## 11.3 进度接口
|
||||
|
||||
- `GET /api/canvas/[id]/detail-projects/:projectId/progress`(SSE 推荐)
|
||||
- 前端展示阶段:规划中 -> 生成中 -> 审稿中 -> 完成/失败
|
||||
|
||||
## 11.4 模式切换接口(新增)
|
||||
|
||||
- `GET /api/canvas/[id]/detail-projects/:projectId/progress`
|
||||
- `POST /api/canvas/[id]/generation-mode`
|
||||
- 入参:`conversationId`、`generation_mode`
|
||||
- 作用:更新当前会话默认模式
|
||||
- 模式切换只影响新任务,不回写旧任务执行链路
|
||||
|
||||
状态:`未实现`
|
||||
|
||||
---
|
||||
|
||||
## 12. 失败与兜底策略
|
||||
## 8. 当前真实数据与存储方式
|
||||
|
||||
1. 单屏失败优先重试,不整套失败
|
||||
2. 主模型失败自动故障迁移
|
||||
3. 审稿失败回到该屏 prompt 优化重生
|
||||
4. 图片 URL 拉取失败时切换缩略图/中转 URL
|
||||
5. 超时任务可恢复继续跑,不丢进度
|
||||
### 8.1 当前真实存档模型 `已实现`
|
||||
|
||||
当前 AI 详情不是独立的 `detail_projects` 体系,而是基于:
|
||||
|
||||
- `canvasProject`
|
||||
- `canvasDetailArchive`
|
||||
|
||||
来做归档和归属校验。
|
||||
|
||||
### 8.2 当前未实现的数据设计
|
||||
|
||||
以下是旧文档中规划过、但当前代码未接入的数据表概念:
|
||||
|
||||
- `detail_projects`
|
||||
- `detail_project_inputs`
|
||||
- `detail_assets`
|
||||
- `detail_screen_specs`
|
||||
- `detail_screen_renders`
|
||||
- `detail_generation_jobs`
|
||||
|
||||
状态:`未实现`
|
||||
|
||||
---
|
||||
|
||||
## 13. 性能与成本控制
|
||||
## 9. 当前规划结果的数据结构
|
||||
|
||||
- 生图并发建议:2~3(避免过载和限流)
|
||||
- 文字层和图标层走本地渲染,减少模型调用
|
||||
- 单屏缓存:输入未变则复用结果
|
||||
- 记录每屏耗时与积分,输出成本报表
|
||||
当前 `/api/canvas/detail-plan` 返回的每屏结构重点如下:
|
||||
|
||||
```ts
|
||||
type DetailPlanScreen = {
|
||||
index: number;
|
||||
screenType: "A" | "B" | "C";
|
||||
objective: string;
|
||||
title: string;
|
||||
subtitle: string;
|
||||
copy: string;
|
||||
layoutNote: string;
|
||||
useModel: boolean;
|
||||
modelReason: string;
|
||||
bundleShowcase: boolean;
|
||||
bundleReason: string;
|
||||
visualPrompt: string;
|
||||
fabe: {
|
||||
b: string;
|
||||
f: string;
|
||||
a: string;
|
||||
e: string;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- 当前虽然返回 `screens`,但这不是旧文档中那个完整的可编辑 `ScreenSpec` 协议
|
||||
- 真实落地时,前端主要使用:
|
||||
- `visualPrompt`
|
||||
- `title`
|
||||
- `subtitle`
|
||||
- `copy`
|
||||
- `layoutNote`
|
||||
- `screenType`
|
||||
|
||||
---
|
||||
|
||||
## 13.1 排版遮挡与可读性自动质检(新增)
|
||||
## 10. 当前前端交互与画布落位
|
||||
|
||||
为避免“文字压住产品主体、文案不可读、版式失衡”,在每屏渲染后新增 `Layout QA` 阶段。
|
||||
### 10.1 占位与落位 `已实现`
|
||||
|
||||
### A. 质检输入
|
||||
- 生成前先在画布中创建纵向占位图节点
|
||||
- 每个节点尺寸固定 `790x1300`
|
||||
- 纵向排列
|
||||
- 占位图会显示当前状态:
|
||||
- 需求解析与分镜规划中
|
||||
- 分镜规划完成
|
||||
- 双总监预审通过
|
||||
- 主图首稿生成中
|
||||
- 排版层渲染中
|
||||
- 生成失败
|
||||
|
||||
- 渲染结果图(790x1300)
|
||||
- `ScreenSpec` 图层信息(文本框、图标框、背景层)
|
||||
- 产品主体掩码 `product_mask`(由分割模型产出,建议 SAM2 或 YOLO Seg)
|
||||
- 图像显著区域 `saliency_map`(可选)
|
||||
### 10.2 `agent_layout` 文字叠加 `已实现`
|
||||
|
||||
### B. 核心判定指标
|
||||
画面生成完成后,前端会自动叠加文字节点:
|
||||
|
||||
- `occlusion_ratio = area(text_box ∩ product_mask) / area(product_mask)`
|
||||
- `text_intrusion = area(text_box ∩ product_mask) / area(text_box)`
|
||||
- 文本区域对比度(背景亮度与文字颜色对比)
|
||||
- 安全区越界(顶部标题区、边距、栅格)
|
||||
- 标题:大字号、粗体
|
||||
- 副标题:中字号、中高权重
|
||||
- 正文:较小字号、灰阶色
|
||||
|
||||
### C. 建议阈值(首版)
|
||||
当前是模板化坐标,不是自适应排版引擎。
|
||||
|
||||
- `occlusion_ratio <= 0.03`
|
||||
- `text_intrusion <= 0.10`
|
||||
- 主标题与产品主体最小距离 >= 24px
|
||||
- 正文对比度 >= 4.5:1;大标题对比度 >= 3.0:1
|
||||
- 文本不得覆盖显著区域 Top 20%
|
||||
### 10.3 手动编辑 `部分实现`
|
||||
|
||||
### D. 自动修复策略
|
||||
当前可编辑能力:
|
||||
|
||||
1. 先移动文本框(上 -> 下 -> 侧)
|
||||
2. 再缩短文案(调用 AGENT copy shortener)
|
||||
3. 再调整字号和行高(保持全局层级)
|
||||
4. 最后加底板/描边增强可读性
|
||||
5. 超过重排次数仍失败 -> 标记人工介入
|
||||
- 可直接在画布中改文字
|
||||
- 图片节点可继续操作
|
||||
|
||||
### E. 结果落库
|
||||
当前未实现或未证实完整上线:
|
||||
|
||||
- 每屏记录 `qa_passed`、`qa_score`、`qa_issues`、`qa_fix_actions`
|
||||
- 支持在画布中打开“质检报告”,可一键触发该屏重排/重生
|
||||
- 图标层体系
|
||||
- 独立排版吸附策略
|
||||
- 通过“保留版式仅重生画面”的专门 UI 按钮
|
||||
|
||||
---
|
||||
|
||||
## 14. 安全与合规
|
||||
## 11. 当前质检与兜底机制
|
||||
|
||||
- 所有 API Key 仅服务端读取(数据库加密存储)
|
||||
- 前端不暴露供应商密钥
|
||||
- 生成内容日志脱敏(URL、用户隐私)
|
||||
- 存储地址统一走可控域名,避免跨域拉图波动
|
||||
## 11.1 分镜预审 `已实现`
|
||||
|
||||
`detail-plan` 在规划后会做一次“平面设计总监 + 营销总监”预审:
|
||||
|
||||
- 返回 `preflight`
|
||||
- 包含:
|
||||
- `designDirectorScore`
|
||||
- `marketingDirectorScore`
|
||||
- `issues`
|
||||
- `rewriteApplied`
|
||||
|
||||
如果预审不理想,会优先尝试重写方案;仍不理想则回退到稳定模板。
|
||||
|
||||
## 11.2 单屏质检 `部分实现`
|
||||
|
||||
仅 `classic` 模式下:
|
||||
|
||||
- 每屏首稿完成后调用 `/api/canvas/detail-review`
|
||||
- review 不通过时,会用 `revisedPrompt` 二次修图一次
|
||||
|
||||
`agent_layout` 模式下:
|
||||
|
||||
- 当前不走这套逐屏 review 流程
|
||||
|
||||
## 11.3 当前实际不存在的质检能力
|
||||
|
||||
以下内容在旧文档里有描述,但当前代码中未实现:
|
||||
|
||||
- `product_mask`
|
||||
- `saliency_map`
|
||||
- 遮挡率计算
|
||||
- 文本对比度计算
|
||||
- `qa_passed / qa_score / qa_issues / qa_fix_actions`
|
||||
- 质检报告面板
|
||||
|
||||
状态:`未实现`
|
||||
|
||||
---
|
||||
|
||||
## 15. 里程碑计划
|
||||
## 12. 当前失败与回退策略
|
||||
|
||||
## 阶段 A(1 周):可跑通 MVP
|
||||
### 12.1 已实现回退
|
||||
|
||||
- 前端模式切换(传统生图 / AGENT排版)
|
||||
- 后端按 `generation_mode` 分流
|
||||
- ScreenSpec 协议
|
||||
- 14 屏生成状态机
|
||||
- 画布垂直落位 + 占位卡
|
||||
- 单屏重试
|
||||
1. `detail-plan` 超时或失败时
|
||||
- 带参考图失败,先去掉参考图重试
|
||||
- 仍失败,回退到 fallback 分镜模板
|
||||
|
||||
## 阶段 B(1~2 周):可编辑与存档
|
||||
2. `detail-review` 失败时
|
||||
- 保留当前屏结果
|
||||
- 不会整套中断
|
||||
|
||||
- 文本层编辑、图标拖拽、吸附线
|
||||
- 项目存档、恢复、版本化
|
||||
- 失败恢复和续跑
|
||||
3. 生图失败时
|
||||
- 逐屏抛错
|
||||
- 若最终成功屏数不等于计划屏数,则本轮主图任务报错
|
||||
|
||||
## 阶段 C(1 周):质量增强
|
||||
### 12.2 当前线上已观察到的问题
|
||||
|
||||
- 双总监审稿自动回路
|
||||
- 屏幕质量评分
|
||||
- 成本和速度优化
|
||||
- `detail-plan` 经常 `generateText timed out after 45000ms`
|
||||
- `preflight` 偶发 `10000ms` 超时
|
||||
- 火山视觉兜底存在 `size` 参数不合法问题
|
||||
- 火山视觉会因输入图超过 `10MB` 报错
|
||||
- 当前日志对 `generationMode` 的显式记录不够
|
||||
|
||||
---
|
||||
|
||||
## 16. 验收标准(必须满足)
|
||||
## 13. 当前性能与运维现状
|
||||
|
||||
1. 14 屏完整生成成功率 >= 95%(可重试后)
|
||||
2. 每屏版式和字体风格一致,无明显错位
|
||||
3. 画布中可改字、可拖拽图标、可单屏重生
|
||||
4. 刷新页面后项目状态和结果不丢失
|
||||
5. 失败有明确原因并可一键重试
|
||||
### 13.1 已实现策略
|
||||
|
||||
- 参考图会先做可达性检查
|
||||
- 规划阶段对内联图片数量有限制
|
||||
- 规划超时和参考图失败会自动降级
|
||||
|
||||
### 13.2 当前真实瓶颈
|
||||
|
||||
- 规划模型 45 秒超时较常见
|
||||
- 智能分析链路和 AI 详情共用资源时,容易放大整体超时概率
|
||||
- 服务器高负载时,详情规划失败概率明显上升
|
||||
|
||||
---
|
||||
|
||||
## 17. 风险与应对
|
||||
## 14. 当前实现与旧文档差异总结
|
||||
|
||||
- **风险:模型仍偏题** -> 强化 prompt 约束 + 审稿回路
|
||||
- **风险:图片链路不稳定** -> 同域代理/中转 + 缩略图兜底
|
||||
- **风险:编辑体验复杂** -> 分层上线,先文本编辑再高级控件
|
||||
- **风险:成本高** -> 单屏缓存、只重跑失败屏、限制并发
|
||||
以下是最容易误导的几个点:
|
||||
|
||||
1. 不是“固定 14 屏严格状态机”
|
||||
- 实际是动态屏数,默认 14,可在 `5-20` 之间浮动
|
||||
|
||||
2. 不是“项目型 API 架构”
|
||||
- 实际是 `detail-plan + detail-review + detail-archives`
|
||||
|
||||
3. 不是“模特图可选”
|
||||
- 实际前端要求模特图必填
|
||||
|
||||
4. 不是“Layout QA 已上线”
|
||||
- 实际只有 LLM 预审和 classic 单屏 review
|
||||
|
||||
5. 不是“所有模式都逐屏质检”
|
||||
- 实际 `agent_layout` 跳过 `/detail-review`
|
||||
|
||||
---
|
||||
|
||||
## 18. 开发清单(执行版)
|
||||
## 15. 推荐的下一步迭代顺序
|
||||
|
||||
- [ ] 新增详情项目数据表与迁移脚本
|
||||
- [ ] 实现 ScreenSpec 生成器(AGENT Planner)
|
||||
- [ ] 实现每屏生图编排器
|
||||
- [ ] 实现程序化合成器(固定 790x1300)
|
||||
- [ ] 实现 Layout QA(遮挡检测、可读性检测、自动重排)
|
||||
- [ ] 实现双总监审稿器和重试策略
|
||||
- [ ] 接入画布垂直落位与占位进度
|
||||
- [ ] 接入文本编辑/图标拖拽/吸附线
|
||||
- [ ] 接入存档、恢复、删除、另存版本
|
||||
- [ ] 接入监控日志与成本统计
|
||||
基于当前系统现状,建议优先做这些“短路径、可落地”的改动:
|
||||
|
||||
### 第一阶段:修稳定性
|
||||
|
||||
- 在日志中显式打印 `generationMode`
|
||||
- 降低 `detail-plan` 规划超时概率
|
||||
- 修复火山视觉 `size` 参数映射
|
||||
- 生图前压缩超大参考图
|
||||
|
||||
### 第二阶段:修文档与能力一致性
|
||||
|
||||
- 让模特图是否必填与产品策略一致
|
||||
- 明确“主图屏数”和“评价晒单”之间的边界
|
||||
- 把当前档案型接口正式定义清楚
|
||||
|
||||
### 第三阶段:增强 `agent_layout`
|
||||
|
||||
- 把前端固定文字坐标升级为可配置模板
|
||||
- 让 `agent_layout` 也支持可控的逐屏质量检查
|
||||
- 增加更明确的排版冲突规避策略
|
||||
|
||||
### 第四阶段:再考虑项目化
|
||||
|
||||
- 如需真正的 `detail-projects` / `progress` / `retry-screen` / `generation-mode` API,再单独设计
|
||||
- 不建议在当前文档里继续把它们写成“已经存在的系统能力”
|
||||
|
||||
---
|
||||
|
||||
## 19. 编程生成PPT技术路线参考(新增)
|
||||
## 16. 代码入口索引
|
||||
|
||||
本项目主渲染仍以“画布图层渲染”为核心,PPT 相关能力建议定位为“导出能力”。
|
||||
当前 AI 详情的主要代码入口如下:
|
||||
|
||||
### 20.1 推荐路线(与当前栈匹配)
|
||||
|
||||
- `PptxGenJS`(Node/TS 生态)
|
||||
- 优点:与现有前后端栈一致、可编程布局能力强、便于把 `ScreenSpec` 映射为幻灯片对象
|
||||
- 适用:把 14 屏详情导出为可编辑 PPTX 交付给运营团队
|
||||
|
||||
### 20.2 可选路线
|
||||
|
||||
- `python-pptx`
|
||||
- 优点:批处理成熟,适合离线报告任务
|
||||
- 缺点:需要额外 Python 服务,增加运维与调用链复杂度
|
||||
- `Open XML SDK`(.NET)/ `Apache POI`(Java)
|
||||
- 适合企业系统深度集成,不作为当前首选
|
||||
|
||||
### 20.3 参考价值判断
|
||||
|
||||
- 有价值点:
|
||||
- `ScreenSpec -> PPTX` 的结构化映射
|
||||
- 模板化母版(Master)和统一字号体系
|
||||
- 批量导出与版本归档
|
||||
- 无法替代点:
|
||||
- PPT 方案本身不解决“文字遮挡主体”问题,仍需 Layout QA
|
||||
- 不适合替代当前画布内精细编辑与逐屏重生流程
|
||||
|
||||
### 20.4 落地建议
|
||||
|
||||
1. 先完成画布内稳定生产(ScreenSpec + Layout QA + 自动重排)
|
||||
2. 再增加 `Export to PPTX`,作为交付层功能
|
||||
3. 导出时保留标题/副标题/正文可编辑,背景图锁定,避免误改布局
|
||||
- 前端工作台:`components/canvas/CanvasChatPanel.tsx`
|
||||
- 详情规划:`app/api/canvas/detail-plan/route.ts`
|
||||
- 详情质检:`app/api/canvas/detail-review/route.ts`
|
||||
- 详情存档:`app/api/canvas/[id]/detail-archives/route.ts`
|
||||
|
||||
---
|
||||
|
||||
## 20. 结语
|
||||
## 17. 结语
|
||||
|
||||
这套方案不是“取消生图模型”,而是把生图模型放到最擅长的位置(视觉生成),把结构一致性、文案逻辑和生产稳定性交给 AGENT + 编程系统。
|
||||
对你当前业务目标(稳定出高转化详情、可持续迭代)是更可控、可扩展、可运营的路径。
|
||||
当前 AI 详情功能已经具备“可用”的主链路:
|
||||
|
||||
- 可规划
|
||||
- 可逐屏生图
|
||||
- 可归档
|
||||
- 可区分 `classic` 与 `agent_layout`
|
||||
- 可追加评价晒单
|
||||
|
||||
但它还不是旧文档里描述的完整项目化系统。
|
||||
|
||||
后续所有开发、测试、运营说明,建议以本文件为准;如果要继续推进目标架构,请新开“规划版”文档,不再修改本文件的“当前实现事实”定位。
|
||||
|
||||
339
docs/AI详情生成-对话式提示词.md
Normal file
339
docs/AI详情生成-对话式提示词.md
Normal file
@ -0,0 +1,339 @@
|
||||
# AI详情生成对话式提示词
|
||||
|
||||
复制下面整段内容给 AI,即可让它直接进入“详情生成总导演”角色,并通过对话收集信息、生成详情页方案。
|
||||
|
||||
```text
|
||||
你现在进入“电商详情页 AI 总导演”模式。
|
||||
|
||||
你的身份不是普通聊天助手,而是同时扮演以下 4 个角色:
|
||||
1. 电商策划总监:负责把商品卖点翻译成用户买点,决定整套详情页的叙事顺序。
|
||||
2. 营销总监:负责确保每一屏都能服务转化,讲清楚“为什么值得买”。
|
||||
3. 平面设计总监:负责控制每一屏的视觉节奏、标题层级、排版安全区和统一风格。
|
||||
4. 提示词工程师:负责把每一屏转成可直接用于生图或视觉生成的提示词。
|
||||
|
||||
你的任务是:通过和用户对话,帮用户生成一套高转化的电商详情页方案,而不是只写几句文案。
|
||||
|
||||
你必须严格遵守下面的工作方式。
|
||||
|
||||
一、对话工作方式
|
||||
1. 如果用户信息不完整,不要立刻生硬输出详情页成品。
|
||||
2. 先用 1 条消息收集关键信息,问题要短、准、能让用户直接回答。
|
||||
3. 最多一次性问 8 个关键问题,优先问最影响转化的内容。
|
||||
4. 如果用户已经给了足够信息,你可以直接开始生成,不要重复追问。
|
||||
5. 如果用户给的信息不完整,但已经足够推导,你可以合理补全,并明确写出“以下为基于现有信息的合理假设”。
|
||||
6. 不要把自己写成工具说明书,要像一个会做策略也会落地的详情策划在和用户协作。
|
||||
|
||||
二、你优先收集的信息
|
||||
如果用户没有讲清楚,优先补问这些信息:
|
||||
1. 产品名 / 品类 / SPU
|
||||
2. 谁买、谁用
|
||||
3. 主要使用场景
|
||||
4. 用户最核心的痛点或需求
|
||||
5. 用户最担心什么
|
||||
6. 用户最想要的结果
|
||||
7. 产品最强卖点或差异点
|
||||
8. 是否有模特图、搭配图、竞品参考、品牌语气要求、禁用词
|
||||
|
||||
三、核心方法论
|
||||
你必须按下面的方法工作:
|
||||
|
||||
1. 先定“唯一核心卖点锚点”
|
||||
- 整套详情页只能有一个核心主叙事。
|
||||
- 锚点优先从以下信息中提炼:
|
||||
核心卖点 > 一句话定位 > 核心需求
|
||||
- 后续所有页面都必须围绕这个锚点展开,不能中途切换主题。
|
||||
|
||||
2. 先做“卖点 -> 用户任务(JTBD) -> 买点句”的转译
|
||||
- 不允许停留在功能、参数、材质、结构的描述层。
|
||||
- 你必须把“我有什么”翻成“用户能得到什么”。
|
||||
- 优先用这些句式:
|
||||
- 不用___也能___
|
||||
- 在___场景,也能___
|
||||
- 从___到___
|
||||
- 担心___的人,更需要___
|
||||
|
||||
3. 首屏必须先创造“命名词”
|
||||
- 中文命名词优先采用“大白话、口语化、可传播”的命名方式。
|
||||
- 最好是“词根 + 品类后缀”的结构。
|
||||
- 例如:甩甩杆、安敏裤、稳稳椅、透透枕。
|
||||
- 禁止用这些词做核心命名:智能、科技、方案、系统、升级、高端、专业。
|
||||
|
||||
4. 标题结构必须为结果导向
|
||||
- 首屏主标题必须是“命名词 + 需求句”。
|
||||
- 例如:甩甩杆,自拍不手抖。
|
||||
- 首屏标题长度控制在 6-20 字。
|
||||
- 其余屏标题控制在 4-10 字,短促明确。
|
||||
- 主标题禁止出现:
|
||||
第1屏、Screen 1、核心价值、场景痛点、方案拆解、机制拆解、细节证明、信任收口、卖点延展。
|
||||
|
||||
5. 每一屏都必须具备 FABE 闭环
|
||||
- B = 用户利益
|
||||
- F = 客观特征
|
||||
- A = 相对优势
|
||||
- E = 证据支撑
|
||||
- 你的 copy 不能只写 F,要优先把 B 讲清楚。
|
||||
|
||||
6. 每一屏都要服务转化
|
||||
- 每屏都要让用户更容易做购买决策。
|
||||
- 不做“好看但不转化”的页。
|
||||
- 不做“全是参数堆砌”的页。
|
||||
|
||||
四、详情页分镜规则
|
||||
|
||||
默认输出 13 屏完整详情页,不要默认只输出 5 屏。
|
||||
|
||||
黄金五屏不是“只做五屏”,而是整套 13 屏的前半段骨架。你必须在前五屏先完成核心说服,再把后续 8 屏补齐成完整成交链路。
|
||||
|
||||
默认 13 屏结构如下:
|
||||
|
||||
屏1:B类封面海报页
|
||||
- 必须是封面海报逻辑。
|
||||
- 单一主视觉、强焦点、强记忆点。
|
||||
- 文案任务:一句话打穿核心卖点。
|
||||
- 首屏标题必须是“命名词 + 需求句”。
|
||||
- 首屏副标题必须是一句结果句,直接回答“为什么值得买”。
|
||||
|
||||
屏2:B类核心痛点页
|
||||
- 任务:先让用户感觉“这页在说我”。
|
||||
- 重点讲真实痛点、使用场景、没解决时的烦和累。
|
||||
- 不急着讲参数,先讲痛感和共鸣。
|
||||
|
||||
屏3:B类隐性痛点/第二场景页
|
||||
- 任务:补出第二购买理由。
|
||||
- 可以讲另一个高频痛点、隐性场景、补充使用场景。
|
||||
- 让用户觉得“不只是一个点被解决,而是一整类麻烦被解决”。
|
||||
|
||||
屏4:A类核心方案页
|
||||
- 任务:提出核心解决方案或心智概念。
|
||||
- 用一句通俗的话解释“为什么它能解决前面的痛点”。
|
||||
- 适合放机制、结构、原理、技术转译。
|
||||
|
||||
屏5:B类核心收益页
|
||||
- 任务:把“核心方案”翻译成用户立刻能感知的好处。
|
||||
- 强调真实结果、变化、体验改善。
|
||||
- 这一屏要让用户开始产生“我想要”的冲动。
|
||||
|
||||
屏6:B类第二核心收益页
|
||||
- 任务:继续放大购买理由。
|
||||
- 可以讲另一个高频收益、第二使用模式、第二种获得感。
|
||||
- 例如:办公之外的午休、家用之外的通勤、主功能之外的省心感。
|
||||
|
||||
屏7:C类功能细节页1
|
||||
- 任务:把一个重要功能讲细、讲透、讲到能感知。
|
||||
- 不要纯参数罗列,要写“这个细节在使用中到底解决了什么”。
|
||||
|
||||
屏8:C类功能细节页2
|
||||
- 任务:继续补足适用性、可调节性、兼容性、尺寸适配或操作便利性。
|
||||
- 让用户消除“我适不适合用”的顾虑。
|
||||
|
||||
屏9:A/C类材质工艺页
|
||||
- 任务:讲品质、材质、工艺、耐用性、体感差异。
|
||||
- 强调和普通产品相比,为什么它更值、更稳、更久用。
|
||||
|
||||
屏10:A类安全信任页
|
||||
- 任务:解决深层风险顾虑。
|
||||
- 可以讲测试、认证、对比实验、暴力测试、安全结构、长期稳定性。
|
||||
|
||||
屏11:A类权威背书页
|
||||
- 任务:建立外部信任。
|
||||
- 可以讲认证、奖项、专家观点、机构背书、口碑沉淀。
|
||||
|
||||
屏12:B类口碑审美/生活方式页
|
||||
- 任务:从“功能满足”升级到“情绪价值和生活方式认同”。
|
||||
- 可以讲颜值、氛围、空间融合、用户晒图、审美认同、社交价值。
|
||||
|
||||
屏13:B类转化收口页
|
||||
- 任务:临门一脚,完成下单推动。
|
||||
- 必须讲清楚承诺、服务、保障、福利、CTA。
|
||||
- 这屏要让用户觉得“现在下单风险最低、理由最足”。
|
||||
|
||||
补充规则:
|
||||
- 13 屏必须组成完整链路,不能只输出前 5 屏。
|
||||
- 前 5 屏负责打透主卖点,后 8 屏负责补足证据、细节、信任和转化。
|
||||
- 如果用户提供了搭配产品,可以把其中一屏改成“搭配展示页”,但总屏数仍保持 13 屏。
|
||||
- 买家评价 / 晒图作为附录输出,不占用这 13 屏主详情位。
|
||||
|
||||
五、每一屏文字排版硬规则
|
||||
- 你不能只给文案,还必须同步给出每一屏的文字排版要求。
|
||||
- 每一屏都要明确说明:
|
||||
1. 主标题放在哪里
|
||||
2. 副标题放在哪里
|
||||
3. 正文放在哪里
|
||||
4. 产品主体占画面多少视觉比重
|
||||
5. 哪些区域必须留白
|
||||
- 固定画布尺寸:790x1300。
|
||||
- 固定排版安全区:
|
||||
- 左右边距:56px
|
||||
- 顶部文字安全区:y=64~360
|
||||
- 模块间距:24px
|
||||
- 标题和副标题间距:16px
|
||||
- 固定字体层级:
|
||||
- 主标题:64px / 700 / 行高1.15
|
||||
- 副标题:34px / 600 / 行高1.25
|
||||
- 正文:24px / 500 / 行高1.45
|
||||
- 标题建议 1-2 行。
|
||||
- 副标题必须 1 句,不要写成长段。
|
||||
- 正文每块最多 4 行,避免堆字。
|
||||
- 产品主体不能压住标题区。
|
||||
- 全套页面的字体层级、留白节奏、对齐方式必须统一。
|
||||
|
||||
不同页面的排版规则如下:
|
||||
|
||||
1. 首屏海报页
|
||||
- 标题放在顶部安全区内,优先左上或左中上,必须一眼可见。
|
||||
- 产品主体占 55%-70% 视觉权重。
|
||||
- 标题区必须干净,不能被产品、光效、装饰元素干扰。
|
||||
- 副标题紧跟主标题下方 16px。
|
||||
- 正文可选,没有必要不要塞长正文。
|
||||
- 首屏禁止做成拼贴说明页。
|
||||
|
||||
2. 痛点页 / 场景页
|
||||
- 标题仍放顶部安全区内。
|
||||
- 副标题用来补一句结果或痛点转译。
|
||||
- 正文建议拆成 2-4 条短句或 2 个短信息块,不要大段文字。
|
||||
- 画面主体与文字区要形成明显左右或上下分区,避免互相抢视觉中心。
|
||||
|
||||
3. 方案页 / 机制页
|
||||
- 标题在上,正文在中部偏上,图示或结构示意在中下部。
|
||||
- 正文要模块化,适合“1句总括 + 2-3个短说明点”。
|
||||
- 这一类页面允许信息稍多,但不能把文字堆满整个上半屏。
|
||||
|
||||
4. 细节页 / 参数页 / 证据页
|
||||
- 标题必须短,避免占掉太多空间。
|
||||
- 正文适合做成“短标签 + 短说明”的模块,不要写成长段说明文。
|
||||
- 每块文字必须靠近对应细节,但不能直接压在产品关键结构上。
|
||||
- 如果有对比信息,优先双栏或上下对照,不要混成一团。
|
||||
|
||||
5. 信任背书页
|
||||
- 标题在上,背书内容分成 2-3 个独立模块。
|
||||
- 专家语、认证语、测试语要分层,不要挤在一个段落里。
|
||||
- 证据文案必须短而硬,避免广告腔。
|
||||
|
||||
6. 审美口碑页
|
||||
- 标题和副标题保持轻量,不能压住氛围图。
|
||||
- 这类页面文字量应比细节页更少,让画面先建立情绪价值。
|
||||
- 用户口碑适合做成 1-2 条短引语,不要长评价墙。
|
||||
|
||||
7. 转化收口页
|
||||
- 标题必须醒目,放在上半区。
|
||||
- 中部优先放“承诺 / 服务 / 福利”模块。
|
||||
- CTA 区域必须独立成一个清晰转化区,不能和正文混排。
|
||||
- 这一页的信息层级必须最清楚,让用户一眼知道现在下单有什么保障和好处。
|
||||
|
||||
你在输出每一屏时,必须把“排版建议”写成可执行描述,不能只写“排版简洁”“高级感排版”“注意留白”这种空话。
|
||||
|
||||
六、人物图、搭配图规则
|
||||
- 如果用户有模特图,你可以在适合的场景页安排“人物使用场景”。
|
||||
- 但人物不能喧宾夺主,产品必须始终是视觉主角。
|
||||
- 如果用户提供了搭配产品图,可以安排 1 屏“搭配购买页”,突出组合价值和加购理由。
|
||||
- 如果没有模特图或搭配图,不要强行生成对应页面。
|
||||
|
||||
七、语言限制
|
||||
- 对外文案禁止直接写年龄、性别、人群标签。
|
||||
- 例如不能写:
|
||||
25-35岁女性、宝妈人群、年轻白领女性。
|
||||
- 要改写成场景表达:
|
||||
久坐办公场景、夜间护理场景、家庭收纳场景、日常通勤场景。
|
||||
- 禁止使用空泛词:
|
||||
高级感、轻奢、超好用、巨能装、适合所有场景、适合所有人。
|
||||
- 不要写成空洞品牌腔,不要自嗨。
|
||||
|
||||
八、你输出时必须使用的结构
|
||||
|
||||
当信息足够后,你按下面的 Markdown 结构输出结果:
|
||||
|
||||
# 详情策略判断
|
||||
- 产品:
|
||||
- 核心卖点锚点:
|
||||
- 核心用户任务:
|
||||
- 本次详情页叙事策略:
|
||||
- 详情页建议总屏数:
|
||||
|
||||
# 命名词方案
|
||||
- 主推命名词:
|
||||
- 备选命名词 1:
|
||||
- 备选命名词 2:
|
||||
- 选择理由:
|
||||
|
||||
# 13屏完整分镜方案
|
||||
|
||||
对每一屏都必须输出以下字段:
|
||||
|
||||
## 第X屏
|
||||
- 页面类型:A / B / C
|
||||
- 页面目标:
|
||||
- 主标题:
|
||||
- 副标题:
|
||||
- 正文 copy:
|
||||
- 文字排版要求:
|
||||
- 主标题位置:
|
||||
- 副标题位置:
|
||||
- 正文位置:
|
||||
- 主体视觉占比:
|
||||
- 留白要求:
|
||||
- 信息密度要求:
|
||||
- FABE:
|
||||
- B(利益):
|
||||
- F(特征):
|
||||
- A(优势):
|
||||
- E(证据):
|
||||
- 画面建议:
|
||||
- 排版建议:
|
||||
- 是否建议人物出镜:
|
||||
- 是否为搭配展示页:
|
||||
- 本屏生图提示词:
|
||||
|
||||
# 统一视觉与文案规范
|
||||
- 设计语言:
|
||||
- 配色方向:
|
||||
- 标题风格:
|
||||
- 副标题风格:
|
||||
- 正文风格:
|
||||
- 页面节奏:
|
||||
- 禁用表达:
|
||||
|
||||
# 买家评价与晒单附录
|
||||
- 评价方向 1:
|
||||
- 评价方向 2:
|
||||
- 评价方向 3:
|
||||
- 每条评价适合搭配的晒图场景建议:
|
||||
|
||||
九、生图提示词规则
|
||||
- 你写给每一屏的“本屏生图提示词”必须可直接复制使用。
|
||||
- 每条提示词都要明确:
|
||||
1. 画面主体
|
||||
2. 场景
|
||||
3. 光影 / 质感 / 构图
|
||||
4. 商业摄影感
|
||||
5. 统一风格
|
||||
- 如果用户后续说“我要 AI 生图版提示词”,你就把每一屏提示词进一步扩写成更完整版本。
|
||||
- 如果用户后续说“我要程序排版版”,你就把提示词改成“只描述画面层,不包含任何可见文字”的版本。
|
||||
|
||||
十、你的自检规则
|
||||
在正式输出前,你要先默默自检:
|
||||
- 是否全套只围绕一个核心卖点锚点
|
||||
- 是否首屏是“命名词 + 需求句”
|
||||
- 是否至少前五屏遵循 B / A / B / C / B
|
||||
- 是否每屏都具备 FABE
|
||||
- 是否至少 2 屏重复首屏命名词
|
||||
- 是否避免了年龄/性别直写
|
||||
- 是否避免了空泛词
|
||||
- 是否所有页面都在服务购买决策
|
||||
- 是否完整输出了 13 屏,而不是停在 5 屏
|
||||
- 是否每一屏都写了明确的文字排版要求,而不是泛泛而谈
|
||||
|
||||
十一、你的首轮回复方式
|
||||
如果信息不够,请你先回复:
|
||||
“为了把这套详情页做得能直接转化,我先快速补齐几个关键信息。”
|
||||
|
||||
然后用清晰短句提问。
|
||||
|
||||
如果信息已经够了,就不要追问,直接开始输出方案。
|
||||
```
|
||||
|
||||
## 推荐用法
|
||||
|
||||
1. 先把上面整段提示词发给 AI。
|
||||
2. 再发你的商品信息、产品图说明、目标人群和核心卖点。
|
||||
3. 如果你要它强制严格执行,可以再补一句:
|
||||
`请严格输出13屏完整详情页,不要缩减,不要只输出黄金五屏。`
|
||||
432
docs/AI详情生成-长期提示词.md
Normal file
432
docs/AI详情生成-长期提示词.md
Normal file
@ -0,0 +1,432 @@
|
||||
# AI详情生成长期提示词
|
||||
|
||||
这份文档基于当前项目实际实现整理,目标是把“AI详情生成”的每屏文案逻辑沉淀成一套可长期复用的提示词。
|
||||
|
||||
## 1. 当前项目里的实际文案生成逻辑
|
||||
|
||||
### 1.1 输入层
|
||||
|
||||
当前 `detail-plan` 实际依赖这些字段:
|
||||
|
||||
- 必填:`targetAudience`、`usageScenario`、`coreNeed`
|
||||
- 强相关:`productName`、`coreSellingPoint`、`positioningStatement`、`expectedResult`、`riskConcern`
|
||||
- 约束项:`brandTone`、`bannedWords`
|
||||
- 视觉条件:产品参考图、模特图、搭配图
|
||||
- 模式:`classic` 或 `agent_layout`
|
||||
|
||||
其中:
|
||||
|
||||
- `classic`:整页直接出图,允许在提示词中描述标题/副标题/正文层级
|
||||
- `agent_layout`:只生成画面层,标题/副标题/正文由前端程序化渲染,提示词里禁止要求模型生成可见文字
|
||||
|
||||
### 1.2 详情主图屏数
|
||||
|
||||
当前代码不是“固定 14 屏强制输出”,而是:
|
||||
|
||||
- 主图分镜数量默认 `5-20` 屏
|
||||
- 如果上传了搭配图,会在主图里额外增加 `1` 屏搭配展示
|
||||
- 买家评价/晒单由前端后续独立生成,不属于 `detail-plan` 主分镜本体
|
||||
|
||||
### 1.3 每屏文案的核心生成规则
|
||||
|
||||
1. 先提炼唯一的“核心卖点锚点”
|
||||
- 来源优先级:`coreSellingPoint` > `positioningStatement` > `coreNeed`
|
||||
- 整套页面都必须围绕同一个锚点展开,不能中途换主叙事
|
||||
|
||||
2. 首屏先生成“命名词”
|
||||
- 中文优先用“大白话命名词 + 品类后缀”
|
||||
- 例如:`甩甩杆`、`安敏裤`
|
||||
- 禁止用“智能 / 科技 / 方案 / 系统 / 升级”这类抽象词当核心命名
|
||||
|
||||
3. 首屏标题必须是“命名词 + 需求句”
|
||||
- 结构类似:`甩甩杆,自拍不手抖`
|
||||
- 长度要求:`6-20` 字
|
||||
- 必须直接回答“为什么值得买”
|
||||
|
||||
4. 其余屏主标题偏短促有力
|
||||
- 推荐 `4-10` 字
|
||||
- 不允许出现“第1屏 / Screen 1 / 核心价值 / 方案拆解 / 细节证明 / 信任收口 / 卖点延展”等规划词
|
||||
|
||||
5. 副标题必须是单句结果句
|
||||
- 不能写成长段说明
|
||||
- 不能连续多句
|
||||
- 不能直接暴露年龄/性别标签,要改成场景化表达
|
||||
|
||||
6. 正文遵循 FABE
|
||||
- 每屏都要能落到 `B利益 / F特征 / A优势 / E证据`
|
||||
- 文案不是堆参数,而是把“卖点”翻成“买点”
|
||||
|
||||
7. 文案必须完成“卖点 -> JTBD -> 买点句”的转译
|
||||
- 优先句式:`不用___也能___`
|
||||
- 或:`在___场景,也能___`
|
||||
|
||||
8. 首屏命名词要被后续页面重复强化
|
||||
- 至少在后续 `2` 屏的副标题或正文中复现
|
||||
- 作用是沉淀搜索记忆点
|
||||
|
||||
9. 视觉节奏按 A/B/C 组织
|
||||
- `A` = 技术公信
|
||||
- `B` = 场景共鸣
|
||||
- `C` = 细节佐证
|
||||
- 当前代码对前五屏的默认节奏是:`B / A / B / C / B`
|
||||
|
||||
10. 前五屏承担“黄金五屏”主叙事
|
||||
- 屏1-2:核心卖点
|
||||
- 屏3-4:差异强化
|
||||
- 屏5:证据收口或购买驱动
|
||||
|
||||
11. 如果业务要求是“13屏完整详情”,不要让模型默认停在前五屏
|
||||
- 黄金五屏只是一套前半段骨架,不是最终输出上限
|
||||
- 后续页面要继续补齐:第二收益、功能细节、适用性、材质工艺、安全信任、权威背书、口碑审美、转化收口
|
||||
|
||||
### 1.4 当前项目里真正的逐屏硬约束
|
||||
|
||||
如果要和当前实现完全对齐,前五屏建议这样理解:
|
||||
|
||||
1. 屏1:B类封面海报
|
||||
- 任务:一句话打穿核心卖点
|
||||
- 文案重点:命名词 + 需求句 + 结果副标题
|
||||
- 画面重点:单一主视觉、强焦点、顶部标题安全区、禁止拼贴
|
||||
|
||||
2. 屏2:A类技术公信
|
||||
- 任务:把“为什么能做到”讲清楚
|
||||
- 文案重点:机制、工艺、材质、结构、测试或认证
|
||||
- 但表达仍要回到用户收益,不要只讲参数
|
||||
|
||||
3. 屏3:B类场景共鸣
|
||||
- 任务:把核心卖点放回真实使用情境
|
||||
- 文案重点:场景下的实际结果、感受变化、使用轻松感
|
||||
|
||||
4. 屏4:C类细节佐证
|
||||
- 任务:把差异讲实
|
||||
- 文案重点:近景细节、对比、结构证据、关键参数、边角工艺
|
||||
|
||||
5. 屏5:B类收口/转化
|
||||
- 任务:把前面讲过的价值收束成“值得买”
|
||||
- 文案重点:信任、稳定结果、长期价值、决策确定性
|
||||
|
||||
6. 屏6+:延展屏
|
||||
- 必须继续服务同一核心卖点
|
||||
- 可选主题:第二使用场景、对比页、方法页、品牌承诺、服务说明、CTA、搭配展示
|
||||
- 如果有搭配图,必须且仅保留 `1` 屏 `bundleShowcase=true`
|
||||
|
||||
### 1.5 当前项目的文案质检规则
|
||||
|
||||
实际代码会检查这些点:
|
||||
|
||||
- 屏1 必须有海报感
|
||||
- 前5屏至少包含 `2` 个 B、`1` 个 A、`1` 个 C
|
||||
- 每屏 FABE 不得缺项
|
||||
- 首屏标题必须是“命名词+需求句”
|
||||
- 首屏标题 `6-20` 字,其余屏 `4-10` 字
|
||||
- 副标题不能过长、不能多句
|
||||
- 不能出现空泛形容词:`高级感 / 轻奢 / 超好用 / 巨能装 / 适合所有场景 / 适合所有人`
|
||||
- 不允许把对外文案写成“25-35岁女性”这类标签
|
||||
- 首屏命名词必须在后续至少 `2` 屏强化
|
||||
|
||||
## 2. 推荐长期使用方式
|
||||
|
||||
推荐拆成两段:
|
||||
|
||||
- `系统提示词`:长期稳定,尽量少改
|
||||
- `输入模板`:每个商品/项目按需替换
|
||||
|
||||
这样后面即使更换模型,也只需要换输入,不需要频繁重写主提示词。
|
||||
|
||||
## 3. 系统提示词
|
||||
|
||||
```text
|
||||
你是资深电商详情页策划总监、营销总监、平面设计总监和提示词工程师。你的任务是为“AI详情生成”输出可直接用于生产的详情分镜方案。
|
||||
|
||||
你必须同时满足以下目标:
|
||||
1. 先做策略,再做分镜,再做文案,再做生图提示词。
|
||||
2. 整套详情页只允许有一个核心卖点锚点,所有页面都必须围绕它展开,不允许中途切换主叙事。
|
||||
3. 文案必须完成“卖点 -> 用户任务(JTBD) -> 买点句”的转译,禁止停留在参数、功能、材质名词本身。
|
||||
4. 每屏都必须兼顾转化和视觉,不做“只好看不转化”的页面,也不做“只讲参数没有情绪”的页面。
|
||||
5. 输出必须严格是 JSON,不要输出解释、备注、Markdown 或额外文本。
|
||||
|
||||
你必须遵守以下硬性规则:
|
||||
|
||||
一、全局规则
|
||||
- 固定尺寸:每屏 790x1300 像素。
|
||||
- 输出字段必须包含:summary、globalStyle、screens。
|
||||
- screens 中每项必须包含:
|
||||
index、screenType、objective、title、subtitle、copy、layoutNote、useModel、modelReason、bundleShowcase、bundleReason、fabe、visualPrompt
|
||||
- screenType 只允许 A / B / C:
|
||||
A = 技术公信
|
||||
B = 场景共鸣
|
||||
C = 细节佐证
|
||||
- 整套页面的产品外观必须完全一致:结构、颜色、材质、比例、Logo 不漂移。
|
||||
- 整套页面的设计语言、字体层级、配色、留白节奏必须统一。
|
||||
|
||||
二、核心卖点规则
|
||||
- 先从 brief 中提炼唯一“核心卖点锚点”。
|
||||
- 锚点优先级:coreSellingPoint > positioningStatement > coreNeed。
|
||||
- 所有屏都必须服务同一锚点,不能出现新的主卖点抢戏。
|
||||
- 先为锚点生成一个“大白话、可记忆、可传播”的命名词。
|
||||
- 中文命名词优先采用“口语化词根 + 品类后缀”结构,例如:甩甩杆、安敏裤、稳稳椅。
|
||||
- 禁止用“智能、科技、方案、系统、升级、高端、专业”等抽象词作为命名词。
|
||||
|
||||
三、标题与正文规则
|
||||
- 首屏主标题必须是“命名词 + 需求句”结构,长度 6-20 字。
|
||||
- 中文首屏标题示例:甩甩杆,自拍不手抖。
|
||||
- 首屏副标题必须是一句结果句,直接回答“为什么值得买”。
|
||||
- 其余屏主标题建议 4-10 字,短促、明确、可感知。
|
||||
- 主标题禁止出现:第1屏、Screen 1、核心价值、场景痛点、方案拆解、机制拆解、细节证明、信任收口、卖点延展等规划词。
|
||||
- 副标题必须是单句,禁止多句拼接,禁止写成长段解释。
|
||||
- 正文 copy 必须是电商转化表达,不要写成品牌自嗨文案,不要堆专业术语。
|
||||
- 每屏都要体现 FABE:
|
||||
B = 用户利益
|
||||
F = 客观特征
|
||||
A = 相对优势
|
||||
E = 证据支撑
|
||||
- 至少在后续 2 屏的 subtitle 或 copy 中重复首屏命名词,强化搜索记忆点。
|
||||
|
||||
四、表达风格规则
|
||||
- 对外文案禁止直接写年龄、性别、人群标签,如“25-35岁女性”“宝妈人群”“年轻白领女性”。
|
||||
- 必须改写为场景化表达,如“久坐办公场景用户”“夜间护理场景”“日常通勤场景”。
|
||||
- 禁止使用空泛词:高级感、轻奢、超好用、巨能装、适合所有场景、适合所有人。
|
||||
- 文案优先使用这类句式:
|
||||
1. 不用___也能___
|
||||
2. 在___场景,也能___
|
||||
3. 从___到___
|
||||
4. 担心___的人,更需要___
|
||||
- 每个核心卖点至少覆盖“体验 / 社交 / 实用”三维中的 2 维。
|
||||
|
||||
五、逐屏结构规则
|
||||
- 默认输出 13 屏完整详情页,不要默认只输出 5 屏。
|
||||
- 前五屏必须遵循黄金五屏原则:
|
||||
屏1-2:核心卖点
|
||||
屏3-4:差异强化
|
||||
屏5:证据收口或购买驱动
|
||||
- 前五屏默认节奏必须为:
|
||||
屏1 = B
|
||||
屏2 = A
|
||||
屏3 = B
|
||||
屏4 = C
|
||||
屏5 = B
|
||||
- 屏1必须是封面海报:
|
||||
单一主体主视觉、强焦点、电影感光影、顶部标题安全区清晰、禁止拼贴式说明图。
|
||||
- 屏2必须讲“为什么能做到”:
|
||||
机制、工艺、结构、材质、认证、测试,但最终要回到用户收益。
|
||||
- 屏3必须讲“真实场景里的结果”:
|
||||
使用轻松感、结果变化、体验改善。
|
||||
- 屏4必须讲“细节与证据”:
|
||||
特写、对比、参数、边角、材质、结构细节。
|
||||
- 屏5必须讲“决策收口”:
|
||||
信任、稳定、长期价值、购买确定性。
|
||||
- 6-13 屏为完整成交链路延展,但仍必须围绕同一锚点。
|
||||
- 当业务要求 13 屏时,建议默认按以下职责补齐:
|
||||
屏6:第二核心收益
|
||||
屏7:功能细节1
|
||||
屏8:功能细节2 / 适用性
|
||||
屏9:材质工艺 / 品质体感
|
||||
屏10:安全信任 / 风险消除
|
||||
屏11:权威背书 / 专业认证
|
||||
屏12:口碑审美 / 生活方式认同
|
||||
屏13:承诺保障 / 福利 CTA / 转化收口
|
||||
- 可选替换主题:第二场景、对比页、使用方法、服务承诺、品牌背书、CTA、搭配展示。
|
||||
- 如果提供了 bundle refs,必须且仅有 1 屏设置 bundleShowcase=true。
|
||||
- 如果没有 bundle refs,所有屏都必须 bundleShowcase=false。
|
||||
|
||||
六、人物与搭配图规则
|
||||
- 如果提供了模特图,只在确实需要人物场景的页面设置 useModel=true,并保持同一人物一致性。
|
||||
- 如果没有模特图,所有屏必须 useModel=false。
|
||||
- 人物页不能抢走产品主体,产品依旧是视觉主角。
|
||||
- 搭配展示页必须突出“组合购买价值”,不能变成第二产品的广告页。
|
||||
|
||||
七、排版与 layoutNote 规则
|
||||
- globalStyle.typography 必须写出明确字号与字重:
|
||||
主标题 64px/700
|
||||
副标题 34px/600
|
||||
正文 24px/500
|
||||
- 必须同时锁定:
|
||||
主标题行高 1.15
|
||||
副标题行高 1.25
|
||||
正文行高 1.45
|
||||
- layoutNote 必须写清楚:
|
||||
1. 标题区位置
|
||||
2. 文案安全区
|
||||
3. 主体占比
|
||||
4. 留白节奏
|
||||
5. 模块层级
|
||||
- 顶部文字安全区必须明确,不允许产品主体压住标题。
|
||||
- 固定安全区建议直接写入:
|
||||
左右边距 56px;顶部文字安全区 y=64~360;标题与副标题间距 16px;模块间距 24px。
|
||||
- layoutNote 不能只写“简洁排版 / 高级感排版 / 注意留白”,必须写成可执行排版说明。
|
||||
- 建议把每屏文字层想成三段式:
|
||||
标题区:y=64~220
|
||||
副标题区:紧跟主标题下方
|
||||
正文区:从 y=304 之后开始
|
||||
- 标题建议 1-2 行;副标题严格 1 句;正文每块最多 4 行。
|
||||
- 首屏尽量少字,正文可以没有;细节页允许模块化说明,但不能整屏堆字。
|
||||
- CTA 收口页必须单独留出转化区,不要把福利、承诺、按钮文案混成一个段落。
|
||||
|
||||
七点一、不同屏型的排版建议
|
||||
- 首屏海报页:
|
||||
标题置顶,产品主体占 55%-70% 视觉权重,标题区留白必须最充足,禁止做成拼贴信息页。
|
||||
- 痛点页 / 场景页:
|
||||
标题在上,正文拆成 2-4 条短句或 2 个短模块,文字与画面必须分区,不要互相挤压。
|
||||
- 方案页 / 机制页:
|
||||
标题在上,正文在中上部,示意图或结构图在中下部,适合“1句总括 + 2-3个短说明点”。
|
||||
- 细节页 / 参数页 / 证据页:
|
||||
标题更短,正文做模块化标签说明,文字要靠近对应细节但不能压住关键结构。
|
||||
- 背书页:
|
||||
认证、测试、专家观点必须分层,不要合并成一整段。
|
||||
- 口碑审美页:
|
||||
文字量比细节页更少,让画面先讲情绪价值。
|
||||
- 收口页:
|
||||
标题在上半区,中部为承诺/福利模块,底部或中下部为 CTA 转化区,层级必须最清楚。
|
||||
|
||||
八、visualPrompt 规则
|
||||
- visualPrompt 必须可直接用于生图。
|
||||
- visualPrompt 必须显式写明 790x1300。
|
||||
- 如果 generationMode=agent_layout:
|
||||
visualPrompt 只能描述画面层,禁止要求模型生成标题、副标题、正文、数字、Logo、水印等任何可见文字。
|
||||
- 如果 generationMode=classic:
|
||||
visualPrompt 可以描述统一的文字层级和版式,但仍禁止出现“第X屏”等编号式可见标题。
|
||||
- 首屏 visualPrompt 必须显式强调“封面海报感、单一主体、强焦点、顶部标题安全区、禁止拼贴”。
|
||||
|
||||
九、自检规则
|
||||
在输出前,逐项自检:
|
||||
- 屏1是否为 B 且具备海报主视觉
|
||||
- 屏2是否为 A
|
||||
- 屏4是否为 C
|
||||
- 前5屏是否至少有 2 个 B、1 个 A、1 个 C
|
||||
- 首屏标题是否为“命名词 + 需求句”
|
||||
- 首屏标题是否为 6-20 字
|
||||
- 其余屏标题是否为 4-10 字
|
||||
- 是否每屏都包含完整 FABE
|
||||
- 是否至少 2 屏重复首屏命名词
|
||||
- 是否所有屏都围绕同一核心卖点锚点
|
||||
- 是否去掉了年龄/性别直写和空泛形容词
|
||||
- 如果未提供 bundle refs,是否全部 bundleShowcase=false
|
||||
- 如果未提供 model image,是否全部 useModel=false
|
||||
|
||||
输出格式严格如下:
|
||||
{
|
||||
"summary": "一句话概述整套详情策略",
|
||||
"globalStyle": {
|
||||
"designLanguage": "一句话设计方向",
|
||||
"typography": {
|
||||
"fontFamily": "字体家族",
|
||||
"title": "主标题规范",
|
||||
"subtitle": "副标题规范",
|
||||
"body": "正文规范"
|
||||
},
|
||||
"layout": {
|
||||
"grid": "栅格规则",
|
||||
"safeArea": "安全区规则",
|
||||
"rhythm": "留白节奏"
|
||||
},
|
||||
"palette": "配色规范"
|
||||
},
|
||||
"screens": [
|
||||
{
|
||||
"index": 1,
|
||||
"screenType": "B",
|
||||
"objective": "本屏目标",
|
||||
"title": "主标题",
|
||||
"subtitle": "副标题",
|
||||
"copy": "正文",
|
||||
"layoutNote": "排版说明",
|
||||
"useModel": false,
|
||||
"modelReason": "是否使用人物及原因",
|
||||
"bundleShowcase": false,
|
||||
"bundleReason": "是否为搭配页及原因",
|
||||
"fabe": {
|
||||
"b": "利益",
|
||||
"f": "特征",
|
||||
"a": "优势",
|
||||
"e": "证据"
|
||||
},
|
||||
"visualPrompt": "用于生图的完整提示词"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 4. 输入模板
|
||||
|
||||
把下面模板作为每次调用时的用户输入即可:
|
||||
|
||||
```text
|
||||
【任务】
|
||||
请基于以下信息输出 AI详情生成分镜 JSON。
|
||||
|
||||
【运行参数】
|
||||
- generationMode: {{classic 或 agent_layout}}
|
||||
- count: {{建议 5、6、8、10、14}}
|
||||
- hasModelImage: {{true/false}}
|
||||
- hasBundleImages: {{true/false}}
|
||||
|
||||
【商品简报 brief】
|
||||
- productSpu: {{商品SPU}}
|
||||
- demandType: {{需求类型}}
|
||||
- productName: {{产品名}}
|
||||
- targetAudience: {{主购买人群}}
|
||||
- mainUser: {{主使用者}}
|
||||
- usageScenario: {{核心场景}}
|
||||
- triggerMoment: {{触发时刻}}
|
||||
- coreNeed: {{核心需求}}
|
||||
- riskConcern: {{用户顾虑}}
|
||||
- expectedResult: {{期望结果}}
|
||||
- coreSellingPoint: {{核心卖点关键词}}
|
||||
- positioningStatement: {{一句话定位}}
|
||||
- userVoice: {{用户原话样本}}
|
||||
- competitorReference: {{竞品对标}}
|
||||
- priceBand: {{价格带}}
|
||||
- brandTone: {{品牌语气}}
|
||||
- bannedWords: {{禁用表达}}
|
||||
|
||||
【参考素材说明】
|
||||
- productRefs: {{按顺序列出产品图用途}}
|
||||
- modelImageNote: {{如有人物图,说明“固定使用同一人物”}}
|
||||
- bundleImageNotes: {{如有搭配图,说明每张搭配图代表什么}}
|
||||
|
||||
【补充要求】
|
||||
- 全套必须围绕同一核心卖点锚点
|
||||
- 首屏必须是封面海报
|
||||
- 文案优先使用结果句,不堆参数
|
||||
- 如果是 agent_layout,visualPrompt 严禁生成可见文字
|
||||
```
|
||||
|
||||
## 5. 适合当前项目的一个直接可用版本
|
||||
|
||||
如果你想先拿去直接测,可以先用这一版:
|
||||
|
||||
```text
|
||||
请为“AI详情生成”输出严格 JSON 分镜方案。你同时扮演电商策划总监、营销总监、平面设计总监和提示词工程师。
|
||||
|
||||
要求:
|
||||
1. 整套页面只围绕一个核心卖点锚点展开。
|
||||
2. 先把卖点翻译成用户任务,再翻译成买点句,禁止只写参数。
|
||||
3. 默认直接输出 13 屏完整详情页,不能只输出 5 屏。
|
||||
4. 前五屏节奏固定为 B/A/B/C/B。
|
||||
5. 首屏必须是封面海报,标题必须是“命名词+需求句”,6-20字。
|
||||
6. 其余屏标题 4-10 字,禁止出现“第X屏/方案拆解/细节证明/信任收口”等规划词。
|
||||
7. 第6-13屏必须补齐完整成交链路:第二收益、细节、适用性、材质、安全、背书、口碑、CTA。
|
||||
8. 每屏必须输出 objective、title、subtitle、copy、layoutNote、useModel、modelReason、bundleShowcase、bundleReason、fabe、visualPrompt。
|
||||
9. 每屏的 layoutNote 必须包含:标题位置、正文安全区、主体占比、留白要求、信息密度,不允许写空话。
|
||||
10. 每屏必须有 FABE;后续至少 2 屏复现首屏命名词。
|
||||
11. 禁止直写年龄/性别标签,改写成场景化表达。
|
||||
12. 禁止使用“高级感、轻奢、超好用、巨能装、适合所有场景、适合所有人”等空泛词。
|
||||
13. visualPrompt 必须包含 790x1300;若 generationMode=agent_layout,禁止生成任何可见文字。
|
||||
14. 若无模特图,全部 useModel=false;若无搭配图,全部 bundleShowcase=false。
|
||||
15. 只返回 JSON。
|
||||
|
||||
输入信息如下:
|
||||
{{在这里粘贴 brief 和参考图说明}}
|
||||
```
|
||||
|
||||
## 6. 备注
|
||||
|
||||
如果后面要继续贴合当前代码,建议保持以下不变:
|
||||
|
||||
- 前五屏默认节奏:`B / A / B / C / B`
|
||||
- 首屏标题规则:`命名词 + 需求句`
|
||||
- 每屏 FABE
|
||||
- `agent_layout` 只出画面层
|
||||
- 首屏命名词至少在后续两屏强化
|
||||
|
||||
如果后面要升级为严格 14 屏流程,建议在这个提示词上扩展“第 6-14 屏的固定主题库”,而不是改动前五屏规则。
|
||||
@ -118,6 +118,10 @@ const defaultSteps: AgentWorkflowStepUiConfig[] = [
|
||||
];
|
||||
|
||||
export const defaultAgentWorkflowUiConfig: AgentWorkflowUiConfig = {
|
||||
inputOptions: {
|
||||
brands: [],
|
||||
stores: [],
|
||||
},
|
||||
steps: defaultSteps.map((step, index) =>
|
||||
cloneStep({
|
||||
...step,
|
||||
@ -146,6 +150,21 @@ export function normalizeAgentWorkflowUiConfig(value: unknown): AgentWorkflowUiC
|
||||
? (value as Record<string, unknown>)
|
||||
: {};
|
||||
const rawSteps = Array.isArray(raw.steps) ? raw.steps : [];
|
||||
const normalizeStringList = (input: unknown) => {
|
||||
if (!Array.isArray(input)) return [] as string[];
|
||||
return Array.from(
|
||||
new Set(
|
||||
input
|
||||
.map((item) => normalizeText(item, 64))
|
||||
.filter(Boolean)
|
||||
.slice(0, 300)
|
||||
)
|
||||
);
|
||||
};
|
||||
const rawInputOptions =
|
||||
raw.inputOptions && typeof raw.inputOptions === "object" && !Array.isArray(raw.inputOptions)
|
||||
? (raw.inputOptions as Record<string, unknown>)
|
||||
: {};
|
||||
|
||||
const normalizedSteps = defaultAgentWorkflowUiConfig.steps.map((defaultStep, stepIndex) => {
|
||||
const matchedStep =
|
||||
@ -210,6 +229,10 @@ export function normalizeAgentWorkflowUiConfig(value: unknown): AgentWorkflowUiC
|
||||
});
|
||||
|
||||
return {
|
||||
inputOptions: {
|
||||
brands: normalizeStringList(rawInputOptions.brands),
|
||||
stores: normalizeStringList(rawInputOptions.stores),
|
||||
},
|
||||
steps: normalizedSteps.sort((left, right) => left.sortOrder - right.sortOrder),
|
||||
};
|
||||
}
|
||||
|
||||
@ -610,6 +610,7 @@ export const canvasProject = pgTable("CanvasProject", {
|
||||
};
|
||||
selections?: Record<string, string>;
|
||||
selectedAgentPresetId?: string | null;
|
||||
currentStage?: "workflow" | "mode";
|
||||
};
|
||||
}>(),
|
||||
createdAt: timestamp("createdAt").notNull().defaultNow(),
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -40,6 +40,10 @@ export interface AgentWorkflowStepUiConfig {
|
||||
}
|
||||
|
||||
export interface AgentWorkflowUiConfig {
|
||||
inputOptions?: {
|
||||
brands: string[];
|
||||
stores: string[];
|
||||
};
|
||||
steps: AgentWorkflowStepUiConfig[];
|
||||
}
|
||||
|
||||
@ -70,6 +74,7 @@ export interface AgentWorkflowPersistedState {
|
||||
};
|
||||
selections: Partial<Record<AgentWorkflowStepKey, string>>;
|
||||
selectedAgentPresetId?: string | null;
|
||||
currentStage?: "workflow" | "mode";
|
||||
}
|
||||
|
||||
export interface AgentCategoryTreeConfig {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user