Skip to content

refactor(model): unify dpmodel backend factories#5786

Open
njzjz-bot wants to merge 2 commits into
deepmodeling:masterfrom
njzjz:refactor/unify-dpmodel-get-model
Open

refactor(model): unify dpmodel backend factories#5786
njzjz-bot wants to merge 2 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

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

An error occurred during the review process. Please try again later.

✨ 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 96.69421% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.29%. Comparing base (2c0a54e) to head (b1392f5).
⚠️ Report is 17 commits behind head on master.

Files with missing lines Patch % Lines
deepmd/dpmodel/model/model_factory.py 95.45% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5786      +/-   ##
==========================================
- Coverage   79.76%   78.29%   -1.47%     
==========================================
  Files        1023     1051      +28     
  Lines      117463   120417    +2954     
  Branches     4325     4351      +26     
==========================================
+ Hits        93691    94282     +591     
- Misses      22229    24565    +2336     
- Partials     1543     1570      +27     

☔ 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
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