Skip to content

feat(tf2): support DPA4 descriptor - #5749

Merged
njzjz merged 20 commits into
deepmodeling:masterfrom
njzjz:feat/dpa4-tf2-train
Aug 3, 2026
Merged

feat(tf2): support DPA4 descriptor#5749
njzjz merged 20 commits into
deepmodeling:masterfrom
njzjz:feat/dpa4-tf2-train

Conversation

@njzjz

@njzjz njzjz commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

  • Add and register the TF2 DPA4/SeZM descriptor adapter and its TensorFlow-backed submodule mappings.
  • Add the TensorFlow array operations, dynamic-shape handling, and trackable parameter support required by the DPA4 descriptor.
  • Enable TF2 coverage in the existing DPA4 descriptor consistency tests and add focused descriptor state, checkpoint, graph-shape, and array-operation tests.
  • Keep this pull request descriptor-only; fitting, model factory, trainer, and model-conversion changes are excluded.

Validation

  • ruff format .
  • ruff check .
  • python -m py_compile deepmd/dpmodel/array_api.py deepmd/dpmodel/descriptor/dpa4.py deepmd/dpmodel/descriptor/dpa4_nn/so2.py deepmd/tf2/common.py deepmd/tf2/descriptor/dpa4.py source/tests/consistent/descriptor/test_dpa4.py source/tests/consistent/test_array_api.py source/tests/tf2/test_dpa4.py
  • DP_TEST_TF2_ONLY=1 pytest source/tests/tf2/test_dpa4.py -v — 6 passed
  • DP_TEST_TF2_ONLY=1 pytest source/tests/consistent/test_array_api.py::TestXpMaximumAtConsistent::test_tf_preserves_all_negative_infinity_segment -v — 1 passed

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

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@dosubot dosubot Bot added the new feature label Jul 7, 2026
@github-actions github-actions Bot added the Python label Jul 7, 2026
Comment thread deepmd/tf2/descriptor/dpa4.py Fixed
Comment thread deepmd/tf2/descriptor/dpa4.py Fixed
Comment thread deepmd/tf2/fitting/dpa4_ener.py Fixed
@coderabbitai

coderabbitai Bot commented Jul 7, 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
📝 Walkthrough

Walkthrough

This PR adds TF2 support for DPA4/SeZM descriptors and fitting networks, registers model and component aliases, adapts PT checkpoints, extends TensorFlow-backed array operations, normalizes force shapes, and adds backend and training tests.

Changes

TF2 DPA4/SeZM integration

Layer / File(s) Summary
TensorFlow-backed indexed array operations
deepmd/dpmodel/array_api.py
Uses TensorFlow scatter and segment reductions for ndtensorflow indexed updates.
DPModel DPA4 behavior and trainability
deepmd/dpmodel/descriptor/..., deepmd/dpmodel/fitting/dpa4_ener.py
Supports empty-edge block execution, dynamic shape validation, and per-layer GLU trainability serialization.
TF2 managed variable storage
deepmd/tf2/common.py
Stores managed arrays as TensorFlow variables and refreshes trackable lists after initialization and deserialization.
TF2 DPA4 descriptor adapters
deepmd/tf2/descriptor/...
Adds wrappers, parameter promotion, mappings, runtime validation, deserialization, and exports.
TF2 SeZM fitting adapters
deepmd/tf2/fitting/...
Adds fitting wrappers, registrations, trainability preservation, and public exports.
Model routing and checkpoint conversion
deepmd/tf2/model/...
Normalizes DPA4/SeZM configurations and adapts PT checkpoints for TF2 deserialization.
Trainer force-shape normalization
deepmd/tf2/train/trainer.py
Matches force output shapes to labels using static and runtime checks.
Validation coverage
source/tests/consistent/..., source/tests/tf2/...
Adds backend, tracking, conversion, model-factory, optimizer, retracing, and training tests.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested reviewers: OutisLi, iProzd

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.66% 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
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is relevant and accurately points to the new TF2 DPA4 support, though it understates the broader fitting, model, and test changes.
✨ 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
deepmd/tf2/common.py (1)

362-387: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

__getattribute__ allocates a new set on every attribute access.

This override intercepts every attribute read on the module, and for each read it calls _tf2_array_variable_attr_names() / _tf2_array_variable_list_attr_names(), both of which materialize a fresh set(...) from the class-level tuple. On hot descriptor/fitting paths this adds a per-access allocation. Consider a cheaper membership check against the raw tuple (or a cached frozenset) to avoid rebuilding the set on every access.

♻️ Cheaper membership check
         def __getattribute__(self, name: str) -> Any:
             if not name.startswith("_tf2_"):
-                array_attrs = object.__getattribute__(
-                    self,
-                    "_tf2_array_variable_attr_names",
-                )()
-                if name in array_attrs:
+                if name in object.__getattribute__(
+                    self, "_tf2_array_variable_attrs", ()
+                ):
🤖 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/tf2/common.py` around lines 362 - 387, The __getattribute__ override
in common.py is doing extra work on every attribute read by calling
_tf2_array_variable_attr_names() and _tf2_array_variable_list_attr_names(),
which rebuild sets repeatedly. Update __getattribute__ to use a cheaper
membership path for the array/list attribute names, such as checking the
underlying tuple directly or reusing a cached frozenset, while keeping the
existing storage-name lookup and to_tensorflow_array conversion behavior
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.

Inline comments:
In `@deepmd/dpmodel/array_api.py`:
- Around line 285-296: The TensorFlow branch in array_api.py is overwriting
prefilled -inf entries because tf.maximum(x_tensor, reduced) replaces
empty-segment sentinels with dtype minimum values. Update the
unsorted-segment-max handling in this branch so empty segments remain -inf,
matching the behavior expected by segment.py and the other backends; use the
existing x_tensor, indices_tensor, values_tensor, and reduced flow, but avoid
applying a blanket maximum that changes sentinel slots.

In `@deepmd/tf2/train/trainer.py`:
- Around line 1490-1493: The shape-iteration guard in the trainer’s
rank-checking helper only handles TypeError, but tf.TensorShape(None) can also
raise ValueError during tracing. Update the try/except around iter(shape) to
return None for both exception types in the same helper path so unknown-rank
shapes are handled safely.

---

Nitpick comments:
In `@deepmd/tf2/common.py`:
- Around line 362-387: The __getattribute__ override in common.py is doing extra
work on every attribute read by calling _tf2_array_variable_attr_names() and
_tf2_array_variable_list_attr_names(), which rebuild sets repeatedly. Update
__getattribute__ to use a cheaper membership path for the array/list attribute
names, such as checking the underlying tuple directly or reusing a cached
frozenset, while keeping the existing storage-name lookup and
to_tensorflow_array conversion behavior unchanged.
🪄 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: 76f9add6-fdb8-4b7b-8908-ab6d1ed973d8

📥 Commits

Reviewing files that changed from the base of the PR and between 1cd6556 and 6194ff6.

📒 Files selected for processing (11)
  • deepmd/dpmodel/array_api.py
  • deepmd/tf2/common.py
  • deepmd/tf2/descriptor/__init__.py
  • deepmd/tf2/descriptor/dpa4.py
  • deepmd/tf2/fitting/__init__.py
  • deepmd/tf2/fitting/dpa4_ener.py
  • deepmd/tf2/model/ener_model.py
  • deepmd/tf2/model/model.py
  • deepmd/tf2/train/trainer.py
  • source/tests/consistent/descriptor/test_dpa4.py
  • source/tests/consistent/fitting/test_dpa4_ener.py

Comment thread deepmd/dpmodel/array_api.py Outdated
Comment thread deepmd/tf2/train/trainer.py Outdated
@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.33333% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.28%. Comparing base (5cc4c57) to head (994f411).
⚠️ Report is 4 commits behind head on master.

Files with missing lines Patch % Lines
deepmd/dpmodel/descriptor/dpa4_nn/so2.py 77.77% 6 Missing ⚠️
deepmd/tf2/common.py 94.64% 6 Missing ⚠️
deepmd/tf2/descriptor/dpa4.py 96.98% 5 Missing ⚠️
deepmd/dpmodel/array_api.py 85.18% 4 Missing ⚠️
deepmd/tf2/train/trainer.py 77.77% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5749      +/-   ##
==========================================
- Coverage   79.47%   79.28%   -0.20%     
==========================================
  Files        1072     1074       +2     
  Lines      125055   125638     +583     
  Branches     4536     4569      +33     
==========================================
+ Hits        99385    99607     +222     
- Misses      24044    24393     +349     
- Partials     1626     1638      +12     

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

@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/tf2/descriptor/se_atten_v2.py (1)

17-21: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the extra refresh call here. TF2Module already refreshes _refresh_tf2_trackable_lists() for deepmd.tf2.descriptor.se_atten_v2, so this second call is redundant and can be dropped.

🤖 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/tf2/descriptor/se_atten_v2.py` around lines 17 - 21, The
DescrptSeAttenV2.deserialize method is calling _refresh_tf2_trackable_lists()
twice because TF2Module already performs that refresh for
deepmd.tf2.descriptor.se_atten_v2. Remove the explicit refresh call from
DescrptSeAttenV2.deserialize and keep the deserialization flow limited to
delegating to DescrptSeAttenV2DP.deserialize.__func__(cls, data) and returning
the object.
🤖 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/tf2/descriptor/se_atten_v2.py`:
- Around line 17-21: The DescrptSeAttenV2.deserialize method is calling
_refresh_tf2_trackable_lists() twice because TF2Module already performs that
refresh for deepmd.tf2.descriptor.se_atten_v2. Remove the explicit refresh call
from DescrptSeAttenV2.deserialize and keep the deserialization flow limited to
delegating to DescrptSeAttenV2DP.deserialize.__func__(cls, data) and returning
the object.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e4a0ef32-c262-4207-8de7-5e2559fd9048

📥 Commits

Reviewing files that changed from the base of the PR and between 6194ff6 and 789aa79.

📒 Files selected for processing (6)
  • deepmd/dpmodel/array_api.py
  • deepmd/tf2/common.py
  • deepmd/tf2/descriptor/se_atten_v2.py
  • deepmd/tf2/train/trainer.py
  • source/tests/consistent/descriptor/test_dpa4.py
  • source/tests/consistent/fitting/test_dpa4_ener.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • deepmd/tf2/train/trainer.py
  • source/tests/consistent/descriptor/test_dpa4.py
  • deepmd/tf2/common.py

@njzjz

njzjz commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

Pushed follow-ups 789aa79ca and 8136fb11 for the TF2 CI/review feedback.\n\nChanges kept:\n- Preserve empty-segment -inf values in the TensorFlow branch of xp_maximum_at.\n- Treat unknown-rank tf.TensorShape(None) as non-static by catching ValueError.\n- Avoid per-access set allocation in TF2Module.__getattribute__.\n- Route TF2 se_atten_v2 deserialization through the se_atten_v2 serializer path instead of DPA1.\n\nI then reverted the extra source/tests/consistent changes in 8136fb11, per request.\n\nLocal validation:\n- TF2 smoke for se_atten_v2 serialize/deserialize passed.\n- TensorFlow xp_maximum_at 1D and 2D empty-segment checks passed.\n- DPTrainer._static_shape(tf.TensorShape(None)) returns None.\n- ruff format . && ruff check . passed.\n\nCI is rerunning.

Comment thread deepmd/tf2/descriptor/dpa4.py
Comment thread deepmd/tf2/common.py
Coding-Agent: Codex
Codex-Version: codex-cli 0.144.1
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
@njzjz

njzjz commented Jul 11, 2026

Copy link
Copy Markdown
Member Author

Pushed follow-up commit 4328329 for the remaining review feedback.

Changes:

  • Promote optional cross-grid FrameContract/FrameExpand weights and FFN LayerScale leaves to tracked, trainable TensorFlow variables.
  • Remove the redundant imports reported by CodeQL.
  • Remove the duplicate DescrptSeAttenV2 refresh call; the tf2_module deserialize wrapper already performs it.
  • Normalize explicit null descriptor/fitting blocks and add focused factory, trackable round-trip, and force-shape tests.

Validation:

  • Focused TF2 tests: 14 passed.
  • DPA4 fitting consistency: 28 passed, 36 skipped.
  • ruff format . and ruff check . passed.

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

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

Requesting changes for the dynamic-shape DPA4 force-loss correctness issue described inline.

Comment thread deepmd/tf2/train/trainer.py Outdated

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

Adding the approved graph-safety correctness finding.

Comment thread deepmd/tf2/descriptor/dpa4.py

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

Adding the approved fitting-trainability correctness finding.

Comment thread deepmd/tf2/fitting/dpa4_ener.py Outdated

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

Adding the approved frozen-descriptor tracking correctness finding.

Comment thread deepmd/tf2/descriptor/dpa4.py Outdated

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

Adding the approved normalized-exclusion routing correctness finding.

Comment thread deepmd/tf2/model/model.py Outdated

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

Adding the approved default-random-gamma training semantics finding.

Comment thread deepmd/tf2/descriptor/dpa4.py

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

Adding the approved DPA4 property-fitting factory compatibility finding.

Comment thread deepmd/tf2/model/model.py Outdated

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

Adding the approved DPA4 parameter-promotion resident-memory finding.

Comment thread deepmd/tf2/common.py

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

Adding the approved PT DPA4 .pt to TF2 conversion integration finding.

Comment thread deepmd/tf2/model/ener_model.py Outdated
Make DPA4 dynamic-shape training graph-safe, preserve frozen state, and support the schema-approved factory and PT conversion paths.

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.

Actionable comments posted: 1

🤖 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/descriptor/dpa4_nn/so2.py`:
- Around line 747-762: Update the shape validation around the visible
x_local/radial_feat checks and _project_radial() to use runtime shape values
rather than assuming concrete symbolic rank metadata. Explicitly reject inputs
with rank below 3 before indexing dimensions, compare dimensions through runtime
shape handling, and reshape radial_feat using its runtime batch dimension or -1.
🪄 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: 741870f5-a817-453c-80e8-1695eec6fccb

📥 Commits

Reviewing files that changed from the base of the PR and between 8136fb1 and aa1ed89.

📒 Files selected for processing (14)
  • deepmd/dpmodel/descriptor/dpa4.py
  • deepmd/dpmodel/descriptor/dpa4_nn/so2.py
  • deepmd/dpmodel/fitting/dpa4_ener.py
  • deepmd/tf2/common.py
  • deepmd/tf2/descriptor/dpa4.py
  • deepmd/tf2/descriptor/se_atten_v2.py
  • deepmd/tf2/fitting/dpa4_ener.py
  • deepmd/tf2/model/base_model.py
  • deepmd/tf2/model/model.py
  • deepmd/tf2/train/trainer.py
  • source/tests/tf2/test_dpa4.py
  • source/tests/tf2/test_dpa4_conversion.py
  • source/tests/tf2/test_model_factory.py
  • source/tests/tf2/test_training.py
💤 Files with no reviewable changes (1)
  • deepmd/tf2/fitting/dpa4_ener.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • deepmd/tf2/common.py

Comment thread deepmd/dpmodel/descriptor/dpa4_nn/so2.py
Address the outstanding requested-change review comments.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
Copilot AI review requested due to automatic review settings July 30, 2026 03:35

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@njzjz
njzjz requested a review from OutisLi July 30, 2026 03:40
Resolve the DPA4 graph-interface conflict on the current master API and port the empty-edge regression to call_graph.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
Copilot AI review requested due to automatic review settings July 30, 2026 03:48

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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

TF2 DPA4 must support random_gamma=True; rejecting the standard DPA4 configuration is blocking.

Comment thread deepmd/tf2/descriptor/dpa4.py Outdated
Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
Copilot AI review requested due to automatic review settings August 1, 2026 14:34

Copilot AI 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.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (3)

deepmd/tf2/descriptor/dpa4.py:317

  • DescrptDPA4 is introduced as a TF2 wrapper for DescrptDPA4DP, but this module does not register a register_dpmodel_mapping(DescrptDPA4DP, ...) converter. That means try_convert_module() cannot convert a dpmodel DPA4 descriptor instance into its TF2 wrapper when encountered as a nested object during TF2 value conversion. Add an explicit mapping (consistent with other components in this file) so dpmodel → TF2 conversion works reliably.
@BaseDescriptor.register("SeZM")
@BaseDescriptor.register("sezm")
@BaseDescriptor.register("DPA4")
@BaseDescriptor.register("dpa4")
@tf2_module
class DescrptDPA4(DescrptDPA4DP):
    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, **kwargs)
        self._tf2_training_mode = False
        _promote_trainable_tree(self)

    @classmethod
    def deserialize(cls, data: dict) -> "DescrptDPA4":
        obj = super().deserialize(data)
        return _promote_trainable_tree(obj)

deepmd/tf2/descriptor/se_atten_v2.py:19

  • This deserialize() override bypasses the tf2_module-added post-deserialization refresh logic (_refresh_tf2_trackable_lists) that was introduced to ensure lists containing converted tf.Modules are properly re-wrapped as trackable containers. If se_atten_v2 contains module lists, this can lead to missing checkpoint tracking after deserialize. Recommended fix: after constructing the object via DescrptSeAttenV2DP.deserialize.__func__, explicitly call obj._refresh_tf2_trackable_lists() when available (mirroring the wrapper behavior in deepmd/tf2/common.py).
@BaseDescriptor.register("se_atten_v2")
class DescrptSeAttenV2(DescrptDPA1, DescrptSeAttenV2DP):
    @classmethod
    def deserialize(cls, data: dict) -> "DescrptSeAttenV2":
        return DescrptSeAttenV2DP.deserialize.__func__(cls, data)

deepmd/dpmodel/array_api.py:324

  • In the TF branch of xp_maximum_at, tf.shape(x_tensor, out_type=tf.int64)[0] is recomputed multiple times and feeds several segment ops. Since this is likely on a hot path (descriptor graph execution), cache num_segments = tf.shape(x_tensor, out_type=tf.int64)[0] once and reuse it for unsorted_segment_max/min/sum. Optionally, compute segment_counts/touched first and gate the all_negative_infinity correction to touched segments to reduce extra work for large x with sparse updates.
        x_tensor = x.unwrap()
        indices_tensor = tf.reshape(tf.cast(indices.unwrap(), tf.int64), (-1,))
        values_tensor = values.unwrap()
        reduced = tf.math.unsorted_segment_max(
            values_tensor,
            indices_tensor,
            tf.shape(x_tensor, out_type=tf.int64)[0],
        )
        if values_tensor.dtype.is_floating:
            # TensorFlow uses the lowest finite value as the identity of
            # unsorted_segment_max. Restore the true maximum-at identity when
            # every update for a touched segment element is negative infinity.
            all_negative_infinity = (
                tf.math.unsorted_segment_min(
                    tf.cast(
                        tf.math.is_inf(values_tensor) & (values_tensor < 0),
                        tf.int32,
                    ),
                    indices_tensor,
                    tf.shape(x_tensor, out_type=tf.int64)[0],
                )
                > 0
            )
            reduced = tf.where(
                all_negative_infinity,
                tf.cast(float("-inf"), values_tensor.dtype),
                reduced,
            )
        segment_counts = tf.math.unsorted_segment_sum(
            tf.ones_like(indices_tensor, dtype=tf.int32),
            indices_tensor,
            tf.shape(x_tensor, out_type=tf.int64)[0],
        )

Copilot AI review requested due to automatic review settings August 2, 2026 10:31

Copilot AI 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.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (3)

deepmd/tf2/descriptor/dpa4.py:318

  • DescrptDPA4.deserialize() calls _promote_trainable_tree() after super().deserialize(), but super().deserialize() already instantiates cls(**config), which runs DescrptDPA4.__init__() and promotes the tree once. The second promotion re-creates tf.Variable objects unnecessarily (and may change trackable identity).
    @classmethod
    def deserialize(cls, data: dict) -> "DescrptDPA4":
        obj = super().deserialize(data)
        return _promote_trainable_tree(obj)

deepmd/tf2/descriptor/dpa4.py:257

  • SO2Linear.deserialize() promotes weight_m a second time even though super().deserialize() constructs the object via cls(**config), which already runs __init__() and promotes weight_m. Re-promoting here re-creates a fresh set of tf.Variable objects (extra allocations and can disrupt trackable identity).

This issue also appears on line 314 of the same file.

    @classmethod
    def deserialize(cls, data: dict) -> "SO2Linear":
        obj = super().deserialize(data)
        _promote_parameter_lists(obj, ("weight_m",), trainable=bool(obj.trainable))
        return obj

deepmd/tf2/train/trainer.py:1332

  • PR description says trainer changes are excluded ("descriptor-only"), but this PR modifies the TF2 trainer to pass a training flag and mutate descriptor state via _set_model_training_mode(). Either update the PR description/scope or split the trainer change into a separate PR so the stated scope matches the actual changes.
    def _call_model(
        self,
        task_key: str,
        input_dict: dict[str, Any],
        *,
        label_dict: dict[str, Any] | None = None,
        do_virial: bool = True,
        training: bool,
    ) -> dict[str, Any]:
        model = self.models[task_key]
        self._set_model_training_mode(model, training)

_trainer._call_model now requires the keyword-only training argument; the
atomic-virial-disabled regression was written before that signature change
and failed with TypeError. Pass training=False (eval path).

Coding-Agent: opencode
opencode-Version: 1.18.9
Model: ustc/deepseek-v4-flash
Reasoning-Effort: max
Copilot AI review requested due to automatic review settings August 2, 2026 14:15

Copilot AI 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.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

Suppressed comments (1)

deepmd/tf2/descriptor/se_atten_v2.py:19

  • The new DescrptSeAttenV2.deserialize override bypasses the tf2_module deserialize wrapper’s post-deserialization _refresh_tf2_trackable_lists() call (see deepmd/tf2/common.py:432-446). That refresh is what rebuilds list containers so nested tf.Module items are tracked correctly after deserialization/conversion. Add the refresh step here as well to keep deserialization behavior consistent with other TF2 modules.
    @classmethod
    def deserialize(cls, data: dict) -> "DescrptSeAttenV2":
        return DescrptSeAttenV2DP.deserialize.__func__(cls, data)

@njzjz
njzjz added this pull request to the merge queue Aug 3, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 3, 2026
@njzjz
njzjz added this pull request to the merge queue Aug 3, 2026
Merged via the queue into deepmodeling:master with commit 6330a2f Aug 3, 2026
57 of 58 checks passed
@njzjz
njzjz deleted the feat/dpa4-tf2-train branch August 3, 2026 17:30
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.

6 participants