Skip to content

Add generic GP components#746

Open
AdrianSosic wants to merge 20 commits intodev/gpfrom
refactor/gp_components
Open

Add generic GP components#746
AdrianSosic wants to merge 20 commits intodev/gpfrom
refactor/gp_components

Conversation

@AdrianSosic
Copy link
Collaborator

  • Generalizes the existing GP kernel into multi-purpose component logic using generics
  • Adds support for GPyTorch GP components
  • Enables configuration of GP mean and likelihood
  • Adds EDBO and SMOOTHED_EDBO GP preset
  • Completes preset logic by including mean and likelihood components

@AdrianSosic AdrianSosic self-assigned this Feb 11, 2026
@AdrianSosic AdrianSosic added enhancement Expand / change existing functionality new feature New functionality refactor labels Feb 11, 2026
@AdrianSosic AdrianSosic marked this pull request as ready for review February 11, 2026 14:29
Copilot AI review requested due to automatic review settings February 11, 2026 14:29
@AdrianSosic AdrianSosic mentioned this pull request Feb 11, 2026
15 tasks
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Generalizes Gaussian Process (GP) surrogate configuration into reusable, generic “component” factories and adds new GP presets, including EDBO variants, while improving serialization behavior and adding tests for GPyTorch kernel support.

Changes:

  • Introduces generic GP component factory infrastructure (kernel/mean/likelihood) and wires it into GaussianProcessSurrogate.
  • Adds EDBO and smoothed EDBO preset implementations including mean/likelihood factories.
  • Updates serialization hooks to better support generic base-class dispatch and clearer error messages; adds tests for GPyTorch kernel usage + serialization blocking.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
tests/test_gp.py Adds tests for using GPyTorch kernels and blocking serialization.
baybe/utils/boolean.py Extends is_abstract to handle parameterized generics.
baybe/utils/basic.py Extends get_subclasses to handle parameterized generics.
baybe/surrogates/gaussian_process/presets/utils.py Adds lazy-loaded constant mean factory for presets.
baybe/surrogates/gaussian_process/presets/edbo_smoothed.py Implements smoothed EDBO kernel + likelihood factories.
baybe/surrogates/gaussian_process/presets/edbo.py Refactors EDBO logic into kernel/mean/likelihood factories.
baybe/surrogates/gaussian_process/presets/default.py Re-exports default factories via smoothed EDBO + constant mean.
baybe/surrogates/gaussian_process/presets/core.py Adds EDBO presets and constructs GP from preset factories.
baybe/surrogates/gaussian_process/presets/init.py Exposes new preset factories in public API.
baybe/surrogates/gaussian_process/kernel_factory.py Removes legacy kernel-factory module in favor of generic components.
baybe/surrogates/gaussian_process/core.py Adds mean/likelihood factories and generic component conversion.
baybe/surrogates/gaussian_process/components/mean.py Adds mean component type aliases around generic factory base.
baybe/surrogates/gaussian_process/components/likelihood.py Adds likelihood component type aliases around generic factory base.
baybe/surrogates/gaussian_process/components/kernel.py Adds kernel component type aliases around generic factory base.
baybe/surrogates/gaussian_process/components/generic.py Introduces generic component factory + serialization blocking for GPyTorch kernels.
baybe/surrogates/gaussian_process/components/init.py Adds package exports for component factory types.
baybe/serialization/core.py Updates abstract-base hooks (generic-aware) + improves error messages.
baybe/kernels/base.py Updates import path for PlainKernelFactory after refactor.
CHANGELOG.md Documents new GP component support and presets.

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

Comment on lines +3 to +5
from baybe.surrogates.gaussian_process.components.kernel import (
KernelFactory,
PlainComponentFactory,
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PlainComponentFactory is not defined/exported by components.kernel (that module defines PlainKernelFactory). This import will fail at runtime. Import PlainComponentFactory from baybe.surrogates.gaussian_process.components.generic, or change the export to PlainKernelFactory (and update __all__ accordingly).

Suggested change
from baybe.surrogates.gaussian_process.components.kernel import (
KernelFactory,
PlainComponentFactory,
from baybe.surrogates.gaussian_process.components.generic import (
PlainComponentFactory,
)
from baybe.surrogates.gaussian_process.components.kernel import (
KernelFactory,

Copilot uses AI. Check for mistakes.
Comment on lines +40 to +49
def _validate_component(instance, attribute: Attribute, value: Any):
"""Validate that an object is a BayBE or a GPyTorch GP component."""
if isinstance(value, Kernel) or _is_gpytorch_kernel_class(type(value)):
return

raise TypeError(
f"The object provided for '{attribute.alias}' of "
f"'{instance.__class__.__name__}' must be a BayBE or a GPyTorch GP component. "
f"Got: {type(value)}"
)
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This validator currently only accepts BayBE kernels or GPyTorch kernels, but the PR also introduces MeanFactory and LikelihoodFactory. Passing a GPyTorch mean/likelihood instance (which GaussianProcessSurrogate claims to accept) will raise TypeError. Expand validation to also accept GPyTorch mean and likelihood instances (ideally via lazy issubclass(type(value), gpytorch.means.Mean) / gpytorch.likelihoods.Likelihood checks similar to _is_gpytorch_kernel_class).

Copilot uses AI. Check for mistakes.
Comment on lines +75 to +79
def to_component_factory(x: Component | ComponentFactory, /) -> ComponentFactory:
"""Wrap a component into a plain component factory (with factory passthrough)."""
if isinstance(x, Component) or _is_gpytorch_kernel_class(type(x)):
return PlainComponentFactory(x)
return x
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At runtime, Component is set to Kernel only (to preserve serialization compatibility), so isinstance(x, Component) will not recognize GPyTorch mean/likelihood objects. As a result, providing mean_or_factory=<gpytorch Mean instance> / likelihood_or_factory=<gpytorch Likelihood instance> will fall through and return the raw object (not a factory), which will fail when called in _fit. Consider using explicit runtime checks for GPyTorch Mean/Likelihood instances (lazy-loaded) in addition to kernels, and wrap them in PlainComponentFactory.

Copilot uses AI. Check for mistakes.
Comment on lines +21 to 24
EDBO_SMOOTHED = "EDBO_SMOOTHED"
"""A smoothed version of the EDBO settings."""


Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description and CHANGELOG.md mention a SMOOTHED_EDBO preset, but the enum value is EDBO_SMOOTHED. Since this is a user-facing API (and affects serialization/config), please align naming across the enum/make_gp_from_preset/changelog/docs. If the external name must be SMOOTHED_EDBO, consider renaming the enum member (or providing a backward-compatible alias if EDBO_SMOOTHED was already released).

Suggested change
EDBO_SMOOTHED = "EDBO_SMOOTHED"
"""A smoothed version of the EDBO settings."""
SMOOTHED_EDBO = "SMOOTHED_EDBO"
"""A smoothed version of the EDBO settings."""
# Backwards-compatible alias; preferred name is ``SMOOTHED_EDBO``.
EDBO_SMOOTHED = SMOOTHED_EDBO
"""Deprecated alias for :attr:`SMOOTHED_EDBO`."""

Copilot uses AI. Check for mistakes.
from baybe.surrogates.gaussian_process.presets.utils import LazyConstantMeanFactory

if TYPE_CHECKING:
from gpytorch.likelihoods import Likelihood as GPyTorchLikelihhood
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct the spelling of GPyTorchLikelihhood to GPyTorchLikelihood.

Copilot uses AI. Check for mistakes.
from baybe.surrogates.gaussian_process.presets.utils import LazyConstantMeanFactory

if TYPE_CHECKING:
from gpytorch.likelihoods import Likelihood as GPyTorchLikelihhood
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct the spelling of GPyTorchLikelihhood to GPyTorchLikelihood.

Suggested change
from gpytorch.likelihoods import Likelihood as GPyTorchLikelihhood
from gpytorch.likelihoods import Likelihood as GPyTorchLikelihood

Copilot uses AI. Check for mistakes.
@@ -26,7 +26,9 @@ class Kernel(ABC, SerialMixin):

def to_factory(self) -> PlainKernelFactory:
"""Wrap the kernel in a :class:`baybe.surrogates.gaussian_process.kernel_factory.PlainKernelFactory`.""" # noqa: E501
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring still references the removed module path baybe.surrogates.gaussian_process.kernel_factory.PlainKernelFactory. Update it to baybe.surrogates.gaussian_process.components.kernel.PlainKernelFactory (or whatever the intended public path is) to avoid stale documentation.

Suggested change
"""Wrap the kernel in a :class:`baybe.surrogates.gaussian_process.kernel_factory.PlainKernelFactory`.""" # noqa: E501
"""Wrap the kernel in a :class:`baybe.surrogates.gaussian_process.components.kernel.PlainKernelFactory`.""" # noqa: E501

Copilot uses AI. Check for mistakes.
Comment on lines +115 to +118
Accepts:
* :class:`baybe.kernels.base.Kernel`
* :class:`.kernel_factory.KernelFactory`
* :class:`gpytorch.kernels.Kernel`
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These docstring references (.kernel_factory.KernelFactory, similarly .mean_factory.* / .likelihood_factory.* below) no longer match the refactored module layout (components.kernel, components.mean, components.likelihood). Update the paths so docs/rendered references point to the correct types.

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +26
def test_gpytorch_kernel():
"""The GP accepts GPyTorch kernels and produces the same result as with BayBE kernels.""" # noqa: E501
measurements = create_fake_input(searchspace.parameters, objective.targets)
k1 = GPyTorchScaleKernel(GPyTorchMaternKernel() + GPyTorchRBFKernel())
k2 = ScaleKernel(AdditiveKernel([MaternKernel(), RBFKernel()]))
gp1 = GaussianProcessSurrogate(k1)
gp2 = GaussianProcessSurrogate(k2)
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR also adds support for configuring GPyTorch means and likelihoods, but tests only cover kernel acceptance + kernel serialization blocking. Add tests that (1) passing a GPyTorch Mean and Likelihood instance through GaussianProcessSurrogate(mean_or_factory=..., likelihood_or_factory=...) trains successfully, and (2) serialization is either explicitly blocked (raising NotImplementedError) or supported in a defined way for these components.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dev enhancement Expand / change existing functionality new feature New functionality refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant