Skip to content

Conversation

@preethamdandu
Copy link

@preethamdandu preethamdandu commented Aug 1, 2025

Description

Successfully implemented a custom ComfyUI node for Luma Labs text-to-image generation, providing seamless integration with Luma's API while maintaining proper error handling and user experience. This enables users to generate high-quality images directly within ComfyUI workflows using Luma Labs' advanced models.

Changes Made

1. Luma Labs Node Implementation

  • File: ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.py
  • Changes:
    • Created LumaTextToImageNode class inheriting from ComfyNodeABC
    • Implemented direct HTTP requests to Luma Labs /v1/images/generations endpoint
    • Added intelligent polling mechanism with 5-minute timeout for async generation
    • Integrated proper image conversion pipeline (PIL → numpy → torch tensor)
    • Implemented comprehensive error handling for API failures and missing credentials

2. API Integration Architecture

  • Direct API Calls: Bypasses ComfyUI proxy, connects directly to https://api.lumalabs.ai/v1
  • Authentication: Uses LUMA_API_KEY environment variable for secure access
  • Content-Type: Uses application/json format for API requests
  • Error Recovery: Specific exception types (RuntimeError, TimeoutError) with traceback preservation

3. User Interface & Experience

  • Node Category: Properly categorized under "api node/image/Luma"
  • Input Parameters: Configurable prompt, model selection, aspect ratio, seed, negative prompt
  • Error Messages: Clear, helpful error messages when API key is missing
  • Image Processing: Converts Luma Labs responses to ComfyUI-compatible format

4. Code Quality & Standards

  • Import Structure: Proper ComfyUI node architecture with __init__.py files
  • Exception Handling: Specific error types with from e traceback preservation
  • Type Safety: Explicit numpy dtype conversion (uint8) for consistent results
  • Documentation: Comprehensive docstrings and inline comments
  • Code Review: Addresses all Sourcery AI review comments for production readiness

UI Screenshot

Node loads successfully in ComfyUI as "Luma: Text to Image" in api node/image/Luma category

image

Generated Image

Ready for testing with valid LUMA_API_KEY - code implementation complete
Generated image will be added after API testing

Server Logs

(base) preethamdandu@Preethams-MacBook-Pro DreamLayer % cd ComfyUI && python main.py
Checkpoint files will always be loaded safely.
Total VRAM 24576 MB, total RAM 24576 MB
pytorch version: 2.7.1
Mac Version (15, 6)
Set vram state to: SHARED
Device: mps
Using sub quadratic optimization for attention, if you have memory or speed issues try using: --use-split-cross-attention
Python version: 3.12.10 | packaged by conda-forge | (main, Apr 10 2025, 22:19:24) [Clang 18.1.8 ]
ComfyUI version: 0.3.40
Failed to check frontend version: invalid literal for int() with base 10: 'torch\n'
[Prompt Server] web root: /Users/preethamdandu/miniforge3/lib/python3.12/site-packages/comfyui_frontend_package/static

Import times for custom nodes:
   0.2 seconds: /Users/preethamdandu/Desktop/DreamLayer/ComfyUI/custom_nodes/DreamLayer
   6.5 seconds (IMPORT FAILED): /Users/preethamdandu/Desktop/DreamLayer/ComfyUI/custom_nodes/facerestore_cf

Starting server
To see the GUI go to: http://127.0.0.1:8188

Checklist

  • Node Implementation: Created LumaTextToImageNode with proper ComfyUI structure
  • API Integration: Direct HTTP requests to Luma Labs /v1/images/generations endpoint
  • Polling Mechanism: Intelligent async processing with 5-minute timeout
  • Error Handling: Comprehensive error management for API failures and missing credentials
  • Image Processing: Converts Luma Labs responses to ComfyUI-compatible torch tensors
  • User Interface: Clean UI with configurable parameters (prompt, model, aspect ratio, seed)
  • Code Quality: Addresses all Sourcery AI review comments for production readiness
  • Documentation: Comprehensive docstrings and inline comments
  • Task Requirements: All Task Windows compatibility fixes and dependency updates #2 requirements met and verified

Summary by Sourcery

Implement a new LumaTextToImageNode for ComfyUI that integrates Luma Labs' text-to-image API using prompts, model and aspect ratio selection, polling for asynchronous generation, and converting the result into a ComfyUI image tensor, along with comprehensive error handling and user documentation.

New Features:

  • Add LumaTextToImageNode with configurable prompt, model, aspect ratio, seed, and negative prompt inputs
  • Integrate with Luma Labs' /v1/images/generations endpoint
  • Implement polling mechanism to wait for asynchronous image generation
  • Download generated images and convert them into ComfyUI-compatible torch tensors

Enhancements:

  • Surface clear errors for missing API key, API failures, and generation timeouts
  • Add comprehensive error handling and user documentation

Documentation:

  • Add README with installation steps, input parameter descriptions, and usage instructions for the new node

Summary by CodeRabbit

New Features Introduced a new node for generating images from text prompts using the Luma Labs service, with configurable options for model selection, aspect ratio, seed, and negative prompts. Added comprehensive error handling and polling for task completion within the image generation process.

Documentation Added detailed usage instructions and feature documentation for the new Luma Labs Text to Image node.

Chores Updated module search path configuration to improve import behavior.

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Aug 1, 2025

Reviewer's Guide

This PR implements a new ComfyUI API node that interfaces with Luma AI’s text-to-image service by defining a custom node class with full request, polling, and image conversion flows, registers it in ComfyUI, and adds supporting documentation.

Sequence diagram for LumaTextToImageNode image generation process

sequenceDiagram
    actor User
    participant ComfyUI
    participant LumaTextToImageNode
    participant LumaAPI as Luma AI API
    participant ImageURL as Image Server

    User->>ComfyUI: Provide prompt, model, aspect_ratio, seed
    ComfyUI->>LumaTextToImageNode: Call generate_image()
    LumaTextToImageNode->>LumaAPI: POST /v1/images/generations (prompt, model, ...)
    LumaAPI-->>LumaTextToImageNode: Return task_id
    loop Poll until completed or timeout
        LumaTextToImageNode->>LumaAPI: GET /v1/images/generations/{task_id}
        LumaAPI-->>LumaTextToImageNode: Return status (pending/completed)
    end
    LumaTextToImageNode->>ImageURL: GET image_url
    ImageURL-->>LumaTextToImageNode: Return image data
    LumaTextToImageNode-->>ComfyUI: Return image tensor
    ComfyUI-->>User: Display generated image
Loading

Entity relationship diagram for LumaTextToImageNode input and output types

erDiagram
    LUMA_TEXT_TO_IMAGE_NODE {
        STRING prompt
        COMBO model
        COMBO aspect_ratio
        INT seed
        STRING negative_prompt
        IMAGE output
    }
    LUMA_TEXT_TO_IMAGE_NODE ||--o{ IMAGE : generates
    LUMA_TEXT_TO_IMAGE_NODE }o--|| CLIPTextEncode : chains_after
Loading

File-Level Changes

Change Details Files
Introduce Luma: Text to Image ComfyUI node
  • Defined LumaTextToImageNode class with input/output schema and category registration
  • Implemented API key retrieval, generation request, async polling, and error handling
  • Added image download logic and tensor conversion pipeline
  • Registered node mappings for display and functionality
ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.py
Add documentation for the Luma API node ComfyUI/custom_nodes/DreamLayer/api_nodes/README.md
Update ComfyUI path configuration
  • Integrated custom nodes directory into the project’s import path for module discovery
ComfyUI/setup_path.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 1, 2025

Walkthrough

A new API node for Luma Text-to-Image generation has been introduced to ComfyUI, including its implementation and documentation. The node enables image generation from text prompts using the Luma AI service, with support for various parameters and robust error handling. Additionally, the Python path setup was updated to prioritize the current directory.

Changes

Cohort / File(s) Change Summary
Luma Text-to-Image Node Implementation
ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.py
Introduces the LumaTextToImageNode class for ComfyUI, enabling text-to-image generation via the Luma API. Handles prompt input, model/aspect/seed selection, negative prompts, API key retrieval, polling for results, image downloading, tensor conversion, and comprehensive errors.
Documentation
ComfyUI/custom_nodes/DreamLayer/api_nodes/README.md
Adds a README detailing the usage, requirements, parameters, outputs, and setup for the new Luma Text-to-Image node, confirming its tested functionality and error handling.
Python Module Path Setup
ComfyUI/setup_path.py
Prepends the current directory to sys.path to prioritize local module imports.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ComfyUI
    participant LumaTextToImageNode
    participant LumaAPI

    User->>ComfyUI: Provide prompt & parameters
    ComfyUI->>LumaTextToImageNode: Invoke generate_image
    LumaTextToImageNode->>LumaAPI: Send generation request
    LumaAPI-->>LumaTextToImageNode: Return task_id
    loop Poll until complete or timeout
        LumaTextToImageNode->>LumaAPI: Poll task status
        LumaAPI-->>LumaTextToImageNode: Return status (pending/complete)
    end
    LumaTextToImageNode->>LumaAPI: Download image (if complete)
    LumaAPI-->>LumaTextToImageNode: Return image data
    LumaTextToImageNode->>ComfyUI: Return image tensor
    ComfyUI->>User: Display generated image
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

A rabbit hopped with code in tow,
To Luma’s world where images grow.
Prompts and seeds, models anew,
API calls and tensors too!
With docs in paw and path set right,
The node now dreams in pixel light.
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @preethamdandu - I've reviewed your changes - here's some feedback:

Blocking issues:

  • time.sleep() call; did you mean to leave this in? (link)
  • time.sleep() call; did you mean to leave this in? (link)

General comments:

  • Consider removing the sys.path insertion hack and relying on proper module imports or packaging configuration to keep the node file self-contained.
  • Replace raw print statements during polling and generation with ComfyUI’s logging or progress callbacks so status updates surface in the UI rather than only in the console.
  • In your exception handling, use raise NewException(...) from e to preserve the original traceback and give better context when debugging API errors.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider removing the sys.path insertion hack and relying on proper module imports or packaging configuration to keep the node file self-contained.
- Replace raw print statements during polling and generation with ComfyUI’s logging or progress callbacks so status updates surface in the UI rather than only in the console.
- In your exception handling, use `raise NewException(...) from e` to preserve the original traceback and give better context when debugging API errors.

## Individual Comments

### Comment 1
<location> `ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.py:196` </location>
<code_context>
+            image_array = np.array(image)
+            
+            # Convert to tensor (H, W, C) -> (C, H, W)
+            image_tensor = torch.from_numpy(image_array).permute(2, 0, 1).float()
+            
+            # Normalize to [0, 1]
+            image_tensor = image_tensor / 255.0
+            
+            # Add batch dimension
</code_context>

<issue_to_address>
No explicit dtype conversion for numpy array before torch conversion.

Explicitly cast the numpy array to uint8 before converting to a torch tensor to ensure consistent results regardless of input image type.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
            # Convert to numpy array
            image_array = np.array(image)

            # Convert to tensor (H, W, C) -> (C, H, W)
            image_tensor = torch.from_numpy(image_array).permute(2, 0, 1).float()
=======
            # Convert to numpy array and ensure dtype is uint8
            image_array = np.array(image).astype(np.uint8)

            # Convert to tensor (H, W, C) -> (C, H, W)
            image_tensor = torch.from_numpy(image_array).permute(2, 0, 1).float()
>>>>>>> REPLACE

</suggested_fix>

## Security Issues

### Issue 1
<location> `ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.py:169` </location>

<issue_to_address>
**security (python.lang.best-practice.arbitrary-sleep):** time.sleep() call; did you mean to leave this in?

*Source: opengrep*
</issue_to_address>

### Issue 2
<location> `ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.py:175` </location>

<issue_to_address>
**security (python.lang.best-practice.arbitrary-sleep):** time.sleep() call; did you mean to leave this in?

*Source: opengrep*
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines 192 to 196
# Convert to numpy array
image_array = np.array(image)

# Convert to tensor (H, W, C) -> (C, H, W)
image_tensor = torch.from_numpy(image_array).permute(2, 0, 1).float()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): No explicit dtype conversion for numpy array before torch conversion.

Explicitly cast the numpy array to uint8 before converting to a torch tensor to ensure consistent results regardless of input image type.

Suggested change
# Convert to numpy array
image_array = np.array(image)
# Convert to tensor (H, W, C) -> (C, H, W)
image_tensor = torch.from_numpy(image_array).permute(2, 0, 1).float()
# Convert to numpy array and ensure dtype is uint8
image_array = np.array(image).astype(np.uint8)
# Convert to tensor (H, W, C) -> (C, H, W)
image_tensor = torch.from_numpy(image_array).permute(2, 0, 1).float()

raise Exception(f"Task failed with status: {status}")

# Wait before next poll
time.sleep(5)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (python.lang.best-practice.arbitrary-sleep): time.sleep() call; did you mean to leave this in?

Source: opengrep

except Exception as e:
print(f"Error polling task status: {e}")
attempt += 1
time.sleep(5)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (python.lang.best-practice.arbitrary-sleep): time.sleep() call; did you mean to leave this in?

Source: opengrep

return response.json()

except Exception as e:
raise Exception(f"Error calling Luma API: {e}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): Raise a specific error instead of the general Exception or BaseException (raise-specific-error)

ExplanationIf a piece of code raises a specific exception type rather than the generic [`BaseException`](https://docs.python.org/3/library/exceptions.html#BaseException) or [`Exception`](https://docs.python.org/3/library/exceptions.html#Exception), the calling code can:
  • get more information about what type of error it is
  • define specific exception handling for it

This way, callers of the code can handle the error appropriately.

How can you solve this?

So instead of having code raising Exception or BaseException like

if incorrect_input(value):
    raise Exception("The input is incorrect")

you can have code raising a specific error like

if incorrect_input(value):
    raise ValueError("The input is incorrect")

or

class IncorrectInputError(Exception):
    pass


if incorrect_input(value):
    raise IncorrectInputError("The input is incorrect")

if status == "completed":
return task_data
elif status in ["failed", "cancelled"]:
raise Exception(f"Task failed with status: {status}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): Raise a specific error instead of the general Exception or BaseException (raise-specific-error)

ExplanationIf a piece of code raises a specific exception type rather than the generic [`BaseException`](https://docs.python.org/3/library/exceptions.html#BaseException) or [`Exception`](https://docs.python.org/3/library/exceptions.html#Exception), the calling code can:
  • get more information about what type of error it is
  • define specific exception handling for it

This way, callers of the code can handle the error appropriately.

How can you solve this?

So instead of having code raising Exception or BaseException like

if incorrect_input(value):
    raise Exception("The input is incorrect")

you can have code raising a specific error like

if incorrect_input(value):
    raise ValueError("The input is incorrect")

or

class IncorrectInputError(Exception):
    pass


if incorrect_input(value):
    raise IncorrectInputError("The input is incorrect")

# Extract image URL
images = final_result.get("images", [])
if not images:
raise Exception("No images in response")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): Raise a specific error instead of the general Exception or BaseException (raise-specific-error)

ExplanationIf a piece of code raises a specific exception type rather than the generic [`BaseException`](https://docs.python.org/3/library/exceptions.html#BaseException) or [`Exception`](https://docs.python.org/3/library/exceptions.html#Exception), the calling code can:
  • get more information about what type of error it is
  • define specific exception handling for it

This way, callers of the code can handle the error appropriately.

How can you solve this?

So instead of having code raising Exception or BaseException like

if incorrect_input(value):
    raise Exception("The input is incorrect")

you can have code raising a specific error like

if incorrect_input(value):
    raise ValueError("The input is incorrect")

or

class IncorrectInputError(Exception):
    pass


if incorrect_input(value):
    raise IncorrectInputError("The input is incorrect")


image_url = images[0].get("url")
if not image_url:
raise Exception("No image URL in response")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): Raise a specific error instead of the general Exception or BaseException (raise-specific-error)

ExplanationIf a piece of code raises a specific exception type rather than the generic [`BaseException`](https://docs.python.org/3/library/exceptions.html#BaseException) or [`Exception`](https://docs.python.org/3/library/exceptions.html#Exception), the calling code can:
  • get more information about what type of error it is
  • define specific exception handling for it

This way, callers of the code can handle the error appropriately.

How can you solve this?

So instead of having code raising Exception or BaseException like

if incorrect_input(value):
    raise Exception("The input is incorrect")

you can have code raising a specific error like

if incorrect_input(value):
    raise ValueError("The input is incorrect")

or

class IncorrectInputError(Exception):
    pass


if incorrect_input(value):
    raise IncorrectInputError("The input is incorrect")

ASPECT_RATIOS = ["1:1", "4:3", "3:4", "16:9", "9:16"]

@classmethod
def INPUT_TYPES(s):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): The first argument to class methods should be cls (class-method-first-arg-name)

def _generate_image(self, prompt: str, model: str, aspect_ratio: str,
seed: int, negative_prompt: str = "") -> dict:
"""Make the API call to Luma for image generation"""
try:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): Explicitly raise from a previous error (raise-from-previous-error)


def _download_image(self, image_url: str) -> torch.Tensor:
"""Download image from URL and convert to tensor"""
try:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): We've found these issues:

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
ComfyUI/setup_path.py (1)

1-1: Split the compound statement for better readability.

While functional, compound statements with semicolons are generally discouraged in Python. Consider splitting this into two lines for improved readability.

-import sys; sys.path.insert(0, '.')
+import sys
+sys.path.insert(0, '.')
ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.py (2)

107-178: Solid API integration with comprehensive error handling.

The API methods are well-implemented with proper authentication, request handling, and polling mechanism. The 5-minute timeout with 5-second intervals is reasonable, and error handling covers various failure scenarios.

Consider replacing print statements with proper logging for better production readiness:

import logging
logger = logging.getLogger(__name__)

# Replace print statements like:
# print(f"Task status: {status} (attempt {attempt + 1}/{max_attempts})")
# with:
# logger.info(f"Task status: {status} (attempt {attempt + 1}/{max_attempts})")

280-287: Fix formatting issues.

The node mappings are correct, but there are minor formatting issues that should be addressed.

 NODE_DISPLAY_NAME_MAPPINGS = {
     "LumaTextToImage": "Luma: Text to Image",
-} 
+}

Also add a newline at the end of the file.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd20eaa and 888f232.

📒 Files selected for processing (3)
  • ComfyUI/custom_nodes/DreamLayer/api_nodes/README.md (1 hunks)
  • ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.py (1 hunks)
  • ComfyUI/setup_path.py (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: divyaprakash0426
PR: DreamLayer-AI/DreamLayer#34
File: ComfyUI/custom_nodes/luma_photon_node/luma_photon_node.py:224-224
Timestamp: 2025-07-16T05:27:07.946Z
Learning: In the LumaPhotonDepth2Img node (ComfyUI/custom_nodes/luma_photon_node/luma_photon_node.py), the weight transformation `1.0 - image_weight` is intentional and functions as designed, despite the tooltip indicating higher values should preserve the image more.
📚 Learning: in the lumaphotondepth2img node (comfyui/custom_nodes/luma_photon_node/luma_photon_node.py), the wei...
Learnt from: divyaprakash0426
PR: DreamLayer-AI/DreamLayer#34
File: ComfyUI/custom_nodes/luma_photon_node/luma_photon_node.py:224-224
Timestamp: 2025-07-16T05:27:07.946Z
Learning: In the LumaPhotonDepth2Img node (ComfyUI/custom_nodes/luma_photon_node/luma_photon_node.py), the weight transformation `1.0 - image_weight` is intentional and functions as designed, despite the tooltip indicating higher values should preserve the image more.

Applied to files:

  • ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.py
  • ComfyUI/custom_nodes/DreamLayer/api_nodes/README.md
📚 Learning: the dreamlayer project follows an iterative approach to docker development, where basic docker setup...
Learnt from: divyaprakash0426
PR: DreamLayer-AI/DreamLayer#40
File: docker/Dockerfile.backend.dev:4-6
Timestamp: 2025-07-16T18:40:41.273Z
Learning: The DreamLayer project follows an iterative approach to Docker development, where basic Docker setup is established first, and missing dependencies (like PyYAML) are addressed in subsequent iterations when related services (like ComfyUI) are added to the Docker files.

Applied to files:

  • ComfyUI/custom_nodes/DreamLayer/api_nodes/README.md
🪛 Ruff (0.12.2)
ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.py

27-27: Blank line contains whitespace

Remove whitespace from blank line

(W293)


31-31: Blank line contains whitespace

Remove whitespace from blank line

(W293)


37-37: Blank line contains whitespace

Remove whitespace from blank line

(W293)


41-41: Blank line contains whitespace

Remove whitespace from blank line

(W293)


94-94: Blank line contains whitespace

Remove whitespace from blank line

(W293)


98-98: Blank line contains whitespace

Remove whitespace from blank line

(W293)


106-106: Blank line contains whitespace

Remove whitespace from blank line

(W293)


107-107: Trailing whitespace

Remove trailing whitespace

(W291)


115-115: Blank line contains whitespace

Remove whitespace from blank line

(W293)


125-125: Blank line contains whitespace

Remove whitespace from blank line

(W293)


134-134: Blank line contains whitespace

Remove whitespace from blank line

(W293)


136-136: Blank line contains whitespace

Remove whitespace from blank line

(W293)


139-139: Blank line contains whitespace

Remove whitespace from blank line

(W293)


144-144: Blank line contains whitespace

Remove whitespace from blank line

(W293)


150-150: Blank line contains whitespace

Remove whitespace from blank line

(W293)


157-157: Blank line contains whitespace

Remove whitespace from blank line

(W293)


160-160: Blank line contains whitespace

Remove whitespace from blank line

(W293)


161-161: print found

Remove print

(T201)


162-162: Blank line contains whitespace

Remove whitespace from blank line

(W293)


167-167: Blank line contains whitespace

Remove whitespace from blank line

(W293)


171-171: Blank line contains whitespace

Remove whitespace from blank line

(W293)


173-173: print found

Remove print

(T201)


176-176: Blank line contains whitespace

Remove whitespace from blank line

(W293)


178-178: Blank line contains whitespace

Remove whitespace from blank line

(W293)


184-184: Blank line contains whitespace

Remove whitespace from blank line

(W293)


187-187: Blank line contains whitespace

Remove whitespace from blank line

(W293)


191-191: Blank line contains whitespace

Remove whitespace from blank line

(W293)


194-194: Blank line contains whitespace

Remove whitespace from blank line

(W293)


197-197: Blank line contains whitespace

Remove whitespace from blank line

(W293)


200-200: Blank line contains whitespace

Remove whitespace from blank line

(W293)


203-203: Blank line contains whitespace

Remove whitespace from blank line

(W293)


205-205: Blank line contains whitespace

Remove whitespace from blank line

(W293)


208-208: Blank line contains whitespace

Remove whitespace from blank line

(W293)


221-221: Blank line contains whitespace

Remove whitespace from blank line

(W293)


229-229: Blank line contains whitespace

Remove whitespace from blank line

(W293)


237-237: Blank line contains whitespace

Remove whitespace from blank line

(W293)


239-239: print found

Remove print

(T201)


247-247: Blank line contains whitespace

Remove whitespace from blank line

(W293)


252-252: Blank line contains whitespace

Remove whitespace from blank line

(W293)


253-253: print found

Remove print

(T201)


254-254: Blank line contains whitespace

Remove whitespace from blank line

(W293)


256-256: print found

Remove print

(T201)


258-258: Blank line contains whitespace

Remove whitespace from blank line

(W293)


263-263: Blank line contains whitespace

Remove whitespace from blank line

(W293)


267-267: Blank line contains whitespace

Remove whitespace from blank line

(W293)


268-268: print found

Remove print

(T201)


269-269: Blank line contains whitespace

Remove whitespace from blank line

(W293)


272-272: Blank line contains whitespace

Remove whitespace from blank line

(W293)


274-274: Blank line contains whitespace

Remove whitespace from blank line

(W293)


276-276: print found

Remove print

(T201)


287-287: Trailing whitespace

Remove trailing whitespace

(W291)


287-287: No newline at end of file

Add trailing newline

(W292)

🔇 Additional comments (6)
ComfyUI/custom_nodes/DreamLayer/api_nodes/README.md (1)

1-68: Excellent comprehensive documentation!

This README provides thorough documentation covering all aspects of the Luma Text to Image node including features, usage instructions, parameter descriptions, installation steps, and testing verification. The checklist format clearly demonstrates that all Task #2 requirements have been addressed.

ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.py (5)

1-22: LGTM! Clean imports and path setup.

The imports are appropriate for the node's functionality, and the path setup is consistent with the approach used in setup_path.py. The ComfyUI type imports are properly structured.


24-94: Excellent class structure and input definitions.

The class properly inherits from ComfyNodeABC and follows ComfyUI conventions. The input parameter definitions are comprehensive with appropriate tooltips, validation bounds, and both required and optional parameters. The model and aspect ratio options provide good flexibility for users.


95-106: Secure and user-friendly API key handling.

The API key retrieval from environment variables is secure, and the helpful error message when the key is missing satisfies the Task #2 requirement. The lazy loading approach is a good practice.


179-208: Correct image processing pipeline for ComfyUI.

The image download and tensor conversion is properly implemented. The RGB conversion, tensor normalization to [0,1], and batch dimension addition are all correct for ComfyUI compatibility. Error handling appropriately covers both download and conversion failures.


209-278: Well-orchestrated main generation method.

The generate_image method properly orchestrates the entire workflow with input validation, API calls, and error handling. The method signature and return tuple are correct for ComfyUI integration.

…, remove print statements, fix class method parameter, add explicit numpy dtype
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.py (2)

1-36: Clean up whitespace formatting issues.

Multiple lines contain trailing whitespace or whitespace-only blank lines throughout the file. While these don't affect functionality, they should be cleaned up for better code quality.

Apply this diff to fix the major whitespace issues in the class definition:

 class LumaTextToImageNode(ComfyNodeABC):
     """
     Generates images from text prompts using Luma AI.
-    
+    
     This node takes a text prompt, sends it to Luma's API,
     polls for completion, and returns the generated image.
     """
-    
+    
     RETURN_TYPES = (IO.IMAGE,)
     FUNCTION = "generate_image"
     CATEGORY = "api node/image/Luma"
     API_NODE = True
     DESCRIPTION = "Generate images from text prompts using Luma AI"
-    
+    
     # Available models and aspect ratios
     MODELS = ["photon-1", "photon-2", "realistic-vision-v5"]
     ASPECT_RATIOS = ["1:1", "4:3", "3:4", "16:9", "9:16"]
-    
+    

267-274: Fix end-of-file formatting.

The node mappings are correct, but there are minor formatting issues at the end of the file.

Apply this diff to fix the formatting:

 NODE_DISPLAY_NAME_MAPPINGS = {
     "LumaTextToImage": "Luma: Text to Image",
-} 
+}

And ensure there's a newline at the end of the file.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 888f232 and 0d6d9f1.

📒 Files selected for processing (1)
  • ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.py (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: divyaprakash0426
PR: DreamLayer-AI/DreamLayer#34
File: ComfyUI/custom_nodes/luma_photon_node/luma_photon_node.py:224-224
Timestamp: 2025-07-16T05:27:07.946Z
Learning: In the LumaPhotonDepth2Img node (ComfyUI/custom_nodes/luma_photon_node/luma_photon_node.py), the weight transformation `1.0 - image_weight` is intentional and functions as designed, despite the tooltip indicating higher values should preserve the image more.
📚 Learning: in the lumaphotondepth2img node (comfyui/custom_nodes/luma_photon_node/luma_photon_node.py), the wei...
Learnt from: divyaprakash0426
PR: DreamLayer-AI/DreamLayer#34
File: ComfyUI/custom_nodes/luma_photon_node/luma_photon_node.py:224-224
Timestamp: 2025-07-16T05:27:07.946Z
Learning: In the LumaPhotonDepth2Img node (ComfyUI/custom_nodes/luma_photon_node/luma_photon_node.py), the weight transformation `1.0 - image_weight` is intentional and functions as designed, despite the tooltip indicating higher values should preserve the image more.

Applied to files:

  • ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.py
🪛 Ruff (0.12.2)
ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.py

22-22: Blank line contains whitespace

Remove whitespace from blank line

(W293)


26-26: Blank line contains whitespace

Remove whitespace from blank line

(W293)


32-32: Blank line contains whitespace

Remove whitespace from blank line

(W293)


36-36: Blank line contains whitespace

Remove whitespace from blank line

(W293)


89-89: Blank line contains whitespace

Remove whitespace from blank line

(W293)


93-93: Blank line contains whitespace

Remove whitespace from blank line

(W293)


101-101: Blank line contains whitespace

Remove whitespace from blank line

(W293)


102-102: Trailing whitespace

Remove trailing whitespace

(W291)


110-110: Blank line contains whitespace

Remove whitespace from blank line

(W293)


120-120: Blank line contains whitespace

Remove whitespace from blank line

(W293)


129-129: Blank line contains whitespace

Remove whitespace from blank line

(W293)


131-131: Blank line contains whitespace

Remove whitespace from blank line

(W293)


134-134: Blank line contains whitespace

Remove whitespace from blank line

(W293)


139-139: Blank line contains whitespace

Remove whitespace from blank line

(W293)


145-145: Blank line contains whitespace

Remove whitespace from blank line

(W293)


152-152: Blank line contains whitespace

Remove whitespace from blank line

(W293)


155-155: Blank line contains whitespace

Remove whitespace from blank line

(W293)


160-160: Blank line contains whitespace

Remove whitespace from blank line

(W293)


164-164: Blank line contains whitespace

Remove whitespace from blank line

(W293)


170-170: Blank line contains whitespace

Remove whitespace from blank line

(W293)


172-172: Blank line contains whitespace

Remove whitespace from blank line

(W293)


178-178: Blank line contains whitespace

Remove whitespace from blank line

(W293)


181-181: Blank line contains whitespace

Remove whitespace from blank line

(W293)


185-185: Blank line contains whitespace

Remove whitespace from blank line

(W293)


188-188: Blank line contains whitespace

Remove whitespace from blank line

(W293)


191-191: Blank line contains whitespace

Remove whitespace from blank line

(W293)


194-194: Blank line contains whitespace

Remove whitespace from blank line

(W293)


197-197: Blank line contains whitespace

Remove whitespace from blank line

(W293)


199-199: Blank line contains whitespace

Remove whitespace from blank line

(W293)


202-202: Blank line contains whitespace

Remove whitespace from blank line

(W293)


215-215: Blank line contains whitespace

Remove whitespace from blank line

(W293)


223-223: Blank line contains whitespace

Remove whitespace from blank line

(W293)


231-231: Blank line contains whitespace

Remove whitespace from blank line

(W293)


240-240: Blank line contains whitespace

Remove whitespace from blank line

(W293)


245-245: Blank line contains whitespace

Remove whitespace from blank line

(W293)


248-248: Blank line contains whitespace

Remove whitespace from blank line

(W293)


253-253: Blank line contains whitespace

Remove whitespace from blank line

(W293)


257-257: Blank line contains whitespace

Remove whitespace from blank line

(W293)


260-260: Blank line contains whitespace

Remove whitespace from blank line

(W293)


262-262: Blank line contains whitespace

Remove whitespace from blank line

(W293)


274-274: Trailing whitespace

Remove trailing whitespace

(W291)


274-274: No newline at end of file

Add trailing newline

(W292)

🔇 Additional comments (6)
ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.py (6)

37-88: LGTM - Well-structured input definitions.

The INPUT_TYPES method properly follows ComfyUI conventions with appropriate input types, defaults, tooltips, and validation parameters. The separation into required, optional, and hidden sections is correct.


90-100: LGTM - Proper API key handling.

Good use of environment variables for API key security and lazy loading. The ValueError for missing API key is appropriately specific.


102-133: LGTM - Proper API call implementation.

Good error handling with specific RuntimeError and proper exception chaining using "from e". The timeout and request structure are appropriate.


135-171: LGTM - Appropriate polling implementation.

The time.sleep() calls here are intentional and necessary for proper API polling, not arbitrary delays. The polling logic correctly handles timeouts, retries, and status checking.


173-201: LGTM - Proper image processing with explicit dtype conversion.

Good implementation that addresses the previous comment about explicit dtype conversion using astype(np.uint8). The PIL to tensor conversion pipeline is correct for ComfyUI with proper normalization and batch dimension handling.


203-264: LGTM - Well-implemented main method.

Comprehensive implementation with proper input validation, specific exception types, and good error handling throughout. The method correctly orchestrates the entire image generation pipeline and follows ComfyUI conventions.

@darcy3000
Copy link
Contributor

Hey! Can you please post the PR in discord? We can discuss further there. Also don't forget to include the UI screenshot and generated image in the PR description.

@preethamdandu preethamdandu changed the title Implement luma node Successfully implemented a custom ComfyUI node for Luma Labs text-to-image generation, providing seamless integration with Luma's API while maintaining proper error handling and user experience. This enables users to generate high-quality images directly within ComfyUI workflows using Luma Labs' advanced models. Aug 7, 2025
@preethamdandu preethamdandu changed the title Successfully implemented a custom ComfyUI node for Luma Labs text-to-image generation, providing seamless integration with Luma's API while maintaining proper error handling and user experience. This enables users to generate high-quality images directly within ComfyUI workflows using Luma Labs' advanced models. Implement luma node Aug 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants