Skip to content

fix(dpmodel): preserve model dictionaries during serialization#5788

Open
njzjz wants to merge 1 commit into
deepmodeling:masterfrom
njzjz:codex/code-scan-5639
Open

fix(dpmodel): preserve model dictionaries during serialization#5788
njzjz wants to merge 1 commit into
deepmodeling:masterfrom
njzjz:codex/code-scan-5639

Conversation

@njzjz

@njzjz njzjz commented Jul 14, 2026

Copy link
Copy Markdown
Member

Summary

  • preserve the caller-owned model dictionary while save_dp_model() rewrites variables into YAML or HDF5 references;
  • copy only the nested dict and list containers that traversal mutates, so large arrays are not duplicated;
  • retain support for non-copyable variable objects such as h5py.Dataset;
  • add regressions for nested YAML/native serialization and an HDF5-backed variable.

Why existing tests missed this

The existing save/load tests pass deepcopy(self.model_dict) into save_dp_model() and then validate only the serialized round trip. That disposable copy hides mutations of the object supplied by a real caller, so the shallow-copy bug was never observed.

The new tests pass a caller-owned nested structure directly, assert that its containers and variables remain unchanged, and cover both serialization implementations. The HDF5 dataset case also prevents a memory-heavy full deepcopy from becoming the fix.

Validation

  • targeted serialization tests and existing save/load tests: 6 passed;
  • ruff format .;
  • ruff check .;
  • git diff --check.

Closes #5639.

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

Summary by CodeRabbit

  • Bug Fixes
    • Saving models no longer alters the original nested data structures.
    • Preserves shared and non-copyable objects, including HDF5-backed datasets, during serialization.
    • Ensures saved models retain expected data when loaded across supported formats.

Copy only the dict and list containers that serialization traversal rewrites. This keeps caller-owned model dictionaries unchanged without duplicating large array buffers or requiring variable objects such as h5py datasets to support deepcopy.

Add YAML and native-format regressions for nested input preservation, plus an HDF5 dataset case that protects the non-copyable variable path.

Fixes deepmodeling#5639.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.1
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
Copilot AI review requested due to automatic review settings July 14, 2026 16:10
@dosubot dosubot Bot added the bug label Jul 14, 2026

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.

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 75f041f5-4316-445a-a296-97b013364bc8

📥 Commits

Reviewing files that changed from the base of the PR and between 7d5ad38 and 1daea00.

📒 Files selected for processing (2)
  • deepmd/dpmodel/utils/serialization.py
  • source/tests/common/dpmodel/test_serialization.py

📝 Walkthrough

Walkthrough

save_dp_model now traverses an independent dict/list container tree while preserving variable references. Tests cover unchanged nested inputs for YAML/native outputs and HDF5 dataset handling.

Changes

Serialization mutation isolation

Layer / File(s) Summary
Container-only copy in save_dp_model
deepmd/dpmodel/utils/serialization.py
Adds recursive copying for mutable containers and uses it before model traversal, leaving variable objects shared.
Mutation and HDF5 regression coverage
source/tests/common/dpmodel/test_serialization.py
Verifies input preservation across YAML and native outputs, including nested arrays and HDF5 datasets.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: preventing model dictionary mutation during serialization.
Linked Issues check ✅ Passed The code and tests address #5639 by avoiding container mutation during save_dp_model and adding regression coverage for nested structures.
Out of Scope Changes check ✅ Passed The changes stay focused on serialization behavior and regression tests, with no obvious unrelated scope creep.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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.

@codecov

codecov Bot commented Jul 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.88889% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 79.58%. Comparing base (7d5ad38) to head (1daea00).

Files with missing lines Patch % Lines
deepmd/dpmodel/utils/serialization.py 88.88% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5788      +/-   ##
==========================================
- Coverage   79.85%   79.58%   -0.27%     
==========================================
  Files        1022     1022              
  Lines      117351   117358       +7     
  Branches     4313     4311       -2     
==========================================
- Hits        93706    93401     -305     
- Misses      22101    22409     +308     
- Partials     1544     1548       +4     

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

@njzjz njzjz requested a review from wanghan-iapcm July 14, 2026 22:56

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

Correct and minimal. save_dp_model did a shallow model_dict.copy(), but traverse_model_dict reassigns nested dict/list entries in place, so serialization mutated the caller's dict (arrays replaced by YAML/HDF5 references). _copy_model_containers rebuilds only the container tree and shares the variable objects, which is safe because the save callbacks read variables (data=x, x.dtype, x.tolist()) and create new @is_variable dicts rather than mutating inputs. The regression tests genuinely fail pre-fix -- passing a caller-owned dict directly and asserting equality/identity -- and the h5py.Dataset test additionally prevents a naive full deepcopy from being the fix, since Datasets aren't deep-copyable. Good catch on why the existing tests missed it (they fed in a deepcopy). LGTM.

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.

[Code scan] Avoid mutating model dictionaries during save_dp_model

4 participants