ComfyUIのDynamicPromptsの出力過多問題を修正した

起きる事象

comfyUIで使っているDynamicPromptsというカスタムノードが、下のようなアウトプットをほぼすべてのwildcardsで出す問題が長らく発生していた。いつからかはよくわかってない。

Unsupported list item: <MyValue1>
Unsupported list item: <MyValue2>
Unsupported list item: ...
Unsupported list item: ...
...

なお、これは、wildcards機能を使って、yamlファイルからプロンプトを生成している場合に起こっていた。

原因の発見

comfyUIのディレクトリをVSCodeで開いて、Ctrl+Shift+FからのUnsupported list itemで検索すると、ComfyUI\venv\Lib\site-packages\dynamicprompts\wildcards\collection\structured.pyというファイルがヒットする。

その中の、以下のコードが原因だった:


def _parse_structured_file_list(value: list[Any]) -> Iterable[str | WildcardItem]:
    """
    Parse a single list in a structured file (JSON or YAML) and yield the wildcard items.
    """
    for item in value:
        if not item:
            continue
        if isinstance(item, str):
            # See if the item _could_ have a prefix weight before attempting to parse.
            if item[0].isdigit() and "::" in item:
                weight_text, _, content = item.rpartition("::")
                try:
                    yield WildcardItem(content=content, weight=float(weight_text))
                    continue
                except ValueError:
                    # When failing to parse the weight,
                    # fall through to yielding the item as-is.
                    pass
            yield item
        elif isinstance(item, dict):
            # Support {"text": "foo", "weight": 1.1} syntax
            #     and {"content": "foo", "weight": 1.1}
            weight = float(item.get("weight", 1))
            content = item.get("text") or item.get("content") or ""
            if content:
                if weight == 1:
                    yield content
                else:
                    yield WildcardItem(content=content, weight=weight)
                continue
        log.warning("Unsupported list item: %s", item)

この最後の行の出力が大量に出ている模様。

問題を修正

ちょっと調べてみると、問題の出力はここのisinstance(item, str)を通って、yield itemでyieldしていた。そのあと、最後尾の文が実行されるので、出力が垂れ流しになってしまっていたようだ。

なので、yieldしたあと、continueするようにすればいい。修正はこのように:


def _parse_structured_file_list(value: list[Any]) -> Iterable[str | WildcardItem]:
    """
    Parse a single list in a structured file (JSON or YAML) and yield the wildcard items.
    """
    for item in value:
        if not item:
            continue
        if isinstance(item, str):
            # See if the item _could_ have a prefix weight before attempting to parse.
            if item[0].isdigit() and "::" in item:
                weight_text, _, content = item.rpartition("::")
                try:
                    yield WildcardItem(content=content, weight=float(weight_text))
                    continue
                except ValueError:
                    # When failing to parse the weight,
                    # fall through to yielding the item as-is.
                    pass
            yield item
            continue ### ここに追加する。最下部のログ出力を抑えるため。###
        elif isinstance(item, dict):
            # Support {"text": "foo", "weight": 1.1} syntax
            #     and {"content": "foo", "weight": 1.1}
            weight = float(item.get("weight", 1))
            content = item.get("text") or item.get("content") or ""
            if content:
                if weight == 1:
                    yield content
                else:
                    yield WildcardItem(content=content, weight=weight)
                continue
        log.warning("Unsupported list item: %s", item)

これで直る。

そのほか

この部分のスクリプトは、カスタムノードから切り離されている、dynamicpromptsのコア部分に相当する。外部モジュールとしてこれを利用しているので、このスクリプトはカスタムノード部分のコードには存在しておらず、ふつうはvenvディレクトリの中に存在するはずである。

また、githubにあるこのスクリプトのコードを見ると、上の修正と同じようにcontinueがされていた。どうやら古いバージョンのdynamicpromptsコアモジュールが何かの原因でインストールされているため、このような出力大量を起こしていたようだ。

以上です。

タイトルとURLをコピーしました