From 1834264c7f26e6edd1f2f107d6b825f886f6ba53 Mon Sep 17 00:00:00 2001 From: Alexandros Pappas Date: Thu, 23 Jan 2025 14:26:48 +0100 Subject: [PATCH] Refactor OpenAIAudio builder methods - Refactor the builder methods to remove `with` as the prefix. - Introduce new methods with updated naming conventions. - Deprecate the existing `with*` methods to maintain backward compatibility. Signed-off-by: Alexandros Pappas --- .../ai/openai/OpenAiAudioSpeechModel.java | 10 +- .../openai/OpenAiAudioTranscriptionModel.java | 14 +- .../ai/openai/api/OpenAiAudioApi.java | 153 ++++++++++++++++++ .../ai/openai/audio/api/OpenAiAudioApiIT.java | 17 +- .../pages/api/audio/speech/openai-speech.adoc | 8 +- .../transcriptions/openai-transcriptions.adoc | 12 +- 6 files changed, 184 insertions(+), 30 deletions(-) diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioSpeechModel.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioSpeechModel.java index 3dc15d40df6..baf772ed4e7 100644 --- a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioSpeechModel.java +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioSpeechModel.java @@ -177,11 +177,11 @@ private OpenAiAudioApi.SpeechRequest createRequest(SpeechPrompt request) { : request.getInstructions().getText(); OpenAiAudioApi.SpeechRequest.Builder requestBuilder = OpenAiAudioApi.SpeechRequest.builder() - .withModel(options.getModel()) - .withInput(input) - .withVoice(options.getVoice()) - .withResponseFormat(options.getResponseFormat()) - .withSpeed(options.getSpeed()); + .model(options.getModel()) + .input(input) + .voice(options.getVoice()) + .responseFormat(options.getResponseFormat()) + .speed(options.getSpeed()); return requestBuilder.build(); } diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioTranscriptionModel.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioTranscriptionModel.java index 3d5768eaf7e..4c7bb105648 100644 --- a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioTranscriptionModel.java +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioTranscriptionModel.java @@ -168,13 +168,13 @@ OpenAiAudioApi.TranscriptionRequest createRequest(AudioTranscriptionPrompt trans } return OpenAiAudioApi.TranscriptionRequest.builder() - .withFile(toBytes(transcriptionPrompt.getInstructions())) - .withResponseFormat(options.getResponseFormat()) - .withPrompt(options.getPrompt()) - .withTemperature(options.getTemperature()) - .withLanguage(options.getLanguage()) - .withModel(options.getModel()) - .withGranularityType(options.getGranularityType()) + .file(toBytes(transcriptionPrompt.getInstructions())) + .responseFormat(options.getResponseFormat()) + .prompt(options.getPrompt()) + .temperature(options.getTemperature()) + .language(options.getLanguage()) + .model(options.getModel()) + .granularityType(options.getGranularityType()) .build(); } diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiAudioApi.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiAudioApi.java index eb2196a82c0..1f4ca2a590d 100644 --- a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiAudioApi.java +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiAudioApi.java @@ -457,31 +457,76 @@ public static class Builder { private Float speed; + /** + * @deprecated use {@link #model(String)} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withModel(String model) { this.model = model; return this; } + public Builder model(String model) { + this.model = model; + return this; + } + + /** + * @deprecated use {@link #input(String)} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withInput(String input) { this.input = input; return this; } + public Builder input(String input) { + this.input = input; + return this; + } + + /** + * @deprecated use {@link #voice(Voice)} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withVoice(Voice voice) { this.voice = voice; return this; } + public Builder voice(Voice voice) { + this.voice = voice; + return this; + } + + /** + * @deprecated use {@link #responseFormat(AudioResponseFormat)} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withResponseFormat(AudioResponseFormat responseFormat) { this.responseFormat = responseFormat; return this; } + public Builder responseFormat(AudioResponseFormat responseFormat) { + this.responseFormat = responseFormat; + return this; + } + + /** + * @deprecated use {@link #speed(Float)} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withSpeed(Float speed) { this.speed = speed; return this; } + public Builder speed(Float speed) { + this.speed = speed; + return this; + } + public SpeechRequest build() { Assert.hasText(this.model, "model must not be empty"); Assert.hasText(this.input, "input must not be empty"); @@ -569,41 +614,104 @@ public static class Builder { private GranularityType granularityType; + /** + * @deprecated use {@link #file(byte[])} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withFile(byte[] file) { this.file = file; return this; } + public Builder file(byte[] file) { + this.file = file; + return this; + } + + /** + * @deprecated use {@link #model(String)} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withModel(String model) { this.model = model; return this; } + public Builder model(String model) { + this.model = model; + return this; + } + + /** + * @deprecated use {@link #language(String)} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withLanguage(String language) { this.language = language; return this; } + public Builder language(String language) { + this.language = language; + return this; + } + + /** + * @deprecated use {@link #prompt(String)} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withPrompt(String prompt) { this.prompt = prompt; return this; } + public Builder prompt(String prompt) { + this.prompt = prompt; + return this; + } + + /** + * @deprecated use {@link #responseFormat(TranscriptResponseFormat)} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withResponseFormat(TranscriptResponseFormat response_format) { this.responseFormat = response_format; return this; } + public Builder responseFormat(TranscriptResponseFormat responseFormat) { + this.responseFormat = responseFormat; + return this; + } + + /** + * @deprecated use {@link #temperature(Float)} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withTemperature(Float temperature) { this.temperature = temperature; return this; } + public Builder temperature(Float temperature) { + this.temperature = temperature; + return this; + } + + /** + * @deprecated use {@link #granularityType(GranularityType)} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withGranularityType(GranularityType granularityType) { this.granularityType = granularityType; return this; } + public Builder granularityType(GranularityType granularityType) { + this.granularityType = granularityType; + return this; + } + public TranscriptionRequest build() { Assert.notNull(this.file, "file must not be null"); Assert.hasText(this.model, "model must not be empty"); @@ -658,31 +766,76 @@ public static class Builder { private Float temperature; + /** + * @deprecated use {@link #file(byte[])} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withFile(byte[] file) { this.file = file; return this; } + public Builder file(byte[] file) { + this.file = file; + return this; + } + + /** + * @deprecated use {@link #model(String)} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withModel(String model) { this.model = model; return this; } + public Builder model(String model) { + this.model = model; + return this; + } + + /** + * @deprecated use {@link #prompt(String)} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withPrompt(String prompt) { this.prompt = prompt; return this; } + public Builder prompt(String prompt) { + this.prompt = prompt; + return this; + } + + /** + * @deprecated use {@link #responseFormat(TranscriptResponseFormat)} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withResponseFormat(TranscriptResponseFormat responseFormat) { this.responseFormat = responseFormat; return this; } + public Builder responseFormat(TranscriptResponseFormat responseFormat) { + this.responseFormat = responseFormat; + return this; + } + + /** + * @deprecated use {@link #temperature(Float)} instead. + */ + @Deprecated(forRemoval = true, since = "1.0.0-M6") public Builder withTemperature(Float temperature) { this.temperature = temperature; return this; } + public Builder temperature(Float temperature) { + this.temperature = temperature; + return this; + } + public TranslationRequest build() { Assert.notNull(this.file, "file must not be null"); Assert.hasText(this.model, "model must not be empty"); diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/api/OpenAiAudioApiIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/api/OpenAiAudioApiIT.java index a5c4123a912..9f7d9681ae4 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/api/OpenAiAudioApiIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/api/OpenAiAudioApiIT.java @@ -48,9 +48,9 @@ void speechTranscriptionAndTranslation() throws IOException { byte[] speech = this.audioApi .createSpeech(SpeechRequest.builder() - .withModel(TtsModel.TTS_1_HD.getValue()) - .withInput("Hello, my name is Chris and I love Spring A.I.") - .withVoice(Voice.ONYX) + .model(TtsModel.TTS_1_HD.getValue()) + .input("Hello, my name is Chris and I love Spring A.I.") + .voice(Voice.ONYX) .build()) .getBody(); @@ -60,22 +60,23 @@ void speechTranscriptionAndTranslation() throws IOException { StructuredResponse translation = this.audioApi .createTranslation( - TranslationRequest.builder().withModel(WhisperModel.WHISPER_1.getValue()).withFile(speech).build(), + TranslationRequest.builder().model(WhisperModel.WHISPER_1.getValue()).file(speech).build(), StructuredResponse.class) .getBody(); assertThat(translation.text().replaceAll(",", "")).isEqualTo("Hello my name is Chris and I love Spring AI."); - StructuredResponse transcriptionEnglish = this.audioApi.createTranscription( - TranscriptionRequest.builder().withModel(WhisperModel.WHISPER_1.getValue()).withFile(speech).build(), - StructuredResponse.class) + StructuredResponse transcriptionEnglish = this.audioApi + .createTranscription( + TranscriptionRequest.builder().model(WhisperModel.WHISPER_1.getValue()).file(speech).build(), + StructuredResponse.class) .getBody(); assertThat(transcriptionEnglish.text().replaceAll(",", "")) .isEqualTo("Hello my name is Chris and I love Spring AI."); StructuredResponse transcriptionDutch = this.audioApi - .createTranscription(TranscriptionRequest.builder().withFile(speech).withLanguage("nl").build(), + .createTranscription(TranscriptionRequest.builder().file(speech).language("nl").build(), StructuredResponse.class) .getBody(); diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/audio/speech/openai-speech.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/audio/speech/openai-speech.adoc index 56858824a9a..a72107b08f6 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/audio/speech/openai-speech.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/audio/speech/openai-speech.adoc @@ -156,10 +156,10 @@ var openAiAudioApi = new OpenAiAudioApi(System.getenv("OPENAI_API_KEY")); var openAiAudioSpeechModel = new OpenAiAudioSpeechModel(this.openAiAudioApi); OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder() - .withVoice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY) - .withSpeed(1.0f) - .withResponseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3) - .withModel(OpenAiAudioApi.TtsModel.TTS_1.value) + .voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY) + .speed(1.0f) + .responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3) + .model(OpenAiAudioApi.TtsModel.TTS_1.value) .build(); SpeechPrompt speechPrompt = new SpeechPrompt("Today is a wonderful day to build something people love!", this.speechOptions); diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/audio/transcriptions/openai-transcriptions.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/audio/transcriptions/openai-transcriptions.adoc index da3119376df..fa93772064f 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/audio/transcriptions/openai-transcriptions.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/audio/transcriptions/openai-transcriptions.adoc @@ -91,10 +91,10 @@ For example: OpenAiAudioApi.TranscriptResponseFormat responseFormat = OpenAiAudioApi.TranscriptResponseFormat.VTT; OpenAiAudioTranscriptionOptions transcriptionOptions = OpenAiAudioTranscriptionOptions.builder() - .withLanguage("en") - .withPrompt("Ask not this, but ask that") - .withTemperature(0f) - .withResponseFormat(this.responseFormat) + .language("en") + .prompt("Ask not this, but ask that") + .temperature(0f) + .responseFormat(this.responseFormat) .build(); AudioTranscriptionPrompt transcriptionRequest = new AudioTranscriptionPrompt(audioFile, this.transcriptionOptions); AudioTranscriptionResponse response = openAiTranscriptionModel.call(this.transcriptionRequest); @@ -132,8 +132,8 @@ var openAiAudioApi = new OpenAiAudioApi(System.getenv("OPENAI_API_KEY")); var openAiAudioTranscriptionModel = new OpenAiAudioTranscriptionModel(this.openAiAudioApi); var transcriptionOptions = OpenAiAudioTranscriptionOptions.builder() - .withResponseFormat(TranscriptResponseFormat.TEXT) - .withTemperature(0f) + .responseFormat(TranscriptResponseFormat.TEXT) + .temperature(0f) .build(); var audioFile = new FileSystemResource("/path/to/your/resource/speech/jfk.flac");