📍 无忆研习社 › 搜索获客 › 用 Dify Chatflow 搭建多模态视觉创作 Agent 与 SEO 自动化全链路工作流:节点设计、提示词调优与 API 接入完整拆解

用 Dify Chatflow 搭建多模态视觉创作 Agent 与 SEO 自动化全链路工作流:节点设计、提示词调优与 API 接入完整拆解

摘要:我把多模态Agent和SEO自动化两条线从头拆开讲透:用Dify Chatflow搭一套问题分类器,把SEO文案拆成图片需求后走文生图、图生图、智能抠图、图生视频四条子链路,切换模型只改四个地方;再用三个Workflow串联关键词挖掘、双引擎素材采集(Tavily广度+Firecrawl深度)、Kimi K2长上下文模型搭大纲、写作型模型出正文、Google Sheets当后端,最终实现“种子词→自动产出文章→自动入库→自动规划站内架构”的闭环。关键在于每个环节交给最擅长的工具,所有分支靠指令而非关键词判断,准确率提升一个数量级。附完整踩坑、API模板、模型切换方法和JSON Schema写法。
字号 100%
行距 2.05
当前可见 60% 的内容
本文由 莫潇羽@无忆研习社(www.wuyi.wiki)撰写,转载请注明出处。

快速摘要(只看结论就够了)

这篇文章把两条核心链路从头到尾拆开来讲清楚。第一条是"多模态视觉创作 Agent",在 Dify 的 Chatflow 里用问题分类器把一篇 SEO 文案拆成图片需求,再分别走文生图、图生图、智能抠图、图生视频四条子链路,统一通过聚合 API 平台调用底层模型,切模型只需改四个地方。第二条是"SEO 全自动化生产线",三个 Workflow 串起来用:DataForSEO 负责挖关键词,Tavily + Firecrawl 双引擎做素材采集与深度抓取,Kimi K2 类长上下文模型负责大纲,创作型模型负责正文,Google Apps Script 把 Sheets 改造成可读可写的轻量后端,实现"输入种子词 → 自动产出整篇正文 → 自动入库 → 自动规划站内架构"的闭环。

这套打法的关键不在于堆模型,而在于把每个环节交给最擅长它的工具:广度搜索给 Tavily,深度抓取给 Firecrawl,逻辑推理给长上下文模型,文字润色给写作型模型,持久化给 Google Sheets。所有节点都用提示词指令而非关键词列表来判断分支,这一改动直接把分类准确率提升了一个数量级。文末附完整的踩坑总结、API 调用模板、模型切换方法论以及结构化输出避错的 JSON Schema 写法。

想看完整拆解,往下翻。


一、单点对话的瓶颈,与"工作流式 AI"为什么是更稳的解

我最近这一年折腾下来,跟身边几位做内容、做出海、做独立产品的朋友交流,几乎所有人都有过同一种感受——刚开始接触大模型那阵子,大家都泡在对话框里:把要求丢进去、看着它生成、不满意就改一句重发。这个过程很爽,但只要把它放到真正的"产能"语境下,就会立刻露怯。

露怯的地方有三处。第一,结果不稳定。同样一段提示词,今天生成的东西能用,明天再发就不一定有那个味儿了。第二,深度不够。模型的知识库截止于训练时点,即使开了联网,搜出来的也常常是浮在表面的几条新闻摘要,写出来的东西读起来像新闻拼接,没真功夫。第三,没法规模化。一次只能写一篇,人盯着对话框,出活效率被人的注意力捆死。

工作流式 AI 解决的就是这三件事。它的核心思想很简单:不再把一个复杂任务整个塞给模型,而是把它拆成若干个步骤,每一步交给最擅长那一步的工具去处理,前一步的输出作为后一步的输入。 这就跟工厂的流水线一个意思——磨刀的不切菜,切菜的不掌勺,每个工位只做自己最熟的那一件事。

这套理念落到 AI 应用里,会带来三个非常实在的好处。

第一个是确定性。 每个节点都有明确的输入和输出。文档解析节点的输出是结构化文本,搜索节点的输出是一个 JSON 数组,大模型节点的输出是一段符合 schema 的内容。出了问题,一眼就能定位到是哪一环掉链子,不像传统的"一句 prompt 包打天下",崩了根本不知道崩在哪。

第二个是上限被打开了。 单一模型的上下文窗口、联网能力、推理深度都是有限的。但只要把任务拆出来,你就能把"广度搜索"、"深度抓取"、"逻辑统筹"、"创作润色"这几件事分别交给不同的工具,各自发挥到极限,最后再拼起来。我自己用这套方法生产的长文,跟单纯让模型"联网写一篇"出来的内容,质感差距大到几乎不像同一类东西。

第三个是可复制。 工作流一旦调通,就可以批量跑。喝杯茶的功夫,一篇有深度的好文章已经躺在表格里等着你了。这件事的复利效应是非常吓人的,跑一天和跑一个月,在内容积累上完全是两个量级。

回到我们今天要拆解的内容,本文要彻底讲明白的是两条主线:

  • 多模态视觉创作链路——用 Dify 的 Chatflow 搭一个能识别意图、能调用图像引擎、能生成视频的 Agent,从一篇 SEO 文章直接产出配图与短视频。
  • SEO 内容生产链路——三个 Workflow 串起来,从关键词挖掘、内容生产到站内架构规划,全部跑成自动化。

我会逐个节点讲清楚每一条连线背后的逻辑,以及踩过的坑。这不是一篇"复制粘贴跟着抄"的教程,而是一次关于提示词工程与系统架构的完整复盘——这点是我做完两版工作流之后特别想强调的。光知道怎么连线没用,你得理解为什么这么连。莫潇羽@无忆研习社今天的目标,就是让你看完之后能自己改、自己魔改、自己往业务里嵌。

二、Dify Chatflow 与 Workflow:先选对类型再开工

工具选错,后面全是麻烦。在 Dify 里建应用的第一步就是选类型,这个选择会决定你整个项目的形态。先把两种类型的差别说清楚。

2.1 Chatflow 与 Workflow 的核心差别

Dify 把可视化编排分成两种:

类型

适用场景

是否支持多轮对话

是否支持记忆

输出形态

Chatflow

多轮对话、需要意图理解的交互式应用

是

是(对话历史)

流式回复

Workflow

单轮自动化任务、批处理

否

否

一次性产出

简单一句话区分:用户要不要跟它聊天?要聊,选 Chatflow;不聊,选 Workflow。

多模态创作那条链路,用户得跟 Agent 多轮交互——上传文章、看方案 A/B/C、选定一个、追加生成视频的指令——所以必须用 Chatflow,因为只有它支持 Memory(对话历史)和 Answer 回复节点。SEO 关键词挖掘那条链路,用户输入一个种子词,流程跑完直接把结果写进表格,中间不需要任何交互,这种就是典型的 Workflow 场景。

新手最容易犯的错就是把交互式应用做成了 Workflow,做完发现没法承接"用户的下一句话",只能从头再来。我刚开始也犯过这毛病,后来才慢慢摸清楚两者的分工。

2.2 会话变量与环境变量:别搞混

进到 Chatflow 编辑器里,右上角能看到两个图标:会话变量和环境变量。这俩长得像,但作用完全不同。

  • 会话变量(Conversation Variable):作用域是"这一次会话"。用户开一次对话,变量就生效一次,关掉就清空。典型用途是临时保存用户上传的图片 URL、保存某一轮生成结果的句柄,方便后续节点取用。
  • 环境变量(Environment Variable):作用域是"整个应用"。所有用户、所有会话共享同一份。典型用途是存 API Key、存某个第三方服务的 base URL,改一次全应用生效。

我在多模态 Agent 里设了一个会话变量叫 image_url,专门用来保存当前会话里那张待处理的图片地址。当用户上传图片之后,系统先把 URL 存进这个变量,后面无论是抠图节点还是图生视频节点要用图,都从这个会话变量里拿,逻辑非常清爽。

2.3 文件与图片上传:别忘了开

Chatflow 默认不开图片、文件上传,需要手动点开。位置在编辑器右上角的"功能"按钮里,把"图片上传"和"文件上传"分别打开,然后点进设置:

  • 最大上传数:拉到最大。Dify 当前版本一次最多支持上传 10 个文件,反正都是用户决定上传几个,给足上限不亏。
  • 文件类型:按需勾选。视觉创作 Agent 主要要"文档"和"图片",其它格式可以不勾;SEO 工作流如果让用户输入种子词就用纯文本输入即可,不需要打开文件上传。

顺手再说一下"对话开场白",这个特别容易被忽略。开场白是用户打开应用第一眼看到的提示语,合理设计能极大降低用户的上手成本。比如可以写:"你好,我是视觉创作助手,你可以上传一篇 SEO 文章,我会分析需要什么配图;也可以直接上传一张产品图,我会帮你生成融合后的成图或视频。"——这种带使用示例的开场白,比一句"请输入您的问题"友好太多了。

把这些基础设施铺好之后,真正的活就要开始干了。下一章讲的是整个多模态 Agent 的骨架——问题分类器与它带出来的六条子链路。

三、多模态视觉创作 Chatflow 的整体架构

把骨架搭好之前,先把整张地图画出来,后面看每一节会清晰很多。这套 Chatflow 的全貌长这样:

flowchart TD
    A[用户输入<br/>文档/图片/文字] --> B[问题分类器]
    B -->|分类一<br/>方案规划| C[文档提取器]
    C --> C1[视觉规划大模型]
    C1 --> C2[直接回复方案]
    B -->|分类二<br/>产品融合| D[视觉大模型]
    D --> D1[代码节点<br/>提取图片URL]
    D1 --> D2[变量赋值<br/>保存到会话变量]
    D2 --> D3[直接回复融合提示词]
    B -->|分类三<br/>智能抠图| E[代码节点<br/>调用抠图API]
    E --> E1[直接回复抠图结果链接]
    B -->|分类四<br/>图生视频| F[代码节点<br/>提交视频任务]
    F --> F1[直接回复任务查看链接]
    B -->|分类五<br/>图生图| G[代码节点<br/>调用图生图API]
    G --> G1[直接回复融合后的成图]
    B -->|分类六<br/>纯文生图| H[清洗大模型]
    H --> H1[代码节点<br/>调用文生图API]
    H1 --> H2[直接回复成图链接]

整张图看下来,问题分类器就是中枢神经。它要把用户那句话理解清楚,然后正确地导向某一条子链路。整个 Agent 能不能用,关键就在这一个节点上。

3.1 输入字段:三态共存的写法

进到"开始"节点配置用户输入,我建议只设一个字段就够了,起名叫 文档(也可以叫别的,但要跟后面的引用对应上)。这个字段的类型选单文件——它对应的就是"一个可选的文件/图片占位符"。

这里有个关键细节:必填项关掉。如果开了必填,用户没传文件就不能发消息,体验非常不好。我们要做到的是:用户既可以传图、也可以传文档、也可以什么都不传只发一句话。

打开"文件上传"功能,允许的类型勾上"文档"和"图片"。在 Chatflow 内,这两类文件背后都对应 array[file] 类型的变量,后面节点引用的时候按需取就行。

3.2 为什么不在用户输入这里做"必填"约束

很多新手会想:既然图生视频必须要图,那为什么不在输入端就强制要求传图?

道理是这样的——意图识别要在"问题分类器"这一步做,不要在"开始"节点做。 开始节点做硬性约束会让 UI 体验变僵,用户得提前知道"哦原来你要图我才让我说话"。而把判断挪到问题分类器里,系统就可以做得更聪明:用户没传图、但说了"帮我生成视频",分类器可以直接回一句"请上传一张参考图再试",体验会自然得多。

把硬约束往后挪、把柔性判断往前提,这是我做 Agent 这两年总结出来的一个小心得,用户感知到的"聪明"绝大多数都来自这种设计,跟模型本身的强弱关系反而没那么大。莫潇羽自己在无忆研习社发的几个内嵌 Agent 都是这个思路,确实管用。

3.3 子链路的功能定位

六个分类各自负责什么,先讲一遍,有个全局观:

分类编号

名称

触发条件

主要节点

输出

1

方案规划

用户上传 SEO 文档,问图片应该怎么配

文档提取 + 视觉规划大模型

配图方案 A/B/C

2

产品融合

用户上传产品图,让 AI 分析并出提示词

视觉大模型 + URL 提取

文生图提示词

3

智能抠图

用户上传图片,要求抠出主体

代码节点调用抠图 API

透明背景 PNG

4

图生视频

用户上传图片,要求让它动起来

代码节点调用视频 API

视频任务链接

5

图生图

用户上传图片,要求融合元素重生成

代码节点调用图生图 API

融合后的图片

6

纯文生图

没有图,纯文字描述生成图

清洗大模型 + 文生图 API

生成图片

每条子链路单独看都很简单,串起来才有威力。一个常见使用路径是:用户先走分类 1 拿到配图方案,看中方案 A 之后,把方案 A 的提示词复制回来交给分类 6 生成图,觉得图还行但想要动效,再把生成的图丢给分类 4 出视频。整套 Agent 的乐趣就在于它可以"接力"——前一步的产物可以作为后一步的输入,实现真正的多模态闭环。

骨架画完了,下一节把问题分类器单独拎出来重点讲。这一节我会同时给出"旧方案"和"新方案"的对比,这是这套工作流升级前后最大的改动,也是踩坑最多的地方。

四、问题分类器:从关键词列表到指令式提示词的关键升级

问题分类器是这套 Agent 唯一一个"绝对不能错"的节点。它判断错了,整条链路就跑偏,后面再聪明的模型也救不回来。我前后做了两版工作流,在这个节点上栽了两次跟头,最终找到的解法,值得单独拿一章来讲。

4.1 模型选择:别贪强

分类器的工作量并不大——读一段几十个字到几百个字的用户输入,判断它属于六个分类里的哪一个。这种任务根本不需要旗舰模型,选个性价比高的中端模型就够用了。

我目前用的是 Gemini 2.5 这一档的模型,主要是国内通过中转使用 token 单价控制得住,而且这一档的模型在"分类、判别、结构化输出"这类任务上表现稳定。如果你预算更紧,Kimi 系列的中等档位、智谱 GLM 系列的标准款都可以胜任,实测准确率掉得不多。

4.2 旧方案:把关键词塞进分类条目

我第一版的做法非常朴素——在每个分类条目下面,把可能触发这个分类的关键词列出来。比如:

  • 分类 4 图生视频:关键词列表填 让它动起来 / 生成视频 / 做成视频 / 动效 / 动画 / 视频
  • 分类 5 图生图(产品融合):关键词列表填 融合 / 合成 / 结合 / 加上元素 / 背景换

这种写法直观,看起来非常符合"程序员思维"——你给我关键词,我去匹配。但跑起来之后会发现一个问题:关键词冲突。

举个真实的例子。用户上传了一张产品图,说"帮我把这个图融合成一个视频"。这句话里同时出现了"融合"和"视频",触发了分类 5(产品融合)和分类 4(图生视频)两个分类的关键词。模型在两个之间犹豫,有时候选对,有时候选错——尤其是分类 5 和分类 6(纯文生图),触发词长得太像了,经常错位跳进图生图,但图生图必须要图片,用户没传就直接报错。

那段时间我做了上百次测试,错位率大概有 30% 到 40%,这个失败率对一个生产级 Agent 是完全不能接受的。

4.3 新方案:把判别逻辑写进指令

后来我把整个写法翻了过来——关键词列表全部清空,改成在分类器的"指令"区写一段结构化提示词。

这一段提示词的核心结构长这样:

你是一个意图分类器,需要根据用户的输入和上下文,把用户的意图归到下面 6 个分类之一。

判断时遵循以下优先级规则:
1. 如果用户【没有上传任何图片】,且需求是生成新图或视频,优先归入"纯文生图"(分类 6),不要归入需要图片输入的分类(2/3/4/5)。
2. 如果用户【上传了图片】+ 提到"动""转视频""动画""动效",归入"图生视频"(分类 4),即使句中出现"融合""加上"等词也以视频意图为准。
3. 如果用户【上传了图片】+ 明确要求"去背景""抠出""只保留主体",归入"智能抠图"(分类 3)。
4. 如果用户【上传了图片】+ 提到"融合""结合""加上""换背景""加元素",归入"产品融合"(分类 2 或 5)。
5. 如果用户【上传了 SEO 文档/纯文本文章】并询问配图建议,归入"方案规划"(分类 1)。
6. 不能确定时,优先归入"纯文生图"。

请只输出分类编号,不要输出其它内容。

差别在哪?指令式提示词让模型理解的是"规则"而不是"匹配词"。 当用户说"帮我把这个图融合成一个视频",模型会按规则 2 判断——因为出现了"视频"意图,直接归图生视频,不会再被"融合"这个词带偏。

切到指令式之后,我又跑了一轮同等规模的测试,错位率从 30% 多降到了不到 5%,而且剩下的那 5% 几乎都属于"用户输入本身就有歧义"的边界情况——这种连人都判断不出来,就不能怪模型。

4.4 记忆窗口的合理值

分类器节点要把"记忆"功能打开。Dify 里这个开关叫 Memory,默认窗口是 50,在对话型应用里这个值通常够用。

但我建议有意识地控制这个值,不要无脑拉满。原因是:

  • 窗口越大,token 消耗越高——分类器每次都会把历史上下文带进去,如果记忆窗口是 50,且每轮对话都很长,token 消耗会指数级膨胀。
  • 窗口太小,识别意图会丢上下文——比如用户上一轮已经选了方案 A,这一轮说"给我做成视频",分类器需要知道"是"才能正确归类。窗口太小,这层关联就丢了。

我的实测经验是,对话型 Agent 把记忆窗口设到 10~20 之间,效果与成本平衡得最好。莫潇羽@无忆研习社现在挂出来的几个 Agent 默认都用的 15,没出过乱子。

4.5 视觉能力:开还是不开?

问题分类器节点本身有一个"视觉"开关。开了之后,分类器就能"看"到用户上传的图片,理论上判断会更准。

我的建议是:对分类器这种轻量任务,不要开视觉。理由是分类器的核心任务是看文字、做归类,看不看图基本不影响——只要在指令里写清楚"判断用户有没有上传图片",Dify 会自动把"图片是否存在"这个布尔状态传给模型。开视觉会让 token 消耗暴涨,得不偿失。

视觉能力开在真正需要"读图"的节点上,比如分类 2 的视觉规划大模型——那个节点要真的看着图分析画面元素,必须开。

五、视觉规划节点:从 SEO 文章到可执行的配图方案

分类 1 是这套 Agent 里最长链的一条,也是最有内容价值的一条。它要做的事情是:用户上传一篇 SEO 文章,Agent 帮他分析这篇文章应该怎么配图、配几张、每张图放在哪一段、需要什么风格,直接给出可执行的方案。

5.1 文档提取器:别把这个节点跳过

用户上传的文档可能是 .txt、.md、也可能是 .docx。这些格式 LLM 都没法直接吃,得先转成纯文本。Dify 内置的"文档提取器"节点就是干这个的——把上传的文件解析成 LLM 能读的字符串。

节点配置很简单,只要把"输入变量"指向用户上传文档对应的那个变量(我前面叫 文档)即可。它会自动按文件类型走对应的解析器。

这里有个细节值得拎出来:Dify 的内置文档提取器对 PDF 支持是有限的,尤其是含大量图片、复杂排版的 PDF,提出来的文本会比较乱。如果你的业务里 PDF 是主力输入,建议绕开内置节点,改用代码节点 + Python 库(比如 pdfplumber 或 PyMuPDF)做提取。对于 SEO 文章这种以 docx 和 md 为主的场景,内置节点完全够用。

5.2 大模型节点的选型逻辑

视觉规划这个任务,对模型的要求是"逻辑统筹"而不是"创作发挥"。它要把一篇文章读完、拆出结构、按照 SEO 的最佳实践给出配图建议——这是一个判别 + 编排类型的任务,推理力比想象力重要。

我目前用的是 Gemini 2.5 Pro,主要理由是上下文窗口足够大(128k 以上),用户上传的 SEO 文章可能动辄几千字,加上提示词和示例,小窗口模型会撑爆。Kimi K2 系列在这个任务上也表现很好,而且单价比 Gemini 便宜不少,如果你做的是中文 SEO,Kimi 反而是首选——它对中文长文本的结构化理解能力,我个人测下来比 Gemini 2.5 Pro 还更稳一些。

温度参数要低。我把它压到 0.2~0.3 这一档。视觉规划这种任务最忌讳"飘",温度低能让输出更可控,符合预先定义的结构。

5.3 上下文与提示词:用角色提示词承载主体逻辑

Dify 的大模型节点里,"上下文"和"提示词"是两个不同的字段。上下文一般用来塞动态数据(比如上一步节点的输出),提示词用来定义模型的人设、任务、输出格式。

视觉规划节点的写法,我推荐把所有变量都引用到"提示词"里,而不是"上下文"里。原因是当变量较多的时候,在提示词里能更清晰地组织它们的位置——比如"用户上传的文章正文如下:{{文章}}"、"用户偏好的图片风格是:{{风格}}",这种写法读起来跟人写的一样,模型也更容易理解。

提示词的结构我用的是角色 + 任务 + 输出格式三段式:

[角色]
你是一位资深的 SEO 视觉编辑,专精于为 B 端长文配图。

[任务]
根据下面这篇文章的内容、目标受众和核心关切,规划出 3~5 个图片插入点。
对每个插入点,给出:
- 在文章中的具体位置(用相关段落的开头一句话标识)
- 这张图应该承载什么信息
- 推荐的画面风格
- 如果用户没有现成素材,给出可直接复制的文生图提示词(英文)

[输入]
文章正文:{{文章}}
偏好风格:{{风格}}

[输出格式]
按下列模板输出,使用 Markdown:

方案 A:[一句话方案概括]
- 插入点 1:...
- 插入点 2:...
- 插入点 3:...

方案 B:[一句话方案概括]
- 插入点 1:...
...

方案 C:[一句话方案概括]
- ...

最后用一段话给出选择建议。

5.4 输出"方案 A/B/C"的设计意图

直接给一个方案不行吗?为什么要给三个?

这里有个交互层面的考虑。Agent 给三个方案,用户从中选,远比 Agent 自作主张给一个方案的体验好。 心理学上叫"被赋予控制感"——用户没法接受"我没得选",但很愿意接受"我从你给的三个里挑一个"。

而且三个方案彼此风格要拉开差距:方案 A 偏极简、方案 B 偏插画、方案 C 偏实拍。这样无论用户的品牌调性是什么,总有一个能落地。

5.5 直接回复节点:把方案推给用户

视觉规划链路的最后一步是 Answer 节点(直接回复)。这个节点要做的事情非常简单——把上一步大模型生成的文本流式吐给用户。

引用方式是在 Answer 节点的输出框里点斜杠,选择"视觉规划大模型"这个节点的输出变量(默认叫 text),保存即可。Chatflow 会自动把这段文本流式发送到对话窗口,用户看到的体验跟在 ChatGPT 里对话一模一样。

到这一步,用户已经拿到三套方案了。他下一步要做什么?复制方案 A 里的提示词,发回给 Agent,触发分类 6(纯文生图),让 Agent 真的把图生出来。 这就是前面说的"接力",视觉规划这条链路的价值就是把"想法"转成"可执行的提示词",真正出图交给下一条链路。

六、产品融合节点:让大模型从图片里反推文生图提示词

分类 2 这条链路,名字叫"产品融合",但它做的事情其实是"看图说话再反推"——用户上传一张产品图(或者工厂图、场景图),大模型分析画面里有什么,然后输出一段可以指导文生图模型重生成的提示词。

这条链路的核心难点不在工程,在让大模型说"对"的话——它说出来的提示词得让后续的文生图模型能够稳定复现。

6.1 视觉大模型的选择

这一节必须用有视觉能力的大模型。Gemini 2.5 系列、Kimi K2.5/K2.6、智谱 GLM-4V、通义 Qwen-VL,这几个都是可选项。

我个人的选型偏好:

场景

推荐模型

理由

中文场景为主、预算紧

Kimi K2.5

中文理解强,Token 单价低

海外场景、英文提示词

Gemini 2.5 Pro

英文产物质量稳

极致性价比

Qwen-VL-Max

国产平台调用便宜

记忆窗口开 20 就够,因为这个节点拿到的就是一张图加一句"分析这张图"的指令,不需要太长的对话上下文。

视觉功能开关务必打开,这是这个节点的核心能力。

6.2 提示词:告诉它"该提哪些维度"

仅仅说"分析这张图",模型可能给你来一段散文式描述,这不是我们要的。我们要的是结构化的提示词,后面才能直接喂给文生图模型。

我写的提示词大致结构是:

[角色]
你是一名专业的产品摄影提示词工程师。

[任务]
仔细分析用户上传的图片,然后用英文输出一段 Stable Diffusion / FLUX / Imagen 风格的文生图提示词,
要求覆盖以下维度:

- subject(主体描述):是什么物品、形态、关键特征
- composition(构图):正面/侧面/俯视/特写
- lighting(光照):柔光/硬光/逆光/侧光
- color palette(色彩):主色调、点缀色
- style(风格):极简/工业/写实/概念
- background(背景):纯色/场景/虚化
- camera(机位与焦段):比如 35mm、85mm
- mood(情绪):科技感/温馨感/严肃感

只输出提示词本身,不要解释,不要前缀。

这种"维度清单"式的提示词,比"自由发挥"稳定得多。模型每次输出都按这八个维度走,你拿到的提示词风格高度一致,丢进文生图模型也好控制。

6.3 代码节点:把图片 URL 单独提取出来

视觉大模型节点跑完之后,我紧接着加了一个代码执行节点,作用是从用户输入里把图片的 URL 单独提取出来。

为什么要单独提取?因为后续如果用户要走"图生图"或"图生视频",必须把这张图的 URL 传给 fal.ai 之类的聚合 API。而 Dify 的 array[file] 变量直接传给 HTTP 请求节点会出问题——它的结构是嵌套的,API 那边接收不了。

代码节点的实现很简短:

def main(uploaded_files: list) -> dict:
    # uploaded_files 是 Dify 上传文件变量,结构是 list of dict
    if not uploaded_files:
        return {"image_url": ""}
    # 取第一张图,Dify 提供的 url 字段就是可直接外部访问的临时链接
    first = uploaded_files[0]
    return {"image_url": first.get("url", "")}

这段代码很短,但作用关键——它把 Dify 内部的复杂对象拍扁成了一个字符串 URL,后面随便用。

6.4 变量赋值:把 URL 存进会话变量

提取出来的 URL,下一步用变量赋值节点写进我们前面建好的会话变量 image_url。这一步是给后续节点埋的"钩子"——只要这一次会话里图片还在,任何子链路都能从 image_url 里取到它。

操作很简单:在变量赋值节点里选定目标变量(image_url)、选定数据源(代码节点的输出 image_url)、操作模式选"覆盖"。完成。

6.5 直接回复:把生成的提示词推给用户

链路最后是 Answer 节点,把视觉大模型生成的英文提示词流式回给用户。

用户拿到提示词之后,典型用法有两种:

  • 想要一张全新生成的图:复制提示词,发回 Agent,触发分类 6(纯文生图)。
  • 想要在原图基础上做局部融合:复制提示词,加一句"用这个风格融合到我刚才那张图上",触发分类 5(图生图)。

可以看到,这条链路本身不出图,它只产出"指导下一步的指令"。它是一个翻译器,把视觉信息翻译成可执行的文字。这种"中间层节点"在工作流里是非常常见的,它们看起来不起眼,但能极大降低整个 Agent 对用户输入质量的依赖——用户随手上传一张图,Agent 自己就能补出后面所有步骤需要的提示词,根本不用用户去懂什么是 Stable Diffusion 的 prompt 写法。

莫潇羽在这一节想强调一点:好的 Agent 设计,要让用户像跟一个懂行的助理对话,而不是像在编程。能在 Agent 内部消化的复杂度,就别让用户去消化。

七、抠图、文生图、图生视频:聚合 API 平台的统一调用方法论

这一章是整个多模态 Agent 里最实操的一节,也是最容易做出"工程美感"的一节。讲完这一章,你切换任何一个图像 / 视频底层模型,都只需要改四个地方。

7.1 为什么不直接调原厂 API,要走聚合平台?

很多人第一反应是:"我直接调 OpenAI 的 DALL·E、调 Midjourney、调 Runway 不就好了?"

实操之后会发现一堆痛点:

  • 每家 API 的鉴权方式都不同——OpenAI 用 Bearer Token,Midjourney 走 Discord 协议,有的家用 Basic Auth,有的家要签名。
  • 每家的请求参数结构都不同——同样是"生成一张图",有的家叫 prompt,有的家叫 text,有的家把尺寸放 size,有的家放 width/height。
  • 每家的计费、配额管理都要单独打理——账号、Token、对账,各搞各的。

聚合 API 平台干的就是"把这些差异封装起来",对外提供一套统一的接口规范。你认准一家聚合平台,后面想换底层模型就跟换插头一样简单——把模型名改一下、参数稍微调一下,接口该怎么调还怎么调。

我目前用的是 fal.ai 这家。它聚合了图像、视频、音频、3D 一共 600 多个生产级模型,从 Stable Diffusion 到 FLUX、从 SVD 到 Kling、从 Pika 到 Luma,主流的开源 / 闭源模型基本都能查得到。计费按调用次数收,一张图大概几美分到几十美分,一段视频几美分到几十美分,试错成本很低。

国内的替代品也有,比如 DMXAPI、UniAPI、UIUIAPI 这一类聚合中转,价格更敏感、付款更方便。你自己测一下哪家稳定就用哪家,接入逻辑都是一样的。

7.2 抠图节点的标准模板

抠图是这条链路里最简单的一个分类,因为它的请求结构最直接:输入一张图 URL,返回一张去背景后的图 URL。

代码节点的实现:

import requests
import os

def main(image_url: str) -> dict:
    api_key = os.environ.get("FAL_KEY")  # 从环境变量取
    endpoint = "https://api.fal.ai/v1/models/imageutils/rembg"

    headers = {
        "Authorization": f"Key {api_key}",
        "Content-Type": "application/json",
    }
    payload = {
        "image_url": image_url,
    }

    resp = requests.post(endpoint, headers=headers, json=payload, timeout=120)
    resp.raise_for_status()
    data = resp.json()

    return {
        "result_url": data.get("image", {}).get("url", "")
    }

输入变量挂上会话变量 image_url,输出变量叫 result_url,后面 Answer 节点引用 result_url 直接回复用户即可。

这段代码本身没什么花活,但要注意三点:

  • 超时给足——抠图通常 5~15 秒就回来了,但留 120 秒余量,防止网络抖动。
  • 错误处理——raise_for_status() 让 HTTP 错误直接抛出,Dify 会捕获并展示给开发者,不用自己写 try/except。
  • API Key 走环境变量——不要硬编码在代码里,改一次满世界找。Dify 的代码节点支持读环境变量,把 Key 放进 Dify 的"环境变量"配置里就行。

7.3 图生视频节点:异步返回链接的设计

视频生成跟图像生成最大的差别是——慢。一个 5 秒的视频,推理时间动辄两三分钟,如果你的代码节点同步等结果,Dify 那边等不了那么久,直接超时。

解法是:异步提交,返回查看链接,让用户自己去看。

代码改成这样:

import requests
import os

def main(image_url: str, user_prompt: str) -> dict:
    api_key = os.environ.get("FAL_KEY")
    submit_endpoint = "https://queue.fal.ai/fal-ai/kling-video/v1/standard/image-to-video"

    headers = {
        "Authorization": f"Key {api_key}",
        "Content-Type": "application/json",
    }
    payload = {
        "image_url": image_url,
        "prompt": user_prompt,
        "duration": "5",
    }

    # 提交任务,拿到 request_id
    resp = requests.post(submit_endpoint, headers=headers, json=payload, timeout=30)
    resp.raise_for_status()
    data = resp.json()
    request_id = data.get("request_id", "")

    # 拼出可访问的状态页 / 结果页链接
    status_url = f"https://fal.ai/dashboard/requests/{request_id}"

    return {
        "task_link": status_url,
        "tip": "视频生成已提交,通常需要 2~5 分钟,点击链接查看进度和下载成品。"
    }

Answer 节点的回复模板可以写成:

视频任务已经提交 ✅

预计 2~5 分钟出结果,点这个链接看进度和下载:
{{task_link}}

{{tip}}

7.4 切换模型只改四个地方

这是这一节的核心方法论。只要锁定 fal.ai 这家聚合平台,你以后想换任何一个图像或视频模型,都只需要改四个地方:

序号

改哪里

怎么找

1

API Key

同一个 Key,聚合平台共用

2

Endpoint URL

从模型详情页"API"标签复制

3

模型 ID(URL 里那一段)

比如 kling-video/v1/standard

4

请求参数字段

看模型详情页的"参数"列表

我做了一张速查表,挂在自己电脑桌面上:

切换图像模型清单
----------------
□ 打开 fal.ai/models 找到新模型
□ 复制 endpoint URL 替换代码里的 endpoint
□ 看参数文档,更新 payload 字段
□ Dify 里点击"运行"测试,看输出结构是否对得上
□ 调整 return 里的字段提取路径

这五步走完,新模型就接上了。整个过程不会超过 20 分钟。

7.5 文生图节点:多加一个"提示词清洗"环节

纯文生图分类(分类 6)的链路里,有一个跟前面几条不一样的细节——要在调用 API 之前,加一个大模型节点专门"清洗"提示词。

为什么?因为用户输入到这个节点的内容来源很杂。可能他刚刚从方案规划那里复制了一段方案 A 的描述,可能他从产品融合那里拿到了英文提示词,可能他就自己写了一句"帮我画一张猫"。这些输入直接喂给文生图 API,效果会非常不稳定——文生图模型对提示词的"洁净度"很敏感,有中文夹英文、有多余的连接词、有 Markdown 标记,都会影响出图质量。

所以加一个清洗节点,作用是:

  • 把混杂语言统一到一种(通常英文,因为大部分图像模型对英文提示词反应更好)
  • 去掉无关的连接词、Markdown 标记、敬语
  • 按主体 / 风格 / 光线 / 构图的顺序重排
  • 输出一段干净的、纯文生图风格的 prompt

清洗节点的模型选个便宜的就行——这种轻活,Kimi 入门款、智谱 GLM-4-Flash、Qwen-Plus 都能干。温度调到 0.1~0.2,要稳不要飘。

清洗完的提示词,再传给后面的代码节点调用文生图 API。这一步加完,文生图的成图质量我个人感受是肉眼可见地提升了一档。

八、把六条子链路串起来:端到端调试与典型踩坑

骨架、分类器、六条子链路全部就位之后,真正的考验才开始——把它们串起来,跑一遍完整流程,看哪里报错。

8.1 第一次跑通的典型路径

我第一次串通的测试用例是这样:

  1. 上传一篇 SEO 文章(主题是家用洗车机)
  2. 问"我应该在哪些段落配图,该配什么样的图"
  3. Agent 走分类 1,给出方案 A/B/C
  4. 我选方案 A,把方案 A 的提示词复制回来,加一句"帮我生成这张图"
  5. Agent 走分类 6(纯文生图),出图
  6. 我把出来的图丢回去,说"让它转起来,做成 5 秒视频"
  7. Agent 走分类 4(图生视频),返回视频任务链接
  8. 等 3 分钟,点链接看视频成品

这一套跑下来不到 10 分钟,端到端就实现了"一篇文章 → 配图方案 → 成图 → 成片"的完整链路。

8.2 第一次跑的时候踩了什么坑

跑第一次必然出问题,把我当时遇到的几个典型问题列出来,你大概率也会遇到:

坑一:第二步触发了错误的分类。

我说"我应该在哪些段落配图",Agent 直接走到了分类 2(产品融合)。原因是旧版分类器用关键词列表,"配图"两个字触发了产品融合的关键词。解法就是前面讲过的——把分类器的关键词列表清空,改用指令式提示词。

坑二:文生图的提示词被乱码污染。

方案 A 给出的提示词原文是带 Markdown 高亮的,我复制回去之后,文生图 API 直接报错。解法是在文生图链路里加一个清洗大模型节点,负责剔除所有非 ASCII 符号、Markdown 标记。

坑三:图生视频任务一直 pending。

排查了半天,发现是聚合平台那边模型名拼错了——我把 kling-video 写成了 kling-vedio,提交是成功的,但查询状态时找不到对应模型。解法是从模型详情页直接复制 endpoint,不要手动敲。

坑四:会话变量没接住图片 URL。

用户上传图之后,我直接在抠图节点用 image_url 变量,结果发现是空的——是因为变量赋值节点没成功执行(它前面的代码提取节点报错了)。解法是给代码提取节点加默认返回值,即使没拿到 URL 也返回空字符串,保证下游节点能拿到一个"存在但为空"的变量,而不是变量本身不存在。

8.3 测试套件:每次改完都要跑一遍

我现在改完工作流,都会跑一个固定的"测试套件",大概 8 个用例,覆盖六个分类 + 两个边界情况(空输入、模糊意图)。每次 5 分钟,跑完才放心发布更新。

用例

输入

期望分类

1

上传 SEO 文档 + "需要配什么图"

分类 1 方案规划

2

上传产品图 + "分析一下"

分类 2 产品融合

3

上传图片 + "把背景去掉"

分类 3 抠图

4

上传图片 + "做成视频"

分类 4 图生视频

5

上传图片 + "换个森林背景"

分类 5 图生图

6

纯文字 + "画一只赛博朋克猫"

分类 6 文生图

7

纯文字 + "把图融合一下"

应反问"上传图片"

8

上传图片 + "你好"

应反问"想做什么"

这种测试小清单看起来烦,但能帮你在发布之前就发现大部分回归性问题。莫潇羽@无忆研习社这边的几个内置 Agent,我都按这个流程走,上线之后用户反馈的 bug 量明显比临时改临时发的版本少很多。

九、SEO 关键词挖掘 Workflow:用 DataForSEO 把成本压到极致

第二条主线开始了——SEO 内容自动化生产。这一节先讲入口:关键词挖掘。

9.1 为什么选 DataForSEO,而不是 Semrush / Ahrefs

做 SEO 的人都知道,头部 SEO 工具(Semrush、Ahrefs、Moz)每个月动辄上百美元的订阅费,对个人和小团队来说门槛太高。而且这些工具是面向"用户操作"设计的——你只能在它们的网页界面里点点点,想批量、想自动化、想把数据塞进自己的工作流,要么没接口,要么接口贵得离谱。

DataForSEO 是数据供应商,它跟前面那些 SaaS 的区别是——它只卖原始数据,API 一调用就出。这种模式有三个优势:

  • 价格低——一次关键词查询 0.0075 美金左右,挖一千个词成本不到 10 美金。
  • 数据全——支持 Google、Bing、Yandex、百度等多个搜索引擎,覆盖全球。
  • 能进自动化——纯 API,天然适合塞进 Dify、n8n、Make 这类自动化平台。

DataForSEO 的官方文档:https://dataforseo.com/apis。注册之后会送一笔试用额度,大概几美金,够你试个上百次。如果是个人用,充值 10~20 美金通常能用半年到一年。

9.2 注册与 API 凭证获取

DataForSEO 的鉴权方式是 HTTP Basic Auth——把你的邮箱当用户名、密码当密码,组合成 email:password,做 base64 编码,放进请求头 Authorization: Basic <base64-string>。

它在控制台直接给你算好这串编码,你不用手动转。位置在控制台左侧"API Access"→"通过邮件发送",它会把完整的 Authorization Header 发到你邮箱里,直接复制粘贴就行。

9.3 Dify 里的 HTTP 请求节点配置

新建一个 Workflow 类型应用(注意是 Workflow 不是 Chatflow,这是单次任务),起名"关键词挖掘"。

用户输入字段就一个:种子关键词,文本类型,设为必填,最大长度建议 200 字符。

第一个真正干活的节点是 HTTP 请求:

字段

取值

Method

POST

URL

https://api.dataforseo.com/v3/keywords_data/google/keywords_for_keywords/live

Header - Authorization

Basic <你的 base64 串>

Header - Content-Type

application/json

Body

JSON,见下方

Body 模板:

[
  {
    "language_code": "en",
    "location_code": 2840,
    "keywords": [
      "{{种子关键词}}"
    ]
  }
]

location_code 2840 是美国,2156 是中国,2826 是英国。语言代码 en 是英文,zh_CN 是简体中文。按你的目标市场改即可。

9.4 暴力提取代码:不要试图"优雅地解析"

DataForSEO 返回的 JSON 结构比较深,搜索量、CPC、竞争度等字段嵌在好几层数组里。新手的本能反应是写一个干净的 JSON 解析器——按层级取字段、按字段名取值。

我建议放弃这种思路,写一段暴力提取的代码。原因是返回结构不稳定:有时候关键词没数据,某个字段返回 null,严格解析就崩了;有时候 API 那边小幅调整字段名,你的解析器又崩了。

我用的代码大概是这样:

import json

def main(api_response: dict) -> dict:
    """从 DataForSEO 响应里暴力提取关键词及指标"""
    keywords = []
    try:
        tasks
🔒
该内容仅对更高等级社区用户开放
请谨慎解锁时效性强且发布日期较早的文章
单篇解锁后若未显示全文请刷新页面
您当前:游客 · 可见 60% 内容 · 升级至 注册用户 可见 70%
👀
游客
可见 60%
✓ 当前
注册用户
注册用户
可见 70%
社区精英
社区精英
可见 100%
社区守护
社区守护
可见 100%
仅解锁本文,永久有效。如需PDF珍藏版,请联系站长获取。 当前单篇价格 ¥9.9
✏️ 发表评论

请先登录后发表评论

前往登录
📊 站点统计
今日发布0 篇
文章总数1107 篇
昨日发布1 篇
本月发布31 篇
建站时间456 天
🔍 搜索
站长微语

联系站长

QQ:2805463528
AIGC 技术社区
致力于解码 AI前沿技术 与经验分享
纯粹的技术应用社区

💡 欢迎您的建议与反馈,让社区变得更好

快速通道
联系站长
站长QQ二维码
AI交流群
AI交流群
仍在路上

那些寒夜里追赶过的方向

那些冷眼下没放弃的理想

一篇一篇写到现在

仍在路上

"不羁放纵爱自由"

—— 致敬 Beyond
持续创作中 莫潇羽 · 无忆研习社
▲