Skip to content

Commit bbc3908

Browse files
wanghan-iapcmHan Wang
andauthored
fix(tf2): register se_t, se_t_tebd, and se_atten_v2 descriptors (deepmodeling#5721)
## Problem Fixes deepmodeling#5677. TF2 standard-model construction resolves descriptor classes through `BaseDescriptor.get_class_by_type(<type>)`, and the TF2 descriptor registry is a distinct registry from the dpmodel and JAX ones (each backend builds its own via `make_base_descriptor`). The `se_t`, `se_t_tebd`, and `se_atten_v2` wrappers were defined without the `@BaseDescriptor.register(...)` decorators their JAX counterparts carry, so their config type names could not be resolved and TF2 model construction failed with an unknown-descriptor error even though the wrapper classes exist and are exported by `deepmd.tf2.descriptor`. The affected type names are `se_e3`, `se_at`, `se_a_3be` (all `se_t`), `se_e3_tebd` (`se_t_tebd`), and `se_atten_v2`. ## Fix Add the missing `@BaseDescriptor.register(...)` decorators, matching the JAX registrations for the same descriptor names. The `se_e3_tebd` registration goes on the outer `DescrptSeTTebd` only (not the block), mirroring JAX. ## Test Adds `source/tests/consistent/test_tf2_descriptor_registration.py`, which asserts that every TF2 descriptor config type name resolves via `get_class_by_type`. It fails on master for the five previously-unregistered names and passes with the fix. The test is gated on `INSTALLED_TF2` (run with `DEEPMD_TEST_TF2=1`). Existing TF2 consistency tests never caught this because they instantiate the wrapper classes directly rather than through the registry string lookup. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Expanded TF2 descriptor availability so more descriptor names are recognized and usable. * **Bug Fixes** * Improved descriptor lookup reliability, helping ensure the correct TF2 descriptor is resolved at runtime. * **Tests** * Added coverage to verify that all expected TF2 descriptor types are registered and callable when the TF2 backend is available. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Han Wang <wang_han@iapcm.ac.cn>
1 parent dd38b35 commit bbc3908

4 files changed

Lines changed: 68 additions & 0 deletions

File tree

deepmd/tf2/descriptor/se_atten_v2.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44
from ..common import (
55
register_dpmodel_mapping,
66
)
7+
from .base_descriptor import (
8+
BaseDescriptor,
9+
)
710
from .dpa1 import (
811
DescrptDPA1,
912
)
1013

1114

15+
@BaseDescriptor.register("se_atten_v2")
1216
class DescrptSeAttenV2(DescrptDPA1, DescrptSeAttenV2DP):
1317
pass
1418

deepmd/tf2/descriptor/se_t.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,14 @@
66
)
77
from ..utils import exclude_mask as _tf2_exclude_mask # noqa: F401
88
from ..utils import network as _tf2_network # noqa: F401
9+
from .base_descriptor import (
10+
BaseDescriptor,
11+
)
912

1013

14+
@BaseDescriptor.register("se_e3")
15+
@BaseDescriptor.register("se_at")
16+
@BaseDescriptor.register("se_a_3be")
1117
@tf2_module
1218
class DescrptSeT(DescrptSeTDP):
1319
pass

deepmd/tf2/descriptor/se_t_tebd.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,17 @@
1010
from ..utils import exclude_mask as _tf2_exclude_mask # noqa: F401
1111
from ..utils import network as _tf2_network # noqa: F401
1212
from ..utils import type_embed as _tf2_type_embed # noqa: F401
13+
from .base_descriptor import (
14+
BaseDescriptor,
15+
)
1316

1417

1518
@tf2_module
1619
class DescrptBlockSeTTebd(DescrptBlockSeTTebdDP):
1720
pass
1821

1922

23+
@BaseDescriptor.register("se_e3_tebd")
2024
@tf2_module
2125
class DescrptSeTTebd(DescrptSeTTebdDP):
2226
pass
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# SPDX-License-Identifier: LGPL-3.0-or-later
2+
"""Every TF2 descriptor wrapper must register its config type names.
3+
4+
TF2 standard-model construction resolves descriptors through
5+
``BaseDescriptor.get_class_by_type(<type>)``. The wrapper classes exist and are
6+
exported by ``deepmd.tf2.descriptor``, but several used to be defined without the
7+
``@BaseDescriptor.register(...)`` decorators the JAX wrappers carry, so their
8+
config type names could not be resolved and model construction failed with an
9+
unknown-descriptor error.
10+
"""
11+
12+
import unittest
13+
14+
from .common import (
15+
INSTALLED_TF2,
16+
)
17+
18+
if INSTALLED_TF2:
19+
import deepmd.tf2.descriptor # noqa: F401
20+
from deepmd.tf2.descriptor.base_descriptor import (
21+
BaseDescriptor,
22+
)
23+
24+
# type names that must resolve on the TF2 descriptor registry, mirroring the
25+
# JAX wrapper registrations for the same descriptors.
26+
TF2_DESCRIPTOR_TYPES = [
27+
"se_e2_a",
28+
"se_a",
29+
"se_e2_r",
30+
"se_r",
31+
"se_e3", # se_t
32+
"se_at", # se_t
33+
"se_a_3be", # se_t
34+
"se_e3_tebd", # se_t_tebd
35+
"se_atten_v2",
36+
"se_atten", # dpa1
37+
"dpa1",
38+
"dpa2",
39+
"dpa3",
40+
"hybrid",
41+
]
42+
43+
44+
@unittest.skipUnless(INSTALLED_TF2, "TF2 backend is not installed")
45+
class TestTF2DescriptorRegistration(unittest.TestCase):
46+
def test_all_types_resolve(self) -> None:
47+
for descriptor_type in TF2_DESCRIPTOR_TYPES:
48+
with self.subTest(descriptor_type=descriptor_type):
49+
cls = BaseDescriptor.get_class_by_type(descriptor_type)
50+
self.assertTrue(callable(cls))
51+
52+
53+
if __name__ == "__main__":
54+
unittest.main()

0 commit comments

Comments
 (0)