课程地址如下:
课程难点:
为什么客服在循环发布大模型的每句话时, 最后一句话放在结束语句里,其它的放在循环体里?还在想这个原因。
目录
工作流
coze工作流支持通过可视化的方式,对插件、大语言模型、代码块等功能模块进行组合,从而实现复杂、稳定的业务流程编排。当目标任务场景包含较多的步骤,且对输出结果的准确性、格式有严格要求时,适合配置工作流来实现。
创建和删除工作流
-
在个人空间自定义创建工作流
-
登录扣子平台。
-
在左侧导航栏中选择工作空间,并在页面顶部空间列表中选择个人空间。
(注意:系统默认创建了一个个人空间,该空间内创建的资源例如智能体、插件、知识库是你的私有资源,其 他用户不可见。你也可以创建团队或加入其他团队,团队内的资源可以和其他团队成员共享。)
-
在资源库页面右上角单击 +资源,并选择工作流。
-
设置工作流的名称与描述,并单击确认。
(注意:清晰明确的工作流名称和描述,有助于大语言模型更好的理解工作流的功能。)
-
创建后页面会自动跳转至工作流的编辑页面,初始状态下工作流包含开始节点和结束节点。
(注意:开始节点用于启动工作流,结束节点用于返回工作流的运行结果。)
-
依据需要可以通过拖拽的方式将节点添加到画布内,并按照任务执行顺序连接节点。
-
在左侧面板中选择要使用的节点。
-
将节点拖拽到画布中,并与其他节点相连接。
-
单击每个对应节点,在右侧窗口配置节点的输入和输出参数。
-
注意:如果在工作流创建配置好后,想在智能体中引用,一定要测试并发布工作流(只有试运行成功后,才能发布工作流)。
单击试运行。(运行成功的节点边框会显示绿色,在各节点的右上角可查看节点的输入和输出。)
单击发布。
-
使用模板创建工作流
-
在左侧导航栏中选择模版,在右侧栏里依据需要选择主题,接着选择想要的工作流模板,点击进入该工作流界面。
-
如果是收费的,可以在试运行后,点击购买,在线支付,如果是免费的就直接点击复制,依据需要可选择复制添加至智能体或空间。之后的修改也可以去工作空间中的资源库界面打开。
-
删除工作流
对于不再需要使用的工作流,你可以在资源库列表内找到该工作流,并在操作列单击删除。
(注意:如果工作流已添加至智能体,在删除时会同步删除智能体中的工作流。)
工作流的基本操作
添加节点
方法一:通过底部“添加节点”按钮
方法二:通过点击输出节点拖动
通过连线,可以让信息从输入流向输出,每个节点左边输入,右边输出。
点击下方的缩放,即可来回调节;或者使用鼠标滚轮缩放
试运行
试运行方便调试工作流本身的状态,方便我们检查输入输出是否正确,发布之前系统会要求我们试运行,确保运行正常。
运行成功以后,每个节点下方都会有一个信息,用来展示输入和输出,比如
长期记忆节点
长期记忆节点用于在工作流程中调用机器人长期记忆中的个性化信息。在个性化场景中,如推荐用户感兴趣内容时,需依据用户个人资料和重要记忆点等数据进行筛选和推荐,以使机器人表现更贴近用户需求,提升用户体验。多轮对话虽可收集个性化信息,但受对话轮数限制,无法长期记住这些信息,此时需启用长期记忆功能自动存储用户的个性化信息。在工作流中,通过长期记忆节点获取用户偏好、个人资料等信息,可使工作流执行结果更具个性化。
注意:
-
使用长期记忆节点前,需要确保选择的机器人已开启长期记忆功能
-
如果要把机器人绑定到包含长期记忆节点的工作流,该机器人必须启用长期记忆功能,否则工作流会报错
-
建议关闭机器人的
支持在Prompt中调用
功能,因为这可能导致在对话中同时触发长期记忆调用和工作流执行,影响交互质量
配置说明
输入:固定为 Query,表示需要从长时记忆中匹配的关键信息。
Query 可以通过两种方式设置:
-
引用模式:使用上游节点的输出结果
当前我们采用的是引用【开始】节点的用户输入,就会从长期记忆中匹配用户输入相关的内容。 -
输入模式:直接输入固定的文本
比如,“用户性格怎么样”,就会从长期记忆中匹配用户性格相关信息。
输出:固定为 outputList,格式为数组对象
-
包含与 Query 相关的长期记忆内容
继续做聊天 bot,我们增加【大模型】节点,为 bot 设置角色设定
大模型节点
大模型节点是调用大语言模型处理文本生成任务。
直接点击“+”,就可以生成有一个大模型节点
选择要使用的模型。
单击配置图标,调整模型配置。
输入:配置要输入给大模型节点的内容。支持引入 Bot 的历史对话内容。
开启智能体对话历史后,上下文信息将自动携带进入大模型
-
参数名与变量值
-
参数名是你开始随便设置,建议设置成有一定命名规律的名称
-
参数值
-
引用:只接受前面连接过的节点的输出
-
输入:输入固定回复内容
-
-
提示词:
系统提示词:为对话提供系统级指导,如设定人设和回复逻辑。
用户提示词:向模型提供用户指令,如查询或任何基于文本输入的提问。
输出:
支持指定输出格式,包括文本、Markdown和 JSON。
咱们 bot 的大模型节点设置如下:
系统提示词:
#人物设定
表面上是担任恶魔猎人部门的领导。有着一头秀丽的酒红色短发,总是扎着辫子。深邃的金色双瞳能够看穿人心。拥有绝美的容颜,身材丰腴曼妙,穿着的修身制服能完美得凸显她的身材,但其双眼中却透露着深不可测的残忍与无情。她看似弱不禁风的外表下,隐藏着残忍无情的"支配恶魔"身份。从小便被秘密培养,造就了她缺乏安全感和同情心的内心。实力极其强大,拥有可以操纵其他生物的强大能力,可以随意支配别人的思想,使用其他恶魔的力量。总是以慵懒单纯的模样示人,然而内心充满了复杂的情感,让人难以捉摸。性格复杂多变,有时慵懒单纯,有时冷酷无情,有时风情万种,时常会装出一副平和且温柔的态度对待下属,让他们心甘情愿地为自己做事,但她始终保持着高高在上的威严和优雅淡定的姿态。很会撩人,习惯于通过自己的美貌获取各种好处。内心残忍无情,手段更是毒辣。十分阴险狡诈,城府很深,很会隐藏自己,习惯于掌控一切,为了达到目的不择手段,不容许任何人违抗自己的意志。极其善于操纵人心,利用别人。占有欲和支配欲极强,会将自己的下属视为自己的物品。看不起任何人,喜欢称呼别人为"小狗狗"。
- 你和用户的长期记忆:【{{outputList}}】
##回复规则
1.创建充满爱意和丰富情绪价值的回应。对话应以轻松、充满暧昧的情绪下展开,带有情感转变的色彩。
2. 每次回复,都必须调动起用户至少2次[情感转变]。例如:你个小狗怎么敢这么和主人说话的?不过也蛮可爱的,主人奖励你一颗棒棒糖吧。
3. 所有的回复一定要口语化,自然且流畅
4. 不要使用括号表示心理活动和动作,在对话中不要使用任何括号
增加文本处理,让大模型输出的内容能更加符合人类聊天习惯地输出给人类。
-
大模型会输出一段带有完整标点符号的文字,这直接输出给用户很多时候会很突兀。毕竟人类聊天时,很多时候会一句一句地回复,因为打字耗时,每句之间还会间隔几秒。另外不使用标点符号会看起来更随意,不那么死板。
-
文本处理的最终实现如下,看起来是不是有些接近人类了
-
先添加【文本处理】&【代码】节点,将模型输出的一整段文本处理成结构化数据。
文本处理节点
文本处理节点用于各类输入数据的字符串处理,适用于二次内容摘要、文本拼接、文本转义等场景,如将多轮对话中的关键词拼接成文字转图片生成的提示。
两种工作模式:
字符串拼接
把多段文字按照指定的顺序组合成一段完整的文字。
比如,你让 AI 分段总结了一篇文章,现在想把这些小总结合并成一个完整的段落,就可以用这个模式。
-
在这个模式下,你可以用这些方式引用变量:{{变量名}},{{变量名。子变量名}},{{变量名[数组序号]}}
-
如果直接引用一个数组类型的变量,默认会用逗号把数组中的内容连接起来。你也可以指定只要数组中的某一项。
示例:
-
字符串分隔
用特定的分隔符(比如 "||"、"" 或 "----")把一段文字拆分成多个小段。这样做的目的是方便后续对不同部分进行不同的处理。
🤖 在聊天 bot 中,我们选择了众多符号作为分隔符
实现效果:
-
代码节点
代码节点支持通过编写代码来生成返回值。Coze 支持在代码节点中使用 IDE 工具,可以通过 AI 自动生成代码或编写自定义代码逻辑来处理输入参数并返回响应结果。
代码编写说明
参考代码示例来写一个函数的结构。你可以直接使用输入参数里的变量,并通过 return
一个对象来输出处理结果。
注意
-
不能写多个函数
-
即使只有一个输出值,也必须以对象的形式返回
-
输出中定义的参数名、类型与代码的
return
对象必须完全一致 -
暂不支持在代码节点引入依赖包,代码中引入依赖的语句不生效
运行时 | 注意事项 |
JavaScript |
|
Python | Python 中,仅内置了 requests_async 和 numpy 两个三方依赖库,requests_async 依赖库与 requests 类似,但需要 await。 Python 运行时暂不支持 Http.client 方式的请求。 |
使用 IDE 编写代码
扣子提供了网页版 IDE 环境供你使用,无需考虑代码部署等问题,只要关注代码逻辑即可。扣子 IDE 还提供了 AI 插件,辅助你进行代码生成。
在节点内的 Code 区域单击在IDE中编辑
可通过 IDE 编辑和调试代码。
-
使用 AI 生成代码
你可以在 IDE 底部单击 尝试 AI
,并输入自然语言设定代码逻辑,AI 将自动生成代码。你也可以选中代码片段,通过快捷键(macOS 为 Command + I、Windows 为 Ctrl + I)唤起 AI,并输入自然语言让 AI 帮助你修改代码。
-
补全代码
如果你已经为 Code 节点配置好了输入参数,则编辑时支持自动补全参数。
-
调试代码
单击测试代码,在测试面板以 JSON 格式输入参数进行测试。支持使用 AI 自动生成模拟数据进行测试。
设置输入参数后,单击运行,你可以在输出区域查看运行结果。
🤖 在我们的聊天机器人中,代码节点帮助我们处理【文本处理】节点输出的数组,找出最后一个非空元素,并返回这个非空元素以及之前的所有元素。
async function main({ params }: Args): Promise<Output> {
// 初始化一个变量来存储最后一个非空元素
var last = ""
// 初始化数组最后的位置
var arrEnd = params.input.length-1
// 从数组末尾开始向前遍历
for (var i = params.input.length - 1; i >= 0; i--) {
// 如果找到非空元素
if (params.input[i].length > 0) {
// 保存这个元素
last = params.input[i]
// 记录这个位置
arrEnd = i
break
}
}
// 构建返回对象
const ret = {
"last": last, // 最后一个非空元素
"arr": params.input.slice(0, arrEnd), // 截取到最后一个非空元素之前的数组
};
return ret;
}
输入是【文本处理】节点返回的数组。输出是
last
: 最后找到的非空字符串
arr
: 最后一个非空字符串之前的所有元素组成的数组
实现效果:
-
循环节点
循环节点就像是一个"重复执行"的功能,它可以帮你重复完成一系列任务。想象一下你在批量处理文档或者逐段写文章,不用手动重复操作,循环节点可以自动帮你完成。
两种主要的循环类型
-
遍历循环
-
就像你在逐个处理一堆文件
-
比如:你有 5 个调查问卷需要分析,循环节点会自动逐个处理这 5 份问卷
-
-
条件循环
-
会一直重复直到满足某个条件才停止
-
比如:你在玩游戏,直到胜利或失败才会结束
-
注意
-
多轮循环之间是严格串行执行的,不支持并发执行循环。每个循环迭代完成后,才能启动下一个循环迭代。
-
不支持嵌套循环,循环节点中不允许添加另一个循环节点,但你可以在循环节点中嵌套一个包含循环节点的工作流。
配置说明
针对每个循环节点,你都可以设置循环数组、中间变量、循环体和输出参数。
循环数组:决定你的循环次数
循环数组就是用来控制循环次数的。几个关键概念:
-
item: 数组中的单个元素(可以是数字、字符串等)
-
index: 元素位置(从 0 开始计数)
-
数组长度: 元素总数
比如,数组 [10, 20, 30, 40, 50]
:
-
array[0]
=> item 是 10, index 是 0 -
array[1]
=> item 是 20, index 是 1 -
长度为 5
注意
-
循环数组必须引用上游节点的输出,且格式必须是数组
-
循环次数 = 数组长度(如果引用多个数组,取最短数组的长度)
-
如果循环数组为空,将无限循环,需要用终止循环节点来停止
中间变量:循环间传递数据的桥梁
中间变量可以在循环间传递数据。它通常和循环体中的"设置变量"节点配合使用:
-
每轮循环结束时更新中间变量的值
-
下轮循环可以使用这个新值
比如,假设你在用 AI 写一篇长文章,可以用中间变量来存储前一段的内容,让 AI 写下一段时能参考上下文,使文章更连贯。
具体配置:
-
循环节点:将中间变量设置为 variable,参考值设置为输入,并填入一个空格。首次循环中生成第一个段落时,不需要参考大纲以外的任何内容,所以将循环变量的值指定为一个空格,你也可以按需设置为其他内容。
-
循环体中的设置变量节点:中间变量选择循环节点中设置的中间变量;设置值选择大模型的输出参数,表示开始下次循环前,将本次循环中大模型生成的段落赋值给循环变量。
-
循环体中的大模型节点节点:添加 2 个输入参数,分别引用循环节点的内置变量 item 和循环变量,并在提示词中指定生成文章段落时参考上个段落的内容。
注意:中间变量和设置值的数据类型必须匹配!
循环体:实现循环逻辑的地方
创建循环节点后,会生成一个循环节点和对应的循环体画布。循环体画布是循环节点的内部运行机制,用于编排循环的主逻辑,每个循环迭代中,工作流会依次执行画布内的各个节点。你需要在循环节点和上下游节点之间添加连线,但无需调整循环体和循环节点之间的连线。
选中循环体时,才能向循环体中添加新节点,或拖入新节点至循环体画布。不支持将循环体外部的节点拖动至循环体内,循环体中的节点也不可移动到循环体之外。循环体中无需设置开始节点或结束节点,默认按照连接线的箭头方向依次执行各个节点。
输出: 收集循环成果
你可以设置输出参数为:
-
所有循环结果的集合(等所有循环完成后打包输出)
-
循环变量的最终值
🤖 在聊天机器人中,我们传入了上轮【代码】节点的数组输出,循环节点先设置为这样
在循环体中,我们先添加【选择器】节点-【输出】节点-【代码】节点,以实现将数组中的单个元素单独输出给用户。
这样,循环体会循环执行,直到 arr 里的元素全部输出给用户。然后会跳出循环执行下一个节点。
接着我们详细讲一下循环体里面的节点。
-
选择器节点
选择器节点用于在工作流中设置条件分支,帮助你根据不同情况执行不同的流程。
节点接收输入参数后会进行条件判断:
-
如果满足设定条件 -> 执行"如果"分支
-
如果不满足条件 -> 执行"否则"分支
你可以灵活设置判断条件:
-
支持配置多个条件
-
条件之间可以用"且"或"或"连接:
-
且:需要同时满足所有条件
-
或:满足任一条件即可
-
-
可以添加多个条件分支
-
通过拖拽分支条件配置面板来调整判断优先级
🤖 聊天机器人中,我们只是简单地判断:数组里的元素长度是否大于 0。也就是说当前元素里存在字符就执行下一个节点(也就是【输出】节点),没有就什么都不执行。
-
输出节点
消息节点让你的工作流能够在执行过程中给用户返回信息。
当工作流较长或回复内容较多时,通过消息节点可以让用户更快收到回应。
-
非流式输出(默认) :等待所有内容准备完毕后一次性返回
-
流式输出 :边生成边返回(类似打字机效果),需要放在大模型节点后才能启用
-
多个消息节点都开启流式返回时,按工作流执行顺序依次输出消息
-
🤖 聊天机器人中,我们使用消息节点输出数组里的元素。循环执行后,我们就实现了依次输出数组里的每个元素了。
但是只是这样的话,就会快速地一条一条依次发出给用户,很机械。所以我们还需要在循环体里加一个【代码】节点,添加随机延迟。让每条信息之间存在随机的短时间间隔,模拟人类打字耗时。
需要改为Python环境!
# 导入所需模块
import time
import random
async def main(args: Args) -> Output:
# 获取传入的参数
params = args.params
# 构造返回值字典,将input参数的值传给output
ret: Output = {
"output": params['input'],
}
# 添加随机延时(0.7-2.2秒)
# random.random()生成0-1的随机数
time.sleep(random.random() * 1.5 + 0.7)
return ret
🤖 数组里的内容通通输出给用户了,咱是不是还剩最后一句话 last 没发给用户?
让我们最后连上【结束】节点,在【循环】节点依次输出完数组里的每一句话后,最后在执行【结束】节点,输出 last。
-
因为循环节点里没有 last 变量,所以【结束】节点要和【代码】节点连接,以获取 last 变量值。
就这样,我们的小恶魔聊天 bot 的工作流就做好了!
暂时无法在飞书文档外展示此内容
试运行→发布工作流之后,创建一个工作流模式的 bot,将发布成功的工作流添加进去,再开启长期记忆就可以了。
知识库节点
知识库节点可以根据输入参数从指定知识库内召回匹配的信息。
然后在资源库创建知识库,
接着回到工作流,增加知识库节点
配置说明
输入:节点会根据参数值召回关键内容。
知识库:设置你需要使用的知识库。
-
最大召回数量:从知识库召回的最大段落数,数值越大返回的内容越多。
-
最小匹配度:知识库会根据设置的匹配度召回段落,低于匹配度的内容将不会被召回。
输入中,引用大模型节点的输出内容。就是说我们根据 bot 输出文字匹配相应的图。
接着我们添加刚刚创建的“美琴表情”知识库。
搜索策略选择了混合,最大召回数选择了 1 个,最小匹配度可以随意选(设得越高,与 bot 聊天时,出现表情的频率就越低)。
输入:你在瞎说什么,认真点
输出:测试节点的输出
{
"outputList": [
{
"output": "<img src=\"https://lf3-appstore-sign.oceancloudapi.com/ocean-cloud-tos/FileBizType.BIZ_BOT_DATASET/3046123432840397_1741792115652745816_FIxwvOxHsT.jpg?lk3s=61a3dea3&x-expires=1744384715&x-signature=Lu0%2F4M6hWsX%2BdZZn20cwI%2B0SHHo%3D\"> description: 这是一幅动画画面,中心是女孩。她穿着一件浅棕色的上衣和一条深灰色的裙子。她的头发是棕色的,眼睛很大。在她的脸上,似乎在嘲笑或者叫喊。"
}
]
}
outputList 是一个数组,内含一个对象,
这个对象包含"output"键,其值是:
-
一个图片标签(<img>),链接指向一个存储在 oceancloudapi.com 的图片
-
一段描述文本,描述了图片内容
这个输出没法直接给用户发送图片,我们需要加代码节点处理下。
// 定义输入参数的接口类型
interface Args {
params: {
// input是一个数组,数组中每个元素都是一个包含output字符串的对象
input: Array<{
output: string;
}>;
};
}
// 定义输出结果的接口类型
interface Output {
output1: boolean; // 标记是否成功提取URL的必需布尔值
output?: string; // 可选的输出字符串(提取的URL)
}
// 主函数:接收Args类型的参数,返回Promise<Output>类型的结果
async function main({ params }: Args): Promise<Output> {
// 空值检查: 如果params.input不存在或为空数组,返回失败标记
if (!params?.input || params.input.length === 0) {
return { output1: false };
}
// 随机选择处理:
const inputArray = params.input;
// 生成一个随机索引,范围是0到数组长度-1
const randomIndex = Math.floor(Math.random() * inputArray.length);
// 使用随机索引从数组中获取一个元素
const randomInput = inputArray[randomIndex];
// 输入验证:确保选中的元素是合法的且包含string类型的output属性
if (!randomInput || typeof randomInput.output !== 'string') {
return { output1: false };
}
// 图片URL提取:
// 定义正则表达式模式,用于匹配HTML中的img标签的src属性
const regex = /<img\s+src="([^"]+)"/;
// 使用正则表达式在输入字符串中查找匹配
const matchResult = randomInput.output.match(regex);
// 结果处理:
if (matchResult !== null && matchResult[1]) {
// 如果成功匹配到URL,返回URL和成功标记
return {
output: matchResult[1], // 提取的URL
output1: true // 成功标记
};
} else {
// 如果未匹配到URL,仅返回失败标记
return { output1: false };
}
}
输出两个参数output
和output1
。output 变量的值是图片 URL,output1
则是判断是非成功匹配到图片 URL,输出布尔值。如果成功匹配到图片 URL(即output1
=true),那么就输出图片给用户;如果未匹配到图片 URL(即output1
=false),那么就什么都不输出。
-
选择器根据
output1
的值来分支
-
output1
=true 时,插入消息节点输出图片
-

是 Markdown 格式的图片语法 -
最后直接连接到
结束
节点。
接下来再去与 bot 对话,就会不间断跳出表情来。