Skip to content

experiment: support for uma#319

Open
timurbazhirov wants to merge 12 commits into
mainfrom
experiment/uma
Open

experiment: support for uma#319
timurbazhirov wants to merge 12 commits into
mainfrom
experiment/uma

Conversation

@timurbazhirov
Copy link
Copy Markdown
Member

@timurbazhirov timurbazhirov commented May 19, 2026

Summary by CodeRabbit

  • New Features

    • Interactive in-browser notebook for UMA-based crystal relaxation with real-time optimization charts, per-step energies, and side-by-side before/after visualizations.
  • New Features / Improvements

    • Enhanced Pyodide–PyTorch interoperability and optional FAIRChem compatibility to support heavier UMA models in-browser.
  • Chores

    • Environment config updated to include required packages and model pointers.
    • Git LFS tracking and model artifact pointers added/updated; repository ignore rules updated (node_modules).

Review Change Stack

@review-notebook-app
Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 24eb5465-afae-4c0f-ac9a-cc65a660cd72

📥 Commits

Reviewing files that changed from the base of the PR and between 28aec58 and 3acca48.

📒 Files selected for processing (1)
  • src/py/mat3ra/notebooks_utils/pyodide/packages/torch.py

📝 Walkthrough

Walkthrough

This PR extends Pyodide Torch patching to support FAIRChem/UMA, adds a uma notebook config and a JupyterLite notebook demonstrating UMA-based ASE BFGS relaxation with real-time Plotly tracking, and updates packaging LFS pointers plus .gitattributes/.gitignore.

Changes

FAIRChem UMA Support in Pyodide

Layer / File(s) Summary
Torch Pyodide Patching Infrastructure
src/py/mat3ra/notebooks_utils/pyodide/packages/torch.py
Adds WASM-safe linalg NumPy interop fallbacks; extracts patch_torch_compiler(); updates patch_torch_testing(); adds patch_torch_distributed() to stub distributed/FSDP/DTensor/checkpoint APIs; adds _make_stub_module() + patch_fairchem_deps() to stub heavy FAIRChem optional deps, monkey-patch torch.load for INT8 dequantization, and wrap registry.get_model_class; replaces apply_all_patches() with apply_all_patches(include_fairchem=False) that conditionally applies FAIRChem stubs.
UMA Notebook Configuration and Structure Relaxation Demo
config.yml, other/experiments/jupyterlite/relax_structure_with_uma.ipynb
Adds uma notebook config with packages_pyodide list; new JupyterLite notebook installs UMA packages and patches, loads a mat3ra structure and UMA checkpoint, constructs an FAIRChemCalculator, runs ASE BFGS relaxation with a Plotly streaming callback, visualizes pre/post structures, and computes interlayer-distance comparison.
Packaging pointers, LFS metadata, and .gitignore
.gitattributes, packages/antlr4_python3_runtime-4.9.3-py3-none-any.whl, packages/models/uma-s-1p1-f16.pt, packages/models/uma-s-1p1-int8.pt, .gitignore
Adds .gitattributes LFS rule for *.pt; updates LFS pointer metadata for the bundled wheel and UMA model artifacts; adds INT8 model LFS pointer; adds node_modules to .gitignore.

🎯 4 (Complex) | ⏱️ ~45 minutes

"A rabbit hops through a Pyodide wood so merry,
Patching torch and fairchem with whiskers airy,
UMA calms atoms while BFGS hums steady,
Steps and energies dance on a Plotly-ready,
Hooray — relaxed structures, soft and merry! 🐰"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.50% 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 clearly identifies the main change: adding experimental support for UMA model functionality across configuration, notebooks, and torch patches.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch experiment/uma

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

@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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@other/experiments/jupyterlite/relax_structure_with_uma.ipynb`:
- Around line 64-80: The notebook cell is malformed: remove the duplicated
"cell_type": "code" key so the JSON object has a single cell_type entry, and fix
the Python indentation by trimming the leading spaces on the lines importing and
calling apply_all_patches (the lines referencing
mat3ra.notebooks_utils.pyodide.packages.torch and apply_all_patches) so they are
left-aligned with the other statements; ensure the cell's "source" array
contains only correctly-indented strings and valid JSON keys.

In `@src/py/mat3ra/notebooks_utils/pyodide/packages/torch.py`:
- Around line 569-571: The file
src/py/mat3ra/notebooks_utils/pyodide/packages/torch.py was reformatted by
Black; run the formatter (e.g., run `black
src/py/mat3ra/notebooks_utils/pyodide/packages/torch.py` or `pre-commit run
--all-files`) and commit the updated file so the assignment to
sys.modules["ray.util.scheduling_strategies"].PlacementGroupSchedulingStrategy =
_PlacementGroupSchedulingStrategy matches Black's formatting; then push the
formatted changes.
- Around line 517-518: The lambda for numba_mod.njit currently returns the same
decorator in both branches, breaking direct usage like `@njit`; change the
conditional so that when a first positional argument is present and is callable
(i.e., the decorator used directly as `@njit`), `njit` returns that function
immediately, otherwise it returns a decorator function; update the expression
for numba_mod.njit accordingly and keep numba_mod.jit = numba_mod.njit to
preserve aliasing.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1bded097-58b6-42c4-9e82-3995f373b0e1

📥 Commits

Reviewing files that changed from the base of the PR and between f828635 and dc60d5a.

📒 Files selected for processing (3)
  • config.yml
  • other/experiments/jupyterlite/relax_structure_with_uma.ipynb
  • src/py/mat3ra/notebooks_utils/pyodide/packages/torch.py

Comment thread other/experiments/jupyterlite/relax_structure_with_uma.ipynb
Comment on lines +517 to +518
numba_mod.njit = lambda *a, **k: (lambda f: f) if not a or callable(a[0]) else lambda f: f
numba_mod.jit = numba_mod.njit
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Bug: Both ternary branches return identical values, breaking @njit direct decoration.

The condition (lambda f: f) if not a or callable(a[0]) else lambda f: f returns lambda f: f in both branches. When used as @njit (without parentheses), njit(fn) is called and should return fn directly, not a decorator.

🐛 Proposed fix
-    numba_mod.njit = lambda *a, **k: (lambda f: f) if not a or callable(a[0]) else lambda f: f
+    numba_mod.njit = lambda *a, **k: a[0] if a and callable(a[0]) else lambda f: f
📝 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
numba_mod.njit = lambda *a, **k: (lambda f: f) if not a or callable(a[0]) else lambda f: f
numba_mod.jit = numba_mod.njit
numba_mod.njit = lambda *a, **k: a[0] if a and callable(a[0]) else lambda f: f
numba_mod.jit = numba_mod.njit
🧰 Tools
🪛 Ruff (0.15.13)

[warning] 517-517: Useless if-else condition

(RUF034)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/py/mat3ra/notebooks_utils/pyodide/packages/torch.py` around lines 517 -
518, The lambda for numba_mod.njit currently returns the same decorator in both
branches, breaking direct usage like `@njit`; change the conditional so that
when a first positional argument is present and is callable (i.e., the decorator
used directly as `@njit`), `njit` returns that function immediately, otherwise
it returns a decorator function; update the expression for numba_mod.njit
accordingly and keep numba_mod.jit = numba_mod.njit to preserve aliasing.

Comment thread src/py/mat3ra/notebooks_utils/pyodide/packages/torch.py
Copy link
Copy Markdown

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

♻️ Duplicate comments (1)
src/py/mat3ra/notebooks_utils/pyodide/packages/torch.py (1)

583-585: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix numba_mod.njit direct-decorator behavior.

This stub returns a decorator in both branches; direct usage (@njit / njit(fn)) should return fn immediately, otherwise decorated call paths can break at runtime.

🐛 Proposed fix
-    numba_mod.njit = lambda *a, **k: (lambda f: f) if not a or callable(a[0]) else lambda f: f
+    numba_mod.njit = lambda *a, **k: a[0] if a and callable(a[0]) else (lambda f: f)
#!/bin/bash
# Verify the faulty expression is still present.
rg -nP 'numba_mod\.njit\s*=\s*lambda \*a, \*\*k: \(lambda f: f\) if not a or callable\(a\[0\]\) else lambda f: f'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/py/mat3ra/notebooks_utils/pyodide/packages/torch.py` around lines 583 -
585, The stub numba_mod.njit currently always returns a decorator, breaking
direct-usage patterns like `@njit` or njit(fn); change njit to return the callable
immediately when invoked with a single callable positional arg and no kwargs,
otherwise return the identity decorator. Concretely, replace the lambda with a
small function (named njit or assigned to numba_mod.njit) that does: if len(a)
== 1 and callable(a[0]) and not k: return a[0] else: return (lambda f: f); keep
numba_mod.jit assigned to the same implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@src/py/mat3ra/notebooks_utils/pyodide/packages/torch.py`:
- Around line 583-585: The stub numba_mod.njit currently always returns a
decorator, breaking direct-usage patterns like `@njit` or njit(fn); change njit to
return the callable immediately when invoked with a single callable positional
arg and no kwargs, otherwise return the identity decorator. Concretely, replace
the lambda with a small function (named njit or assigned to numba_mod.njit) that
does: if len(a) == 1 and callable(a[0]) and not k: return a[0] else: return
(lambda f: f); keep numba_mod.jit assigned to the same implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4936510c-3730-43c3-b257-acde9062f8c6

📥 Commits

Reviewing files that changed from the base of the PR and between fc7eb52 and 8758ac8.

📒 Files selected for processing (4)
  • config.yml
  • other/experiments/jupyterlite/relax_structure_with_uma.ipynb
  • packages/models/uma-s-1p1-int8.pt
  • src/py/mat3ra/notebooks_utils/pyodide/packages/torch.py

Copy link
Copy Markdown

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

🧹 Nitpick comments (1)
src/py/mat3ra/notebooks_utils/pyodide/packages/torch.py (1)

823-851: 💤 Low value

Consider guarding the fairchem import in INT8 dequantization path.

If torch.load is called on an INT8 checkpoint before FAIRChem is installed, the import on line 827 will raise ImportError. This monkey-patch runs unconditionally when patch_fairchem_deps() is called.

Potential guard
     if isinstance(result, dict) and "quantized_ema_state_dict" in result:
+        try:
+            from fairchem.core.units.mlip_unit.api.inference import MLIPInferenceCheckpoint
+        except ImportError:
+            print("⚠ INT8 checkpoint detected but fairchem-core not installed; returning raw dict")
+            return result
         import gc as _gc
-        from fairchem.core.units.mlip_unit.api.inference import MLIPInferenceCheckpoint
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/py/mat3ra/notebooks_utils/pyodide/packages/torch.py` around lines 823 -
851, The monkey-patched loader _int8_aware_torch_load unconditionally imports
MLIPInferenceCheckpoint from fairchem which raises ImportError if fairchem isn't
installed; wrap the fairchem import (the line importing MLIPInferenceCheckpoint
inside _int8_aware_torch_load) in a try/except ImportError and handle the
missing dependency by skipping dequantization and returning the original result
(or otherwise returning a sensible fallback) instead of raising—ensure
torch.load remains safe when patch_fairchem_deps() runs but fairchem is absent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/py/mat3ra/notebooks_utils/pyodide/packages/torch.py`:
- Around line 823-851: The monkey-patched loader _int8_aware_torch_load
unconditionally imports MLIPInferenceCheckpoint from fairchem which raises
ImportError if fairchem isn't installed; wrap the fairchem import (the line
importing MLIPInferenceCheckpoint inside _int8_aware_torch_load) in a try/except
ImportError and handle the missing dependency by skipping dequantization and
returning the original result (or otherwise returning a sensible fallback)
instead of raising—ensure torch.load remains safe when patch_fairchem_deps()
runs but fairchem is absent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4e2ca0a5-5bf6-48a1-9000-37dba3a6e0f2

📥 Commits

Reviewing files that changed from the base of the PR and between 8758ac8 and 28aec58.

📒 Files selected for processing (4)
  • .gitignore
  • config.yml
  • other/experiments/jupyterlite/relax_structure_with_uma.ipynb
  • src/py/mat3ra/notebooks_utils/pyodide/packages/torch.py
✅ Files skipped from review due to trivial changes (1)
  • .gitignore
🚧 Files skipped from review as they are similar to previous changes (1)
  • config.yml

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