feat: Conditional queries and schema v3 - #15
Merged
Merged
Conversation
Accept a ConditionBlock on forecast_mean, forecast_samples, and forecast_quantiles so conditional queries reach every high-level surface, not only forecast(). Document conditional queries in the README and API reference, add the forecast_condition notebook, and move the sample env schema pin to v3.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the
conditionquery mode to the SDK and moves the supported service schema fromv2tov3. A caller can now ask the deployment for the joint distribution at one future position given pinned or bounded values of some columns at that same position, throughforecast()and all three high-level helpers.What changes
Public contract (
contract.py)SCHEMA_VERSIONisv3. The SDK supports exactly one schema, sov2deployments are refused byvalidate_service_metadata()after this lands.QueryModegainscondition; newConditionKind(equality,interval) andSUPPORTED_CONDITION_KINDS.EqualityCondition(column, value),IntervalCondition(column, lower, upper), andConditionBlock(query_time_index, conditions). Each validates itself on construction (finite numbers,lower < upper, at least one bound, one condition per column).ForecastRequestacceptscondition. It requiresquery_mode="condition"and the block to go together, and checks the block against the request's own schema andquery_timesbefore any round trip: undeclared columns, an index outside the requested horizons, conditioning every column, and pinned columns listed inrequested_columnsall fail locally.ConditionPlausibility(equality_log_density,region_log_probability) andIntervalEstimator(points,effective_sample_size).ForecastResponse.plausibilityisNoneon forecast responses.ForecastDiagnosticsgainscondition_drawsandinterval_estimator. Condition responses carry only the conditioned position inoutputs.query_times.require_condition_support(metadata, block)refuses a block whose mode or kinds the deployment does not advertise, raisingUnsupportedServiceContractErrorbefore the request is sent.UNSUPPORTED_HEAD_QUERY_COMBINATIONandUNSUPPORTED_RETURN_MODE.Health metadata validation
supported_query_modeswas required to equal the SDK's list. It is now a non-empty subset, because the service derives the modes from the mounted head and a head that cannot condition legitimately advertises fewer.HealthMetadatagainssupported_condition_kinds, a possibly empty subset of the SDK's kinds. The field is required in/healthz; a payload without it fails validation. An advertised value the SDK does not know is still a contract mismatch.Client (
client.py,adapters.py)forecast,forecast_mean,forecast_samples,forecast_quantiles, andbuild_forecast_payload_from_dataframeacceptcondition. Passing it setsquery_mode="condition"; the client checks the cached/healthzadvertisement first.condition_drawsreports the merged count andplausibilityis carried from the first batch, since every batch answers the same request.Docs and samples
notebooks/forecast_condition.ipynbwalks through an equality pin, reading the plausibility, and a mixed equality-plus-interval request..env.sample,config.sample.yaml, and all fixtures move tov3;health_metadata.jsonadvertisessupported_condition_kinds: [].AGENTS.mdadds the rule to present comparable items as a Markdown table.Tests
tests/test_condition_mode.pycovers block validation, request-level checks, payload shape, the capability gate, response parsing for both kinds, the client round trip through a fake transport, batched sample merging, the DataFrame adapter, and health-metadata rejection of unknown advertisements.condition_mean_request.json,condition_mean_response.json,condition_interval_response.json.v3pin and the new health field.Behavior changes to note for reviewers
v2, or whose/healthzlackssupported_condition_kinds, are refused by this SDK version.supported_query_modesvalidation is relaxed from exact match to subset.Note
Medium Risk
Breaking schema pin and stricter health field requirements reject older deployments; request/response contract changes affect all predict paths but are guarded by local validation and extensive tests.
Overview
Bumps the SDK’s supported JointFM service contract from
schema_versionv2tov3across configuration samples, docs, and fixtures. Callers must pinJOINTFM_SCHEMA_VERSION=v3; services still onv2or health payloads missingsupported_condition_kindsfail compatibility checks.Adds the
conditionquery mode so forecasts can target the joint distribution at a single future step given equality pins or interval bounds on other columns at that step. New public types (ConditionBlock,EqualityCondition,IntervalCondition, plausibility/diagnostic types) validate requests locally, serialize into predict payloads, and parse responses includingplausibilityand condition-specific diagnostics.forecast, theforecast_*helpers, andbuild_forecast_payload_from_dataframeaccept optionalcondition; the client callsrequire_condition_supportagainst cached/healthzbefore posting.Relaxes health advertisement rules for head-derived capabilities:
supported_query_modesandsupported_condition_kindsmust be non-empty (where required) subsets of what the SDK knows, not exact equality. New structured error codes and docs/notebook (forecast_condition.ipynb) cover the feature;AGENTS.mdadds guidance to present comparable items as tables.Reviewed by Cursor Bugbot for commit aca06f8. Configure here.