refactor(issue-607): extract _state_to_dict and _load_state_dict methods#609
Conversation
- Add _state_to_dict() to serialize optimizer state to dictionary - Add _load_state_dict() to load optimizer state from dictionary - Update save_state() to use _state_to_dict() - Update load_state() to use _load_state_dict() - Enables JSON-based state manipulation without file I/O
📝 WalkthroughWalkthrough
ChangesState Serialization Refactoring
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
bayes_opt/bayesian_optimization.py (1)
431-449:⚠️ Potential issue | 🟠 Major | ⚡ Quick winValidate the receiving optimizer before replaying saved observations.
_state_to_dict()serializeskeys,pbounds,allow_duplicate_points, andtransformed_bounds, but_load_state_dict()replaysstate["params"]straight into the currentTargetSpacewithout checking that this instance was built with matching parameter order, bounds, duplicate-point policy, or transformer configuration. That makes the new dict-based round-trip fragile: a different key order can silently remap coordinates, a stricter duplicate policy can fail duringregister(), and missingself._bounds_transformerjust drops saved transformed bounds.Suggested guardrail
def _load_state_dict(self, state: dict[str, Any]) -> None: + saved_keys = list(state["keys"]) + current_keys = list(self._space.keys) + if saved_keys != current_keys: + raise ValueError("Saved state keys do not match optimizer keys") + + saved_bounds = {k: tuple(v) for k, v in state["pbounds"].items()} + current_bounds = {k: tuple(self._space._bounds[i]) for i, k in enumerate(current_keys)} + if saved_bounds != current_bounds: + raise ValueError("Saved state bounds do not match optimizer bounds") + + if (state["constraint_values"] is not None) != self.is_constrained: + raise ValueError("Saved state constraint mode does not match optimizer configuration") + + if state["allow_duplicate_points"] != self._allow_duplicate_points: + raise ValueError( + "Saved state duplicate-point policy does not match optimizer configuration" + ) + + if state["transformed_bounds"] is not None and self._bounds_transformer is None: + raise ValueError("Saved state requires a bounds transformer") + params_array = np.asarray(state["params"], dtype=np.float64) target_array = np.asarray(state["target"], dtype=np.float64)Also applies to: 451-479
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@bayes_opt/bayesian_optimization.py` around lines 431 - 449, When loading a saved state in _load_state_dict, first validate that the current optimizer/TargetSpace matches the saved metadata from _state_to_dict: check that state["keys"] equals self._space.keys (same order), state["pbounds"] matches self._space._bounds (or transformed_bounds vs self._bounds_transformer), and state["allow_duplicate_points"] equals self._allow_duplicate_points; if any mismatch is detected, raise a clear ValueError (or provide a documented migration path) instead of blindly calling self._space.register on state["params"]; also handle the case where state["transformed_bounds"] exists but self._bounds_transformer is absent by rejecting the load or requiring a compatible transformer, and include state["random_state"]/acquisition metadata only after validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@bayes_opt/bayesian_optimization.py`:
- Around line 431-449: When loading a saved state in _load_state_dict, first
validate that the current optimizer/TargetSpace matches the saved metadata from
_state_to_dict: check that state["keys"] equals self._space.keys (same order),
state["pbounds"] matches self._space._bounds (or transformed_bounds vs
self._bounds_transformer), and state["allow_duplicate_points"] equals
self._allow_duplicate_points; if any mismatch is detected, raise a clear
ValueError (or provide a documented migration path) instead of blindly calling
self._space.register on state["params"]; also handle the case where
state["transformed_bounds"] exists but self._bounds_transformer is absent by
rejecting the load or requiring a compatible transformer, and include
state["random_state"]/acquisition metadata only after validation.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 7aa478e3-7948-4f39-9744-bc633291d475
📒 Files selected for processing (1)
bayes_opt/bayesian_optimization.py
Extracted state serialization logic into separate methods to enable saving/loading optimizer state without using the local file system.
Summary by CodeRabbit