test(e2e): cover /v1/responses OpenAI vision and Anthropic basic - #33838
Conversation
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
|
Greptile SummaryThis PR adds two e2e tests for the
Confidence Score: 4/5Both files are confined to the tests/e2e directory with no production code changes, and the new helpers follow the established test patterns. The vision test assertion checks only two keywords ("cat" and "feline"), so valid single-word model answers like "kitten" or "tabby" would cause a spurious failure. The test has passed in practice, but the narrow keyword list leaves a small non-determinism window that could surface in CI against a different model snapshot. tests/e2e/llm_translation/test_responses_e2e.py — the vision keyword assertion at lines 172–175
|
| Filename | Overview |
|---|---|
| tests/e2e/llm_translation/endpoints_client.py | Adds typed multimodal input models and a responses_vision() helper; the image_url field is a plain string which matches the Responses API's input_image schema |
| tests/e2e/llm_translation/test_responses_e2e.py | Adds two e2e tests: vision image description (OpenAI gpt-4o) and Anthropic basic completion; assertions are tight but the keyword list for the vision test could miss edge-case valid answers |
Reviews (1): Last reviewed commit: "test(e2e): cover /v1/responses OpenAI vi..." | Re-trigger Greptile
| assert any( | ||
| keyword in text | ||
| for keyword in ("cat", "feline") | ||
| ), f"vision response did not describe the image: {parsed.text[:300]}" |
There was a problem hiding this comment.
Vision assertion keyword coverage is narrow
The assertion only matches "cat" or "feline", so it would fail if the model replies with a different valid single-word answer for that image such as "kitten", "kitty", or a breed name like "persian" or "tabby". Prompt-compliance ("answer in one word") reduces this risk in practice, but extending the keyword list or anchoring the assertion with a broader substring check would make the test more robust against non-deterministic model output.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>
d79e2b9 to
685948a
Compare
Relevant issues
Linear ticket
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
@greptileaito re-request a review after pushing changes)Delays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).
Screenshots / Proof of Fix
Captured against a live proxy (docker compose stack) hitting real OpenAI and Anthropic APIs. The proof was captured at commit d79e2b9; the branch was later rebased onto
litellm_internal_stagingwith byte-identical test content (head 685948a)The two new tests pass:
The same behavior driven by hand through the live proxy, showing the vision request actually reads the image and the Anthropic translation returns real Responses-shaped text:
Type
✅ Test
Changes
This is PR 3 of a stacked series adding e2e coverage for
/v1/responses. Its base (#33835) has since merged intolitellm_internal_staging, so this PR now targets staging directly and the diff is only the two new tests plus the typed multimodal input they needIt closes two registry rows that were previously uncovered
test_responses_vision_describes_imageregisters a vision-capableopenai/gpt-4odeployment at runtime, sends a multimodal/v1/responsesrequest (aninput_textpart plus aninput_imagepart pointing at a stable public cat image), and asserts the returned text names the animal (cat/feline), so a model that did not actually see the image fails the test rather than passing on any non-empty answertest_responses_anthropic_returns_completionregistersanthropic/claude-haiku-4-5and drives a non-streaming/v1/responsescall, parsing the body asResponsesResultand asserting.text.strip()is non-empty, which proves the Responses to Anthropic translation returns valid Responses-shaped output with real text rather than a 200 with an empty or mistranslated bodyTo support multimodal input without raw dicts or
Any,endpoints_client.pywidensResponsesRequest.inputfromstrto a typed unionstr | list[ResponsesInputMessage], where each message's content is a list of a composed part union (input_textandinput_imagevariants sharing atypediscriminant). The existingstrpath keeps working for the basic, streaming, cost, and tool tests. Aresponses_vision(...)helper sends the multimodal shapeQA runbook
Prerequisites:
OPENAI_API_KEYandANTHROPIC_API_KEYintests/e2e/.env, then fromtests/e2e/rundocker compose up -dand confirmcurl -fs http://localhost:4000/health/livelinessreturns oktests/e2e/llm_translation/test_responses_e2e.py::TestResponses::test_responses_vision_describes_image - a multimodal
/v1/responsescall to a vision model returns text that actually describes the supplied imagecurl -s http://localhost:4000/v1/responses -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{"model":"gpt-5.5","input":[{"role":"user","content":[{"type":"input_text","text":"What animal is shown in this image? Answer in one word"},{"type":"input_image","image_url":"https://upload.wikimedia.org/wikipedia/commons/3/3a/Cat03.jpg"}]}]}'output[].content[].textsaysCat(case-insensitive), proving the model read the image and not just any non-empty replytests/e2e/llm_translation/test_responses_e2e.py::TestResponses::test_responses_anthropic_returns_completion - a non-streaming
/v1/responsescall backed by Anthropic returns valid Responses-shaped output with real textcurl -s http://localhost:4000/v1/responses -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{"model":"claude-haiku-4-5","input":"reply with one word"}'output[].content[].textis non-empty real text, proving the Responses to Anthropic translation round-tripsuv run --no-sync pytest llm_translation/test_responses_e2e.py -v -k 'vision or anthropic'passes both, andPYTHONPATH=. python -m coverage_registry.collector --strictreports the two rows as covered with no unknown markersVideo of the live run and curl proof
https://app.devin.ai/attachments/7e22b083-6bda-4325-bcda-9c64b37543ec/rec-2504f162-ba2f-4f5d-a61e-3771a45253f2-edited.mp4
Final Attestation
Link to Devin session: https://app.devin.ai/sessions/b54b82329e57464f908f57e73f6a766c
Requested by: @ishaan-berri