test: derive streamed-usage expectations from the SDK object (unbreaks main) - #12367
Conversation
`main` is red on all three OS jobs: test_convert_chat_completion_chunk_to_streaming_chunk and test_handle_stream_response fail because the expected usage payload was restated as a literal listing openai 2.x's field set. Since `chore: unpin openai` (deepset-ai#12348) relaxed the constraint to `openai>=2.6.0`, openai 3.1.0 resolves and CompletionUsage gained additive fields (prompt_tokens_details.image_tokens / .text_tokens, completion_tokens_details.text_tokens), so the literals no longer match. The contract under test is that haystack forwards the SDK's usage unchanged, not that the SDK's schema has exactly these keys. The expectations are now derived from the same CompletionUsage object the fixture streams, so an additive field in a future openai release cannot break them. Verified the assertion still has teeth: making _serialize_object drop prompt_tokens_details fails both tests, restoring it passes them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@lets-order-some-fries is attempting to deploy a commit to the deepset Team on Vercel. A member of the Team first needs to authorize it. |
|
Hi @lets-order-some-fries, thanks a lot for your contribution! 🙏 We noticed that the Contributor License Agreement (CLA) check ( To get your PR reviewed, please sign the CLA via the link in the |
|
Thanks for signing the CLA, @lets-order-some-fries! 🎉 This PR is now ready for review again and the reviewer has been re-assigned. |
|
Thanks for the PR @lets-order-some-fries! We already fixed this in #12374 so I'm closing this one. |
|
Makes sense — thanks for the quick triage @bogdankostic, and glad main is green again. #12365 remains open and is unrelated to the openai bump. |
Related Issues
mainis currently red and I hit it while running the suite for another PR. Filing the fix directly since CI is blocking everyone.Proposed Changes:
mainis failing on all three OS jobs. Run 31934088851 at915888bb—Unit / ubuntu-latest,Unit / macos-latestandUnit / windows-latestall end with:Cause.
chore: unpin openai(#12348) relaxed the constraint toopenai>=2.6.0, so a fresh environment now resolves openai 3.1.0, andCompletionUsagegained additive fields:prompt_tokens_details→image_tokens,text_tokenscompletion_tokens_details→text_tokensBoth failing tests restated the expected usage payload as a literal enumerating openai 2.x's exact field set, so
model_dump()now returns more keys than the literal lists and the comparison fails. The diff is confined tometa["usage"]; nothing inhaystack/is wrong —_serialize_objectforwardsmodel_dump()faithfully, which is precisely what it should do.Fix. The contract these tests exist to protect is "haystack forwards the SDK's usage unchanged", not "the SDK's usage schema has exactly these keys". Restating the schema as a literal encodes the second, which is not this repo's invariant to own — and with the dependency now unpinned it will drift again on the next release that adds a field.
The expected value is therefore derived from the same
CompletionUsageobject the fixture streams. Net -38/+18 lines: two duplicated literals collapse into one shared object.used both as the chunk's
usage=and, via.model_dump(), as the expectation in thestreaming_chunksfixture and intest_handle_stream_response.How did you test it?
At this head (
9141ca50):hatch run test:unit test/components/generators/chat/test_openai.py→ 55 passed (both previously-failing tests now pass)hatch run test:unit(full suite) → 6115 passed, 10 skipped, 0 failed — againstmain's 6113 passed / 2 failedhatch run test:types→ Success: no issues found in 432 source fileshatch run fmt→ All checks passed!pre-commit run --files test/components/generators/chat/test_openai.py→ all hooks PassedMutation test, because a derived expectation is worth distrusting. An assertion built from the same object it validates can be tautological, so I checked that this one still fails when the behaviour it guards actually breaks. Patching
_serialize_objectinhaystack/components/generators/utils.pyto dropprompt_tokens_detailsfrom the dump:and with that patch reverted,
2 passed. So the tests still catch a real pass-through regression; they no longer catch additive changes to openai's own schema, which is the part that should not have been asserted.Notes for the reviewer
No release note, per CONTRIBUTING: this is limited to tests, so it needs the
ignore-for-release-noteslabel from a maintainer to bypass that CI check. Say the word if you'd rather I add one instead.Deliberately scoped to unbreaking CI: I did not re-pin
openai, since #12348 unpinned it on purpose, and I did not touch the otherPromptTokensDetails(...)fixtures elsewhere in the file — those are inputs rather than expectations, so they are unaffected by additive fields.Worth noting the general shape, since the unpin makes it recurrent: any assertion that enumerates a third-party model's fields is a scheduled failure. The two sites fixed here were the only ones the suite currently trips on.
AI assistance disclosure: this PR was written with an AI assistant. I reviewed the change, and ran the tests and checks reported above.
Checklist
test:.ignore-for-release-notes(see notes above).