Skip to content

feat: add SCAO (Sparse Curvature-Aware Adaptive Optimizer) support#3624

Open
whispering3 wants to merge 13 commits into
axolotl-ai-cloud:mainfrom
whispering3:main
Open

feat: add SCAO (Sparse Curvature-Aware Adaptive Optimizer) support#3624
whispering3 wants to merge 13 commits into
axolotl-ai-cloud:mainfrom
whispering3:main

Conversation

@whispering3
Copy link
Copy Markdown

@whispering3 whispering3 commented Apr 24, 2026

Description

Following the discussion in Issue #3616, this PR adds native support for SCAO (Sparse Curvature-Aware Adaptive Optimizer).

As requested, the optimizer math itself is fully isolated in an external, pip-installable package (scao). This PR simply adds the routing logic in the Trainer Builder to allow users to set optimizer: scao in their .yml config files.

You can check the PyPI package here: https://pypi.org/project/scao/

Benchmark / Rationale

SCAO is designed to bring 2nd-order convergence to QLoRA setups without the typical memory or speed penalties. Because QLoRA is heavily memory-bound, SCAO computes curvature essentially for free.

T4 GPU / Qwen-2.5-3B (First 100 Steps):

  • AdamW: 16.65 s/it | Final Loss: 2.741
  • SCAO: 16.52 s/it | Final Loss: 2.523

Changes

  • Added "scao" handling in _configure_custom_optimizer.
  • Imports dynamically via try/except to guide users to run pip install scao.

Testing

Tested locally with a Qwen-2.5-3B config. No OOM issues, parameters inject correctly.

Summary by CodeRabbit

  • New Features
    • Added support for the scao optimizer. Users can now configure and use this optimizer option in their training configurations.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 24, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8a7cd894-564f-479e-b863-5d7e7bdd46d3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds support for the SCAO custom optimizer by extending the CustomSupportedOptimizers enum and implementing its initialization in the optimizer configuration builder with proper import error handling and beta parameter setup.

Changes

Cohort / File(s) Summary
Custom Optimizer Support
src/axolotl/core/builders/base.py
Implements SCAO optimizer initialization with import error handling, beta parameter extraction from training args defaults, and kwargs merging.
Optimizer Enum Extension
src/axolotl/utils/schemas/enums.py
Adds scao identifier to CustomSupportedOptimizers enum to enable configuration validation.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • NanoCode012
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and specifically describes the main change: adding SCAO optimizer support to the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with 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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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: 1

🧹 Nitpick comments (1)
src/axolotl/utils/schemas/enums.py (1)

98-98: Nit: trailing whitespace.

There's a trailing space after "scao" on this line. Most pre-commit/linter configs (e.g. trailing-whitespace) will flag or auto-fix this.

✂️ Proposed fix
-    scao = "scao" 
+    scao = "scao"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/axolotl/utils/schemas/enums.py` at line 98, The line defining the enum
entry scao has a trailing whitespace after the string literal (scao = "scao" ),
remove the trailing space so the assignment is exactly scao = "scao" to satisfy
linters; update the enum entry in enums.py where the symbol scao is defined to
remove the extra space character.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/axolotl/core/builders/base.py`:
- Around line 384-395: The ImportError raised when importing SCAO should
suppress the internal traceback by chaining it with from None; in the block
where you check self.cfg.optimizer == "scao" and try to from scao.optimizer
import SCAO, change the re-raised ImportError to use "raise ImportError('SCAO
optimizer not found. Please install it with \'pip install scao\'') from None" so
the user-facing install hint replaces the internal traceback.

---

Nitpick comments:
In `@src/axolotl/utils/schemas/enums.py`:
- Line 98: The line defining the enum entry scao has a trailing whitespace after
the string literal (scao = "scao" ), remove the trailing space so the assignment
is exactly scao = "scao" to satisfy linters; update the enum entry in enums.py
where the symbol scao is defined to remove the extra space character.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1138560b-1f2c-495c-903f-aa69882c7f8b

📥 Commits

Reviewing files that changed from the base of the PR and between 798c8fb and 46d1e42.

📒 Files selected for processing (2)
  • src/axolotl/core/builders/base.py
  • src/axolotl/utils/schemas/enums.py

Comment on lines +384 to +395
elif self.cfg.optimizer == "scao":
try:
from scao.optimizer import SCAO
except ImportError:
raise ImportError(
"SCAO optimizer not found. Please install it with 'pip install scao'"
)
optimizer_cls = SCAO
beta1 = training_args_kwargs.get("adam_beta1", 0.9)
beta2 = training_args_kwargs.get("adam_beta2", 0.999)
adam_kwargs["betas"] = (beta1, beta2)
optimizer_kwargs.update(adam_kwargs)
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 | 🟡 Minor

Chain the re-raised ImportError (Ruff B904).

Ruff flags raise ... from err/from None inside an except block to avoid obscuring the original traceback. Since the intent here is to replace the internal traceback with a user-facing install hint, from None is appropriate and matches the style used elsewhere for optional-dependency imports.

🛠️ Proposed fix
             elif self.cfg.optimizer == "scao":
                 try:
                     from scao.optimizer import SCAO
-                except ImportError:
+                except ImportError as err:
                     raise ImportError(
                         "SCAO optimizer not found. Please install it with 'pip install scao'"
-                    )
+                    ) from err
                 optimizer_cls = SCAO
                 beta1 = training_args_kwargs.get("adam_beta1", 0.9)
                 beta2 = training_args_kwargs.get("adam_beta2", 0.999)
                 adam_kwargs["betas"] = (beta1, beta2)
                 optimizer_kwargs.update(adam_kwargs)
📝 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 == "scao":
try:
from scao.optimizer import SCAO
except ImportError:
raise ImportError(
"SCAO optimizer not found. Please install it with 'pip install scao'"
)
optimizer_cls = SCAO
beta1 = training_args_kwargs.get("adam_beta1", 0.9)
beta2 = training_args_kwargs.get("adam_beta2", 0.999)
adam_kwargs["betas"] = (beta1, beta2)
optimizer_kwargs.update(adam_kwargs)
elif self.cfg.optimizer == "scao":
try:
from scao.optimizer import SCAO
except ImportError as err:
raise ImportError(
"SCAO optimizer not found. Please install it with 'pip install scao'"
) from err
optimizer_cls = SCAO
beta1 = training_args_kwargs.get("adam_beta1", 0.9)
beta2 = training_args_kwargs.get("adam_beta2", 0.999)
adam_kwargs["betas"] = (beta1, beta2)
optimizer_kwargs.update(adam_kwargs)
🧰 Tools
🪛 Ruff (0.15.11)

[warning] 388-390: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/axolotl/core/builders/base.py` around lines 384 - 395, The ImportError
raised when importing SCAO should suppress the internal traceback by chaining it
with from None; in the block where you check self.cfg.optimizer == "scao" and
try to from scao.optimizer import SCAO, change the re-raised ImportError to use
"raise ImportError('SCAO optimizer not found. Please install it with \'pip
install scao\'') from None" so the user-facing install hint replaces the
internal traceback.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 26, 2026

Codecov Report

❌ Patch coverage is 10.00000% with 9 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/axolotl/core/builders/base.py 0.00% 9 Missing ⚠️

📢 Thoughts on this report? Let us know!

@whispering3
Copy link
Copy Markdown
Author

Hi! I just updated the branch to sync with main, and all CI checks are green. Let me know if you need any adjustments to the code or documentation before review. Thanks!

whispering3 and others added 3 commits May 16, 2026 08:11
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@whispering3
Copy link
Copy Markdown
Author

Added E2E coverage for the SCAO optimizer in tests/e2e/test_optimizers.py (test_scao), following the existing optimizer test pattern.

CI is currently waiting for maintainer approval to run workflows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants