Skip to content

fix gradio#587

Merged
gushiqiao merged 1 commit intomainfrom
gsq_gradio
Dec 9, 2025
Merged

fix gradio#587
gushiqiao merged 1 commit intomainfrom
gsq_gradio

Conversation

@gushiqiao
Copy link
Contributor

No description provided.

@gushiqiao gushiqiao merged commit 9a765f9 into main Dec 9, 2025
2 checks passed
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @gushiqiao, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a major refactor of the Gradio user interface and underlying model loading logic. The primary goal is to enhance usability by shifting model and task configuration from command-line arguments to interactive UI elements. This includes dynamic model discovery, automatic quantization detection, and intelligent auto-configuration of inference parameters based on hardware capabilities and selected model characteristics. The changes streamline the user experience, making it easier to experiment with different models and settings without manual script modifications, while also improving memory management and providing clearer feedback on model loading requirements.

Highlights

  • Gradio UI Refactor: The Gradio interface has been significantly overhauled to provide a more dynamic and user-friendly experience. Model selection (type, task, specific files) and configuration are now handled directly within the UI, replacing previous command-line arguments.
  • Dynamic Model Selection and Quantization: New utility functions have been introduced to scan model directories, dynamically list available DIT, T5, CLIP, and VAE models, and automatically detect their quantization schemes. This allows users to select models and their precision directly from dropdowns in the UI.
  • Simplified Startup and Auto-Configuration: Startup scripts (run_gradio.sh, run_gradio_win.bat) have been simplified by removing model-specific command-line arguments. The auto-configuration feature has been enhanced to dynamically adjust inference parameters based on hardware and selected model properties, such as setting inference steps and CFG scale for distilled models.
  • Attention Operator Enhancements: The system now includes support for 'sage_attn3' and prioritizes installed attention operators in the UI, ensuring optimal performance by leveraging available hardware acceleration.
  • Improved Memory Management and Error Handling: Updates to the OffloadManager ensure more robust cleanup of thread pool executors. Error messages related to lazy loading have been clarified to guide users on supported model weight formats.
  • Documentation Updates: The deployment guides for Gradio have been thoroughly updated to reflect the new UI-driven configuration, model directory structures, and simplified startup procedures.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a major refactoring of the Gradio demo application, significantly improving its flexibility and user experience. The key changes include moving model and task selection from command-line arguments to a dynamic UI, which now discovers available models from the filesystem. The UI has been redesigned for better clarity, and the underlying configuration logic, including auto-configuration of performance settings, has been simplified and made more robust. The startup scripts and documentation have also been updated to reflect these changes.

My review focuses on improving code maintainability by reducing duplication in the new helper functions and enhancing the robustness of resource management in the offloading manager. Overall, this is a very positive set of changes that makes the Gradio demo much more powerful and easier to use.

Comment on lines +127 to 134
def __del__(self):
if hasattr(self, "executor") and self.executor is not None:
# Wait for all pending futures to complete before shutting down
if hasattr(self, "prefetch_futures"):
for f in self.prefetch_futures:
try:
if not f.done():
f.result()
except Exception:
pass
self.executor.shutdown(wait=wait)
for f in self.prefetch_futures:
if not f.done():
f.result()
self.executor.shutdown(wait=False)
self.executor = None
logger.debug("ThreadPoolExecutor shut down successfully.")
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The shutdown logic has been moved into __del__. Relying on __del__ for resource cleanup is fragile, as its execution is not guaranteed in all circumstances. Additionally, the try...except block around f.result() was removed. If a future has an exception, it will be raised inside __del__, which can lead to unhandled exceptions and warnings from the interpreter. It's safer to catch and log potential exceptions here.

For more robust resource management, consider using a context manager (__enter__ and __exit__) instead of __del__.

Suggested change
def __del__(self):
if hasattr(self, "executor") and self.executor is not None:
# Wait for all pending futures to complete before shutting down
if hasattr(self, "prefetch_futures"):
for f in self.prefetch_futures:
try:
if not f.done():
f.result()
except Exception:
pass
self.executor.shutdown(wait=wait)
for f in self.prefetch_futures:
if not f.done():
f.result()
self.executor.shutdown(wait=False)
self.executor = None
logger.debug("ThreadPoolExecutor shut down successfully.")
def __del__(self):
if hasattr(self, "executor") and self.executor is not None:
for f in self.prefetch_futures:
try:
if not f.done():
f.result()
except Exception as e:
logger.warning(f"Exception in prefetch future during shutdown: {e}")
self.executor.shutdown(wait=False)
self.executor = None
logger.debug("ThreadPoolExecutor shut down successfully.")

Comment on lines +78 to +95
if model_type == "wan2.1":
# wan2.1: filter files/dirs containing wan2.1 or Wan2.1
def is_valid(name):
name_lower = name.lower()
if "wan2.1" not in name_lower:
return False
if not fp8_supported and "fp8" in name_lower:
return False
return not any(kw in name_lower for kw in excluded_keywords)
else:
paths_to_check.append(os.path.join(model_path, subdir, filename))
print(paths_to_check)
for path in paths_to_check:
if os.path.exists(path):
logger.info(f"Found PyTorch model checkpoint: {path}")
return path
raise FileNotFoundError(f"PyTorch model file '{filename}' not found.\nPlease download the model from https://huggingface.co/lightx2v/ or specify the model path in the configuration file.")
# wan2.2: filter files/dirs containing wan2.2 or Wan2.2
def is_valid(name):
name_lower = name.lower()
if "wan2.2" not in name_lower:
return False
if not fp8_supported and "fp8" in name_lower:
return False
return not any(kw in name_lower for kw in excluded_keywords)
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

There is significant code duplication in this function. The is_valid nested function is defined twice with almost identical logic for model_type == 'wan2.1' and the else block. This pattern of duplication is also present across other get_*_choices functions (e.g., get_high_noise_choices, get_t5_choices).

To improve maintainability, this can be refactored. For get_dit_choices, you can define is_valid once and use the model_type variable from the outer scope. For the other functions, consider creating a single, more generic helper function that takes keywords as an argument to handle the filtering logic.

    def is_valid(name):
        name_lower = name.lower()
        if model_type not in name_lower:
            return False
        if not fp8_supported and "fp8" in name_lower:
            return False
        return not any(kw in name_lower for kw in excluded_keywords)

Comment on lines +78 to +95
if model_type == "wan2.1":
# wan2.1: 筛选包含 wan2.1 或 Wan2.1 的文件/目录
def is_valid(name):
name_lower = name.lower()
if "wan2.1" not in name_lower:
return False
if not fp8_supported and "fp8" in name_lower:
return False
return not any(kw in name_lower for kw in excluded_keywords)
else:
paths_to_check.append(os.path.join(model_path, subdir, filename))
print(paths_to_check)
for path in paths_to_check:
if os.path.exists(path):
logger.info(f"Found PyTorch model checkpoint: {path}")
return path
raise FileNotFoundError(f"PyTorch model file '{filename}' not found.\nPlease download the model from https://huggingface.co/lightx2v/ or specify the model path in the configuration file.")
# wan2.2: 筛选包含 wan2.2 或 Wan2.2 的文件/目录
def is_valid(name):
name_lower = name.lower()
if "wan2.2" not in name_lower:
return False
if not fp8_supported and "fp8" in name_lower:
return False
return not any(kw in name_lower for kw in excluded_keywords)
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

此函数中存在大量重复代码。is_valid 嵌套函数在 model_type == 'wan2.1'else 分支中被定义了两次,其逻辑几乎完全相同。这种重复模式也存在于其他的 get_*_choices 函数中(例如 get_high_noise_choices, get_t5_choices)。

为了提高可维护性,可以对此进行重构。对于 get_dit_choices,您可以只定义一次 is_valid 函数,并使用外部作用域的 model_type 变量。对于其他函数,可以考虑创建一个更通用的辅助函数,接收关键字作为参数来处理过滤逻辑。

    def is_valid(name):
        name_lower = name.lower()
        if model_type not in name_lower:
            return False
        if not fp8_supported and "fp8" in name_lower:
            return False
        return not any(kw in name_lower for kw in excluded_keywords)

@gushiqiao gushiqiao deleted the gsq_gradio branch December 11, 2025 10:27
helloyongyang pushed a commit that referenced this pull request Mar 6, 2026
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