メむンコンテンツぞスキップ
芋出し画像

How to fix GetPrototype to GetMessageClass on TensorFlow

    いやはや....難易床高かったわ

    ゚ンゞニアでもないのに、これを䜕ずかした自分を自画自賛したいですよ。

    発端は以䞋蚘事です。

    これはこれで、必芁な措眮なんですよ。間違っちゃいねえ。
    (Protobufを叀い4.xに戻せば発生しない゚ラヌだったが、最新の6.31が出おいる以䞊巻き戻しお固定する自䜓が、本来良くない。そもそも゚ラヌの性栌自䜓からしおそういう皮類のもの)

    ただ、今床はTensorFlow偎が぀いおこられねえ お問題が発生した蚳です。珟時点で具䜓的に動䜜䞍良起こす蚳じゃないのですが、ずにかく゚ラヌ衚瀺だけは出おいたした。

    AttributeError: 'MessageFactory' object has no attribute 'GetPrototype'

    最初、簡単かず思ったら、これが性質悪かったわ 

    経過自䜓、Cursor先生に総括しおもらいたした。途䞭で、自分が䜕やっおるかわかんなくなるくらい苊戊したしたからね。

    ちなみに、以䞋の流れに入る前に、原因がtensorflowらしい 圓たりは付けおいたしたが、その予枬が出来た経緯もたた色々あるのですが、最早芚えきれおいないので割愛したす。

    その凡その圓たりがあっおこそ、以䞋の流れに持っおいくこずが出来たのです。その圓たりを付けられた 理由は、身も蓋もなく経隓倀、経隓則的なものです。

    承知したした。これたでの経緯ず、なぜ䞀連の䜜業が必芁だったのかを最初から芁玄したす。


    今回の目的

    ComfyUI 起動䞭や特定の操䜜䞭に発生しおいた、以䞋の゚ラヌを解消するこず。

    `AttributeError: 'MessageFactory' object has no attribute 'GetPrototype'`

    ゚ラヌの根本原因

    1. `GetPrototype` ずは

      • これは Google の Protocol Buffersprotobuf ずいうラむブラリで䜿われおいたメ゜ッド名です。

      • `MessageFactory` クラスの䞀郚ずしお存圚し、特定のメッセヌゞタむプの「プロトタむプ」ひな圢ずなるむンスタンスを取埗するために䜿われおいたした。

    2. なぜ゚ラヌになったのか

    3. protobuf ラむブラリはバヌゞョンアップを重ねおおり、protobuf 4.x 以降珟圚の 6.x も含むで、`GetPrototype` メ゜ッドは非掚奚たたは削陀されたした。
      (䜆し、実際にはProtbuf5.29.4以前でこの゚ラヌは出ない。6.31で初めお出る)

    4. 代わりに `GetMessageClass` などの新しいメ゜ッドを䜿うように倉曎されたした。

    5. 今回の環境には新しいバヌゞョンの protobuf (6.31.0) がむンストヌルされおいたしたが、ComfyUI 環境内のどこかComfyUI本䜓、カスタムノヌド、あるいは他の䟝存ラむブラリが、叀いバヌゞョンの protobuf を前提ずしたコヌドを持っおおり、存圚しない `GetPrototype` メ゜ッドを呌び出そうずしお゚ラヌが発生しおいたした。


    ゚ラヌ発生箇所の特定を詊みた経緯

    1. `GetPrototype` を䜿っおいるコヌドを探す

      • ゚ラヌメッセヌゞは Python の `AttributeError` でしたが、Pythonコヌドのどこで `GetPrototype` が呌ばれおいるか特定する必芁がありたした。

      • たず、Pythonラむブラリsite-packagesや ComfyUI本䜓の Python ファむル`.py`を察象に `GetPrototype` を党文怜玢したした。

      • しかし、該圓する Python コヌドは芋぀かりたせんでした。

      • 次に、怜玢察象を C++ ヘッダファむル`.h`や他のテキストファむルに広げたずころ、TensorFlow に含たれる protobuf の C++ ヘッダファむルに `GetPrototype` の蚘述が倚数芋぀かりたした。これは、protobuf の内郚 C++ 実装で䜿われおいる名前であるこずを瀺しおいたしたが、盎接゚ラヌの原因ずなる Python コヌドの堎所は特定できたせんでした。

    2. 結論

      • Python コヌド内で盎接 `MessageFactory.GetPrototype` ず曞かれおいる堎所は特定できたせんでしたが、䜕らかのコヌドおそらく叀いカスタムノヌドやラむブラリが、新しい protobuf バヌゞョンず互換性のない方法で `MessageFactory` を䜿おうずしおいるこずが原因ず刀断したした。


    解決策の怜蚎ず採甚

    1. protobuf のバヌゞョンを䞋げる

      • ゚ラヌが出ない叀いバヌゞョン䟋: 3.x系に戻す方法です。これは最も簡単な解決策の䞀぀ですが、ナヌザヌ様が「叀い protobuf に䞋げるは出来ない」ずのこずでしたので、この方法は採甚したせんでした。

    2. ゚ラヌを出すコヌドを修正する

      • もし゚ラヌを出しおいるコヌドが特定できれば、その䞭で `GetPrototype` を `GetMessageClass` に曞き換えるのが理想です。しかし、コヌドの堎所特定が難しく、特にカスタムノヌドの堎合は自分で修正するのが難しい堎合もありたす。

    3. Monkey Patch を䜿う採甚した方法

      • ゚ラヌを出しおいるコヌドを修正するこずなく、新しい protobuf ラむブラリに䞀時的に `GetPrototype` メ゜ッドを远加しおしたう方法です。

      • `GetPrototype` が呌ばれたら、内郚的に新しい `GetMessageClass` を実行するようにしたす。

      • これにより、叀いコヌドは `GetPrototype` を呌んでも゚ラヌにならず、新しい API (`GetMessageClass`) の機胜を䜿うこずができたす。


    Monkey Patch の実装ず ComfyUI ぞの適甚手順

    1. パッチコヌドの䜜成:

      • `monkey_patch_protobuf.py` ずいう Python ファむルを䜜成したした。

      • このファむルには、`MessageFactory` クラスに `GetPrototype` メ゜ッドを远加するコヌドが曞かれおいたす。

    2. ComfyUI 起動前にパッチを適甚する方法の怜蚎:

      • ComfyUI が起動し、゚ラヌが出るコヌドが実行される前に、`monkey_patch_protobuf.py` を import する必芁がありたした。

      • 圓初、ComfyUI の `main.py` の先頭に `import monkey_patch_protobuf` を远加するこずを考えたしたが、ComfyUI の起動方法によっおは難しいため、別の方法を怜蚎したした。

      • Python の `runpy` モゞュヌルを䜿っお、パッチファむルを import した埌に ComfyUI の `main.py` をモゞュヌルずしお実行する方法を採甚したした。

    3. 起動スクリプトの䜜成:

      • `run_comfyui_with_patch.py` ずいう Python ファむルを䜜成したした。

      • このファむルは、`monkey_patch_protobuf` を import した埌、`runpy.run_module('main', run_name='main')` で ComfyUI 本䜓を起動したす。

      • 圓初 `'ComfyUI.main'` ず指定しお `ModuleNotFoundError` が発生したしたが、`sys.path` の調査から、ComfyUI の埋め蟌み Python 環境では `D:\USERFILES\ComfyUI\ComfyUI` がモゞュヌル怜玢パスの先頭に来るため、`main.py` を `'main'` ずいう名前で盎接 import できるこずが分かりたした。

    4. ファむルの配眮:

      • Python が `run_comfyui_with_patch.py` ず `monkey_patch_protobuf.py` を芋぀けられるように、これらを `D:\USERFILES\ComfyUI\ComfyUI` ディレクトリに配眮したした。このディレクトリが `sys.path` の先頭に来るため

    5. バッチファむルの䜜成:

      • ComfyUI を起動するための `start_comfyui_with_patch.bat` を䜜成したした。

      • このバッチファむルでは、環境倉数の蚭定、`PYTHONPATH` の蚭定`D:\USERFILES\ComfyUI\ComfyUI` を指定、そしお絶察パスを䜿っお `run_comfyui_with_patch.py` を Python で実行するコマンドを蚘述したした。

      • パスの指定ミス盞察パスの問題や、゚ラヌが確認できない問題`pause` の远加などがありたしたが、最終的に絶察パスを䜿った信頌性の高いバッチファむルになりたした。


    結果

    䜜成した `monkey_patch_protobuf.py` ず `run_comfyui_with_patch.py` を `D:\USERFILES\ComfyUI\ComfyUI` ディレクトリに眮き、`start_comfyui_with_patch.bat` を実行するこずで、monkey patch が適甚された状態で ComfyUI が起動するようになりたした。

    これにより、Protocol Buffers の `AttributeError: 'MessageFactory' object has no attribute 'GetPrototype'` ずいう゚ラヌは発生しなくなるたたは、゚ラヌを出しおいた叀いコヌドが正しく動䜜するようになるこずが期埅されたす。


    これが、䞀連の䜜業で行ったこずず、それぞれのステップが必芁だった理由の芁玄です。
    䜕か䞍明な点があれば、遠慮なく質問しおください。

    䞊にある「怜出」自䜓から、壮絶に苊戊したした。だっお、芋぀かんねえんもんよ、該圓する郚分が。結局、以䞋のスクリプトを自䜜しおいたす。

    怜出の為に䜿甚したスクリプト

    import os
    
    search_dir = r"D:\USERFILES\ComfyUI"
    keyword = "GetPrototype"
    # 怜玢したい拡匵子をリストで指定
    target_exts = [
        ".py", ".txt", ".json", ".yaml", ".yml", ".md", ".ini", ".cfg", ".toml",
        ".js", ".ts", ".c", ".cpp", ".h", ".hpp"
    ]
    
    for root, dirs, files in os.walk(search_dir):
        for file in files:
            if any(file.endswith(ext) for ext in target_exts):
                file_path = os.path.join(root, file)
                try:
                    with open(file_path, encoding="utf-8", errors="ignore") as f:
                        for i, line in enumerate(f, 1):
                            if keyword in line:
                                print(f"{file_path}:{i}: {line.strip()}")
                except Exception as e:
                    print(f"Error reading {file_path}: {e}")
    

    結局Python郚分にはGetPrototypeの定矩がなかったんですよ。やっず芋぀かったのが以䞋です いや、わかんねえだろうよ、これは。

    D:\USERFILES\ComfyUI\search_getprototype.py:7: keyword = "GetPrototype"
    D:\USERFILES\ComfyUI\python_embeded\Lib\site-packages\tensorflow\include\google\protobuf\dynamic_message.h:128: const Message* GetPrototype(const Descriptor* type) override;
    D:\USERFILES\ComfyUI\python_embeded\Lib\site-packages\tensorflow\include\google\protobuf\dynamic_message.h:139: const Message* GetPrototypeNoLock(const Descriptor* type);
    D:\USERFILES\ComfyUI\python_embeded\Lib\site-packages\tensorflow\include\google\protobuf\extension_set.h:811: const MessageLite* GetPrototypeForLazyMessage(const MessageLite* extendee,
    D:\USERFILES\ComfyUI\python_embeded\Lib\site-packages\tensorflow\include\google\protobuf\message.h:641: // factory->GetPrototype(field->message_type()) MUST return an instance of
    D:\USERFILES\ComfyUI\python_embeded\Lib\site-packages\tensorflow\include\google\protobuf\message.h:1286: // Some implementations do not support all types.  GetPrototype() will
    D:\USERFILES\ComfyUI\python_embeded\Lib\site-packages\tensorflow\include\google\protobuf\message.h:1291: virtual const Message* GetPrototype(const Descriptor* type) = 0;
    D:\USERFILES\ComfyUI\python_embeded\Lib\site-packages\tensorflow\include\google\protobuf\message.h:1295: //   MessageFactory::generated_factory()->GetPrototype(
    D:\USERFILES\ComfyUI\python_embeded\Lib\site-packages\tensorflow\include\google\protobuf\message.h:1299: // pool, GetPrototype() will return nullptr.  (You can also check if a
    D:\USERFILES\ComfyUI\python_embeded\Lib\site-packages\tensorflow\include\google\protobuf\message.h:1303: // This factory is 100% thread-safe; calling GetPrototype() does not modify
    D:\USERFILES\ComfyUI\python_embeded\Lib\site-packages\tensorflow\include\google\protobuf\message.h:1310: // time, to be placed in generated_factory.  The first time GetPrototype()
    D:\USERFILES\ComfyUI\python_embeded\Lib\site-packages\tensorflow\include\google\protobuf\reflection.h:208: reflection->GetMessageFactory()->GetPrototype(field->message_type());
    D:\USERFILES\ComfyUI\python_embeded\Lib\site-packages\tensorflow\include\google\protobuf\reflection.h:269: reflection->GetMessageFactory()->GetPrototype(field->message_type());
    D:\USERFILES\ComfyUI\python_embeded\Lib\site-packages\tensorflow\include\google\protobuf\compiler\cpp\service.h:103: void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer);
    D:\USERFILES\ComfyUI\python_embeded\Lib\site-packages\tensorflow\include\google\protobuf\compiler\java\service.h:108: void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer);
    D:\USERFILES\ComfyUI\python_embeded\Lib\site-packages\tensorflow\include\google\protobuf\io\coded_stream.h:477: // GetPrototype() MUST return non-NULL for any Descriptor which can be found
    D:\USERFILES\ComfyUI\python_embeded\Lib\site-packages\tensorflow\include\google\protobuf\io\coded_stream.h:483: // GetPrototype() is given a Descriptor which resides in
    (base) PS D:\USERFILES\ComfyUI>
    
    

    で、これを螏たえお、䞊の流れの察策に向かっおいく蚳です。

    久々に出たしたよ、monkey patch 以前reForgeの譊告察策で䜜ったんですよね、それ以来だ。䞀応、䞋蚘に公開しおおきたす。

    # monkey_patch_protobuf.py
    from google.protobuf.message_factory import MessageFactory
    
    def get_message_class(self, descriptor):
        return self.GetMessageClass(descriptor)
    
    MessageFactory.GetPrototype = get_message_class
    import monkey_patch_protobuf
    import runpy
    runpy.run_module('main', run_name='__main__') # ← この3行目が 'main' になっおいるか確認

    改めお、こんな捻くれた察策を捻り出しおくれたCursor先生、改めおすげえよ ゚ンゞニアでもない私が、これを䜕ずか出来おしたう蚳ですから。

    ただ、この方向にCursor先生を誘導したのは、私の「聞き方」 ぀たりプロンプト゚ンゞニアリングの技術ではある蚳ですよ。そこは自画自賛しおいい郚分でしょうよ。

    察策以前の方法で起動するず以䞋の様になる蚳です。゚ラヌ自䜓が゜ヌスを特定しおねえんだもん これはわかんねえよ。

    画像

    尚、察策埌のバッチファむルは以䞋です。以䞋は、Flux1甚ですね。前述しおいるように、私はtorch.compile最適化の為に、Flux1ずHiDream、動画それぞれモデルごずに環境を切り替えおいたす。
    (SDXLではtorch.compileを䜿甚しない為、どの環境でも共通に䜿える。䜆し、SD1.5はsage-atttentionが未察応(䜆し完走はする)の為、xformers専甚環境を別途甚意しおいる)

    set PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:32,garbage_collection_threshold:0.8
    set TORCH_COMPILE_DEBUG=0
    set TORCH_COMPILE_OPT_LEVEL=2
    set TORCH_LOGS=recompiles,dynamo,inductor
    set TORCH_INDUCTOR_VERBOSE=1
    set TORCH_DYNAMO_CONFIG=force_parameter_static_shapes=false
    set TRITON_CACHE_DIR=D:\USERFILES\Flux1\triton
    set TORCH_HOME=D:\USERFILES\Flux1\torch
    set TORCHINDUCTOR_CACHE_DIR=D:\USERFILES\Flux1\Inductor
    set TEMP=D:\USERFILES\Flux1\Temp
    set PYTHONPATH=D:\USERFILES\ComfyUI\ComfyUI
    
    D:\USERFILES\ComfyUI\python_embeded\python.exe -m pip install -U protobuf
    
    D:\USERFILES\ComfyUI\python_embeded\python.exe D:\USERFILES\ComfyUI\ComfyUI\run_comfyui_with_patch.py --use-sage-attention --windows-standalone-build --output-directory D:\USERFILES\A1111\outputs\ComfyUI
    

    尚、TensorFlow偎が完党にGetMessageClassロゞックに切り替われば、この察策は䞍芁になりたす。い぀になるかわかりたせんけどね。少なくずも最新の2.19.0では、ただ未察応ずいう事です。

    


    今日のBGMは 完党感芚Dreamerを止める止める蚀い぀぀、結局優しいTAKAさんなので、最近たで最埌にやり続けおいたしたが、遂に止めたしたね、本圓に。そしお、代わりに勿論これです。

    ONE OK ROCK: Wasted Nights

    最早、代名詞ず化しおた名曲 だけど、前を向き、前に進み続けるTAKAさんの性栌からしおも、い぀たでも「歀凊」で時間が止たったようにむメヌゞ瞛られおいるのは奜きじゃないでしょう。

    モヌニング嚘。だっお、い぀たでもLOVEマシヌンずTHEぎヌすだけで語られおたら、こっちずしおも「お前い぀たで、そこで時蚈止たっおんだよ」、お思いたすからね。

    ONE OK ROCK - 完党感芚Dreamer [THIS IS MY BUDOKAN ?! 2010.11.28]

    ただ、これが名曲である事には違いありたせん。この䞀曲だけでも圌らは音楜史に名前が残りたす。

    圌らず芪亀があるRADWIMPSの掋次郎さんも、圌ら䞭での奜きな曲ずしお「べただけど」ず蚀い぀぀これを䞊げおいたす。理由が「リズム」ずいう理由はよくわかるんですよ。ヒルクラむムは嫌いですが、ヒルクラむムでは、私はこれにリズムがずにかく合いたす。

    勿論、既に賌入枈みですが、ただロヌラヌ台ず合わせたトレヌニングはしおいたせん。もっず肺を戻さないず、こっちの心臓が぀いおこられない。

    ヒルクラむムで合わせる曲...は、あずは私はこれですね。

    2000幎代初頭にVロック界で䞀䞖を颚靡した䞭島卓偉さんの名曲「むノノェむタヌ」。圓時はTAKUI名矩でした。2010幎代には、ハロプロにも深く関わるこずになりたした。

    もう䞀぀は、やっぱこれか ずにかくリズムが良いんですよ

    モヌニング嚘。'14 『What is LOVE?』(Dance Shot Ver.)

    ぀んく♂さんの曲にしおは、リズムは結構玠盎です。あの人の転調効きたくった捻り効いおるリズムの曲も、それはそれで奜きですが、ヒルクラむムで心臓にも脚にも負荷かけおる時に、あんた捻られおもこっちが付いおいけねえんですよ。ヒルクラむムで倧事なのはずにかくリズム ロヌドバむク党般そうですけど、登りには登り也のリズムっおものがあるんですよ。


     
     

    GJL

     
     
    Road bikeCycling Road Race, Respecting Mr.Greg LeMond,  Anti Doping, Football, RockPops, History.

    あなたぞのおすすめ