tauopt.local#

LocalDriver: the full optimization loop in-process, zero server.

Mirrors the hosted service’s semantics (bandwidth cap included) behind the same Client surface, so a local script upgrades to hosted by changing two constructor arguments. State lives in this process; determinism comes from the engine (suggest is a pure function of state + config + the ask’s intents).

Math extras are probed lazily and LOUDLY: a missing extra raises ImportError naming the exact pip install target, never a silent degradation.

Module Contents#

Classes#

LocalDriver

In-process implementation of the driver surface consumed by tauopt.Client.

Data#

API#

tauopt.local.TAG_MAX_CHARS#

128

tauopt.local.PAGE_WINDOW_MAX#

200

tauopt.local.LOCAL_QUEUE_PROVENANCE: dict[str, Any]#

None

class tauopt.local.LocalDriver(*, supervisor: Literal[auto, process, off] = 'auto', backstop_alpha: float | None = None, backstop_grace_s: float | None = None)#

In-process implementation of the driver surface consumed by tauopt.Client.

NOT thread-safe – uniformly: every method does unsynchronized check-then-set on plain-dict state (the hosted plane serializes the same operations with advisory locks and DB constraints). One thread per driver; concurrent workers belong on the hosted plane. Parity claims are therefore scoped to the single-threaded envelope, inside which the semantics mirror the service exactly.

Initialization

close() → None#

Stop the worker process if one is running (the next supervised ask starts a fresh one). Idempotent; the exit hook does the same at interpreter exit.

create_experiment(*, name: str, parameters: list[dict[str, Any]], metric: dict[str, Any] | None = None, metrics: list[dict[str, Any]] | None = None, linear_constraints: list[dict[str, Any]] | None = None, num_solutions: int = 1, observation_budget: int | None = None, parallel_bandwidth: int = 1, metadata: dict[str, Any] | None = None, suggestion_ttl_s: int | None = None) → tauopt.models.Experiment#

Validate and register a new in-process experiment, mirroring the hosted plane’s request validation (same 400 error shapes): metric XOR metrics, positive budgets/bandwidth, a suggestion TTL in the hosted field’s integer domain (0..2147483647, lax-coerced as the service coerces), a buildable Space, and a sobol feasibility probe on linear constraints (an infeasible region 400s at creation, never at the first ask). Returns the Experiment with its initial progress. suggestion_ttl_s is recorded and served exactly as the hosted plane serves it (None = the service default applies there; 0 = never) and never acted on: the in-process driver expires no suggestion, so expired_at is always None here.

experiment(experiment_id: str) → tauopt.models.Experiment#

Return the experiment with live progress. Multimetric experiments report no scalar best_observation (undefined); read the frontier via best() instead.

update_experiment(experiment_id: str, *, name: str | None = None, observation_budget: int | None = None, parallel_bandwidth: int | None = None, metadata: dict[str, Any] | None = None, metric_thresholds: dict[str, float | None] | None = None, suggestion_ttl_s: int | None = None) → tauopt.models.Experiment#

PATCH semantics: None means leave unchanged. metric_thresholds updates thresholds on declared metrics (SigOpt allowed mid-experiment threshold moves); space and metric structure are immutable. suggestion_ttl_s is recorded and served, never acted on (see create_experiment); as on the hosted plane’s PATCH, a value replaces the recorded one, and the explicit-null revert of the REST body has no keyword form here either.

archive_experiment(experiment_id: str) → None#

Archive (soft-delete), mirroring the hosted plane exactly: state flips to “deleted”; experiment()/best()/listings/dismissals keep working, suggest/observe/update_experiment 404, a second archive 404s. There is no unarchive.

experiments(limit: int = 50, offset: int = 0, *, q: str | None = None, sort: str | None = None, dir: str | None = None, include_deleted: bool = False) → tauopt.models.ExperimentList#

The hosted list route’s mirror (GET /v1/experiments): the window through the hosted rules (limit bounded then clamped to 1..200; a negative offset the 400, never floored), q a case-insensitive substring of the name (the LIKE wildcards literal, as the service escapes them; a NUL the route’s own 400), sort/dir the four keys with the newest id breaking ties (name by code point here, the database collation there), active rows unless include_deleted; count the total under the filters, each row with its live progress. The refusals run in the route’s declaration order: the window, q’s length, sort, dir, then the route’s NUL check.

health() → tauopt.models.Health#

The in-process engine’s liveness: always "ok" (the hosted probe’s database round-trip has no local counterpart).

auth_check() → tauopt.models.AuthCheck#

No accounts in-process: user_id is None (hosted: the token’s account id, or a 401).

suggest(experiment_id: str, config: dict[str, Any] | None = None, max_wait_s: float | None = None, on_timeout: str = 'ladder', intents: list[dict[str, Any]] | None = None, tag: str | None = None) → tauopt.models.Suggestion#

Run one engine ask against current state and open the resulting suggestion. Mirrors the hosted plane end to end: the worker tag’s field rule (400, before anything else, as the body is parsed first), parallel_bandwidth enforcement (429 bandwidth_full), config/intent validation (400), TimeboxExceeded mapped to 503 suggest_timeout, the caps-mode AskDeadlineExceeded re-raised as the 503 ask_deadline_exceeded it already is (no Retry-After; the receipt in details), and the completion ladder on draftless terminal asks – SpaceExhausted (409, proof in details.dedup) when exhaustion is proven, a plain non-retryable 409 unique_candidate_unavailable when it is not.

suggestions(experiment_id: str, state: str | None = None, tag: str | None = None, *, limit: int | None = None, offset: int = 0) → tauopt.models.Page[tauopt.models.Suggestion]#

List the experiment’s suggestions in id order as a Page (total the service’s count under the filters), optionally filtered by state (“open” | “closed”) and by the worker tag (an exact match, the hosted ?tag=), the filters and the window under the hosted rules in the route’s order: state, tag, limit (None = every row; present clamped to 1..200), offset (a negative one the 400, never floored).

close_suggestion(experiment_id: str, suggestion_id: str) → None#

Dismiss an open suggestion without observing it (404 on an unknown id; a no-op when already closed). Dismissals count into n_dismissed, advancing the sequential streams; a dismissed-unobserved point leaves the dedup universe and may be re-suggested later.

close_all_suggestions(experiment_id: str) → int#

Bulk dismissal of every open suggestion (parity: bulk lifecycle ops).

observe(experiment_id: str, *, suggestion_id: str | None = None, assignments: tauopt.models.Assignments | None = None, value: float | None = None, values: dict[str, float] | None = None, value_stddev: float | None = None, values_stddev: dict[str, float] | None = None, failed: bool = False, metadata: dict[str, Any] | None = None) → tauopt.models.Observation#

Report a result against a suggestion (by id) or bare assignments (exactly one of the two; value(s) XOR failed=true). Validation runs against a candidate state and commits only on success, so a 400 never closes the suggestion or frees its bandwidth slot; observing the same suggestion twice answers 409 (the hosted unique-index mirror).

observations(experiment_id: str, *, limit: int | None = None, offset: int = 0, sort: str = 'created', dir: str = 'asc') → tauopt.models.Page[tauopt.models.Observation]#

List the experiment’s observations as a Page (total the service’s count): report order by default, or the hosted route’s sort/dir (_observation_order, the service’s observation_order), windowed by the hosted rules (limit None = every row, present clamped to 1..200; a negative offset the 400, never floored). The refusals run in the route’s order: the window, dir, the experiment’s 404, then sort’s own texts.

best(experiment_id: str) → tauopt.models.BestAssignments#

Best-so-far: the Pareto frontier in metrics mode, k diverse top picks when num_solutions > 1, else the single best observation (empty BestAssignments before any successful observation).