Skip to content

refactor(model): unify dpmodel backend factories - #5786

Merged
njzjz merged 4 commits into
deepmodeling:masterfrom
njzjz:refactor/unify-dpmodel-get-model
Jul 28, 2026
Merged

refactor(model): unify dpmodel backend factories#5786
njzjz merged 4 commits into
deepmodeling:masterfrom
njzjz:refactor/unify-dpmodel-get-model

Conversation

@njzjz-bot

@njzjz-bot njzjz-bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Summary

  • introduce BackendModelFactory to bind backend descriptor, fitting, model, atomic-model, pair-table, and ZBL registries once
  • centralize descriptor/fitting parameter injection, standard-model selection, ZBL assembly, legacy model routing, plugin fallback, and spin preprocessing
  • make JAX and TF2 export the bound shared factory methods directly; keep only genuine backend special cases in dpmodel and pt_expt
  • reuse the shared component path for pt_expt DPA4/SeZM and linear submodels
  • register/export all dpmodel model types through the package, removing unused side-effect imports
  • preserve configured ZBL smin_alpha values and route pt_expt use_srtab configurations to its backend-native DPZBLModel
  • use descriptor-derived cutoff and selection values for JAX/TF2 ZBL pair tables, carrying the normalized fix: dpmodel zbl rcut sel #4339 behavior beyond dpmodel

Validation

  • ruff check .
  • ruff format .
  • all commit hooks, including isort, Ruff, Velin, and pylint
  • shared routing, construction, input-immutability, and unsupported-variant tests
  • dpmodel standard/spin construction tests
  • JAX standard and ZBL factory tests
  • pt_expt standard, spin, ZBL, DPA4/SeZM, and linear-model tests
  • isolated TF2 standard-model construction smoke test

Coding agent: Codex
Codex version: codex-cli 0.144.4
Model: gpt-5.6-sol
Reasoning effort: xhigh

Summary by CodeRabbit

  • New Features
    • Added unified, backend-agnostic model construction with routing for standard, spin, ZBL, linear-energy, and registered variants.
    • Expanded the public model API to include linear-energy, DPA4 energy, native-spin, ZBL, and additional property models (DOS, Dipole, Polar).
  • Bug Fixes
    • Improved configuration handling so caller-provided settings are preserved.
    • Ensured tabulated-potential (use_srtab) configurations correctly produce ZBL models.
  • Tests
    • Added coverage for model routing, unsupported variants, shared construction behavior, and configuration preservation.
    • Added a dedicated pt-expt ZBL selection test using use_srtab.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b54d439e-0e0c-46c6-84f6-d326a5ad845d

📥 Commits

Reviewing files that changed from the base of the PR and between 757ccb3 and b03a169.

📒 Files selected for processing (1)
  • deepmd/dpmodel/model/__init__.py

📝 Walkthrough

Walkthrough

Model construction is centralized in BackendModelFactory and shared helpers, then wired into dpmodel, JAX, TF2, and pt_expt entry points. Dispatch now handles standard, spin, native-spin, ZBL, specialized types, and registry fallback through common routing.

Changes

Model factory dispatch

Layer / File(s) Summary
Shared construction and dispatch helpers
deepmd/dpmodel/model/model_factory.py
Adds shared descriptor/fitting construction, standard and ZBL builders, spin adaptation, factory precedence, registry fallback, and backend-bound factory methods.
dpmodel factory integration
deepmd/dpmodel/model/model.py
Routes standard, ZBL, spin, and top-level model construction through the shared factory while retaining analytical bridging composition.
JAX and TF2 delegation
deepmd/jax/model/model.py, deepmd/tf2/model/model.py
Configures backend-specific factories and aliases standard, ZBL, and general model entry points to factory methods.
pt_expt construction and dispatch
deepmd/pt_expt/model/get_model.py
Uses shared component construction and factory routing for standard, ZBL, spin, linear, SeZm, DPA4, and related model types.
Public exports and validation
deepmd/dpmodel/model/__init__.py, source/tests/common/dpmodel/test_model_factory.py, source/tests/pt_expt/model/test_get_model_zbl.py
Exports additional model classes and tests routing, construction fields, non-mutation, registry precedence, and pt_expt ZBL selection.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant BackendModelFactory
  participant get_model_components
  participant BackendModel
  Caller->>BackendModelFactory: request model from configuration
  BackendModelFactory->>get_model_components: build descriptor and fitting
  get_model_components-->>BackendModelFactory: return components and fitting type
  BackendModelFactory->>BackendModel: construct standard, ZBL, or specialized model
  BackendModel-->>Caller: return configured model
Loading

Possibly related PRs

Suggested reviewers: iprozd, njzjz, outisli

🚥 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 clearly reflects the main change: refactoring model code to unify backend factory handling.
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.
✨ 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.

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
source/tests/common/dpmodel/test_model_factory.py (1)

71-79: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add symmetric test coverage for the ZBL NotImplementedError branch.

Only the spin_model_factory is None branch is tested; the sibling zbl_model_factory is None branch (model_factory.py lines 58-61) has no direct test.

♻️ Suggested additional test
     def test_unsupported_standard_variant(self) -> None:
         with self.assertRaisesRegex(
             NotImplementedError, "Spin model is not implemented yet"
         ):
             get_model(
                 {"spin": {}},
                 base_model=_BaseModel,
                 standard_model_factory=_factory("standard"),
             )
+
+    def test_unsupported_zbl_variant(self) -> None:
+        with self.assertRaisesRegex(
+            NotImplementedError, "ZBL model is not implemented yet"
+        ):
+            get_model(
+                {"use_srtab": "table"},
+                base_model=_BaseModel,
+                standard_model_factory=_factory("standard"),
+            )
🤖 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 `@source/tests/common/dpmodel/test_model_factory.py` around lines 71 - 79, Add
a test alongside test_unsupported_standard_variant that exercises get_model with
a ZBL configuration and zbl_model_factory set to None, while providing the other
required factory arguments. Assert that it raises NotImplementedError with the
expected ZBL-not-implemented message, covering the sibling branch in get_model.
🤖 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 `@source/tests/common/dpmodel/test_model_factory.py`:
- Around line 71-79: Add a test alongside test_unsupported_standard_variant that
exercises get_model with a ZBL configuration and zbl_model_factory set to None,
while providing the other required factory arguments. Assert that it raises
NotImplementedError with the expected ZBL-not-implemented message, covering the
sibling branch in get_model.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 66d07fa5-94c0-4fc4-97a7-2ff40358cf54

📥 Commits

Reviewing files that changed from the base of the PR and between 2c0a54e and 0580ee6.

📒 Files selected for processing (7)
  • deepmd/dpmodel/model/model.py
  • deepmd/dpmodel/model/model_factory.py
  • deepmd/jax/model/model.py
  • deepmd/pt_expt/model/get_model.py
  • deepmd/tf2/model/model.py
  • source/tests/common/dpmodel/test_model_factory.py
  • source/tests/pt_expt/model/test_get_model_zbl.py

@njzjz
njzjz force-pushed the refactor/unify-dpmodel-get-model branch 2 times, most recently from 9d6222c to 083e5b2 Compare July 13, 2026 23:32

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
source/tests/common/dpmodel/test_model_factory.py (1)

123-131: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add symmetric coverage for the ZBL unsupported branch.

test_unsupported_standard_variant only exercises the spin branch (zbl_model_factory=None with "use_srtab" in data is untested). Given this shared factory now backs dpmodel, JAX, TF2, and pt_expt routing, testing both NotImplementedError branches would guard against regressions in the precedence/error logic.

🧪 Suggested addition
     def test_unsupported_standard_variant(self) -> None:
         with self.assertRaisesRegex(
             NotImplementedError, "Spin model is not implemented yet"
         ):
             get_model(
                 {"spin": {}},
                 base_model=_BaseModel,
                 standard_model_factory=_factory("standard"),
             )
+        with self.assertRaisesRegex(
+            NotImplementedError, "ZBL model is not implemented yet"
+        ):
+            get_model(
+                {"use_srtab": "table"},
+                base_model=_BaseModel,
+                standard_model_factory=_factory("standard"),
+            )
🤖 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 `@source/tests/common/dpmodel/test_model_factory.py` around lines 123 - 131,
Add a symmetric test alongside test_unsupported_standard_variant that calls
get_model with data containing "use_srtab" and zbl_model_factory=None, while
providing the required base_model and standard_model_factory arguments. Assert
that this ZBL route raises NotImplementedError with the expected unsupported-ZBL
error message, preserving coverage of both unsupported branches and their
precedence.
🤖 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 `@deepmd/dpmodel/model/model_factory.py`:
- Around line 105-120: Update get_zbl_model’s zbl_model construction to forward
data["smin_alpha"] alongside sw_rmin and sw_rmax, preserving configured softmin
values instead of relying on the constructor default.

---

Nitpick comments:
In `@source/tests/common/dpmodel/test_model_factory.py`:
- Around line 123-131: Add a symmetric test alongside
test_unsupported_standard_variant that calls get_model with data containing
"use_srtab" and zbl_model_factory=None, while providing the required base_model
and standard_model_factory arguments. Assert that this ZBL route raises
NotImplementedError with the expected unsupported-ZBL error message, preserving
coverage of both unsupported branches and their precedence.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 29148648-bb52-4911-9dee-b80c916543a8

📥 Commits

Reviewing files that changed from the base of the PR and between 0580ee6 and 083e5b2.

📒 Files selected for processing (7)
  • deepmd/dpmodel/model/model.py
  • deepmd/dpmodel/model/model_factory.py
  • deepmd/jax/model/model.py
  • deepmd/pt_expt/model/get_model.py
  • deepmd/tf2/model/model.py
  • source/tests/common/dpmodel/test_model_factory.py
  • source/tests/pt_expt/model/test_get_model_zbl.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • source/tests/pt_expt/model/test_get_model_zbl.py

Comment thread deepmd/dpmodel/model/model_factory.py
Comment thread deepmd/dpmodel/model/model.py Fixed
Comment thread deepmd/dpmodel/model/model.py Fixed
Comment thread deepmd/dpmodel/model/model.py Fixed
@codecov

codecov Bot commented Jul 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.12230% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.03%. Comparing base (2f419f4) to head (b03a169).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
deepmd/dpmodel/model/model_factory.py 95.65% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5786      +/-   ##
==========================================
- Coverage   79.06%   78.03%   -1.03%     
==========================================
  Files        1067     1068       +1     
  Lines      123805   123681     -124     
  Branches     4510     4510              
==========================================
- Hits        97891    96520    -1371     
- Misses      24304    25551    +1247     
  Partials     1610     1610              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Centralize descriptor and fitting parameter injection, standard-model selection, ZBL assembly, and model-type routing across dpmodel, pt_expt, JAX, and TF2. Keep backend modules limited to their native class registries and supported special cases.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.1
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
@njzjz
njzjz force-pushed the refactor/unify-dpmodel-get-model branch from 083e5b2 to 6e5a4a9 Compare July 14, 2026 01:45
@njzjz-bot

Copy link
Copy Markdown
Contributor Author

Addressed the review-summary feedback and further consolidated the backend factories in 6e5a4a9:

  • added symmetric coverage for the unsupported ZBL route;
  • forwarded non-default smin_alpha values through the shared ZBL constructor and added a 0.37 regression assertion;
  • replaced unused side-effect imports with package-level dpmodel model registration/exports;
  • shared the duplicate dpmodel/pt_expt spin preprocessing;
  • added BackendModelFactory so backend registries are bound once; JAX and TF2 now expose the bound shared methods directly, while dpmodel and pt_expt retain wrappers only for supported special cases.

All inline threads have been replied to and resolved. Targeted dpmodel, JAX, pt_expt, spin, ZBL, DPA4/SeZM, linear, and TF2 smoke validations pass, as do all commit hooks.

Coding agent: Codex
Codex version: codex-cli 0.144.1
Model: gpt-5.6-sol
Reasoning effort: xhigh

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
deepmd/dpmodel/model/model_factory.py (1)

89-125: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Redundant deep-copy of data in get_zbl_model.

data is deep-copied at Line 100, but get_zbl_model only ever reads from data afterward (no mutation), and get_model_components already performs its own internal deep-copy at Line 33. This duplicates the copy of the whole config dict on every ZBL build for no benefit; get_standard_model doesn't need this pattern either. Also confirms the earlier smin_alpha forwarding gap from a prior review is now fixed at Line 122.

♻️ Proposed fix
     """Construct a ZBL model from backend-native atomic model classes."""
-    data = copy.deepcopy(data)
     descriptor, fitting, fitting_type = get_model_components(
🤖 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 `@deepmd/dpmodel/model/model_factory.py` around lines 89 - 125, Remove the
redundant copy.deepcopy call from get_zbl_model. Keep passing the original data
into get_model_components and preserve all existing read-only lookups and
smin_alpha forwarding unchanged.
🤖 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 `@deepmd/dpmodel/model/model_factory.py`:
- Around line 89-125: Remove the redundant copy.deepcopy call from
get_zbl_model. Keep passing the original data into get_model_components and
preserve all existing read-only lookups and smin_alpha forwarding unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 20244ca3-1bf1-4ea5-a5d2-007b35fce206

📥 Commits

Reviewing files that changed from the base of the PR and between 083e5b2 and 6e5a4a9.

📒 Files selected for processing (8)
  • deepmd/dpmodel/model/__init__.py
  • deepmd/dpmodel/model/model.py
  • deepmd/dpmodel/model/model_factory.py
  • deepmd/jax/model/model.py
  • deepmd/pt_expt/model/get_model.py
  • deepmd/tf2/model/model.py
  • source/tests/common/dpmodel/test_model_factory.py
  • source/tests/pt_expt/model/test_get_model_zbl.py
🚧 Files skipped from review as they are similar to previous changes (6)
  • source/tests/pt_expt/model/test_get_model_zbl.py
  • deepmd/jax/model/model.py
  • deepmd/tf2/model/model.py
  • source/tests/common/dpmodel/test_model_factory.py
  • deepmd/dpmodel/model/model.py
  • deepmd/pt_expt/model/get_model.py

@njzjz
njzjz requested a review from wanghan-iapcm July 14, 2026 06:21
wanghan-iapcm
wanghan-iapcm previously approved these changes Jul 15, 2026

@wanghan-iapcm wanghan-iapcm left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nice consolidation. I verified the model-registry keys align across all four backends (dipole/polar/dos/ener/property, with direct_force_ener remapped to ener) so get_class_by_type resolves the same classes the old if/elif did, and the init imports make the registrations run. Routing precedence (spin->zbl->standard), the explicit-type fallback, and the pt_expt DPA4/SeZM/linear special cases are all preserved. One non-blocking note for a follow-up: get_zbl_model now honors a configured smin_alpha (data.get('smin_alpha', 0.1)) which the old dp/jax/tf2 path silently dropped -- a good fix, but the pt backend still ignores smin_alpha, so the two backends are now inconsistent on that key. LGTM.

@wanghan-iapcm
wanghan-iapcm dismissed their stale review July 15, 2026 15:35

Dismissing to re-review through the /code-review skill per process.

@wanghan-iapcm wanghan-iapcm left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A few non-blocking notes from re-reviewing this refactor. No blocking issues — registry-key alignment, kwarg/type-pop semantics, routing precedence, and the spin/ZBL special cases are all preserved. The items below sit just under my posting bar; raising them for optional follow-up.

Comment thread deepmd/dpmodel/model/model_factory.py
Comment thread deepmd/dpmodel/model/model_factory.py
Comment thread deepmd/dpmodel/model/model_factory.py
Cover shared model-factory error branches, preserve non-default ZBL softmin values across the dpmodel-driven backends, and avoid an unnecessary ZBL config copy.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.4
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
@njzjz

njzjz commented Jul 18, 2026

Copy link
Copy Markdown
Member

Possible reviewers based on changed lines, exact file history, and exact-file review history:

  • @anyangml — 5 commits on changed files (deepmd/dpmodel/model/__init__.py, deepmd/dpmodel/model/model.py).
  • @iProzd — 4 commits on changed files (deepmd/dpmodel/model/__init__.py, deepmd/dpmodel/model/model.py).

No review request was made automatically.

Coding agent: Codex
Codex version: codex-cli 0.144.4
Model: gpt-5.6-sol
Reasoning effort: xhigh

@njzjz
njzjz requested review from anyangml, iProzd and wanghan-iapcm and removed request for anyangml and iProzd July 18, 2026 07:25

@wanghan-iapcm wanghan-iapcm left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

All three points addressed and verified at HEAD.

The two error branches now have tests (test_model_level_type_embedding_is_rejected, test_zbl_rejects_non_energy_fitting). The smin_alpha regression is covered where it actually matters - 0.37 is asserted in the shared factory test and in both the JAX and TF2 ZBL tests, so the propagation this PR newly activates for dpmodel/jax/tf2 is pinned rather than relying on the pt_expt-only assertion. And the descriptor-derived pair-table path is both covered and documented; thanks for calling out the #4339 behaviour explicitly in the description, since that part isn't pure restructuring.

One observation rather than a request: the same commit also drops data = copy.deepcopy(data) from get_zbl_model. That is safe for construction - get_model_components deepcopies internally, get_zbl_model only reads data, and test_does_not_mutate_input guards it - but the constructed model now holds the caller's type_map list itself instead of a copy, so the two alias afterwards. Worth keeping in mind, and generally worth landing production changes under a non-test(...) commit so they are visible in the log.

@njzjz
njzjz added this pull request to the merge queue Jul 26, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Jul 26, 2026
njzjz-bot and others added 2 commits July 28, 2026 13:45
Preserve the shared backend factory while integrating DPA4 analytical bridging and native-spin routing from master.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
@njzjz
njzjz enabled auto-merge July 28, 2026 05:56
@njzjz
njzjz disabled auto-merge July 28, 2026 11:15
@njzjz
njzjz enabled auto-merge July 28, 2026 17:06
@njzjz
njzjz added this pull request to the merge queue Jul 28, 2026
Merged via the queue into deepmodeling:master with commit 799252d Jul 28, 2026
69 of 72 checks passed
@njzjz
njzjz deleted the refactor/unify-dpmodel-get-model branch July 28, 2026 22:47
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.

4 participants