Skip to content

feat(pt_expt): implement se_t and se_t_tebd descriptors. #5208

Open
wanghan-iapcm wants to merge 37 commits intodeepmodeling:masterfrom
wanghan-iapcm:feat-se-t
Open

feat(pt_expt): implement se_t and se_t_tebd descriptors. #5208
wanghan-iapcm wants to merge 37 commits intodeepmodeling:masterfrom
wanghan-iapcm:feat-se-t

Conversation

@wanghan-iapcm
Copy link
Collaborator

@wanghan-iapcm wanghan-iapcm commented Feb 8, 2026

This PR is considered after #5194 #5204 and #5205

Summary by CodeRabbit

  • New Features

    • Added PyTorch experimental descriptor wrappers for SeT and SeTTebd descriptors
    • Added TypeEmbedNet and EmbeddingNet wrappers for PyTorch integration
    • Exposed experimental descriptors and utilities in public API
  • Bug Fixes

    • Fixed PyTorch compatibility by casting indices to int64 for indexing operations
    • Fixed device specification for tensor initialization
  • Refactor

    • Migrated array operations to Array API for improved backend compatibility
    • Converted EmbeddingNet from factory-based to concrete class with serialization support
    • Enhanced type embedding with Array API support
  • Tests

    • Added comprehensive tests for EmbeddingNet, descriptors, and network wrappers

@wanghan-iapcm wanghan-iapcm requested a review from njzjz February 8, 2026 15:52
@gemini-code-assist
Copy link

Summary of Changes

Hello @wanghan-iapcm, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly advances the PyTorch experimental backend by integrating se_t and se_t_tebd descriptors. It introduces a robust, generic mechanism for seamlessly wrapping dpmodel components as PyTorch modules, which simplifies future extensions and enhances maintainability. Key architectural improvements include refactoring EmbeddingNet into a concrete class and standardizing array operations for improved device handling and compatibility across different array backends.

Highlights

  • Enhanced PyTorch Experimental Backend (pt_expt): Implemented se_t and se_t_tebd descriptors, significantly expanding the capabilities of the pt_expt module for PyTorch integration.
  • Generic dpmodel to PyTorch Module Wrapping: Introduced a new registry-based system (dpmodel_setattr, register_dpmodel_mapping) for automatically converting dpmodel objects and numpy arrays into torch.nn.Module instances and torch buffers, streamlining integration and reducing boilerplate.
  • EmbeddingNet Refactoring: Transformed EmbeddingNet from a factory function into a concrete class, improving its maintainability, testability, and compatibility with PyTorch's module system.
  • Improved Array API Compatibility: Updated dpmodel descriptor and utility functions to consistently use array_api_compat for device-aware array creation and operations, ensuring better cross-backend compatibility.
  • Comprehensive Testing: Added new and updated existing tests to ensure the consistency, correctness, and exportability of the newly integrated pt_expt descriptors and refactored components.
Changelog
  • deepmd/dpmodel/descriptor/descriptor.py
    • Replaced numpy with array_api_compat for array operations and added device specification for array creation.
  • deepmd/dpmodel/descriptor/dpa1.py
    • Ensured idx is cast to int64 for PyTorch backend compatibility.
  • deepmd/dpmodel/descriptor/se_t.py
    • Added device specification for xp.zeros calls.
  • deepmd/dpmodel/descriptor/se_t_tebd.py
    • Added device specification for xp.zeros calls and ensured idx is cast to int64.
  • deepmd/dpmodel/utils/network.py
    • EmbeddingNet refactored into a concrete class with explicit __init__, serialize, and deserialize methods.
  • deepmd/dpmodel/utils/type_embed.py
    • Improved device handling for array creation and operations using array_api_compat.
    • Updated array arithmetic for consistency.
  • deepmd/pt_expt/common.py
    • Introduced a generic _DPMODEL_TO_PT_EXPT registry for mapping dpmodel classes to pt_expt torch.nn.Module wrappers.
    • Added register_dpmodel_mapping and try_convert_module functions to manage this registry.
    • Implemented dpmodel_setattr for automatic attribute handling: converting numpy arrays to torch buffers, clearing buffers, and converting nested dpmodel objects.
    • Added comprehensive docstrings for new functions.
  • deepmd/pt_expt/descriptor/init.py
    • Imported se_t_tebd_block to register converters.
    • Added DescrptSeT and DescrptSeTTebd to the __all__ export list.
  • deepmd/pt_expt/descriptor/se_e2_a.py
    • Refactored __setattr__ to utilize the new dpmodel_setattr for cleaner attribute management.
  • deepmd/pt_expt/descriptor/se_r.py
    • Refactored __setattr__ to utilize the new dpmodel_setattr for cleaner attribute management.
  • deepmd/pt_expt/descriptor/se_t.py
    • Added new DescrptSeT class for the pt_expt backend, inheriting from dpmodel.descriptor.se_t.DescrptSeT and torch.nn.Module.
    • Implemented __init__, __call__, __setattr__ (using dpmodel_setattr), and forward methods.
  • deepmd/pt_expt/descriptor/se_t_tebd.py
    • Added new DescrptSeTTebd class for the pt_expt backend, inheriting from dpmodel.descriptor.se_t_tebd.DescrptSeTTebd and torch.nn.Module.
    • Implemented __init__, __call__, __setattr__ (using dpmodel_setattr), and forward methods.
  • deepmd/pt_expt/descriptor/se_t_tebd_block.py
    • Added new DescrptBlockSeTTebd class for the pt_expt backend.
    • Registered DescrptBlockSeTTebdDP to DescrptBlockSeTTebd in the dpmodel_mapping registry.
  • deepmd/pt_expt/utils/init.py
    • Updated exports to include new utility modules like NetworkCollection and TypeEmbedNet.
  • deepmd/pt_expt/utils/exclude_mask.py
    • Refactored __setattr__ in AtomExcludeMask and PairExcludeMask to use dpmodel_setattr.
    • Registered AtomExcludeMaskDP and PairExcludeMaskDP to their pt_expt wrappers.
  • deepmd/pt_expt/utils/network.py
    • Refactored pt_expt.EmbeddingNet to properly wrap dpmodel.utils.network.EmbeddingNet, converting its layers to pt_expt.utils.network.NativeLayer instances.
    • Registered EmbeddingNetDP and NetworkCollectionDP to their pt_expt wrappers.
  • deepmd/pt_expt/utils/type_embed.py
    • Added new TypeEmbedNet class for the pt_expt backend.
    • Registered TypeEmbedNetDP to TypeEmbedNet in the dpmodel_mapping registry.
  • source/tests/common/dpmodel/test_network.py
    • Added new tests for EmbeddingNet to verify it's a concrete class, its forward pass, and trainable parameter handling.
  • source/tests/consistent/descriptor/test_se_t.py
    • Integrated pt_expt backend into DescrptSeT consistency tests.
  • source/tests/consistent/descriptor/test_se_t_tebd.py
    • Integrated pt_expt backend into DescrptSeTTebd consistency tests.
  • source/tests/pt_expt/descriptor/test_se_t.py
    • Added new consistency and exportability tests for pt_expt.descriptor.se_t.
  • source/tests/pt_expt/descriptor/test_se_t_tebd.py
    • Added new consistency and exportability tests for pt_expt.descriptor.se_t_tebd.
  • source/tests/pt_expt/utils/test_network.py
    • Added new tests for the refactored pt_expt.utils.network.EmbeddingNet covering wrapping, serialization, layer type preservation, cross-backend consistency, registry conversion, dpmodel_setattr auto-conversion, and trainable parameter handling.
Activity
  • The pull request introduces new descriptors (se_t and se_t_tebd) for the PyTorch experimental backend.
  • It includes a significant refactoring of how dpmodel objects are integrated with PyTorch modules, making the pt_expt backend more robust and extensible.
  • This involved creating a generic attribute handling system and converting key dpmodel components into proper PyTorch modules.
  • Extensive testing was added to ensure the correctness and compatibility of these changes.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@dosubot dosubot bot added the new feature label Feb 8, 2026
@github-actions github-actions bot added the Python label Feb 8, 2026
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces se_t and se_t_tebd descriptors for the pt_expt backend and includes a significant, well-executed refactoring. The key improvements are the adoption of array_api_compat for better backend-agnosticism, the refactoring of EmbeddingNet into a concrete class, and the introduction of a registry-based system in pt_expt/common.py for converting dpmodel objects to PyTorch modules. This new system greatly simplifies the __setattr__ logic and enhances maintainability. The new features are well-tested. Overall, this is a high-quality contribution. I have one minor suggestion for code cleanup.

dtype=des["dstd"].dtype,
device=array_api_compat.device(des["dstd"]),
)
xp = array_api_compat.array_namespace(des["davg"])

Choose a reason for hiding this comment

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

medium

This line re-defines xp. It was already defined on line 177 if the else branch was taken. To improve clarity and avoid redundancy, consider defining xp once before the if-else block (e.g., at line 171). This would make xp available in both branches without re-definition.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 8, 2026

📝 Walkthrough

Walkthrough

This PR migrates descriptor implementations to array_api_compat for cross-backend device support, introduces a concrete EmbeddingNet class replacing factory pattern generation, adds PyTorch experimental wrapper classes for descriptors, casts indices to int64 for PyTorch compatibility, and extends test coverage for new implementations.

Changes

Cohort / File(s) Summary
Array API Migration
deepmd/dpmodel/descriptor/descriptor.py, deepmd/dpmodel/descriptor/se_t.py, deepmd/dpmodel/descriptor/se_t_tebd.py, deepmd/dpmodel/utils/type_embed.py
Replaces NumPy operations with array_api_compat equivalents for device-aware tensor creation and concatenation, including explicit device inference from existing tensors.
PyTorch Index Casting
deepmd/dpmodel/descriptor/dpa1.py, deepmd/dpmodel/descriptor/se_t_tebd.py
Casts idx tensor to int64 before take_along_axis/take_along_dim operations to ensure PyTorch backend compatibility.
EmbeddingNet Concrete Class
deepmd/dpmodel/utils/network.py
Replaces factory-generated EmbeddingNet with concrete class subclassing NativeNet, adds explicit __init__, serialize, and deserialize methods, and stores layer metadata.
PT Experimental Descriptor Wrappers
deepmd/pt_expt/descriptor/se_t.py, deepmd/pt_expt/descriptor/se_t_tebd.py, deepmd/pt_expt/descriptor/se_t_tebd_block.py
Introduces new PyTorch wrapper classes inheriting from dpmodel descriptors and torch.nn.Module, with custom __init__, __call__, __setattr__, and forward methods for export/tracing compatibility.
PT Experimental Utils Wrappers
deepmd/pt_expt/utils/network.py, deepmd/pt_expt/utils/type_embed.py
Adds PyTorch wrapper classes for EmbeddingNet and TypeEmbedNet with registry-based deserialization mappings and module lifecycle management.
Module Exports
deepmd/pt_expt/descriptor/__init__.py, deepmd/pt_expt/utils/__init__.py
Extends public API exports to include new DescrptSeT, DescrptSeTTebd, and TypeEmbedNet classes, and registers descriptor converters.
DPModel Tests
source/tests/common/dpmodel/test_network.py
Adds three new tests for concrete EmbeddingNet class: verifying concrete class attributes, forward pass shape/dtype, and trainable parameter variants.
Consistent Descriptor Tests
source/tests/consistent/descriptor/test_se_t.py, source/tests/consistent/descriptor/test_se_t_tebd.py
Extends existing descriptor test classes with PT-EXPT support: conditional imports, skip properties, evaluation methods, and class attributes for experimental descriptor variants.
PT Experimental Descriptor Tests
source/tests/pt_expt/descriptor/test_se_t.py, source/tests/pt_expt/descriptor/test_se_t_tebd.py
Introduces new test modules validating DescrptSeT and DescrptSeTTebd: consistency checks across precisions, serialization round-trips, and torch.export compatibility.
PT Experimental Utils Tests
source/tests/pt_expt/utils/test_network.py
Adds comprehensive test suite for pt_expt EmbeddingNet wrapper: module wrapping, serialization, cross-backend consistency, registry conversion, and trainable state handling.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • wanghan-iapcm
  • iProzd
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary change: implementing se_t and se_t_tebd descriptors in the pt_expt module, which is clearly the main focus of this multi-file PR.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉


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
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@deepmd/dpmodel/utils/network.py`:
- Around line 886-893: The code assumes obj.layers has at least one element
(uses type(obj.layers[0])) which throws IndexError when neuron==[]; fix by
checking for empty layers first: if either the existing obj.layers or the
incoming layers list is empty, set obj.layers to an empty instance of the same
container type (use container_type = type(obj.layers); obj.layers =
container_type() or container_type([])) and return obj; otherwise proceed with
the existing logic that computes layer_type = type(obj.layers[0]) and
reconstructs obj.layers with [layer_type.deserialize(...)]. Ensure you reference
cls, obj.layers, layer_type, and the deserialize call when making the change.

In `@source/tests/pt_expt/descriptor/test_se_t_tebd.py`:
- Around line 62-71: The test is confusing because pt_expt's forward accepts a
type_embedding but the pt_expt implementation deletes it (del type_embedding in
se_t_tebd.forward) and dpmodel.call() generates its own via its internal
TypeEmbedNet; update the test
(source/tests/pt_expt/descriptor/test_se_t_tebd.py) by adding a short clarifying
comment immediately above the creation/use of type_embedding (near the dd0(...)
call) stating that the passed type_embedding is intentionally ignored by the
pt_expt wrapper and that all models use the internal TypeEmbedNet with identical
serialized state, so the external tensor is provided only to keep API parity for
the test.
🧹 Nitpick comments (6)
deepmd/pt_expt/utils/type_embed.py (1)

15-15: Unused noqa directive.

Ruff reports that F401 is not enabled, making the # noqa: F401 directive unnecessary. The side-effect import itself is correct and well-documented by the comment above.

Proposed fix
-from deepmd.pt_expt.utils import network  # noqa: F401
+from deepmd.pt_expt.utils import network  # ensure EmbeddingNet is registered
deepmd/pt_expt/descriptor/__init__.py (1)

2-3: Unused # noqa: F401 directive.

Ruff (RUF100) reports that the F401 rule is not enabled, making the noqa directive a no-op. If F401 is indeed not active in this project's Ruff config, you can drop the directive.

deepmd/dpmodel/utils/network.py (1)

813-816: Mutable default argument for neuron.

Ruff B006 flags neuron: list[int] = [24, 48, 96]. While the list isn't mutated in-place here, using None as the default is the idiomatic safeguard.

Suggested fix
     def __init__(
         self,
         in_dim: int,
-        neuron: list[int] = [24, 48, 96],
+        neuron: list[int] | None = None,
         activation_function: str = "tanh",
         resnet_dt: bool = False,
         precision: str = DEFAULT_PRECISION,
         seed: int | list[int] | None = None,
         bias: bool = True,
         trainable: bool | list[bool] = True,
     ) -> None:
+        if neuron is None:
+            neuron = [24, 48, 96]
         layers = []
source/tests/consistent/descriptor/test_se_t.py (1)

99-107: Unused unpacked variables — consistent with existing pattern, safe to ignore.

Ruff flags resnet_dt, excluded_types, precision, and env_protection as unused. This is consistent with skip_pt and skip_dp above which also unpack without using the values. The pattern exists so that if future skip logic needs to use params, the unpacking is already in place (as skip_tf does on line 117).

source/tests/pt_expt/descriptor/test_se_t_tebd.py (1)

159-159: Nit: missing trailing newline at end of file.

Proposed fix
             torch.export.export(dd0, inputs)
+
source/tests/pt_expt/descriptor/test_se_t.py (1)

65-65: Prefix unused unpacked variables with _ to satisfy linter.

gr1 (Line 65) and gr2 (Line 85) are unpacked but never used. The comment on Line 90 confirms se_t returns None for gr, so these should be prefixed with _.

Proposed fix
-            rd1, gr1, _, _, sw1 = dd1(
+            rd1, _gr1, _, _, sw1 = dd1(
-            rd2, gr2, _, _, sw2 = dd2.call(
+            rd2, _gr2, _, _, sw2 = dd2.call(

Also applies to: 85-85

Comment on lines +886 to +893
obj = cls(**data)
# Reinitialize layers from serialized data, using the same layer type
# that __init__ created (respects subclass overrides via MRO).
layer_type = type(obj.layers[0])
obj.layers = type(obj.layers)(
[layer_type.deserialize(layer) for layer in layers]
)
return obj
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

IndexError when neuron is an empty list.

type(obj.layers[0]) on line 889 will raise IndexError if neuron=[] (producing zero layers). While this may be an uncommon case, deserialize should handle it gracefully — especially since FittingNet already accounts for len(neuron) == 0.

Proposed fix
         obj = cls(**data)
         # Reinitialize layers from serialized data, using the same layer type
         # that __init__ created (respects subclass overrides via MRO).
-        layer_type = type(obj.layers[0])
-        obj.layers = type(obj.layers)(
-            [layer_type.deserialize(layer) for layer in layers]
-        )
+        if obj.layers:
+            layer_type = type(obj.layers[0])
+            obj.layers = type(obj.layers)(
+                [layer_type.deserialize(layer) for layer in layers]
+            )
         return obj
🤖 Prompt for AI Agents
In `@deepmd/dpmodel/utils/network.py` around lines 886 - 893, The code assumes
obj.layers has at least one element (uses type(obj.layers[0])) which throws
IndexError when neuron==[]; fix by checking for empty layers first: if either
the existing obj.layers or the incoming layers list is empty, set obj.layers to
an empty instance of the same container type (use container_type =
type(obj.layers); obj.layers = container_type() or container_type([])) and
return obj; otherwise proceed with the existing logic that computes layer_type =
type(obj.layers[0]) and reconstructs obj.layers with
[layer_type.deserialize(...)]. Ensure you reference cls, obj.layers, layer_type,
and the deserialize call when making the change.

Comment on lines +62 to +71
type_embedding = torch.randn(
[self.nt, dd0.tebd_dim], dtype=dtype, device=self.device
)

rd0, _, _, _, _ = dd0(
torch.tensor(self.coord_ext, dtype=dtype, device=self.device),
torch.tensor(self.atype_ext, dtype=int, device=self.device),
torch.tensor(self.nlist, dtype=int, device=self.device),
type_embedding=type_embedding,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, let's find the test file and understand its structure
find . -name "test_se_t_tebd.py" -type f 2>/dev/null | head -5

Repository: deepmodeling/deepmd-kit

Length of output: 173


🏁 Script executed:

#!/bin/bash
# Look for the pt_expt descriptor implementation
find . -name "se_t_tebd.py" -type f 2>/dev/null | grep -E "(pt_expt|dpmodel)" | head -10

Repository: deepmodeling/deepmd-kit

Length of output: 148


🏁 Script executed:

#!/bin/bash
# Search for TypeEmbedNet and how type_embedding is used in forward methods
rg -n "type_embedding" --type py -B 2 -A 5 | head -100

Repository: deepmodeling/deepmd-kit

Length of output: 6671


🏁 Script executed:

#!/bin/bash
# Read the test file to see the code structure mentioned in the review
cat -n ./source/tests/pt_expt/descriptor/test_se_t_tebd.py | sed -n '55,110p'

Repository: deepmodeling/deepmd-kit

Length of output: 2772


🏁 Script executed:

#!/bin/bash
# Check the pt_expt descriptor implementation
wc -l ./deepmd/pt_expt/descriptor/se_t_tebd.py

Repository: deepmodeling/deepmd-kit

Length of output: 110


🏁 Script executed:

#!/bin/bash
# Check the dpmodel descriptor implementation
wc -l ./deepmd/dpmodel/descriptor/se_t_tebd.py

Repository: deepmodeling/deepmd-kit

Length of output: 111


🏁 Script executed:

#!/bin/bash
# Read the pt_expt descriptor implementation (short file)
cat -n ./deepmd/pt_expt/descriptor/se_t_tebd.py

Repository: deepmodeling/deepmd-kit

Length of output: 2117


🏁 Script executed:

#!/bin/bash
# Search for how type_embedding is handled in dpmodel descriptor
grep -n "type_embedding\|def call\|def forward" ./deepmd/dpmodel/descriptor/se_t_tebd.py | head -30

Repository: deepmodeling/deepmd-kit

Length of output: 1217


🏁 Script executed:

#!/bin/bash
# Look at the context around line 47 in pt_expt file to see if there are comments explaining the deletion
cat -n ./deepmd/pt_expt/descriptor/se_t_tebd.py | sed -n '40,54p'

Repository: deepmodeling/deepmd-kit

Length of output: 594


🏁 Script executed:

#!/bin/bash
# Look at the dpmodel call() method signature to confirm it doesn't accept type_embedding
sed -n '326,380p' ./deepmd/dpmodel/descriptor/se_t_tebd.py | head -60

Repository: deepmodeling/deepmd-kit

Length of output: 1945


🏁 Script executed:

#!/bin/bash
# Check if there are any comments in the test file around the assertion that might explain the intent
sed -n '90,110p' ./source/tests/pt_expt/descriptor/test_se_t_tebd.py

Repository: deepmodeling/deepmd-kit

Length of output: 839


Add a clarifying comment explaining why type_embedding is ignored in the pt_expt wrapper.

The pt_expt descriptor's forward() method accepts type_embedding as a parameter (line 39) but explicitly ignores it via del type_embedding (line 47 of ./deepmd/pt_expt/descriptor/se_t_tebd.py). It then delegates to dpmodel.call() which does not accept type_embedding and generates its own internally via self.type_embedding.call() (line 366 of ./deepmd/dpmodel/descriptor/se_t_tebd.py).

The test works because all three code paths (dd0, dd1, dd2) use the internal TypeEmbedNet with identical serialized state. However, the API is confusing: the parameter is accepted but silently discarded without documentation.

Either:

  1. Add a comment in the test explaining that the external type_embedding is intentionally ignored because both pt_expt and dpmodel use internal TypeEmbedNet, or
  2. Remove type_embedding from the pt_expt forward() signature to avoid the misleading API.
🤖 Prompt for AI Agents
In `@source/tests/pt_expt/descriptor/test_se_t_tebd.py` around lines 62 - 71, The
test is confusing because pt_expt's forward accepts a type_embedding but the
pt_expt implementation deletes it (del type_embedding in se_t_tebd.forward) and
dpmodel.call() generates its own via its internal TypeEmbedNet; update the test
(source/tests/pt_expt/descriptor/test_se_t_tebd.py) by adding a short clarifying
comment immediately above the creation/use of type_embedding (near the dd0(...)
call) stating that the passed type_embedding is intentionally ignored by the
pt_expt wrapper and that all models use the internal TypeEmbedNet with identical
serialized state, so the external tensor is provided only to keep API parity for
the test.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 341a5edf8e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

obj = cls(**data)
# Reinitialize layers from serialized data, using the same layer type
# that __init__ created (respects subclass overrides via MRO).
layer_type = type(obj.layers[0])

Choose a reason for hiding this comment

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

P2 Badge Guard deserialize against empty embedding layers

EmbeddingNet.deserialize() now unconditionally reads obj.layers[0], which raises IndexError when deserializing a valid zero-hidden-layer embedding (neuron=[], serialized as "layers": []). This regresses previous behavior where empty-layer embeddings could deserialize, and it can break model loading/type-conversion paths that rely on round-tripping these minimal networks.

Useful? React with 👍 / 👎.

)

# Import network to ensure EmbeddingNet is registered before TypeEmbedNet is used
from deepmd.pt_expt.utils import network # noqa: F401

Check notice

Code scanning / CodeQL

Unused import Note

Import of 'network' is not used.
@property
def skip_pt_expt(self) -> bool:
(
resnet_dt,

Check notice

Code scanning / CodeQL

Unused local variable Note test

Variable resnet_dt is not used.
def skip_pt_expt(self) -> bool:
(
resnet_dt,
excluded_types,

Check notice

Code scanning / CodeQL

Unused local variable Note test

Variable excluded_types is not used.
(
resnet_dt,
excluded_types,
precision,

Check notice

Code scanning / CodeQL

Unused local variable Note test

Variable precision is not used.
resnet_dt,
excluded_types,
precision,
env_protection,

Check notice

Code scanning / CodeQL

Unused local variable Note test

Variable env_protection is not used.
tebd_dim,
tebd_input_mode,
resnet_dt,
excluded_types,

Check notice

Code scanning / CodeQL

Unused local variable Note test

Variable smooth is not used.
precision,
use_econf_tebd,
use_tebd_bias,
) = self.param

Check notice

Code scanning / CodeQL

Unused local variable Note test

Variable concat_output_tebd is not used.
use_econf_tebd,
use_tebd_bias,
) = self.param
return CommonTest.skip_pt_expt

Check notice

Code scanning / CodeQL

Unused local variable Note test

Variable precision is not used.
use_tebd_bias,
) = self.param
return CommonTest.skip_pt_expt

Check notice

Code scanning / CodeQL

Unused local variable Note test

Variable use_econf_tebd is not used.
) = self.param
return CommonTest.skip_pt_expt

@property

Check notice

Code scanning / CodeQL

Unused local variable Note test

Variable use_tebd_bias is not used.
@codecov
Copy link

codecov bot commented Feb 8, 2026

Codecov Report

❌ Patch coverage is 98.56115% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.02%. Comparing base (97d8ded) to head (5b6c9d8).

Files with missing lines Patch % Lines
deepmd/pt_expt/utils/type_embed.py 88.88% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5208      +/-   ##
==========================================
+ Coverage   82.00%   82.02%   +0.02%     
==========================================
  Files         724      728       +4     
  Lines       73801    73920     +119     
  Branches     3616     3615       -1     
==========================================
+ Hits        60520    60635     +115     
- Misses      12120    12121       +1     
- Partials     1161     1164       +3     

☔ View full report in Codecov by Sentry.
📢 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.

Signed-off-by: Jinzhe Zeng <jinzhe.zeng@ustc.edu.cn>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants