当次task中,多次override_pipeline同一node,前面的会失效
如题,这是计划中的结果吗。
举例: 涉及 NodeOverride 和 DisableNode两个custom动作,于 https://github.com/MaaXYZ/M9A/blob/main/agent/custom/action/general.py 中定义
先命中
"BankPurchase_RabbitFail": {
"recognition": "TemplateMatch",
"template": "Bank/NoMoney.png",
"roi": [
987,
83,
278,
182
],
"action": "Custom",
"custom_action": "NodeOverride",
"custom_action_param": {
"NoRabbit": {
"recognition": "DirectHit"
}
},
"next": [
"Bank_ClickBlank"
]
}
后面过一个节点结束当前 interrupt 内任务链,由于修改 NoRabbit 节点,直接进入该 next 节点。
"NoRabbit": {
"recognition": "OCR",
"expected": ".+",
"replace": [
"独一律",
""
],
"roi": [
325,
286,
87,
23
],
"only_rec": true,
"action": "Custom",
"custom_action": "DisableNode",
"custom_action_param": {
"node_name": "Rabbit"
},
"next": [
"PurchaseRecord_Rabbit"
]
}
这是运行会有报错:
Exception ignored on calling ctypes callback function: <function CustomAction._c_run_agent at 0x000001E72BAFD4E0>
Traceback (most recent call last):
File "D:\github\M9A\install\python\Lib\site-packages\maa\custom_action.py", line 73, in _c_run_agent
result: Union[CustomAction.RunResult, bool] = self.run(
^^^^^^^^^
File "d:\github\M9A\install\agent\custom\action\general.py", line 77, in run
node_name = json.loads(argv.custom_action_param)["node_name"]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
KeyError: 'node_name'
表明 custom_action 字段还是 DisableNode,但原有的 custom_action_param 却变回空字典。
能不能来个最小复现案例(
我看看
{
"first": {
"action": "Custom",
"custom_action": "NodeOverride",
"custom_action_param": {
"second": {
"next": []
}
},
"next": [
"second"
]
},
"second": {
"action": "Custom",
"custom_action": "DisableNode",
"custom_action_param": {
"node_name": "first"
},
"next": [
"first"
]
}
}
还是上面俩custom action,报错:
Exception ignored on calling ctypes callback function: <function CustomAction._c_run_agent at 0x000001F7D4DED4E0>
Traceback (most recent call last):
File "D:\github\M9A\install\python\Lib\site-packages\maa\custom_action.py", line 73, in _c_run_agent
result: Union[CustomAction.RunResult, bool] = self.run(
^^^^^^^^^
File "d:\github\M9A\install\agent\custom\action\general.py", line 77, in run
node_name = json.loads(argv.custom_action_param)["node_name"]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
KeyError: 'node_name'
再测试发现:
{
"first": {
"action": "Custom",
"custom_action": "NodeOverride",
"custom_action_param": {
"second": {
"next": [
"first",
"third"
],
"custom_action_param": {
"node_name": "first"
}
}
},
"next": [
"second"
]
},
"second": {
"action": "Custom",
"custom_action": "DisableNode",
"custom_action_param": {
"node_name": "first"
},
"next": [
"first"
]
},
"third": {}
}
上面这样会报错,但下面居然不会:
{
"first": {
"action": "Custom",
"custom_action": "NodeOverride",
"custom_action_param": {
"second": {
"custom_action_param": {
"node_name": "first"
}
}
},
"next": [
"second"
]
},
"second": {
"action": "Custom",
"custom_action": "DisableNode",
"custom_action_param": {
"node_name": "first"
},
"next": [
"first"
]
},
"third": {}
}
后面又做了别的测试,排除agent问题,看了看cpp源码,感觉也没问题,故从自己写的custom下手。
正好看到mpa也写了同款custom,故拿来尝试,发现问题不再
原custom:
class NodeOverride(CustomAction):
"""
在 node 中执行 pipeline_override 。
参数格式:
{
"node_name": {"被覆盖参数": "覆盖值"},
"node_name1": {"被覆盖参数": "覆盖值"}
}
"""
def run(
self,
context: Context,
argv: CustomAction.RunArg,
) -> CustomAction.RunResult:
nodes = json.loads(argv.custom_action_param)
for node in nodes:
for key in nodes[node]:
print({f"{node}": {f"{key}": nodes[node][key]}})
context.override_pipeline({f"{node}": {f"{key}": nodes[node][key]}})
return CustomAction.RunResult(success=True)
MPA版:
class PPOverride(CustomAction):
def run(
self, context: Context, argv: CustomAction.RunArg
) -> CustomAction.RunResult:
argv = json.loads(argv.custom_action_param)
if not argv:
return CustomAction.RunResult(success=True)
context.override_pipeline(argv)
return CustomAction.RunResult(success=True)
测试node焦点:
"first": {
"action": "Custom",
"custom_action": "NodeOverride",
"custom_action_param": {
"second": {
"next": [
"first",
"third"
],
"custom_action_param": {
"node_name": "first"
}
}
}
}
分析知,前者override顺序为:
{'second': {'custom_action_param': {'node_name': 'first'}}}
{'second': {'next': ['first', 'third']}}
符合python遍历有序字典的顺序,结合之前的现象可以猜想,同一个action中对同一node的多次override仅最后一次生效。
再次测试发现,是当次task都如此,是不是对于每个node,会有专门的pipeline_override字段存放override内容,如果是这样,override时不直接全部替换而是覆盖是不是更合理
https://github.com/MaaXYZ/MaaFramework/issues/592#issue-2974850680 我认为问题是由于override丢失custom param导致的,修复#592应该能帮助解决此问题