spring-projects / spring-projects/spring-ai
OpenAI Audio: JSON transcription responses discard non-text metadata
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 9.5k
- Forks
- 2.9k
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 5
Description
Bug description
The AudioTranscriptionResponse or AudioTranscription implementation discards valuable JSON metadata (language, segments, duration, etc.) from OpenAI's audio transcription API responses. When responseFormat.isJsonType() is true, only the text field is preserved , despite the API returning structured JSON containing additional fields. This violates the principle of least surprise since users explicitly requesting JSON format expect full structured data.
Environment
- Spring AI version: 1.1.0-SNAPSHOT (current main branch)
- Java version: 21
- Model Provider: OpenAI
- Relevant classes:
AudioTranscriptionResponse,AudioTranscription,AudioTranscriptionMetadata
Steps to reproduce
- Configure audio transcription with JSON response format:
spring.ai.openai.audio.options.response-format=verbose_json - Transcribe audio containing metadata (e.g., segments/timestamps)
- Inspect
AudioTranscriptionResponse:AudioTranscriptionResponse response = client.call(prompt); response.getResults().get(0); // Only contains text response.getMetadata(); // Empty, lacks JSON body fields
Expected behavior
- Full JSON response should be accessible in metadata
AudioTranscriptionshould include:class AudioTranscription( // not sure if this should be a JSON String // maybe nullable(or empty) fields such as segments and words in `AudioTranscription` or `AudioTranscriptionResponse` might work private final String text; private AudioTranscriptionMetadata transcriptionMetadata; ) {}- Backward compatibility maintained for non-JSON responses
Minimal Complete Reproducible example
@Test
void shouldReturnFullJsonMetadata() {
OpenAiAudioTranscriptionOptions transcriptionOptions = OpenAiAudioTranscriptionOptions.builder()
.responseFormat(TranscriptResponseFormat.VERBOSE_JSON)
.temperature(0f)
.build();
AudioTranscriptionPrompt transcriptionRequest = new AudioTranscriptionPrompt(this.audioFile,
transcriptionOptions);
AudioTranscriptionResponse response = this.transcriptionModel.call(transcriptionRequest);
assertThat(response.getResults()).hasSize(1);
// this fails
assertThat(response.getResults().get(0))
.isEqualTo(new AudioTranscription("[{\"id\":0,\"seek\":0,\"start\":0.0,\"end\":11.0,\"text\":\"And so my fellow Americans, ask not what your country can do for you, ask what you can do for your country.\",\"tokens\":[50364,400,370,452,7177,6280,11,1029,406,437,428,1941,393,360,337,291,11,1029,437,291,393,360,337,428,1941,13,50914],\"temperature\":0.0,\"avgLogprob\":-0.3053564,\"compressionRatio\":1.3544304,\"noSpeechProb\":0.03939722}]"));
// or maybe metadata should not be empty?
assertThat(response.getMetadata().isEmpty()).isTrue();
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading AudioTranscriptionResponse, AudioTranscription, and AudioTranscriptionMetadata, then run the provided shouldReturnFullJsonMetadata reproducer with verbose_json. The change is done when full JSON metadata is accessible for JSON responses while non-JSON transcription behavior remains backward compatible.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100