Skip to content

test(e2e): TokenSpeed Qwen3-ASR audio transcription - #1912

Open
slin1237 wants to merge 1 commit into
mainfrom
test/e2e-tokenspeed-audio-transcription
Open

test(e2e): TokenSpeed Qwen3-ASR audio transcription#1912
slin1237 wants to merge 1 commit into
mainfrom
test/e2e-tokenspeed-audio-transcription

Conversation

@slin1237

@slin1237 slin1237 commented Jul 13, 2026

Copy link
Copy Markdown
Member

Description

Problem

#1905 added Qwen3-ASR audio transcription served via TokenSpeed but shipped no e2e coverage for POST /v1/audio/transcriptions. (Supersedes the closed #1909, which reinvented the request layer with raw httpx.)

Solution

Add an e2e test driven through the standard api_client (OpenAI SDK) + model fixtures — the same idiom as test_multimodal.py / test_enable_thinking.py — calling api_client.audio.transcriptions.create(...). Covers a whole-file transcription, response_format="text", and 400 rejection of an unsupported language.

Changes

  • e2e_test/chat_completions/test_transcription_tokenspeed.py (new): TestTokenSpeedTranscription, markers @engine("tokenspeed") @gpu(1) @e2e @model("Qwen/Qwen3-ASR-1.7B"), setup_backend=["grpc"].

Test Plan

Runs in the existing e2e-1gpu-chat (tokenspeed) lane. Locally py_compile / ruff / mypy clean. NOTE: CI currently fails at worker startup — the tokenspeed engine's transformers does not recognize the qwen3_asr architecture (Qwen3-ASR is wired for vLLM via an arch override); this is an engine-support gap, not a test defect, and is under discussion.

Checklist
  • cargo +nightly fmt passes
  • cargo clippy --all-targets --all-features -- -D warnings passes
  • (Optional) Documentation updated
  • (Optional) Please join us on Slack #sig-smg to discuss, review, and merge PRs

Add an e2e test for POST /v1/audio/transcriptions against a TokenSpeed
Qwen3-ASR worker, driven through the standard api_client (OpenAI SDK) /
model fixtures like the other chat_completions e2e tests. Covers a
whole-file transcription, the text response_format, and 400 rejection of
an unsupported language. Runs in the existing e2e-1gpu-chat (tokenspeed)
lane via the engine marker.

Refs #1905

Signed-off-by: Simo Lin <linsimo.mark@gmail.com>
@github-actions github-actions Bot added the tests Test changes label Jul 13, 2026
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds end-to-end TokenSpeed coverage for Qwen3-ASR audio transcription, including JSON and plain-text responses plus unsupported-language rejection.

Changes

TokenSpeed transcription coverage

Layer / File(s) Summary
TokenSpeed Qwen3-ASR test setup
e2e_test/chat_completions/test_transcription_tokenspeed.py
Defines the pinned model, reusable 16 kHz WAV fixture, and TokenSpeed GPU E2E markers.
Transcription request checks
e2e_test/chat_completions/test_transcription_tokenspeed.py
Tests non-empty JSON and text-format transcription responses and verifies unsupported languages raise openai.BadRequestError.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant E2ETest
  participant OpenAIClient
  participant TokenSpeedWorker
  E2ETest->>OpenAIClient: submit audio transcription request
  OpenAIClient->>TokenSpeedWorker: send model, WAV, and options
  TokenSpeedWorker-->>OpenAIClient: return text or HTTP 400
  OpenAIClient-->>E2ETest: expose response or BadRequestError
Loading

Suggested reviewers: catherinesue, key4ng, xinyuezhang369

Poem

I’m a rabbit with a WAV in my ear,
Qwen3-ASR makes the words appear.
Text flows plain, errors hop,
TokenSpeed tests never stop.
Thump, thump—coverage is here!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR covers JSON, plain-text, and unsupported-language cases, but it does not add the required streaming rejection test from #1909. Add an e2e case asserting /v1/audio/transcriptions rejects streaming with HTTP 400, alongside the existing transcription tests.
✅ Passed checks (4 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed The new test module stays within the transcription e2e scope and matches the issue objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: new e2e TokenSpeed coverage for Qwen3-ASR audio transcription.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/e2e-tokenspeed-audio-transcription

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces end-to-end tests for audio transcription using the TokenSpeed Qwen3-ASR worker. The feedback suggests explicitly passing the filename and MIME type as a tuple to the transcription client to ensure reliable multipart request formatting, and adding assertions on the error message in the unsupported language test to verify the failure reason.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +44 to +50
with AUDIO_WAV.open("rb") as audio:
result = api_client.audio.transcriptions.create(
model=model,
file=audio,
language="en",
temperature=0.0,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Passing a raw file object to api_client.audio.transcriptions.create relies on the client library correctly guessing the filename and MIME type from the file descriptor. To prevent potential issues with MIME type detection or missing filenames in the multipart payload, it is safer to explicitly pass a tuple containing the filename, file object, and content type.

Suggested change
with AUDIO_WAV.open("rb") as audio:
result = api_client.audio.transcriptions.create(
model=model,
file=audio,
language="en",
temperature=0.0,
)
with AUDIO_WAV.open("rb") as audio:
result = api_client.audio.transcriptions.create(
model=model,
file=(AUDIO_WAV.name, audio, "audio/wav"),
language="en",
temperature=0.0,
)

Comment on lines +61 to +66
with AUDIO_WAV.open("rb") as audio:
result = api_client.audio.transcriptions.create(
model=model,
file=audio,
response_format="text",
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Explicitly pass the filename and MIME type as a tuple to ensure the multipart request is correctly formatted and the backend can properly identify the audio format.

Suggested change
with AUDIO_WAV.open("rb") as audio:
result = api_client.audio.transcriptions.create(
model=model,
file=audio,
response_format="text",
)
with AUDIO_WAV.open("rb") as audio:
result = api_client.audio.transcriptions.create(
model=model,
file=(AUDIO_WAV.name, audio, "audio/wav"),
response_format="text",
)

Comment on lines +76 to +82
with AUDIO_WAV.open("rb") as audio:
with pytest.raises(openai.BadRequestError):
api_client.audio.transcriptions.create(
model=model,
file=audio,
language="zz",
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In addition to passing the explicit file tuple, it is highly recommended to assert on the error message returned by the API. This ensures that the test fails if a BadRequestError is raised for an unrelated reason (e.g., a malformed request structure or invalid model name) rather than the expected unsupported language error.

Suggested change
with AUDIO_WAV.open("rb") as audio:
with pytest.raises(openai.BadRequestError):
api_client.audio.transcriptions.create(
model=model,
file=audio,
language="zz",
)
with AUDIO_WAV.open("rb") as audio:
with pytest.raises(openai.BadRequestError) as exc_info:
api_client.audio.transcriptions.create(
model=model,
file=(AUDIO_WAV.name, audio, "audio/wav"),
language="zz",
)
assert "language" in str(exc_info.value).lower()

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean e2e test addition. Follows existing test patterns (markers, fixtures, parametrize), fixture file exists, good coverage of happy path + response format variant + error rejection. No issues found.

@github-actions

Copy link
Copy Markdown

This pull request has been automatically marked as stale because it has not had any activity within 14 days. It will be automatically closed if no further activity occurs within 16 days. Leave a comment if you feel this pull request should remain open. Thank you!

@github-actions github-actions Bot added the stale PR has been inactive for 14+ days label Jul 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale PR has been inactive for 14+ days tests Test changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant