topfans/dify-laser-workflow.drawio
2026-07-09 16:08:25 +08:00

151 lines
14 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<mxfile host="app.diagrams.net" modified="2026-07-08T10:00:00.000Z" agent="Claude" version="22.0.0" type="device">
<diagram name="Dify Laser Workflow v3" id="laser-workflow-v3-with-compositor">
<mxGraphModel dx="2400" dy="1500" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="2000" pageHeight="1400" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="title" value="镭射卡生成完整链路 v3含后端 compositor 合成)&#10;AI 出金属底 + 后端合成人像 + 镭射光效" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=18;fontStyle=1" vertex="1" parent="1">
<mxGeometry x="500" y="20" width="1000" height="60" as="geometry" />
</mxCell>
<mxCell id="phase_dify" value="=== Dify 工作流laser_card_v2_5series===" style="text;html=1;strokeColor=#9673a6;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontStyle=1" vertex="1" parent="1">
<mxGeometry x="40" y="100" width="1920" height="30" as="geometry" />
</mxCell>
<mxCell id="start" value="开始节点 (Start)&#10;输入变量:&#10;- cutout_url (string, 必填)&#10;&#10;用户风格描述词由 Dify 原生 #context# 注入&#10;(不添加自定义变量)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=11" vertex="1" parent="1">
<mxGeometry x="120" y="140" width="320" height="100" as="geometry" />
</mxCell>
<mxCell id="llm" value="LLM 节点 (gpt-4o-mini)&#10;&#10;系统 promptspec §5.2 中文版&#10;5 系列模板 + 5 字段 JSON Schema&#10;&#10;用户提示:#context#&#10;输出格式JSON结构化输出" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=11;align=left;spacingLeft=10" vertex="1" parent="1">
<mxGeometry x="60" y="280" width="440" height="120" as="geometry" />
</mxCell>
<mxCell id="branch_label" value="5 路并发(每路对应一个卡牌系列)&#10;AI 出『金属底 + 风格氛围』背景图(纯文生图,不带人像)" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=12;fontStyle=2" vertex="1" parent="1">
<mxGeometry x="60" y="420" width="440" height="30" as="geometry" />
</mxCell>
<mxCell id="p1_gen" value="生图节点 1&#10;gen_prizm_blue&#10;&#10;模型image-01-live&#10;Prompt{{ llm_rewrite.prizm_blue }}&#10;尺寸1024x1024&#10;数量1&#10;&#10;→ 金属底背景图 1Prizm Blue 工艺)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontSize=11;align=left;spacingLeft=10" vertex="1" parent="1">
<mxGeometry x="40" y="470" width="180" height="140" as="geometry" />
</mxCell>
<mxCell id="p2_gen" value="生图节点 2&#10;gen_pokemon_rainbow&#10;&#10;Prompt{{ llm_rewrite.pokemon_rainbow }}&#10;→ 金属底背景图 2彩虹稀有" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontSize=11;align=left;spacingLeft=10" vertex="1" parent="1">
<mxGeometry x="240" y="470" width="180" height="140" as="geometry" />
</mxCell>
<mxCell id="p3_gen" value="生图节点 3&#10;gen_topps_refractor&#10;&#10;Prompt{{ llm_rewrite.topps_refractor }}&#10;→ 金属底背景图 3Topps 折射)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontSize=11;align=left;spacingLeft=10" vertex="1" parent="1">
<mxGeometry x="440" y="470" width="180" height="140" as="geometry" />
</mxCell>
<mxCell id="p4_gen" value="生图节点 4&#10;gen_yugioh_secret&#10;&#10;Prompt{{ llm_rewrite.yugioh_secret }}&#10;→ 金属底背景图 4横纹 Secret" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontSize=11;align=left;spacingLeft=10" vertex="1" parent="1">
<mxGeometry x="640" y="470" width="180" height="140" as="geometry" />
</mxCell>
<mxCell id="p5_gen" value="生图节点 5&#10;gen_ws_ssp&#10;&#10;Prompt{{ llm_rewrite.ws_ssp }}&#10;→ 金属底背景图 5WS SSP" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontSize=11;align=left;spacingLeft=10" vertex="1" parent="1">
<mxGeometry x="840" y="470" width="180" height="140" as="geometry" />
</mxCell>
<mxCell id="end_dify" value="Dify 结束节点&#10;&#10;输出 variants[5]&#10;每项 = {preset_id, signed_url(AI背景图), oss_key}&#10;&#10;⚠️ 注意signed_url 是 AI 出的金属底背景图,&#10;不含人像(人像在后端 compositor 叠加)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=11;align=left;spacingLeft=10" vertex="1" parent="1">
<mxGeometry x="60" y="640" width="960" height="80" as="geometry" />
</mxCell>
<mxCell id="phase_backend" value="=== 后端 gateway 服务topfans-gateway===" style="text;html=1;strokeColor=#d6b656;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontStyle=1" vertex="1" parent="1">
<mxGeometry x="40" y="760" width="1920" height="30" as="geometry" />
</mxCell>
<mxCell id="handle_dify" value="handleDifyBlocking() 控制器&#10;&#10;1. POST /v1/workflows/run 调 Dify&#10;2. 解析 5 个 variantAI 背景图)&#10;3. **逐张调 compositor.Compose() 合成**&#10;4. 上传合成图到 OSS&#10;5. 返回 5 张最终镭射卡" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=11;align=left;spacingLeft=10" vertex="1" parent="1">
<mxGeometry x="60" y="800" width="380" height="160" as="geometry" />
</mxCell>
<mxCell id="compositor" value="compositor.Compose()【核心6 层合成】&#10;&#10;输入:&#10; - BackgroundURLAI 出的金属底背景图)&#10; - CutoutURL用户上传的人像&#10; - GratingConfig5 套光栅参数)&#10;&#10;合成 6 层:&#10; 1. AI 艺术背景&#10; 2. 金属反光梯度&#10; 3. 彩虹衍射光栅色带(核心镭射)&#10; 4. AI 装饰层(可选)&#10; 5. 胶片颗粒 + 磨砂哑光&#10; 6. 人物抠图(最顶层)&#10;&#10;输出:合成后的 PNG bytes" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fad7ac;strokeColor=#b46504;fontSize=11;align=left;spacingLeft=10" vertex="1" parent="1">
<mxGeometry x="500" y="800" width="520" height="280" as="geometry" />
</mxCell>
<mxCell id="oss" value="OSS 上传&#10;&#10;把合成 PNG bytes&#10;上传到 top-fans-test bucket&#10;key: laser-card/compositor/&#10;{star_id}/{user_id}/{preset_id}_&#10;{ts}.png&#10;&#10;返回 final_urlsigned URL2h 过期)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;fontSize=11;align=left;spacingLeft=10" vertex="1" parent="1">
<mxGeometry x="1080" y="800" width="380" height="160" as="geometry" />
</mxCell>
<mxCell id="frontend" value="前端 LenticularCard.vue&#10;&#10;5 张最终镭射卡&#10;(每张都是『用户人像 + 镭射金属底 + 风格场景』完整合成)&#10;&#10;用户选 1 张 → 走铸造" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=11;align=left;spacingLeft=10" vertex="1" parent="1">
<mxGeometry x="1500" y="800" width="460" height="160" as="geometry" />
</mxCell>
<mxCell id="phase_db" value="=== 数据库topfans-postgres===" style="text;html=1;strokeColor=#82b366;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontStyle=1" vertex="1" parent="1">
<mxGeometry x="40" y="1130" width="1920" height="30" as="geometry" />
</mxCell>
<mxCell id="db" value="laser_card_instances 表&#10;&#10;INSERT 一行:&#10; - instance_no (LC + 时间戳 + 随机)&#10; - template_id (preset_id → template.id)&#10; - status = &#39;rendered&#39;&#10; - materials_snapshot = [{role:&#39;composite&#39;, oss_key, preset_id} x5]&#10; - composite_oss_key = final image key" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=11;align=left;spacingLeft=10" vertex="1" parent="1">
<mxGeometry x="60" y="1170" width="800" height="160" as="geometry" />
</mxCell>
<mxCell id="legend" value="图例:&#10;■ 绿色 = 开始 / 输入 / 前端 / DB&#10;■ 蓝色 = LLM 处理 / DB 操作&#10;■ 紫色 = AI 生图节点5 路并发)&#10;■ 黄色 = 后端 gateway 处理&#10;■ 橙色 = compositor 合成6 层)&#10;■ 红色 = 结束 / 输出" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;fontSize=11;align=left;spacingLeft=10;verticalAlign=top" vertex="1" parent="1">
<mxGeometry x="1500" y="1170" width="460" height="160" as="geometry" />
</mxCell>
<mxCell id="e_start_llm" value="cutout_url + #context#" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;endArrow=classic;strokeColor=#6c8ebf;strokeWidth=2;fontSize=11" edge="1" parent="1" source="start" target="llm">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e_llm_p1" value="json.prizm_blue" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.1;exitY=1;entryX=0.5;entryY=0;endArrow=classic;strokeColor=#9673a6;strokeWidth=1;fontSize=11" edge="1" parent="1" source="llm" target="p1_gen">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e_llm_p2" value="json.pokemon_rainbow" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.3;exitY=1;entryX=0.5;entryY=0;endArrow=classic;strokeColor=#9673a6;strokeWidth=1;fontSize=11" edge="1" parent="1" source="llm" target="p2_gen">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e_llm_p3" value="json.topps_refractor" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;endArrow=classic;strokeColor=#9673a6;strokeWidth=1;fontSize=11" edge="1" parent="1" source="llm" target="p3_gen">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e_llm_p4" value="json.yugioh_secret" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.7;exitY=1;entryX=0.5;entryY=0;endArrow=classic;strokeColor=#9673a6;strokeWidth=1;fontSize=11" edge="1" parent="1" source="llm" target="p4_gen">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e_llm_p5" value="json.ws_ssp" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.9;exitY=1;entryX=0.5;entryY=0;endArrow=classic;strokeColor=#9673a6;strokeWidth=1;fontSize=11" edge="1" parent="1" source="llm" target="p5_gen">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e_p1_end" value="bg1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;entryX=0.1;entryY=0;endArrow=classic;strokeColor=#b85450;strokeWidth=1;fontSize=10" edge="1" parent="1" source="p1_gen" target="end_dify">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e_p2_end" value="bg2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;entryX=0.25;entryY=0;endArrow=classic;strokeColor=#b85450;strokeWidth=1;fontSize=10" edge="1" parent="1" source="p2_gen" target="end_dify">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e_p3_end" value="bg3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;entryX=0.4;entryY=0;endArrow=classic;strokeColor=#b85450;strokeWidth=1;fontSize=10" edge="1" parent="1" source="p3_gen" target="end_dify">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e_p4_end" value="bg4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;entryX=0.55;entryY=0;endArrow=classic;strokeColor=#b85450;strokeWidth=1;fontSize=10" edge="1" parent="1" source="p4_gen" target="end_dify">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e_p5_end" value="bg5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;entryX=0.7;entryY=0;endArrow=classic;strokeColor=#b85450;strokeWidth=1;fontSize=10" edge="1" parent="1" source="p5_gen" target="end_dify">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e_end_backend" value="variants[5]" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;endArrow=classic;strokeColor=#d6b656;strokeWidth=2;fontSize=12" edge="1" parent="1" source="end_dify" target="handle_dify">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e_handle_compositor" value="5x compose call" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;endArrow=classic;strokeColor=#b46504;strokeWidth=2;fontSize=12" edge="1" parent="1" source="handle_dify" target="compositor">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e_compositor_oss" value="PNG bytes" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;endArrow=classic;strokeColor=#d6b656;strokeWidth=2;fontSize=12" edge="1" parent="1" source="compositor" target="oss">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e_oss_frontend" value="5 final URLs" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;endArrow=classic;strokeColor=#82b366;strokeWidth=2;fontSize=12" edge="1" parent="1" source="oss" target="frontend">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e_handle_dify" value="INSERT" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;endArrow=classic;strokeColor=#6c8ebf;strokeWidth=1;fontSize=11" edge="1" parent="1" source="handle_dify" target="db">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>