Skip to content

Handle LLMMessage serialization at the storage layer (#5024)#5024

Closed
ItsMrLin wants to merge 1 commit intofacebook:mainfrom
ItsMrLin:export-D96434290
Closed

Handle LLMMessage serialization at the storage layer (#5024)#5024
ItsMrLin wants to merge 1 commit intofacebook:mainfrom
ItsMrLin:export-D96434290

Conversation

@ItsMrLin
Copy link
Contributor

@ItsMrLin ItsMrLin commented Mar 13, 2026

Summary:

Move LLMMessage dict conversion from the experiment.llm_messages
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

experiment.py: The setter now stores LLMMessage objects directly
in _properties. The getter handles both LLMMessage objects (new path)
and plain dicts (backward compat with previously stored data).

JSON store: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes LLMMessage with a __type tag,
and LLMMessage is already registered in CORE_DECODER_REGISTRY.

SQA store: The encoder converts LLMMessage → dict via
dataclasses.asdict() in the properties copy before DB write (same
pattern as pruning_target_parameterization). The decoder converts
dicts → LLMMessage after loading properties, in both
_init_experiment_from_sqa and _init_mt_experiment_from_sqa.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290

@meta-cla meta-cla bot added the CLA Signed Do not delete this pull request or issue due to inactivity. label Mar 13, 2026
@meta-codesync
Copy link

meta-codesync bot commented Mar 13, 2026

@ItsMrLin has exported this pull request. If you are a Meta employee, you can view the originating Diff in D96434290.

@codecov-commenter
Copy link

codecov-commenter commented Mar 13, 2026

Codecov Report

❌ Patch coverage is 66.66667% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.73%. Comparing base (2d4750a) to head (03c8353).

Files with missing lines Patch % Lines
ax/storage/sqa_store/decoder.py 60.00% 2 Missing ⚠️
ax/storage/sqa_store/encoder.py 75.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5024   +/-   ##
=======================================
  Coverage   96.73%   96.73%           
=======================================
  Files         606      606           
  Lines       66242    66251    +9     
=======================================
+ Hits        64080    64090   +10     
+ Misses       2162     2161    -1     

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

@meta-codesync meta-codesync bot changed the title Handle LLMMessage serialization at the storage layer Handle LLMMessage serialization at the storage layer (#5024) Mar 16, 2026
ItsMrLin added a commit to ItsMrLin/Ax that referenced this pull request Mar 16, 2026
Summary:

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
ItsMrLin added a commit to ItsMrLin/Ax that referenced this pull request Mar 16, 2026
Summary:
Pull Request resolved: facebook#5024

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
ItsMrLin added a commit to ItsMrLin/Ax that referenced this pull request Mar 16, 2026
Summary:

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
ItsMrLin added a commit to ItsMrLin/Ax that referenced this pull request Mar 16, 2026
Summary:

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
ItsMrLin added a commit to ItsMrLin/Ax that referenced this pull request Mar 17, 2026
Summary:

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
ItsMrLin added a commit to ItsMrLin/Ax that referenced this pull request Mar 17, 2026
Summary:

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
ItsMrLin added a commit to ItsMrLin/Ax that referenced this pull request Mar 17, 2026
Summary:

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
ItsMrLin added a commit to ItsMrLin/Ax that referenced this pull request Mar 18, 2026
Summary:

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
ItsMrLin added a commit to ItsMrLin/Ax that referenced this pull request Mar 18, 2026
Summary:

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
ItsMrLin added a commit to ItsMrLin/Ax that referenced this pull request Mar 18, 2026
Summary:

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
ItsMrLin added a commit to ItsMrLin/Ax that referenced this pull request Mar 18, 2026
Summary:

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
ItsMrLin added a commit to ItsMrLin/Ax that referenced this pull request Mar 18, 2026
Summary:

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
Summary:

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
ItsMrLin added a commit to ItsMrLin/Ax that referenced this pull request Mar 18, 2026
Summary:

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
ItsMrLin added a commit to ItsMrLin/Ax that referenced this pull request Mar 18, 2026
Summary:

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
ItsMrLin added a commit to ItsMrLin/Ax that referenced this pull request Mar 18, 2026
Summary:

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
ItsMrLin added a commit to ItsMrLin/Ax that referenced this pull request Mar 18, 2026
Summary:

Move `LLMMessage` dict conversion from the `experiment.llm_messages`
getter/setter to the storage encoders/decoders, following Ax convention
that domain objects hold domain types and serialization happens at the
storage boundary.

**`experiment.py`**: The setter now stores `LLMMessage` objects directly
in `_properties`. The getter handles both `LLMMessage` objects (new path)
and plain dicts (backward compat with previously stored data).

**JSON store**: No explicit changes needed — the encoder's generic
dataclass fallback auto-serializes `LLMMessage` with a `__type` tag,
and `LLMMessage` is already registered in `CORE_DECODER_REGISTRY`.

**SQA store**: The encoder converts `LLMMessage` → dict via
`dataclasses.asdict()` in the properties copy before DB write (same
pattern as `pruning_target_parameterization`). The decoder converts
dicts → `LLMMessage` after loading properties, in both
`_init_experiment_from_sqa` and `_init_mt_experiment_from_sqa`.

Reviewed By: lena-kashtelyan

Differential Revision: D96434290
@meta-codesync meta-codesync bot closed this in fdddec1 Mar 18, 2026
@meta-codesync
Copy link

meta-codesync bot commented Mar 18, 2026

This pull request has been merged in fdddec1.

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

Labels

CLA Signed Do not delete this pull request or issue due to inactivity. fb-exported Merged meta-exported

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants