-
Notifications
You must be signed in to change notification settings - Fork 215
Implement luma node #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Implement luma node #68
Conversation
Reviewer's GuideThis 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 processsequenceDiagram
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
Entity relationship diagram for LumaTextToImageNode input and output typeserDiagram
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
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
WalkthroughA 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
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
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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 eto 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>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| # 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() |
There was a problem hiding this comment.
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.
| # 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) |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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}") |
There was a problem hiding this comment.
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)
Explanation
If 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?
- Use one of the built-in exceptions of the standard library.
- Define your own error class that subclasses
Exception.
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}") |
There was a problem hiding this comment.
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)
Explanation
If 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?
- Use one of the built-in exceptions of the standard library.
- Define your own error class that subclasses
Exception.
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") |
There was a problem hiding this comment.
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)
Explanation
If 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?
- Use one of the built-in exceptions of the standard library.
- Define your own error class that subclasses
Exception.
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") |
There was a problem hiding this comment.
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)
Explanation
If 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?
- Use one of the built-in exceptions of the standard library.
- Define your own error class that subclasses
Exception.
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): |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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:
- Inline variable that is immediately returned (
inline-immediately-returned-variable) - Explicitly raise from a previous error (
raise-from-previous-error)
There was a problem hiding this 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
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
📒 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.pyComfyUI/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
ComfyNodeABCand 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_imagemethod 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
There was a problem hiding this 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
📒 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.
|
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. |
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
ComfyUI/custom_nodes/DreamLayer/api_nodes/luma_text2img.pyLumaTextToImageNodeclass inheriting fromComfyNodeABC/v1/images/generationsendpoint2. API Integration Architecture
https://api.lumalabs.ai/v1LUMA_API_KEYenvironment variable for secure accessapplication/jsonformat for API requests3. User Interface & Experience
4. Code Quality & Standards
__init__.pyfilesfrom etraceback preservationuint8) for consistent resultsUI Screenshot
Node loads successfully in ComfyUI as "Luma: Text to Image" in api node/image/Luma category
Generated Image
Ready for testing with valid LUMA_API_KEY - code implementation complete
Generated image will be added after API testing
Server Logs
Checklist
LumaTextToImageNodewith proper ComfyUI structure/v1/images/generationsendpointSummary 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:
/v1/images/generationsendpointEnhancements:
Documentation:
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.