## Mellonでのカスタムブロックの使用

[Mellon](https://github.com/cubiq/Mellon)は、Modular Diffusersと統合されたビジュアルワークフローインターフェースであり、ノードベースのワークフロー向けに設計されています。

> [!WARNING]
> Mellon は初期開発段階にあり、まだ本番環境での使用には対応していません。統合の仕組みを垣間見るものとしてお考えください。

Mellon では、カスタムブロックがそのまま動作します。リポジトリに `mellon_pipeline_config.json` を追加するだけです。この設定ファイルは、Mellon がブロックのパラメータを UI コンポーネントとしてどのようにレンダリングするかを指定します。

[Gemini Prompt Expander](https://huggingface.co/diffusers/gemini-prompt-expander-mellon)ブロックを実際に使用した際の動作は以下の通りです:

![Mellon custom block demo](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/modular_demo_dynamic.gif)

Mellon でモジュール化された diffusers カスタムブロックを使用するには:
1. ModularDiffusers セクションから**Dynamic Block Node**をドラッグします
2. `repo_id`（例: `diffusers/gemini-prompt-expander-mellon`）を入力してください
3. **カスタムブロックの読み込み**をクリックします
4. ノードが変形し、ブロックの入力と出力を表示します

では、独自のブロック用にこの設定を作成する方法を順を追って説明します。

## Mellon設定を作成する手順

1. **パラメータにMellonの型を指定する** - 各`InputParam`/`OutputParam`には、MellonがどのUIコンポーネントを描画するかを伝える型が必要です(例: `"textbox"`、`"dropdown"`、`"image"`)。
2. **`mellon_pipeline_config.json` を生成する** - ユーティリティを使用して設定テンプレートを生成し、Hub リポジトリにプッシュします。
3. **（任意）設定を手動で調整する** - 特定のニーズに合わせて生成された設定を微調整します。

## パラメータのMellon型を指定します

Mellon の型は、UI における各パラメータのレンダリング方法を決定します。パラメータの型を指定しない場合、`"custom"`がデフォルトとして使用され、単純な接続点としてレンダリングされます。この設定は、生成された設定ファイルでいつでも後から調整できます。

| 型 | 入力/出力 | 説明 |
|------|--------------|-------------|
| `image` | 両方 | 画像 (PIL Image) |
| `video` | 両方 | 動画 |
| `text` | 両方 | テキスト表示 |
| `textbox` | 入力 | テキスト入力 |
| `dropdown` | 入力 | ドロップダウン選択メニュー |
| `slider` | 入力 | 数値用のスライダー |
| `number` | 入力 | 数値入力 |
| `checkbox` | 入力 | ブール値トグル |

より多くの設定が必要なパラメータ（オプション付きのドロップダウンや、最小値/最大値を持つスライダーなど）には、文字列の代わりに `MellonParam` インスタンスを直接渡します。以下のクラスメソッドのいずれかを使用するか、`MellonParam(name, label, type, ...)` を用いて完全にカスタマイズされたものを作成できます。

| メソッド | 説明 |
|--------|-------------|
| `MellonParam.Input.image(name)` | 画像入力 |
| `MellonParam.Input.textbox(name, default)` | テキストエリアとしてのテキスト入力 |
| `MellonParam.Input.dropdown(name, options, default)` | ドロップダウン選択 |
| `MellonParam.Input.slider(name, default, min, max, step)` | 数値用のスライダー |
| `MellonParam.Input.number(name, default, min, max, step)` | 数値入力（スライダーなし） |
| `MellonParam.Input.seed(name, default)` | ランダム化ボタン付きのシード入力 |
| `MellonParam.Input.checkbox(name, default)` | Boolean チェックボックス |
| `MellonParam.Input.model(name)` | diffusers コンポーネントのモデル入力 |
| `MellonParam.Output.image(name)` | 画像出力 |
| `MellonParam.Output.video(name)` | 動画出力 |
| `MellonParam.Output.text(name)` | テキスト出力 |
| `MellonParam.Output.model(name)` | diffusers コンポーネントのモデル出力 |

Mellon の型を指定するには、以下の方法のいずれかを選択してください。

### ブロック定義における`metadata`の使用

カスタムブロックをゼロから定義する場合は、`metadata={"mellon": "<type>"}` を `InputParam` および `OutputParam` の定義に直接追加してください。Hub 上の既存のカスタムブロックを編集する場合は、ローカルにダウンロードする方法については [カスタムブロックの編集](./custom_blocks#editing-custom-blocks) を参照してください。

```python
class GeminiPromptExpander(ModularPipelineBlocks):
    
    @property
    def inputs(self) -> List[InputParam]:
        return [
            InputParam(
                "prompt",
                type_hint=str,
                required=True,
                description="Prompt to use",
                metadata={"mellon": "textbox"},  # Text input
            )
        ]
    
    @property
    def intermediate_outputs(self) -> List[OutputParam]:
        return [
            OutputParam(
                "prompt",
                type_hint=str,
                description="Expanded prompt by the LLM",
                metadata={"mellon": "text"},  # Text output
            ),
            OutputParam(
                "old_prompt",
                type_hint=str,
                description="Old prompt provided by the user",
<CopyLLMTxtMenu containerStyle="float: inline-end; margin-inline-start: 10px; display: inline-flex; position: relative; z-index: 10;"></CopyLLMTxtMenu>

                # No metadata - we don't want to render this in UI
            )
        ]
```

UI設定を完全に制御するには、`MellonParam`インスタンスを直接渡します:
```python
from diffusers.modular_pipelines.mellon_node_utils import MellonParam

InputParam(
    "mode",
    type_hint=str,
    default="balanced",
    metadata={"mellon": MellonParam.Input.dropdown("mode", options=["fast", "balanced", "quality"])},
)
```

### 設定を生成する際に`input_types`と`output_types`を使用する

既存のパイプラインを使用している場合、またはブロック定義を整理整頓しておきたい場合は、`input_types/output_types` 引数を使用して設定を生成する際に型を指定します。
```python
from diffusers.modular_pipelines.mellon_node_utils import MellonPipelineConfig

mellon_config = MellonPipelineConfig.from_custom_block(
    blocks,
    input_types={"prompt": "textbox"},
    output_types={"prompt": "text"}
)
```

> [!NOTE]
> `metadata` と `input_types`/`output_types` の両方が指定されている場合、引数が `metadata` を上書きします。

## Mellon設定を生成してプッシュします

ブロックにメタデータを追加した後、デフォルトのMellon設定テンプレートを生成し、Hubにプッシュします:

```python
from diffusers import ModularPipelineBlocks
from diffusers.modular_pipelines.mellon_node_utils import MellonPipelineConfig

# load your custom blocks from your local dir
blocks = ModularPipelineBlocks.from_pretrained("/path/local/folder", trust_remote_code=True)

# Generate the default config template
mellon_config = MellonPipelineConfig.from_custom_block(blocks)
# push the default template to `repo_id`, you will need to pass the same local folder path so that it will save the config locally first
mellon_config.save(
    local_dir="/path/local/folder",
    repo_id= repo_id,
    push_to_hub=True
)
```

これにより、リポジトリに`mellon_pipeline_config.json`ファイルが作成されます。

## 設定を確認して調整します

生成されたテンプレートは出発点に過ぎません。必要に応じて調整することをお勧めします。Gemini Prompt Expander の生成された設定を順を追って見ていきましょう。

```json
{
  "label": "Gemini Prompt Expander",
  "default_repo": "",
  "default_dtype": "",
  "node_params": {
    "custom": {
      "params": {
        "prompt": {
          "label": "Prompt",
          "type": "string",
          "display": "textarea",
          "default": ""
        },
        "out_prompt": {
          "label": "Prompt",
          "type": "string",
          "display": "output"
        },
        "old_prompt": {
          "label": "Old Prompt",
          "type": "custom",
          "display": "output"
        },
        "doc": {
          "label": "Doc",
          "type": "string",
          "display": "output"
        }
      },
      "input_names": ["prompt"],
      "model_input_names": [],
      "output_names": ["out_prompt", "old_prompt", "doc"],
      "block_name": "custom",
      "node_type": "custom"
    }
  }
}
```

### 構造の理解

`params` ディクショナリは、各 UI 要素のレンダリング方法を定義します。`input_names`、`model_input_names`、`output_names` のリストは、これらの UI 要素を、基盤となる [ModularPipelineBlocks](/docs/diffusers/v0.43.0/ja/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks) の I/O インターフェースにマッピングします:

| Mellon 設定 | ModularPipelineBlocks |
|---------------|----------------------|
| `input_names` | `inputs`プロパティ |
| `model_input_names` | `expected_components` プロパティ |
| `output_names` | `intermediate_outputs`プロパティ |

この例では、`prompt` が唯一の入力です。モデルのコンポーネントは存在せず、出力には `out_prompt`、`old_prompt`、`doc` が含まれます。

次に、`params`辞書を見てみましょう。

- **`prompt`**: `display: "textarea"`（テキスト入力ボックスとしてレンダリングされる）、`label: "Prompt"`（UIに表示される）、`default: ""`（初期状態は空）を持つ入力パラメータです。`type: "string"` フィールドは Mellon で重要であり、どのノード同士を接続できるかを決定します。"noodles" によって接続できるのは、型が一致するノード同士のみです。

- **`out_prompt`**: 展開されたプロンプトの出力です。入力と出力が同じ名前（`prompt`）を共有しているため、設定内の名前衝突を避けるために`out_`プレフィックスが自動的に付与されました。`display: "output"`が設定されており、出力ソケットとしてレンダリングされます。

- **`old_prompt`**: メタデータを指定していないため、`type: "custom"` になっています。これにより、UI では単純なドットとして表示されます。実際には UI に公開したくないため、削除できます。

- **`doc`**: ドキュメント出力。すべてのカスタムブロックに自動的に追加されます。

### 調整を行う

今後使用しないため、`old_prompt` を `params` と `output_names` の両方から削除してください。

```json
{
  "label": "Gemini Prompt Expander",
  "default_repo": "",
  "default_dtype": "",
  "node_params": {
    "custom": {
      "params": {
        "prompt": {
          "label": "Prompt",
          "type": "string",
          "display": "textarea",
          "default": ""
        },
        "out_prompt": {
          "label": "Prompt",
          "type": "string",
          "display": "output"
        },
        "doc": {
          "label": "Doc",
          "type": "string",
          "display": "output"
        }
      },
      "input_names": ["prompt"],
      "model_input_names": [],
      "output_names": ["out_prompt", "doc"],
      "block_name": "custom",
      "node_type": "custom"
    }
  }
}
```

[diffusers/gemini-prompt-expander-mellon](https://huggingface.co/diffusers/gemini-prompt-expander-mellon) に最終的な設定があります。

