Skip to content

Rework serialization to support pydantic codecs - #459

Draft
nikitakuklev wants to merge 3 commits into
xopt-org:mainfrom
nikitakuklev:modern-serialization
Draft

Rework serialization to support pydantic codecs#459
nikitakuklev wants to merge 3 commits into
xopt-org:mainfrom
nikitakuklev:modern-serialization

Conversation

@nikitakuklev

@nikitakuklev nikitakuklev commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

Summary

Replace the recursive walker / JSON_ENCODERS serialization machinery with context-aware codecs in a new xopt.types module. Serialization behavior is now driven by a single SerializationOptions pydantic context:

  • array_mode: list | b64 (binary numpy/torch payloads)
  • module_mode: drop | file (.pt next to the dump, load looks in same location (not always cwd)) | inline
  • df_mode: dict | b64
  • optional gzip/zstd compression

Encoding is done with special prefixes, and compression detected through magic bytes, following apsopt implementation. We move to using pure pydantic functionality, using advanced hooks like __get_pydantic_core_schema__. See example notebook for usage.

Backward compatibility

Old saves should load correctly. Legacy base64: inline torch tag works but will be swapped on save.

Format-affecting changes:

  • Explicit null for non-Optional fields now raises instead of being silently stripped.
  • supports_* capability flags are frozen and no longer serialized. (bugfix)
  • DataFrame reloads restore the integer index (previously string keys).

Other

  • orjson dependency dropped (pydantic already does fast json in Rust); zstandard added; requires pydantic>=2.12
  • A few incidental bugfixes related to serialization

Fixes #444

@codecov

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

@nikitakuklev

Copy link
Copy Markdown
Collaborator Author

@electronsandstuff opinion on overall arch? This would override #443 changes.

@nikitakuklev
nikitakuklev marked this pull request as draft August 21, 2026 11:46
@electronsandstuff

electronsandstuff commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

I just gave it a skim. Overall, this feels like the most modern way to handle it in pydantic and I support.

My understanding is that you make a "codec" and annotated type,

NDArray = Annotated[np.ndarray, NDArrayCodec()]

and pydantic knows to use __get_pydantic_core_schema__ natively?


Only other thoughts from quickly reading:

  • Do we already support all of these encoding options in SerializationOptions? If not, I tend to err on the side of minimizing the features needed to support. Ie if we could look for an OK set of options which are the "Xopt choice" and drop the rest it will save us from having to maintain 2^n variations moving forward (unless there's a strong reason for some). Users probably don't need to worry about gzip vs zstd for instance and it's just another thing to continue to test and support.
  • I saw some round-trip tests for Bayesian. I wonder if we are standardized enough now that we can make a parameterized test that does round-trip saving on every generator.
  • Another test idea: confirm every generator has the support_flag fields frozen and exclued. IE double check that users subclass correctly. Parametrized pytest check

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Modern Serialization of Custom Datatypes

2 participants