Buckets:
| ## Using Custom Blocks with Mellon | |
| [Mellon](https://github.com/cubiq/Mellon) is a visual workflow interface that integrates with Modular Diffusers and is designed for node-based workflows. | |
| > [!WARNING] | |
| > Mellon is in early development and not ready for production use yet. Consider this a sneak peek of how the integration works! | |
| Custom blocks work in Mellon out of the box - just need to add a `mellon_pipeline_config.json` to your repository. This config file tells Mellon how to render your block's parameters as UI components. | |
| Here's what it looks like in action with the [Gemini Prompt Expander](https://huggingface.co/diffusers/gemini-prompt-expander-mellon) block: | |
|  | |
| To use a modular diffusers custom block in Mellon: | |
| 1. Drag a **Dynamic Block Node** from the ModularDiffusers section | |
| 2. Enter the `repo_id` (e.g., `diffusers/gemini-prompt-expander-mellon`) | |
| 3. Click **Load Custom Block** | |
| 4. The node transforms to show your block's inputs and outputs | |
| Now let's walk through how to create this config for your own custom block. | |
| ## Steps to create a Mellon config | |
| 1. **Specify Mellon types for your parameters** - Each `InputParam`/`OutputParam` needs a type that tells Mellon what UI component to render (e.g., `"textbox"`, `"dropdown"`, `"image"`). | |
| 2. **Generate `mellon_pipeline_config.json`** - Use our utility to generate a config template and push it to your Hub repository. | |
| 3. **(Optional) Manually adjust the config** - Fine-tune the generated config for your specific needs. | |
| ## Specify Mellon types for parameters | |
| Mellon types determine how each parameter renders in the UI. If you don't specify a type for a parameter, it will default to `"custom"`, which renders as a simple connection dot. You can always adjust this later in the generated config. | |
| | Type | Input/Output | Description | | |
| |------|--------------|-------------| | |
| | `image` | Both | Image (PIL Image) | | |
| | `video` | Both | Video | | |
| | `text` | Both | Text display | | |
| | `textbox` | Input | Text input | | |
| | `dropdown` | Input | Dropdown selection menu | | |
| | `slider` | Input | Slider for numeric values | | |
| | `number` | Input | Numeric input | | |
| | `checkbox` | Input | Boolean toggle | | |
| For parameters that need more configuration (like dropdowns with options, or sliders with min/max values), pass a `MellonParam` instance directly instead of a string. You can use one of the class methods below, or create a fully custom one with `MellonParam(name, label, type, ...)`. | |
| | Method | Description | | |
| |--------|-------------| | |
| | `MellonParam.Input.image(name)` | Image input | | |
| | `MellonParam.Input.textbox(name, default)` | Text input as textarea | | |
| | `MellonParam.Input.dropdown(name, options, default)` | Dropdown selection | | |
| | `MellonParam.Input.slider(name, default, min, max, step)` | Slider for numeric values | | |
| | `MellonParam.Input.number(name, default, min, max, step)` | Numeric input (no slider) | | |
| | `MellonParam.Input.seed(name, default)` | Seed input with randomize button | | |
| | `MellonParam.Input.checkbox(name, default)` | Boolean checkbox | | |
| | `MellonParam.Input.model(name)` | Model input for diffusers components | | |
| | `MellonParam.Output.image(name)` | Image output | | |
| | `MellonParam.Output.video(name)` | Video output | | |
| | `MellonParam.Output.text(name)` | Text output | | |
| | `MellonParam.Output.model(name)` | Model output for diffusers components | | |
| Choose one of the methods below to specify a Mellon type. | |
| ### Using `metadata` in block definitions | |
| If you're defining a custom block from scratch, add `metadata={"mellon": ""}` directly to your `InputParam` and `OutputParam` definitions. If you're editing an existing custom block from the Hub, see [Editing custom blocks](./custom_blocks#editing-custom-blocks) for how to download it locally. | |
| ```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", | |
| # No metadata - we don't want to render this in UI | |
| ) | |
| ] | |
| ``` | |
| For full control over UI configuration, pass a `MellonParam` instance directly: | |
| ```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"])}, | |
| ) | |
| ``` | |
| ### Using `input_types` and `output_types` when Generating Config | |
| If you're working with an existing pipeline or prefer to keep your block definitions clean, specify types when generating the config using the `input_types/output_types` argument: | |
| ```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] | |
| > When both `metadata` and `input_types`/`output_types` are specified, the arguments overrides `metadata`. | |
| ## Generate and push the Mellon config | |
| After adding metadata to your block, generate the default Mellon configuration template and push it to the 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 | |
| ) | |
| ``` | |
| This creates a `mellon_pipeline_config.json` file in your repository. | |
| ## Review and adjust the config | |
| The generated template is a starting point - you may want to adjust it for your needs. Let's walk through the generated config for the 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" | |
| } | |
| } | |
| } | |
| ``` | |
| ### Understanding the Structure | |
| The `params` dict defines how each UI element renders. The `input_names`, `model_input_names`, and `output_names` lists map these UI elements to the underlying [ModularPipelineBlocks](/docs/diffusers/pr_12652/en/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks)'s I/O interface: | |
| | Mellon Config | ModularPipelineBlocks | | |
| |---------------|----------------------| | |
| | `input_names` | `inputs` property | | |
| | `model_input_names` | `expected_components` property | | |
| | `output_names` | `intermediate_outputs` property | | |
| In this example: `prompt` is the only input. There are no model components, and outputs include `out_prompt`, `old_prompt`, and `doc`. | |
| Now let's look at the `params` dict: | |
| - **`prompt`**: An input parameter with `display: "textarea"` (renders as a text input box), `label: "Prompt"` (shown in the UI), and `default: ""` (starts empty). The `type: "string"` field is important in Mellon because it determines which nodes can connect together - only matching types can be linked with "noodles". | |
| - **`out_prompt`**: The expanded prompt output. The `out_` prefix was automatically added because the input and output share the same name (`prompt`), avoiding naming conflicts in the config. It has `display: "output"` which renders as an output socket. | |
| - **`old_prompt`**: Has `type: "custom"` because we didn't specify metadata. This renders as a simple dot in the UI. Since we don't actually want to expose this in the UI, we can remove it. | |
| - **`doc`**: The documentation output, automatically added to all custom blocks. | |
| ### Making Adjustments | |
| Remove `old_prompt` from both `params` and `output_names` because you won't need to use it. | |
| ```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" | |
| } | |
| } | |
| } | |
| ``` | |
| See the final config at [diffusers/gemini-prompt-expander-mellon](https://huggingface.co/diffusers/gemini-prompt-expander-mellon). | |
Xet Storage Details
- Size:
- 10.2 kB
- Xet hash:
- b4e1a02499e927daf68ba88d7dd82dcaaab0a02993222ac3c71d78cbbe46da2f
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.