微信扫码
与创始人交个朋友
我要投稿
首先我得说明一下本文提到的多参数条件判断指的是什么,为了方便大家理解,我举例说明:
当我们有两个关联的参数需要判断,假设参数有A和B.
其中A参数共计有10个值需要处理,B参数有20个值要处理。
此时,对于dify工作流开发者而言,这是一个非常头疼的事,我相信大多数开发者跟我一样,乍一看,完了,这可能要写200个对应的分支工作流。
不要觉得这两个参数的取值范围够大了,如果是企业级项目,这根本不算大的,那如果是5个参数呢?那你岂不是写分支工作流要写疯了???
多参条件判断的原则
本节我提到的原则,纯属个人观点哈,因为我在 处理这种情况的时候, 发现遵循这个原则,可以一定程度上大幅缩减分支工作流的数量,并且带来一定的可拓展性,也方便维护。
我先说下我的心得,主要有关联性的两点:
将多参判断,整体改造成单一参数判断,我喜欢称之为“降维判断”;
为保障工作流稳定性,多参处理环节,推荐使用串联模式,尽可能避免采用并行模式。
还是拿上面那个例子来说,当我们有两个参数需要关联起来判断时,如果不降低判断维度,你就得写200个分支工作流,这怎么可能呢?哪有那么多时间去写如此多的分支。
降维的主要特点,就是先判断一个,过滤掉干扰项目,保留跟参数B有必要关联的分支,然后再判断参数B,再次过滤干扰项目,最后再把两个参数有强关联的项目对应起来。
我知道说起来可能很绕,我拿自己的案例给大家说明一下:
我现在正在用dify做一个类似slg的文字游戏,后续也有想法改造成网游文字游戏。我在设计过程中,就遇到了这么一个问题:受dify当前能力的限制,文字游戏,主要又是靠玩家输入的指令触发工作流的,那么我就必须要设计一套符合游戏玩法的指令集,这个指令集也是用dify实现的。
此时,根据我对游戏玩法的规划,我希望工作流能检测用户的输入与玩家npc状态是否匹配,最终确定用户的指令是否能在当前游戏地图场景下,触发一个正确的分支工作流。
此时,我就要面对两个最核心的参数:用户输入(A)、玩家状态(B)。
参数A是玩家输入的,但是我其实并不知道玩家在真实使用的环境下,它到底会输入什么,所以我必须要检测输入的内容能否跟我预设的指令集对应。只有对应上了,后续工作流才可以继续判断,以此类推。
参数A按照规划,其取值范围对应指令集中的22个值,参数B要对应预设的6个值。
如果不考虑降维,工作流起码得长这样,条件判断套条件判断的模式,并且此时,两个条件判断还不能并行,不然就不符合我对游戏玩家的规划逻辑了。面对这种情况,我一开始头都大了,想得过于复杂,把自己给绕进去了。
于是我就仔细研究了一下dify的条件判断节点,如果这个判断,只要需要判断一个参数就好了,那岂不是不用这么疯狂嵌套了,并且还不影响我后续对指令集的扩充。
于是,骚操作就来了。
先预设一个指令集到会话变量中,使用array[object]类型,第一步检测用户的输入,是否与指令集匹配,如果不匹配,直接回复指令错误的引导。如果匹配,继续判断。
与项目某个状态值是否一致,如果一致,就返回需要触发的指令ID,如果不一致,就回复不一致。
然后用条件判断节点为每一个事件ID写一套相应的工作流即可。
于是,工作流就变成了如上图所示。
因为参数B其实好判断,但是参数A的影响因素太多,不可控性太高了,必须用过滤给他安排上,先把不符合条件的全部过滤掉,再把符合条件的找出来跟参数B对比,得出一个条件交叉的新参数,这个新参数,就是我们最终要重点设计的分支工作流的唯一凭证。这就变成了单参数的条件判断了,此时,我想怎么维护就怎么维护,无论两个参数的取值范围有多大,我都不需要大规模改动工作流,也同样适配。
这里用到的重点能力,就是dify的会话变量。首先我按照游戏的规划,预设了一个指令集commands array[object],然后玩家状态预设了一个变量player_hub array[object]。
虽然我这个游戏工作流并没有开发完,我还是愿意给大家分享一下:
commands array[object]
[{"id":1,"text":"返回基地"},{"id":2,"text":"进入星区"},{"id":3,"text":"进入星云"},{"id":4,"text":"商城"},{"id":5,"text":"活动"},{"id":6,"text":"开始战斗"},{"id":7,"text":"撤退"},{"id":8,"text":"修改战斗位"},{"id":9,"text":"改造战舰"},{"id":10,"text":"修改阵型"},{"id":11,"text":"新增战舰"},{"id":12,"text":"下架战舰"},{"id":13,"text":"查看战舰"},{"id":14,"text":"升级武器"},{"id":15,"text":"升级防御"},{"id":16,"text":"购买商品"},{"id":17,"text":"销售战利品"},{"id":18,"text":"活动商品"},{"id":19,"text":"活动规则"},{"id":20,"text":"兑换商品"},{"id":21,"text":"搜索敌人"},{"id":22,"text":"帮助"}]
看到这个ID了吗,这是预设的,每一个ID对于的事件,其实就是最终要做的分支工作流。
player_hub array[object]
[{"id":1,"des":"基地"},{"id":2,"des":"星区"},{"id":3,"des":"星云"},{"id":4,"des":"编辑舰队"},{"id":5,"des":"商城"},{"id":6,"des":"活动"}]
这个变量表示玩家当前所在的地图场景。因为按照我的游戏规划,玩家处于不同地图时候,虽然很多功能都是通用的,但是部分地图对某些功能要有限制作用。
下面是工作流某些关键节点的设计:
import json
def main(arg1: int, arg2: str, command: list) -> dict:
# 将 command_ids 转换为字典,以便快速查找
command_ids = {item["text"]: item["id"] for item in command}
actions = {
1: {
"返回基地": (1, "你已进入基地", command_ids["返回基地"]),
"进入星区": (1, "你已进入星区", command_ids["进入星区"]),
"进入星云": (1, "你已进入星云", command_ids["进入星云"]),
"商城": (1, "你已进入商城", command_ids["商城"]),
"活动": (1, "你已进入活动", command_ids["活动"]),
"开始战斗": (0, "请先输入指令:搜索敌人", command_ids["开始战斗"]),
"撤退": (0, "请先输入指令:搜索敌人", command_ids["撤退"]),
"修改战斗位": (0, "请先输入指令:编辑舰队", command_ids["修改战斗位"]),
"改造战舰": (0, "请先输入指令:编辑舰队", command_ids["改造战舰"]),
"修改阵型": (0, "请先输入指令:编辑舰队", command_ids["修改阵型"]),
"新增战舰": (0, "请先输入指令:编辑舰队", command_ids["新增战舰"]),
"下架战舰": (0, "请先输入指令:编辑舰队", command_ids["下架战舰"]),
"查看战舰": (0, "请先输入指令:编辑舰队", command_ids["查看战舰"]),
"升级武器": (0, "请先输入指令:编辑舰队", command_ids["升级武器"]),
"升级防御": (0, "请先输入指令:编辑舰队", command_ids["升级防御"]),
"购买商品": (0, "请先输入指令:商城", command_ids["购买商品"]),
"销售战利品": (0, "请先输入指令:商城", command_ids["销售战利品"]),
"活动商品": (0, "请先输入指令:活动", command_ids["活动商品"]),
"活动规则": (0, "请先输入指令:活动", command_ids["活动规则"]),
"兑换商品": (0, "请先输入指令:活动", command_ids["兑换商品"]),
"搜索敌人": (1, "你当前在基地中,不能直接搜索敌人,请进入星云或者星区", command_ids["搜索敌人"]),
"帮助": (1, "正在为你展开帮助菜单", command_ids["帮助"])
},
2: {
"返回基地": (1, "你已进入基地", command_ids["返回基地"]),
"进入星区": (1, "你已进入星区", command_ids["进入星区"]),
"进入星云": (1, "你已进入星云", command_ids["进入星云"]),
"商城": (1, "你已进入商城", command_ids["商城"]),
"活动": (1, "你已进入活动", command_ids["活动"]),
"开始战斗": (0, "请先输入指令:搜索敌人", command_ids["开始战斗"]),
"撤退": (0, "请先输入指令:搜索敌人", command_ids["撤退"]),
"修改战斗位": (0, "请先输入指令:编辑舰队", command_ids["修改战斗位"]),
"改造战舰": (0, "请先输入指令:编辑舰队", command_ids["改造战舰"]),
"修改阵型": (0, "请先输入指令:编辑舰队", command_ids["修改阵型"]),
"新增战舰": (0, "请先输入指令:编辑舰队", command_ids["新增战舰"]),
"下架战舰": (0, "请先输入指令:编辑舰队", command_ids["下架战舰"]),
"查看战舰": (0, "请先输入指令:编辑舰队", command_ids["查看战舰"]),
"升级武器": (0, "请先输入指令:编辑舰队", command_ids["升级武器"]),
"升级防御": (0, "请先输入指令:编辑舰队", command_ids["升级防御"]),
"购买商品": (0, "请先输入指令:商城", command_ids["购买商品"]),
"销售战利品": (0, "请先输入指令:商城", command_ids["销售战利品"]),
"活动商品": (0, "请先输入指令:活动", command_ids["活动商品"]),
"活动规则": (0, "请先输入指令:活动", command_ids["活动规则"]),
"兑换商品": (0, "请先输入指令:活动", command_ids["兑换商品"]),
"搜索敌人": (1, "雷达已开启,正在搜索附近敌人", command_ids["搜索敌人"]),
"帮助": (1, "正在为你展开帮助菜单", command_ids["帮助"])
},
3: {
"返回基地": (1, "你已进入基地", command_ids["返回基地"]),
"进入星区": (1, "你已进入星区", command_ids["进入星区"]),
"进入星云": (1, "你已进入星云", command_ids["进入星云"]),
"商城": (1, "你已进入商城", command_ids["商城"]),
"活动": (1, "你已进入活动", command_ids["活动"]),
"开始战斗": (0, "请先输入指令:搜索敌人", command_ids["开始战斗"]),
"撤退": (0, "请先输入指令:搜索敌人", command_ids["撤退"]),
"修改战斗位": (0, "请先输入指令:编辑舰队", command_ids["修改战斗位"]),
"改造战舰": (0, "请先输入指令:编辑舰队", command_ids["改造战舰"]),
"修改阵型": (0, "请先输入指令:编辑舰队", command_ids["修改阵型"]),
"新增战舰": (0, "请先输入指令:编辑舰队", command_ids["新增战舰"]),
"下架战舰": (0, "请先输入指令:编辑舰队", command_ids["下架战舰"]),
"查看战舰": (0, "请先输入指令:编辑舰队", command_ids["查看战舰"]),
"升级武器": (0, "请先输入指令:编辑舰队", command_ids["升级武器"]),
"升级防御": (0, "请先输入指令:编辑舰队", command_ids["升级防御"]),
"购买商品": (0, "请先输入指令:商城", command_ids["购买商品"]),
"销售战利品": (0, "请先输入指令:商城", command_ids["销售战利品"]),
"活动商品": (0, "请先输入指令:活动", command_ids["活动商品"]),
"活动规则": (0, "请先输入指令:活动", command_ids["活动规则"]),
"兑换商品": (0, "请先输入指令:活动", command_ids["兑换商品"]),
'搜索敌人':(1,'雷达已开启,正在搜索附近敌人',command_ids['搜索敌人']),
'帮助':(1,'正在为你展开帮助菜单',command_ids['帮助'])
},
4: {
'返回基地':(1,'你已进入基地',command_ids['返回基地']),
'进入星区':(1,'你已进入星区',command_ids['进入星区']),
'进入星云':(1,'你已进入星云',command_ids['进入星云']),
'商城':(1,'你已进入商城',command_ids['商城']),
'活动':(1,'你已进入活动',command_ids['活动']),
'开始战斗':(0,'请先输入指令:搜索敌人',command_ids['开始战斗']),
'撤退':(0,'请先输入指令:搜索敌人',command_ids['撤退']),
'修改战斗位':(1,'正在为你启动舰队编辑功能',command_ids['修改战斗位']),
'改造战舰':(1,'正在为你启动舰队编辑功能',command_ids['改造战舰']),
'修改阵型':(1,'正在为你启动舰队编辑功能',command_ids['修改阵型']),
'新增战舰':(1,'正在为你启动舰队编辑功能',command_ids['新增战舰']),
'下架战舰':(1,'正在为你启动舰队编辑功能',command_ids['下架战舰']),
'查看战舰':(1,'正在为你启动舰队编辑功能',command_ids['查看战舰']),
'升级武器':(1,'正在为你启动舰队编辑功能',command_ids['升级武器']),
'升级防御':(1,'正在为你启动舰队编辑功能',command_ids['升级防御']),
'购买商品':(0,'请先输入指令:商城',command_ids['购买商品']),
'销售战利品':(0,'请先输入指令:商城',command_ids['销售战利品']),
'活动商品':(0,'请先输入指令:活动',command_ids['活动商品']),
'活动规则':(0,'请先输入指令:活动',command_ids['活动规则']),
'兑换商品':(0,'请先输入指令:活动',command_ids['兑换商品']),
'搜索敌人':(1,'雷达已开启,正在搜索附近敌人',command_ids['搜索敌人']),
'帮助':(1,'正在为你展开帮助菜单',command_ids['帮助'])
},
5: {
'返回基地':(1,'你已进入基地',command_ids['返回基地']),
'进入星区':(1,'你已进入星区',command_ids['进入星区']),
'进入星云':(1,'你已进入星云',command_ids['进入星云']),
'商城':(1,'你已进入商城',command_ids['商城']),
'活动':(1,'你已进入活动',command_ids['活动']),
'开始战斗':(0,'请先输入指令:搜索敌人',command_ids['开始战斗']),
'撤退':(0,'请先输入指令:搜索敌人',command_ids['撤退']),
'修改战斗位':(0,'请先输入指令:编辑舰队',command_ids['修改战斗位']),
'改造战舰':(0,'请先输入指令:编辑舰队',command_ids['改造战舰']),
'修改阵型':(0,'请先输入指令:编辑舰队',command_ids['修改阵型']),
'新增战舰':(0,'请先输入指令:编辑舰队',command_ids['新增战舰']),
'下架战舰':(0,'请先输入指令:编辑舰队',command_ids['下架战舰']),
'查看战舰':(0,'请先输入指令:编辑舰队',command_ids['查看战舰']),
'升级武器':(0,'请先输入指令:编辑舰队',command_ids['升级武器']),
'升级防御':(0,'请先输入指令:编辑舰队',command_ids['升级防御']),
'购买商品':(1,'商品列表已获取',command_ids['购买商品']),
'销售战利品':(0,'战利品正在盘点,将开启自动结算功能',command_ids['销售战利品']),
'活动商品':(0,'请先输入指令:活动',command_ids['活动商品']),
'活动规则':(0,'请先输入指令:活动',command_ids['活动规则']),
'兑换商品':(0,'请先输入指令:活动',command_ids['兑换商品']),
'搜索敌人':(0,'你当前在商城中,不能直接搜索敌人,请进入星云或者星区',command_ids['搜索敌人']),
'帮助':(1,'正在为你展开帮助菜单',command_ids['帮助'])
},
6: {
'返回基地':(1,'你已进入基地',command_ids['返回基地']),
'进入星区':(1,'你已进入星区',command_ids['进入星区']),
'进入星云':(1,'你已进入星云',command_ids['进入星云']),
'商城':(1,'你已进入商城',command_ids['商城']),
'活动':(1,'你已进入活动',command_ids['活动']),
'开始战斗':(0,'请先输入指令:搜索敌人',command_ids['开始战斗']),
'撤退':(0,'请先输入指令:搜索敌人',command_ids['撤退']),
'修改战斗位':(0,'请先输入指令:编辑舰队',command_ids['修改战斗位']),
'改造战舰':(0,'请先输入指令:编辑舰队',command_ids['改造战舰']),
'修改阵型':(0,'请先输入指令:编辑舰队',command_ids['修改阵型']),
'新增战舰':(0,'请先输入指令:编辑舰队',command_ids['新增战舰']),
'下架战舰':(0,'请先输入指令:编辑舰队',command_ids['下架战舰']),
'查看战舰':(0,'请先输入指令:编辑舰队',command_ids['查看战舰']),
'升级武器':(0,'请先输入指令:编辑舰队',command_ids['升级武器']),
'升级防御':(0,'请先输入指令:编辑舰队',command_ids['升级防御']),
'购买商品':(0,'请先输入指令:商城',command_ids['购买商品']),
'销售战利品':(0,'请先输入指令:商城',command_ids['销售战利品']),
'活动商品':(1,'斥候已打听到血鸦正在兜售一些商品,正在加载商品列表',command_ids['活动商品']),
'活动规则':(1,'斥候已打听到一些关键情报,正在加载活动信息',command_ids['活动规则']),
'兑换商品':(1,'正在检测活动积分,将启动商品对话服务',command_ids['兑换商品']),
'搜索敌人':(0,'你当前在商城中,不能直接搜索敌人,请进入星云或者星区',command_ids['搜索敌人']),
'帮助':(1,'正在为你展开帮助菜单',command_ids['帮助'])
}
}
state_actions = actions.get(arg1, {})
response = state_actions.get(arg2, (None, None, None))
a, text, b = response
return {
"a": a,
"text": text,
"arg1": arg1,
"arg2": arg2,
"b": b
}
最后就是为b写一个条件判断就OK了,是不是很简单,并且B的取值范围是指令集ID,指令集有多少个ID,你就写多少个分支就行。
是不是豁然开朗了?
说点个人感悟吧:
dify很好用,基础能力其实已经很强大了,开箱即用,我反正是无脑吹捧的,因为我从去年就开始玩这个。
虽然自己之前用dify做了两个简单点的文字游戏,随着dify版本更新,推出了更多的能力,dify逐渐满足去开发一个复杂项目的基础条件,只是好像很多人对dify的初印象还停留在用来写提示词的。
光鼓吹是没用的,我还是有一些不满意的地方,我给大家举两个例子:
就拿我上述的案例来说吧,dify官方版本如果某一天能延长工作流执行深度和单支节点数量,我这个游戏项目,我就敢大肆扩充我的指令库,从而不用担心系统限制而不敢玩的太激进,否则我就得自己动手去修改dify的源码了。
dify目前要是能直接支持远程,mysql数据库就好了,因为我后续确实有计划:只要本地文字版游戏工作流能跑通,就改造成网游版本,将玩家数据云端存储,实现网游化。
53AI,企业落地应用大模型首选服务商
产品:大模型应用平台+智能体定制开发+落地咨询服务
承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2024-04-25
2024-04-24
2024-07-20
2024-07-16
2024-05-08
2024-05-07
2024-05-09
2024-06-21
2024-04-25
2024-08-06