You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#411 fixed this in src/hflow/build_ai_vlm_checks.py yesterday: max_retries changes which items produce answers, so it belongs in the version identity. The Build AI evaluation example has the same gap in its own run fingerprint, and it was not touched.
max_retries is recorded but sits outside the contract that gets hashed:
It reaches the real request at :359, so it is live rather than decorative.
Why it matters here specifically
The fingerprint is not just a label. It gates output-directory reuse:
examples/build_ai_evaluation/evaluate.py:564ifexisting_metadata.fingerprint!=current_metadata.fingerprint:
raiseValueError(
f"{metadata_path} describes a different experiment; choose another --output"
)
So a run with max_retries=0 and a run with max_retries=5 are currently judged the same experiment and allowed to append to one output directory. Under retries a transient 500 becomes a parsed prediction; without them it becomes a failed row. The two runs have systematically different coverage, and the guard that exists to stop incompatible experiments mixing does not see the difference.
The documentation states the current behaviour accurately, which is how it stayed invisible:
docs/how-to/run-build-ai-evaluation.md:315
the endpoint, model, prompt contents, schema mode, temperature, token limit,
selected rows, sources, and tasks
What to do
Move max_retries into result_contract, and add it to that documented list.
Do not move worker_count. It is excluded for a good reason and the distinction is the interesting part of this issue: parallelism changes how fast the rows are evaluated, not which rows produce answers. Two runs differing only in worker count are genuinely the same experiment. api_key_environment_variable stays out for the same kind of reason: it names where a credential is read from, not what the model does.
Pattern to copy
#411, which made exactly this argument and this change one layer in. Its tests are the shape to follow: one asserting two configurations differing only in max_retries produce different fingerprints, and one asserting a configuration identical in every covered field keeps its fingerprint.
Definition of done
Two configurations differing only in max_retries produce different fingerprints, pinned by a test.
A configuration identical in every covered field keeps the fingerprint it has, so unchanged methodology is not invalidated. Worth a recorded value rather than comparing one config to itself; see the golden pins added to tests/test_build_ai_vlm_checks.py in fix(build-ai): cover completeness knobs in the check version contract #411 for why that distinction matters.
worker_count still does not participate, with a comment saying why.
docs/how-to/run-build-ai-evaluation.md:315 lists the field.
Existing run directories will stop matching, which is correct. Say so in the PR.
Validation
This lives in a workspace example, so it has its own project:
uv run --locked --project examples/build_ai_evaluation ruff check examples/build_ai_evaluation
uv run --locked --project examples/build_ai_evaluation ruff format --check examples/build_ai_evaluation
uv run --locked --project examples/build_ai_evaluation ty check --project examples/build_ai_evaluation --extra-search-path . examples/build_ai_evaluation
uv run --locked --project examples/build_ai_evaluation pytest -q examples/build_ai_evaluation/tests
#411 fixed this in
src/hflow/build_ai_vlm_checks.pyyesterday:max_retrieschanges which items produce answers, so it belongs in the version identity. The Build AI evaluation example has the same gap in its own run fingerprint, and it was not touched.max_retriesis recorded but sits outside the contract that gets hashed:It reaches the real request at
:359, so it is live rather than decorative.Why it matters here specifically
The fingerprint is not just a label. It gates output-directory reuse:
So a run with
max_retries=0and a run withmax_retries=5are currently judged the same experiment and allowed to append to one output directory. Under retries a transient 500 becomes a parsed prediction; without them it becomes a failed row. The two runs have systematically different coverage, and the guard that exists to stop incompatible experiments mixing does not see the difference.The documentation states the current behaviour accurately, which is how it stayed invisible:
What to do
Move
max_retriesintoresult_contract, and add it to that documented list.Do not move
worker_count. It is excluded for a good reason and the distinction is the interesting part of this issue: parallelism changes how fast the rows are evaluated, not which rows produce answers. Two runs differing only in worker count are genuinely the same experiment.api_key_environment_variablestays out for the same kind of reason: it names where a credential is read from, not what the model does.Pattern to copy
#411, which made exactly this argument and this change one layer in. Its tests are the shape to follow: one asserting two configurations differing only in
max_retriesproduce different fingerprints, and one asserting a configuration identical in every covered field keeps its fingerprint.Definition of done
max_retriesproduce different fingerprints, pinned by a test.tests/test_build_ai_vlm_checks.pyin fix(build-ai): cover completeness knobs in the check version contract #411 for why that distinction matters.worker_countstill does not participate, with a comment saying why.docs/how-to/run-build-ai-evaluation.md:315lists the field.Validation
This lives in a workspace example, so it has its own project:
uv run --locked --project examples/build_ai_evaluation ruff check examples/build_ai_evaluation uv run --locked --project examples/build_ai_evaluation ruff format --check examples/build_ai_evaluation uv run --locked --project examples/build_ai_evaluation ty check --project examples/build_ai_evaluation --extra-search-path . examples/build_ai_evaluation uv run --locked --project examples/build_ai_evaluation pytest -q examples/build_ai_evaluation/testsThen the root gate from CONTRIBUTING.md.