How Hypster Ensures Type Safety and Validates Hyper-Parameters

Hypster enforces type safety through a layered validation system that checks function signatures, validates parameter types via specialized validator classes, and detects unknown or duplicate parameters during configuration execution.

Hypster is a Python library for managing hyper-parameter configurations developed by gilad-rubin. The library implements rigorous type safety and validation mechanisms to prevent runtime errors caused by invalid parameter types, out-of-bounds values, or misconfigured options. According to the source code in gilad-rubin/hypster, this validation occurs across multiple layers from initial function inspection through final parameter binding.

Function Signature Validation

Before executing any configuration logic, Hypster validates that user-defined configuration functions adhere to a strict contract. In src/hypster/utils.py, the validate_config_func_signature function inspects the callable and asserts that its first argument is named hp and is annotated with the HP type.

If the signature is malformed—such as missing the hp parameter or lacking the correct type annotation—the system raises a clear ValueError immediately. This check occurs at lines 85-115 in utils.py, ensuring that all downstream validation operates on correctly structured configuration functions.

Validator Classes for Type Safety

Concrete validation logic resides in src/hypster/hp_calls.py. Specialized validator classes enforce type constraints for each parameter category, with every validator implementing validate_value and optionally validate_bounds.

IntValidator ensures supplied values are integers or safely convertible from floats, raising HPCallError on type mismatches. When strict=True, it rejects implicit float-to-int conversions that would lose precision, as implemented at lines 58-60, while general validation spans lines 56-70.

FloatValidator guarantees float types or converts from integers when strict mode is disabled (lines 75-85). TextValidator, BoolValidator, SelectValidator, and MultiValidator perform analogous checks for strings, booleans, enumerated choices, and list-valued parameters at lines 91-127.

Centralized Validation in the HP Class

All public HP methods—including _int, _float, _text, _bool, select, and multi_select—delegate to private helper methods in src/hypster/hp.py. These helpers orchestrate the validation sequence:

  • _validate_name_not_called ensures parameter names are unique and not reused within the same configuration
  • _handle_single_value and _handle_multi_value fetch user-provided values or defaults, then invoke the appropriate validator's validate_value method
  • When bounds (min / max) are declared, the helper calls validator.validate_bounds to enforce numeric limits, as seen at lines 48-50 in hp.py

This centralized approach guarantees consistent error messages and validation behavior across all parameter types.

Strict Mode for Numeric Precision

For numeric parameters, Hypster provides a strict flag that controls type coercion behavior. When strict=True, validators reject implicit conversions entirely. For example, IntValidator will raise an error if passed 32.5 even if it could theoretically be truncated, preventing silent precision loss. This mode is particularly critical for scientific computing configurations where exact integer semantics are required.

Unknown and Duplicate Parameter Detection

After user functions execute, Hypster performs a final validation pass to catch misspelled or unreachable parameters. The HP class tracks every called parameter in self.called_params. In src/hypster/core.py, the _handle_unknown_parameters function (lines 73-106) compares supplied values against the set of actually called parameters, emitting warnings or errors for keys that were never accessed during configuration execution.

This layer prevents silent failures caused by typos in parameter names or attempting to set values for parameters that have been removed from the configuration.

Practical Implementation Examples

The following examples demonstrate Hypster's validation layers in action:

from hypster import instantiate, HP

# Typed parameters with bounds and strict mode

def cfg(hp: HP):
    # int – strict=False allows safe conversion from float

    batch = hp.int(32, name="batch", min=1, max=512, strict=False)
    # float – strict=True rejects int values

    lr = hp.float(0.01, name="lr", min=0.0, max=1.0, strict=True)
    # bool and text parameters

    use_gpu = hp.bool(True, name="use_gpu")
    model_name = hp.text("resnet", name="model")
    return {"batch": batch, "lr": lr, "gpu": use_gpu, "model": model_name}

# Valid instantiation

config = instantiate(cfg, values={"batch": 64, "lr": 0.001})
print(config)   # {'batch': 64, 'lr': 0.001, 'gpu': True, 'model': 'resnet'}

Validation failures raise descriptive errors:


# Bounds violation

try:
    instantiate(cfg, values={"batch": 0})   # below minimum

except ValueError as e:
    print(e)   # Parameter 'batch': value 0 is below minimum bound 1

# Strict mode rejection

try:
    instantiate(cfg, values={"batch": 32.5})   # float precision loss

except ValueError as e:
    print(e)   # Parameter 'batch': float 32.5 would lose precision ...

Enumerated parameters enforce option constraints:

def cfg_select(hp: HP):
    optimizer = hp.select(["sgd", "adam"], name="optimizer", options_only=True)
    return optimizer

# Unknown option detection

try:
    instantiate(cfg_select, values={"optimizer": "rmsprop"})
except ValueError as e:
    print(e)   # 'rmsprop' not in allowed options. Available: ['sgd', 'adam']

Type safety propagates through nested configurations:

def child(hp: HP):
    hidden = hp.int(128, name="hidden", min=1)
    return hidden

def parent(hp: HP):
    hp.nest(child, name="encoder")
    return "done"

# Nested parameter validation

print(instantiate(parent, values={"encoder.hidden": 256}))

Summary

  • Signature validation in utils.py ensures configuration functions accept an hp: HP parameter before execution begins.
  • Specialized validators in hp_calls.py enforce type constraints for integers, floats, booleans, text, and selections, with optional strict mode for numeric precision.
  • Central handling in hp.py coordinates name uniqueness checks, value validation, and bounds enforcement through _handle_single_value and related helpers.
  • Strict mode prevents implicit type conversions that could silently alter numeric values in scientific computations.
  • Unknown parameter detection in core.py compares supplied values against actually called parameters to catch typos and obsolete configuration keys.

Frequently Asked Questions

What happens if I pass a float to an int parameter in Hypster?

The behavior depends on the strict flag. When strict=False (default), IntValidator accepts floats that represent whole numbers (e.g., 32.0) but rejects values like 32.5 that would lose precision. When strict=True, the validator rejects any float input, requiring explicit integer types. In all cases, invalid conversions raise HPCallError with descriptive messages indicating the parameter name and problematic value.

How does Hypster detect unknown or misspelled parameters?

Hypster tracks every parameter accessed during configuration execution in self.called_params. After the configuration function completes, core._handle_unknown_parameters (lines 73-106) compares the keys in the user-supplied values dictionary against this set of called parameters. If a supplied key was never accessed—indicating a typo or obsolete parameter—the system emits a warning or error, preventing silent configuration failures.

What is the purpose of strict mode in Hypster validators?

Strict mode controls type coercion behavior for numeric parameters. When enabled via strict=True in methods like hp.int() or hp.float(), validators reject implicit conversions between integers and floats. This prevents subtle bugs in machine learning pipelines where 1.0 (float) might behave differently from 1 (int) in downstream libraries, or where precision loss from float-to-int conversion could alter experimental results.

How does Hypster validate configuration function signatures?

Before executing a configuration, utils.validate_config_func_signature inspects the callable to verify its first argument is named hp and carries the HP type annotation. This check occurs at lines 85-115 in src/hypster/utils.py. If the signature is incorrect—such as missing the parameter or having the wrong type hint—Hypster raises a ValueError immediately, ensuring that all configuration functions follow the expected interface contract.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →