Skip to content

Optimizer Protocol#828

Merged
AdrianSosic merged 43 commits into
dev/recommenderfrom
feature/refactor-recommender
Jul 7, 2026
Merged

Optimizer Protocol#828
AdrianSosic merged 43 commits into
dev/recommenderfrom
feature/refactor-recommender

Conversation

@StefanPSchmid

@StefanPSchmid StefanPSchmid commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Goal

Decompose the monolithic BotorchRecommender into atomic, reusable optimization procedures that users can compose and pass to BayesianRecommender via a new OptimizerProtocol. This decoupling makes it straightforward to express e.g. subset-based optimization over fragmented spaces, coordinate-wise hybrid strategies, or other multi-phase approaches without new top-level classes — users/callers assemble the strategy externally and hand it to the recommender as a single object.

This PR is the first step: it establishes the ContinuousOptimizer primitive and the BayesianRecommender consumer, and deprecates BotorchRecommender with full backward compatibility at both constructor and serialization level.

Background

1. Opaque and invalid-by-design interface. Its fields (n_restarts, n_raw_samples, sequential_continuous) were BoTorch optimizer parameters exposed directly on the recommender class, with no clear model of how they mapped to the underlying optimization strategy. Worse, the flat field structure made it impossible to enforce valid combinations by construction: certain arguments were only meaningful for specific search space types (continuous-only fields had no effect in discrete or hybrid settings), yet nothing in the type system prevented users from providing them. Invalid combinations were accepted silently, with irrelevant fields quietly dropped — a recurring source of user confusion.

2. Monolithic, hard-coded optimization logic. The recommender owned both the high-level recommendation strategy and the low-level mechanics for optimizing over continuous and discrete spaces — all embedded in its class methods. This made it impossible to compose optimization primitives independently. Any new hybrid strategy (e.g. coordinate-wise ascent) required a new top-level recommender class (hence NaiveHybridRecommender), duplicating logic and proliferating classes instead of assembling reusable parts.

Changes

New optimizers subpackage
Introduces OptimizerProtocol[TSpace] as a generic protocol over search space type, and ContinuousOptimizer as the first concrete primitive. Fields are renamed to be self-describing: n_starts (was n_restarts), n_initial_samples (was n_raw_samples), sequential (was sequential_continuous).

New BayesianRecommender
Replaces BotorchRecommender as the primary public class. Accepts an optimizer: OptimizerProtocol field, making the optimization strategy explicit and swappable. Moves cardinality constraint handling out of the recommender (removing recommend_continuous_without_cardinality_constraints) and into the optimizer, where it belongs. Structured to accommodate future primitives (e.g. discrete + continuous) for hybrid and fragmented-space strategies.

BotorchRecommender deprecation shim
Reduces BotorchRecommender to a shim function that maps legacy constructor arguments to BayesianRecommender + ContinuousOptimizer with a DeprecationWarning. Registers a cattrs structure hook on PureRecommender to intercept "type": "BotorchRecommender" in serialized dicts and remap legacy optimizer fields before forwarding, ensuring full serialization backward compatibility.

Deprecation tests
Adds test_botorch_recommender (constructor shim) and test_botorch_recommender_deserialization (parametrized: no_args, all_args) covering legacy dict round-trip through converter.structure.

StefanPSchmid and others added 2 commits June 15, 2026 15:33
Comment thread baybe/recommenders/pure/bayesian/base.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/basic.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/basic.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/base.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/core.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/base.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/base.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/basic.py Outdated
Comment thread baybe/recommenders/pure/bayesian/base.py Outdated
Comment thread baybe/recommenders/pure/bayesian/core.py
Comment thread baybe/recommenders/pure/bayesian/continuous.py Outdated
Comment thread baybe/recommenders/pure/bayesian/discrete.py Outdated
Comment thread baybe/recommenders/pure/bayesian/hybrid.py Outdated
@AVHopp

AVHopp commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

@StefanPSchmid could it be the case that your pre-commit hook is not activated/configured incorrectly? I'm asking since both the Lint and the pre-commit checks are failing which should not happen, so would be great if you could check that.

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

Some intermediate comments

Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/base.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/basic.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/basic.py Outdated
Comment thread baybe/recommenders/pure/bayesian/base.py Outdated
Comment thread baybe/recommenders/pure/bayesian/core.py
Comment thread baybe/recommenders/pure/bayesian/continuous.py Outdated
Comment thread baybe/recommenders/pure/bayesian/discrete.py Outdated
Comment thread baybe/recommenders/pure/bayesian/hybrid.py Outdated
@StefanPSchmid
StefanPSchmid marked this pull request as ready for review June 30, 2026 08:43
@StefanPSchmid
StefanPSchmid requested a review from Scienfitz as a code owner June 30, 2026 08:43
Copilot AI review requested due to automatic review settings June 30, 2026 08:43

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.

Pull request overview

This PR introduces an optimizer abstraction for Bayesian continuous optimization while standardizing user-facing naming around BayesianRecommender and deprecating BotorchRecommender. It updates examples/docs/streamlit integration accordingly and refactors the continuous recommendation path to call a pluggable optimizer.

Changes:

  • Add a BoTorch-backed optimizer interface (OptimizerProtocol) with a first implementation (GradientOptimizer).
  • Refactor continuous Bayesian recommendation to delegate acquisition optimization to recommender.optimizer.
  • Switch examples/docs/streamlit usage from BotorchRecommender to BayesianRecommender and turn BotorchRecommender into a deprecation wrapper.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
streamlit/surrogate_models.py Update Streamlit app to use BayesianRecommender.
README.md Update README examples to BayesianRecommender.
examples/Serialization/validate_config.py Update serialized type strings to BayesianRecommender.
examples/Serialization/create_from_config.py Update serialized type strings to BayesianRecommender.
examples/Serialization/basic_serialization.py Update example imports/usages to BayesianRecommender.
examples/Searchspaces/hybrid_space.py Update explanatory comment to BayesianRecommender.
examples/Multi_Armed_Bandit/bernoulli_multi_armed_bandit.py Update example to construct BayesianRecommender.
examples/Custom_Surrogates/surrogate_params.py Update example to construct BayesianRecommender.
examples/Custom_Surrogates/custom_pretrained.py Update example to construct BayesianRecommender.
examples/Custom_Hooks/probability_of_improvement.py Update hook typing/docs and usage to BayesianRecommender.
examples/Custom_Hooks/campaign_stopping.py Update hook typing/docs and usage to BayesianRecommender.
examples/Constraints_Continuous/interpoint.py Update continuous-constraints example to BayesianRecommender.
examples/Basics/recommenders.py Update basics example to BayesianRecommender.
baybe/recommenders/pure/bayesian/hybrid.py Rename typing/docs references to BayesianRecommender.
baybe/recommenders/pure/bayesian/discrete.py Rename typing/docs references to BayesianRecommender.
baybe/recommenders/pure/bayesian/continuous.py Delegate continuous acquisition optimization to recommender.optimizer.
baybe/recommenders/pure/bayesian/botorch/optimizers/basic.py Add GradientOptimizer implementation using botorch.optim.optimize_acqf.
baybe/recommenders/pure/bayesian/botorch/optimizers/base.py Add OptimizerProtocol for optimizer pluggability.
baybe/recommenders/pure/bayesian/botorch/optimizers/init.py Export optimizer(s) from package.
baybe/recommenders/pure/bayesian/botorch/core.py Replace class BotorchRecommender with deprecated factory wrapper.
baybe/recommenders/pure/bayesian/base.py Add optimizer field and move recommendation routines into BayesianRecommender.
baybe/recommenders/pure/bayesian/init.py Export BayesianRecommender from pure.bayesian.
baybe/recommenders/pure/init.py Export BayesianRecommender from pure.
baybe/recommenders/naive.py Default hybrid sub-recommenders to BayesianRecommender.
baybe/recommenders/meta/sequential.py Default meta recommender to BayesianRecommender.
baybe/recommenders/init.py Export BayesianRecommender at top-level recommenders package.
AGENTS.md Update naming convention example to BayesianRecommender.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread baybe/recommenders/pure/bayesian/core.py
Comment thread baybe/recommenders/pure/bayesian/botorch/core.py
Comment thread baybe/recommenders/pure/bayesian/core.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/core.py Outdated

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

Few comments that you can look at - hopefully easy fixes :)

Comment thread examples/Constraints_Continuous/interpoint.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/core.py
Comment thread baybe/recommenders/pure/bayesian/base.py Outdated
Comment thread baybe/recommenders/pure/bayesian/core.py Outdated
Comment thread baybe/recommenders/pure/bayesian/continuous.py

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

Here some first comments

Comment thread baybe/recommenders/pure/bayesian/core.py
Comment thread baybe/recommenders/pure/bayesian/botorch/core.py
Comment thread baybe/recommenders/pure/bayesian/core.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/base.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/base.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/base.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/basic.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/basic.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/basic.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/basic.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/base.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/basic.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/optimizers/basic.py Outdated
@AdrianSosic
AdrianSosic force-pushed the feature/refactor-recommender branch from 6190dcb to ad16da8 Compare July 3, 2026 06:41
@AdrianSosic
AdrianSosic force-pushed the feature/refactor-recommender branch from ad16da8 to 268c187 Compare July 3, 2026 06:48
@Scienfitz

Scienfitz commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

@StefanPSchmid @AdrianSosic @AVHopp please can you update the PR descrption witha s ummary of what the intended change in this pR is and what has been changed/deleted etc?

Last I recall Stefan was supposed to work on refactoring recommenders such that multi-step optimization algorithms (naive hybrid, mfbo, currybo) can be naturally included. just form a quick look at the code it not totally clear whether this PR is still about that (also the PR title does not seem to be related to that??)

@AdrianSosic

Copy link
Copy Markdown
Collaborator

@StefanPSchmid @AdrianSosic @AVHopp please can you update the PR descrption witha s ummary of what the intended change in this pR is and what has been changed/deleted etc?

Last I recall Stefan was supposed to work on refactoring recommenders such that multi-step optimization algorithms (naive hybrid, mfbo, currybo) can be naturally included. just form a quick look at the code it not totally clear whether this PR is still about that (also the PR title does not seem to be related to that??)

Let me write a summary 👍🏼

@AdrianSosic AdrianSosic changed the title First draft Continuous optimizer Optimizer Protocol Jul 3, 2026
@AdrianSosic

Copy link
Copy Markdown
Collaborator

@StefanPSchmid @AdrianSosic @AVHopp please can you update the PR descrption witha s ummary of what the intended change in this pR is and what has been changed/deleted etc?

Last I recall Stefan was supposed to work on refactoring recommenders such that multi-step optimization algorithms (naive hybrid, mfbo, currybo) can be naturally included. just form a quick look at the code it not totally clear whether this PR is still about that (also the PR title does not seem to be related to that??)

@Scienfitz: now there

Comment thread tests/test_deprecations.py Outdated

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

The two tests are failing, so I am wondering if this has been tested properly. I would also recommend rebasing the dev branch onto the latest version of main (in particular after the PRs fixing our issues there have been merged) such that we actually see this in the CI.

Comment thread baybe/recommenders/pure/bayesian/botorch/core.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/core.py
Comment thread tests/test_deprecations.py
Comment thread CHANGELOG.md Outdated
Comment thread examples/Custom_Hooks/probability_of_improvement.py Outdated
Comment thread baybe/recommenders/pure/bayesian/botorch/core.py Outdated
Comment thread baybe/optimizers/base.py
Comment thread tests/test_deprecations.py
Comment thread tests/test_deprecations.py
@AdrianSosic
AdrianSosic merged commit 0783d15 into dev/recommender Jul 7, 2026
9 of 11 checks passed
@AdrianSosic
AdrianSosic deleted the feature/refactor-recommender branch July 7, 2026 08:49
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.

6 participants