Skip to content

Build AI check versions exclude max_retries and request_timeout_seconds, so evaluations that can differ share one version identity #404

Description

@Sagar-024

Current behavior

_check_version (src/hflow/build_ai_vlm_checks.py:652-685) derives the version identity stamped into every Build AI check run. The OpenAI-compatible branch includes endpoint, model, response_format, temperature, and max_tokens. It excludes max_retries — validated at :164-167, defaulted at :143, and live at :715, where it is passed into the OpenAI client and decides whether transient errors become retried requests or terminal failures. The hosted branch includes only the execution label and endpoint; it excludes request_timeout_seconds — validated at :190-195 and live at :626 as the HTTP timeout.

Controlled result

Two executions that differ only in max_retries, and two that differ only in request_timeout_seconds, run through the real _check_version:

=== OpenAI path: same version identity, different completeness ===
max_retries=0 -> build-ai-single-frame-v1-eabed1f2e257cc07
max_retries=5 -> build-ai-single-frame-v1-eabed1f2e257cc07
same version: True

=== hosted path: same version identity, different completeness ===
request_timeout_seconds=1.0  -> build-ai-single-frame-v1-ac6fa96b9b859bec
request_timeout_seconds=60.0 -> build-ai-single-frame-v1-ac6fa96b9b859bec
same version: True

Why this is observable semantics, not reliability noise

The distinction that decides this issue: sampling noise changes the value of an answer; retries and timeouts change which items produce answers at all.

Temperature, which is already in the contract, adds sampling noise to a response that exists either way. max_retries and request_timeout_seconds change the failure mode and the completeness of a corpus: with max_retries=0, one transient 500 turns into a failed check run with no result; with max_retries=5, the same request becomes a parsed prediction. A short timeout drops slow-but-valid responses that a long timeout includes. Two corpora evaluated under these different settings have systematically different result sets — different error rates, different episode coverage — and a buyer comparing them under one version identity is told they are comparable when they are not.

That is the rule stated on #365: if the effective measurement path changes observable semantics, version and cache/provenance identity must change with it. The contract's own inclusion of temperature and max_tokens already establishes that behavioral knobs are version-worthy; these two knobs meet the same standard.

What to build

Open call, not assumed:

  1. Add the fields to the contract: max_retries in the OpenAI-compatible branch, request_timeout_seconds in the hosted branch. The precedent is internal (temperature, max_tokens), so this is a consistency fix rather than a design change.
  2. Record the behavior as evidence instead: leave the contract alone and stamp attempts/timeouts as measurements on every check run, so the difference is visible in the record without moving identity.

The first matches the contract's own logic; the second matches a "retries are infrastructure" reading. What cannot stand is the current middle: knobs that change outcomes, invisible to both the identity and the record.

Definition of done

  1. Every execution knob that changes which items produce results is either in the version contract or recorded per run as a measurement.
  2. Two configurations differing only in the newly covered fields produce different version identities, pinned by a test through the real _check_version.
  3. Configurations that are identical in every covered field keep their existing version, so unchanged methodology does not silently invalidate.
  4. The hosted and OpenAI branches treat the rule symmetrically.
  5. The demo above lands as a test.

Non-goals

  • Changing the max_retries or request_timeout_seconds defaults
  • Changing how temperature participates in the contract
  • Restructuring step_version_from_contract or the fingerprint machinery

Validation

uv run ruff check --fix
uv run ruff format
uv run ty check
uv run pytest -q tests/test_build_ai_vlm_checks.py
uv run pytest -q

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    advancedNeeds codebase familiarity; not a starter issuebugSomething isn't workinghelp wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions