Skip to content

Dion optimizer support#3014

Merged
winglian merged 9 commits into
mainfrom
dion-optim
Aug 4, 2025
Merged

Dion optimizer support#3014
winglian merged 9 commits into
mainfrom
dion-optim

Conversation

@winglian
Copy link
Copy Markdown
Collaborator

@winglian winglian commented Aug 4, 2025

Description

Adds support for https://github.com/microsoft/dion via the contribs integration

Motivation and Context

How has this been tested?

Screenshots (if appropriate)

Types of changes

Social Handles (Optional)

Summary by CodeRabbit

  • New Features
    • Added support for the "Dion" optimizer with configurable learning rate, momentum, rank fraction, and rank multiple.
    • Expanded supported custom optimizers to include "Dion".
    • Enhanced parameter filtering for weight decay in optimizers.
  • Tests
    • Added end-to-end test validating training with the "Dion" optimizer.
  • Documentation
    • Added detailed documentation for the "Dion" optimizer and updated sidebar navigation.
    • Updated "N-D Parallelism" documentation heading to indicate beta status.
  • Chores
    • Updated dependency version for axolotl-contribs-mit to 0.0.4.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Aug 4, 2025

📖 Documentation Preview: https://6890ee1bfe0dc2a416e0086a--resonant-treacle-0fd729.netlify.app

Deployed on Netlify from commit a321454

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 4, 2025

📝 Walkthrough

Walkthrough

This change introduces support for a new custom optimizer named "dion" throughout the codebase. It updates configuration schemas, training argument mixins, and the optimizer builder to handle Dion-specific hyperparameters. The test suite is expanded with an end-to-end test for the Dion optimizer, and the requirements are updated to reference a newer version of axolotl-contribs-mit. Additionally, documentation files were added and updated to describe the Dion optimizer and mark N-D Parallelism as beta.

Changes

Cohort / File(s) Change Summary
Dion Optimizer Integration
src/axolotl/core/builders/base.py, src/axolotl/core/training_args_base.py, src/axolotl/integrations/base.py, src/axolotl/utils/schemas/enums.py, src/axolotl/utils/schemas/training.py
Added support for a new "dion" optimizer: updated optimizer configuration logic, extended training argument mixins and config schemas with Dion-specific fields, added Dion to supported optimizers enum, and implemented a method for parameter name filtering for weight decay.
End-to-End Test for Dion Optimizer
tests/e2e/test_optimizers.py
Added a new test case for the Dion optimizer, including configuration, execution, and validation. Updated imports and made a minor correction in an existing test.
Documentation Updates
_quarto.yml, docs/optimizers.qmd, docs/nd_parallelism.qmd
Added new documentation file for the Dion optimizer and included it in the sidebar. Updated the N-D Parallelism doc heading to indicate beta status.
Dependency Update
requirements.txt
Bumped axolotl-contribs-mit package version from 0.0.3 to 0.0.4.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15–20 minutes

Note

⚡️ Unit Test Generation is now available in beta!

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


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dcb5de8 and a321454.

📒 Files selected for processing (1)
  • tests/e2e/test_optimizers.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/e2e/test_optimizers.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: PyTest from Source Dist (3.11, 2.6.0)
  • GitHub Check: PyTest (3.11, 2.6.0)
  • GitHub Check: PyTest from Source Dist (3.11, 2.7.1)
  • GitHub Check: PyTest from Source Dist (3.11, 2.7.0)
  • GitHub Check: PyTest (3.11, 2.7.1)
  • GitHub Check: PyTest (3.11, 2.7.0)
  • GitHub Check: preview
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dion-optim

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.
  • 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.

Support

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

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.

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.

@codecov
Copy link
Copy Markdown

codecov Bot commented Aug 4, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
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: 2

🧹 Nitpick comments (1)
src/axolotl/core/training_args_base.py (1)

247-260: Add help metadata for consistency and documentation.

The dion_rank_fraction and dion_rank_multiple_of fields are missing help metadata, while the other Dion fields have descriptive help text. This inconsistency could impact auto-generated documentation and user experience.

Consider adding help metadata for these fields:

 dion_rank_fraction: float | None = field(
     default=None,
+    metadata={"help": "The rank fraction for Dion optimizer"},
 )
 dion_rank_multiple_of: int | None = field(
     default=None,
+    metadata={"help": "The rank multiple for Dion optimizer"},
 )
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e758343 and e4e13ec.

📒 Files selected for processing (7)
  • requirements.txt (1 hunks)
  • src/axolotl/core/builders/base.py (2 hunks)
  • src/axolotl/core/training_args_base.py (1 hunks)
  • src/axolotl/integrations/base.py (2 hunks)
  • src/axolotl/utils/schemas/enums.py (1 hunks)
  • src/axolotl/utils/schemas/training.py (1 hunks)
  • tests/e2e/test_optimizers.py (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: PyTest from Source Dist (3.11, 2.7.0)
  • GitHub Check: PyTest (3.11, 2.7.0)
  • GitHub Check: PyTest (3.11, 2.6.0)
  • GitHub Check: PyTest (3.11, 2.7.1)
  • GitHub Check: test-axolotl-multigpu (126, 12.6.3, 3.11, 2.6.0, 2, true)
  • GitHub Check: test-axolotl-multigpu (126, 12.6.3, 3.11, 2.7.1, vllm, 2, true)
  • GitHub Check: test-axolotl-multigpu (126, 12.6.3, 3.11, 2.7.0, 2, true)
🔇 Additional comments (13)
requirements.txt (1)

69-69: LGTM: Dependency version update supports new Dion optimizer.

The version bump from 0.0.3 to 0.0.4 for axolotl-contribs-mit correctly aligns with the introduction of Dion optimizer support, which imports from this package.

src/axolotl/utils/schemas/enums.py (1)

82-82: LGTM: Enum addition follows established patterns.

The addition of "dion" to the CustomSupportedOptimizers enum is correctly implemented and consistent with existing optimizer entries.

src/axolotl/utils/schemas/training.py (1)

142-159: LGTM: Well-structured schema extensions for Dion optimizer.

The new Dion optimizer fields are properly implemented with:

  • Consistent naming conventions following existing patterns
  • Appropriate field types and default values
  • Descriptive JSON schema metadata
  • Logical parameter grouping

The schema extensions correctly support the new optimizer's configuration requirements.

tests/e2e/test_optimizers.py (1)

164-205: LGTM: Comprehensive test coverage for Dion optimizer.

The new test_dion method provides excellent test coverage with:

  • Proper PyTorch version requirement enforcement
  • Comprehensive configuration including Dion-specific parameters
  • Standard validation flow following established patterns
  • Appropriate optimizer class name verification
src/axolotl/integrations/base.py (3)

29-29: LGTM: Required import for new parameter filtering functionality.

The torch.nn import is correctly added to support the new get_decay_parameter_names method.


33-33: LGTM: Import follows transformers library patterns.

The get_parameter_names import from transformers provides established parameter filtering functionality.


647-666: LGTM: Well-implemented parameter filtering for weight decay.

The get_decay_parameter_names method provides essential functionality for optimizers with:

  • Proper filtering of normalization layers (LayerNorm)
  • Comprehensive regex patterns for bias and norm parameter exclusion
  • Use of established transformers utility functions
  • Clear documentation explaining the filtering logic

This will enable proper weight decay application in optimizers like Dion.

src/axolotl/core/training_args_base.py (2)

247-250: LGTM!

The Dion learning rate field is properly implemented with appropriate type annotation and descriptive help metadata.


251-254: LGTM!

The Dion momentum field is properly implemented with appropriate type annotation and descriptive help metadata.

src/axolotl/core/builders/base.py (4)

530-532: LGTM!

The Dion optimizer parameters are correctly added to the training arguments list following the existing pattern.


537-542: LGTM!

The argument mapping for dion_learning_rate to dion_lr is implemented correctly and follows a clean pattern for parameter name translation.


279-280: Inefficient PartialState Instantiation – No Reusable Instance in Scope

Each call to PartialState() creates a fresh object, and in this optimizer-building block there is no existing partial_state to reuse. The only other instantiation in this file lives inside a separate method (_configure_accelerator_config), so it isn’t accessible here. Also, PartialState().device_mesh is guaranteed to exist, as downstream code uses it extensively (e.g. in sequence-parallel, FSDP monkey patches, model loaders).

Locations to inspect or improve:

  • src/axolotl/core/builders/base.py (around line 279):
        partial_state = PartialState()
        optimizer_kwargs["device_mesh"] = partial_state.device_mesh
    
  • _configure_accelerator_config (around line 447): separate scope, its partial_state cannot be shared.

Recommendation:

  • If performance is a concern, consider hoisting a single PartialState instance to self (e.g., self._partial_state) in the builder’s constructor or earliest configuration method, then reuse it in both _configure_accelerator_config and optimizer setup.
  • Otherwise, leave as is—device_mesh is always available on a fresh PartialState.

270-273: No changes needed for the dion import
The path axolotl.contribs.mit.dion is correct and the package is declared in requirements.txt (axolotl-contribs-mit==0.0.4). Other contrib imports (e.g. muon) use the same pattern and there’s no missing error handling requirement here.

Comment on lines +270 to +280
elif self.cfg.optimizer == "dion":
from axolotl.contribs.mit.dion import ( # pylint: disable=no-name-in-module
DionOptimizerFactory,
)

optimizer_cls = DionOptimizerFactory
optimizer_kwargs["dion_lr"] = training_args_kwargs["dion_learning_rate"]
optimizer_kwargs["dion_mu"] = training_args_kwargs["dion_momentum"]
optimizer_kwargs.update(adam_kwargs)
partial_state = PartialState()
optimizer_kwargs["device_mesh"] = partial_state.device_mesh
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for required Dion parameters.

The code assumes dion_learning_rate and dion_momentum are always present in training_args_kwargs, but these could be None or missing, which would cause runtime errors.

Add validation for required parameters:

 elif self.cfg.optimizer == "dion":
     from axolotl.contribs.mit.dion import (  # pylint: disable=no-name-in-module
         DionOptimizerFactory,
     )

     optimizer_cls = DionOptimizerFactory
+    
+    dion_lr = training_args_kwargs.get("dion_learning_rate")
+    dion_mu = training_args_kwargs.get("dion_momentum")
+    
+    if dion_lr is None:
+        raise ValueError("dion_learning_rate is required when using dion optimizer")
+    if dion_mu is None:
+        raise ValueError("dion_momentum is required when using dion optimizer")
+        
-    optimizer_kwargs["dion_lr"] = training_args_kwargs["dion_learning_rate"]
-    optimizer_kwargs["dion_mu"] = training_args_kwargs["dion_momentum"]
+    optimizer_kwargs["dion_lr"] = dion_lr
+    optimizer_kwargs["dion_mu"] = dion_mu
     optimizer_kwargs.update(adam_kwargs)
     partial_state = PartialState()
     optimizer_kwargs["device_mesh"] = partial_state.device_mesh
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
elif self.cfg.optimizer == "dion":
from axolotl.contribs.mit.dion import ( # pylint: disable=no-name-in-module
DionOptimizerFactory,
)
optimizer_cls = DionOptimizerFactory
optimizer_kwargs["dion_lr"] = training_args_kwargs["dion_learning_rate"]
optimizer_kwargs["dion_mu"] = training_args_kwargs["dion_momentum"]
optimizer_kwargs.update(adam_kwargs)
partial_state = PartialState()
optimizer_kwargs["device_mesh"] = partial_state.device_mesh
elif self.cfg.optimizer == "dion":
from axolotl.contribs.mit.dion import ( # pylint: disable=no-name-in-module
DionOptimizerFactory,
)
optimizer_cls = DionOptimizerFactory
dion_lr = training_args_kwargs.get("dion_learning_rate")
dion_mu = training_args_kwargs.get("dion_momentum")
if dion_lr is None:
raise ValueError("dion_learning_rate is required when using dion optimizer")
if dion_mu is None:
raise ValueError("dion_momentum is required when using dion optimizer")
optimizer_kwargs["dion_lr"] = dion_lr
optimizer_kwargs["dion_mu"] = dion_mu
optimizer_kwargs.update(adam_kwargs)
partial_state = PartialState()
optimizer_kwargs["device_mesh"] = partial_state.device_mesh
🤖 Prompt for AI Agents
In src/axolotl/core/builders/base.py around lines 270 to 280, the code assumes
that 'dion_learning_rate' and 'dion_momentum' keys exist and are not None in
training_args_kwargs, which can cause runtime errors if missing or None. Add
validation checks before using these parameters to ensure they are present and
not None; if validation fails, raise a clear exception or handle the error
appropriately to prevent runtime failures.

Comment thread tests/e2e/test_optimizers.py Outdated
@winglian winglian merged commit ab49d16 into main Aug 4, 2025
20 checks passed
@winglian winglian deleted the dion-optim branch August 4, 2025 20:33
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.

1 participant