MaaFramework icon indicating copy to clipboard operation
MaaFramework copied to clipboard

当次task中,多次override_pipeline同一node,前面的会失效

Open Windsland52 opened this issue 9 months ago • 10 comments

如题,这是计划中的结果吗。

Windsland52 avatar Apr 02 '25 22:04 Windsland52

举例: 涉及 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 却变回空字典。

Windsland52 avatar Apr 02 '25 22:04 Windsland52

能不能来个最小复现案例(

MistEO avatar Apr 03 '25 01:04 MistEO

我看看

Windsland52 avatar Apr 04 '25 01:04 Windsland52

{
    "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"
        ]
    }
}

Windsland52 avatar Apr 04 '25 14:04 Windsland52

还是上面俩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'

Windsland52 avatar Apr 04 '25 14:04 Windsland52

再测试发现:

{
    "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": {}
}

Windsland52 avatar Apr 04 '25 14:04 Windsland52

后面又做了别的测试,排除agent问题,看了看cpp源码,感觉也没问题,故从自己写的custom下手。
正好看到mpa也写了同款custom,故拿来尝试,发现问题不再

Windsland52 avatar Apr 05 '25 18:04 Windsland52

原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仅最后一次生效。

Windsland52 avatar Apr 05 '25 18:04 Windsland52

再次测试发现,是当次task都如此,是不是对于每个node,会有专门的pipeline_override字段存放override内容,如果是这样,override时不直接全部替换而是覆盖是不是更合理

Windsland52 avatar Apr 05 '25 19:04 Windsland52

https://github.com/MaaXYZ/MaaFramework/issues/592#issue-2974850680 我认为问题是由于override丢失custom param导致的,修复#592应该能帮助解决此问题

Van493 avatar Apr 06 '25 02:04 Van493