openai/openai-dotnet

Public

mirrored from https://github.com/openai/openai-dotnetAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
OpenAI_2.2.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/Custom/Audio/AudioClient.cs

412lines · modecode

1using System;
2using System.ClientModel;
3using System.ClientModel.Primitives;
4using System.Collections.Generic;
5using System.Diagnostics.CodeAnalysis;
6using System.IO;
7using System.Threading;
8using System.Threading.Tasks;
9
10namespace OpenAI.Audio;
11
12// CUSTOM:
13// - Renamed.
14// - Suppressed constructor that takes endpoint parameter; endpoint is now a property in the options class.
15// - Suppressed methods that only take the options parameter.
16/// <summary> The service client for OpenAI audio operations. </summary>
17[CodeGenType("Audio")]
18[CodeGenSuppress("AudioClient", typeof(ClientPipeline), typeof(Uri))]
19[CodeGenSuppress("CreateSpeechAsync", typeof(SpeechGenerationOptions), typeof(CancellationToken))]
20[CodeGenSuppress("CreateSpeech", typeof(SpeechGenerationOptions), typeof(CancellationToken))]
21public partial class AudioClient
22{
23 private readonly string _model;
24
25 // CUSTOM: Added as a convenience.
26 /// <summary> Initializes a new instance of <see cref="AudioClient"/>. </summary>
27 /// <param name="model"> The name of the model to use in requests sent to the service. To learn more about the available models, see <see href="https://platform.openai.com/docs/models"/>. </param>
28 /// <param name="apiKey"> The API key to authenticate with the service. </param>
29 /// <exception cref="ArgumentNullException"> <paramref name="model"/> or <paramref name="apiKey"/> is null. </exception>
30 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
31 public AudioClient(string model, string apiKey) : this(model, new ApiKeyCredential(apiKey), new OpenAIClientOptions())
32 {
33 }
34
35 // CUSTOM:
36 // - Added `model` parameter.
37 // - Used a custom pipeline.
38 // - Demoted the endpoint parameter to be a property in the options class.
39 /// <summary> Initializes a new instance of <see cref="AudioClient"/>. </summary>
40 /// <param name="model"> The name of the model to use in requests sent to the service. To learn more about the available models, see <see href="https://platform.openai.com/docs/models"/>. </param>
41 /// <param name="credential"> The API key to authenticate with the service. </param>
42 /// <exception cref="ArgumentNullException"> <paramref name="model"/> or <paramref name="credential"/> is null. </exception>
43 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
44 public AudioClient(string model, ApiKeyCredential credential) : this(model, credential, new OpenAIClientOptions())
45 {
46 }
47
48 // CUSTOM:
49 // - Added `model` parameter.
50 // - Used a custom pipeline.
51 // - Demoted the endpoint parameter to be a property in the options class.
52 /// <summary> Initializes a new instance of <see cref="AudioClient"/>. </summary>
53 /// <param name="model"> The name of the model to use in requests sent to the service. To learn more about the available models, see <see href="https://platform.openai.com/docs/models"/>. </param>
54 /// <param name="credential"> The API key to authenticate with the service. </param>
55 /// <param name="options"> The options to configure the client. </param>
56 /// <exception cref="ArgumentNullException"> <paramref name="model"/> or <paramref name="credential"/> is null. </exception>
57 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
58 public AudioClient(string model, ApiKeyCredential credential, OpenAIClientOptions options)
59 {
60 Argument.AssertNotNullOrEmpty(model, nameof(model));
61 Argument.AssertNotNull(credential, nameof(credential));
62 options ??= new OpenAIClientOptions();
63
64 _model = model;
65 Pipeline = OpenAIClient.CreatePipeline(credential, options);
66 _endpoint = OpenAIClient.GetEndpoint(options);
67 }
68
69 // CUSTOM:
70 // - Added `model` parameter.
71 // - Used a custom pipeline.
72 // - Demoted the endpoint parameter to be a property in the options class.
73 // - Made protected.
74 /// <summary> Initializes a new instance of <see cref="AudioClient"/>. </summary>
75 /// <param name="pipeline"> The HTTP pipeline to send and receive REST requests and responses. </param>
76 /// <param name="model"> The name of the model to use in requests sent to the service. To learn more about the available models, see <see href="https://platform.openai.com/docs/models"/>. </param>
77 /// <param name="options"> The options to configure the client. </param>
78 /// <exception cref="ArgumentNullException"> <paramref name="pipeline"/> or <paramref name="model"/> is null. </exception>
79 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
80 protected internal AudioClient(ClientPipeline pipeline, string model, OpenAIClientOptions options)
81 {
82 Argument.AssertNotNull(pipeline, nameof(pipeline));
83 Argument.AssertNotNullOrEmpty(model, nameof(model));
84 options ??= new OpenAIClientOptions();
85
86 _model = model;
87 Pipeline = pipeline;
88 _endpoint = OpenAIClient.GetEndpoint(options);
89 }
90
91 #region GenerateSpeech
92
93 /// <summary> Generates a life-like, spoken audio recording of the input text. </summary>
94 /// <remarks>
95 /// The default format of the generated audio is <see cref="GeneratedSpeechFormat.Mp3"/> unless otherwise specified
96 /// via <see cref="SpeechGenerationOptions.ResponseFormat"/>.
97 /// </remarks>
98 /// <param name="text"> The text to generate audio for. </param>
99 /// <param name="voice"> The voice to use in the generated audio. </param>
100 /// <param name="options"> The options to configure the audio generation. </param>
101 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
102 /// <exception cref="ArgumentNullException"> <paramref name="text"/> is null. </exception>
103 /// <returns> The generated audio in the specified output format. </returns>
104 public virtual async Task<ClientResult<BinaryData>> GenerateSpeechAsync(string text, GeneratedSpeechVoice voice, SpeechGenerationOptions options = null, CancellationToken cancellationToken = default)
105 {
106 Argument.AssertNotNull(text, nameof(text));
107
108 options ??= new();
109 CreateSpeechGenerationOptions(text, voice, ref options);
110
111 using BinaryContent content = options.ToBinaryContent();
112 ClientResult result = await GenerateSpeechAsync(content, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
113 return ClientResult.FromValue(result.GetRawResponse().Content, result.GetRawResponse());
114 }
115
116 /// <summary> Generates a life-like, spoken audio recording of the input text. </summary>
117 /// <remarks>
118 /// The default format of the generated audio is <see cref="GeneratedSpeechFormat.Mp3"/> unless otherwise specified
119 /// via <see cref="SpeechGenerationOptions.ResponseFormat"/>.
120 /// </remarks>
121 /// <param name="text"> The text to generate audio for. </param>
122 /// <param name="voice"> The voice to use in the generated audio. </param>
123 /// <param name="options"> The options to configure the audio generation. </param>
124 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
125 /// <exception cref="ArgumentNullException"> <paramref name="text"/> is null. </exception>
126 /// <returns> The generated audio in the specified output format. </returns>
127 public virtual ClientResult<BinaryData> GenerateSpeech(string text, GeneratedSpeechVoice voice, SpeechGenerationOptions options = null, CancellationToken cancellationToken = default)
128 {
129 Argument.AssertNotNull(text, nameof(text));
130
131 options ??= new();
132 CreateSpeechGenerationOptions(text, voice, ref options);
133
134 using BinaryContent content = options.ToBinaryContent();
135 ClientResult result = GenerateSpeech(content, cancellationToken.ToRequestOptions()); ;
136 return ClientResult.FromValue(result.GetRawResponse().Content, result.GetRawResponse());
137 }
138
139 #endregion
140
141 #region TranscribeAudio
142
143 /// <summary> Transcribes the input audio. </summary>
144 /// <param name="audio"> The audio stream to transcribe. </param>
145 /// <param name="audioFilename">
146 /// The filename associated with the audio stream. The filename's extension (for example: .mp3) will be used to
147 /// validate the format of the input audio. The request may fail if the filename's extension and the actual
148 /// format of the input audio do not match.
149 /// </param>
150 /// <param name="options"> The options to configure the audio transcription. </param>
151 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
152 /// <exception cref="ArgumentNullException"> <paramref name="audio"/> or <paramref name="audioFilename"/> is null. </exception>
153 /// <exception cref="ArgumentException"> <paramref name="audioFilename"/> is an empty string, and was expected to be non-empty. </exception>
154 public virtual async Task<ClientResult<AudioTranscription>> TranscribeAudioAsync(Stream audio, string audioFilename, AudioTranscriptionOptions options = null, CancellationToken cancellationToken = default)
155 {
156 Argument.AssertNotNull(audio, nameof(audio));
157 Argument.AssertNotNullOrEmpty(audioFilename, nameof(audioFilename));
158
159 using MultiPartFormDataBinaryContent content
160 = CreatePerCallTranscriptionOptions(options)
161 .ToMultipartContent(audio, audioFilename);
162
163 ClientResult result = await TranscribeAudioAsync(content, content.ContentType, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
164 return ClientResult.FromValue(AudioTranscription.FromResponse(result.GetRawResponse()), result.GetRawResponse());
165 }
166
167 /// <summary> Transcribes the input audio. </summary>
168 /// <param name="audio"> The audio stream to transcribe. </param>
169 /// <param name="audioFilename">
170 /// The filename associated with the audio stream. The filename's extension (for example: .mp3) will be used to
171 /// validate the format of the input audio. The request may fail if the filename's extension and the actual
172 /// format of the input audio do not match.
173 /// </param>
174 /// <param name="options"> The options to configure the audio transcription. </param>
175 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
176 /// <exception cref="ArgumentNullException"> <paramref name="audio"/> or <paramref name="audioFilename"/> is null. </exception>
177 /// <exception cref="ArgumentException"> <paramref name="audioFilename"/> is an empty string, and was expected to be non-empty. </exception>
178 public virtual ClientResult<AudioTranscription> TranscribeAudio(Stream audio, string audioFilename, AudioTranscriptionOptions options = null, CancellationToken cancellationToken = default)
179 {
180 Argument.AssertNotNull(audio, nameof(audio));
181 Argument.AssertNotNullOrEmpty(audioFilename, nameof(audioFilename));
182
183 using MultiPartFormDataBinaryContent content
184 = CreatePerCallTranscriptionOptions(options)
185 .ToMultipartContent(audio, audioFilename);
186
187 ClientResult result = TranscribeAudio(content, content.ContentType, cancellationToken.ToRequestOptions());
188 return ClientResult.FromValue(AudioTranscription.FromResponse(result.GetRawResponse()), result.GetRawResponse());
189 }
190
191 /// <summary> Transcribes the input audio. </summary>
192 /// <param name="audioFilePath">
193 /// The path of the audio file to transcribe. The provided file path's extension (for example: .mp3) will be
194 /// used to validate the format of the input audio. The request may fail if the file path's extension and the
195 /// actual format of the input audio do not match.
196 /// </param>
197 /// <param name="options"> The options to configure the audio transcription. </param>
198 /// <exception cref="ArgumentNullException"> <paramref name="audioFilePath"/> is null. </exception>
199 /// <exception cref="ArgumentException"> <paramref name="audioFilePath"/> is an empty string, and was expected to be non-empty. </exception>
200 public virtual async Task<ClientResult<AudioTranscription>> TranscribeAudioAsync(string audioFilePath, AudioTranscriptionOptions options = null)
201 {
202 Argument.AssertNotNullOrEmpty(audioFilePath, nameof(audioFilePath));
203
204 using FileStream audioStream = File.OpenRead(audioFilePath);
205 return await TranscribeAudioAsync(audioStream, audioFilePath, options).ConfigureAwait(false);
206 }
207
208 /// <summary> Transcribes the input audio. </summary>
209 /// <param name="audioFilePath">
210 /// The path of the audio file to transcribe. The provided file path's extension (for example: .mp3) will be
211 /// used to validate the format of the input audio. The request may fail if the file path's extension and the
212 /// actual format of the input audio do not match.
213 /// </param>
214 /// <param name="options"> The options to configure the audio transcription. </param>
215 /// <exception cref="ArgumentNullException"> <paramref name="audioFilePath"/> is null. </exception>
216 /// <exception cref="ArgumentException"> <paramref name="audioFilePath"/> is an empty string, and was expected to be non-empty. </exception>
217 public virtual ClientResult<AudioTranscription> TranscribeAudio(string audioFilePath, AudioTranscriptionOptions options = null)
218 {
219 Argument.AssertNotNullOrEmpty(audioFilePath, nameof(audioFilePath));
220
221 using FileStream audioStream = File.OpenRead(audioFilePath);
222 return TranscribeAudio(audioStream, audioFilePath, options);
223 }
224
225 // CUSTOM: Added Experimental attribute.
226 [Experimental("OPENAI001")]
227 public virtual AsyncCollectionResult<StreamingAudioTranscriptionUpdate> TranscribeAudioStreamingAsync(Stream audio, string audioFilename, AudioTranscriptionOptions options = null, CancellationToken cancellationToken = default)
228 {
229 Argument.AssertNotNull(audio, nameof(audio));
230 Argument.AssertNotNullOrEmpty(audioFilename, nameof(audioFilename));
231
232 MultiPartFormDataBinaryContent content
233 = CreatePerCallTranscriptionOptions(options, stream: true)
234 .ToMultipartContent(audio, audioFilename);
235
236 return new AsyncSseUpdateCollection<StreamingAudioTranscriptionUpdate>(
237 async () => await TranscribeAudioAsync(content, content.ContentType, cancellationToken.ToRequestOptions(streaming: true)).ConfigureAwait(false),
238 StreamingAudioTranscriptionUpdate.DeserializeStreamingAudioTranscriptionUpdate,
239 cancellationToken);
240 }
241
242 // CUSTOM: Added Experimental attribute.
243 [Experimental("OPENAI001")]
244 public virtual AsyncCollectionResult<StreamingAudioTranscriptionUpdate> TranscribeAudioStreamingAsync(string audioFilePath, AudioTranscriptionOptions options = null, CancellationToken cancellationToken = default)
245 {
246 Argument.AssertNotNullOrEmpty(audioFilePath, nameof(audioFilePath));
247
248 FileStream inputStream = File.OpenRead(audioFilePath);
249
250 MultiPartFormDataBinaryContent content
251 = CreatePerCallTranscriptionOptions(options, stream: true)
252 .ToMultipartContent(inputStream, audioFilePath);
253
254 AsyncSseUpdateCollection<StreamingAudioTranscriptionUpdate> result = new(
255 async () => await TranscribeAudioAsync(content, content.ContentType, cancellationToken.ToRequestOptions(streaming: true)).ConfigureAwait(false),
256 StreamingAudioTranscriptionUpdate.DeserializeStreamingAudioTranscriptionUpdate,
257 cancellationToken);
258 result.AdditionalDisposalActions.Add(() => inputStream?.Dispose());
259 return result;
260 }
261
262 // CUSTOM: Added Experimental attribute.
263 [Experimental("OPENAI001")]
264 public virtual CollectionResult<StreamingAudioTranscriptionUpdate> TranscribeAudioStreaming(Stream audio, string audioFilename, AudioTranscriptionOptions options = null, CancellationToken cancellationToken = default)
265 {
266 Argument.AssertNotNull(audio, nameof(audio));
267 Argument.AssertNotNullOrEmpty(audioFilename, nameof(audioFilename));
268
269 MultiPartFormDataBinaryContent content
270 = CreatePerCallTranscriptionOptions(options, stream: true)
271 .ToMultipartContent(audio, audioFilename);
272
273 return new SseUpdateCollection<StreamingAudioTranscriptionUpdate>(
274 () => TranscribeAudio(content, content.ContentType, cancellationToken.ToRequestOptions(streaming: true)),
275 StreamingAudioTranscriptionUpdate.DeserializeStreamingAudioTranscriptionUpdate,
276 cancellationToken);
277 }
278
279 // CUSTOM: Added Experimental attribute.
280 [Experimental("OPENAI001")]
281 public virtual CollectionResult<StreamingAudioTranscriptionUpdate> TranscribeAudioStreaming(string audioFilePath, AudioTranscriptionOptions options = null, CancellationToken cancellationToken = default)
282 {
283 Argument.AssertNotNullOrEmpty(audioFilePath, nameof(audioFilePath));
284
285 FileStream inputStream = File.OpenRead(audioFilePath);
286
287 MultiPartFormDataBinaryContent content
288 = CreatePerCallTranscriptionOptions(options, stream: true)
289 .ToMultipartContent(inputStream, audioFilePath);
290
291 SseUpdateCollection<StreamingAudioTranscriptionUpdate> result = new(
292 () => TranscribeAudio(content, content.ContentType, cancellationToken.ToRequestOptions(streaming: true)),
293 StreamingAudioTranscriptionUpdate.DeserializeStreamingAudioTranscriptionUpdate,
294 cancellationToken);
295 result.AdditionalDisposalActions.Add(() => inputStream?.Dispose());
296 return result;
297 }
298
299 #endregion
300
301 #region TranslateAudio
302
303 /// <summary> Translates the input audio into English. </summary>
304 /// <param name="audio"> The audio stream to translate. </param>
305 /// <param name="audioFilename">
306 /// The filename associated with the audio stream. The filename's extension (for example: .mp3) will be used to
307 /// validate the format of the input audio. The request may fail if the filename's extension and the actual
308 /// format of the input audio do not match.
309 /// </param>
310 /// <param name="options"> The options to configure the audio translation. </param>
311 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
312 /// <exception cref="ArgumentNullException"> <paramref name="audio"/> or <paramref name="audioFilename"/> is null. </exception>
313 /// <exception cref="ArgumentException"> <paramref name="audioFilename"/> is an empty string, and was expected to be non-empty. </exception>
314 public virtual async Task<ClientResult<AudioTranslation>> TranslateAudioAsync(Stream audio, string audioFilename, AudioTranslationOptions options = null, CancellationToken cancellationToken = default)
315 {
316 Argument.AssertNotNull(audio, nameof(audio));
317 Argument.AssertNotNullOrEmpty(audioFilename, nameof(audioFilename));
318
319 options ??= new();
320 CreateAudioTranslationOptions(audio, audioFilename, ref options);
321
322 using MultiPartFormDataBinaryContent content = options.ToMultipartContent(audio, audioFilename);
323 ClientResult result = await TranslateAudioAsync(content, content.ContentType, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
324 return ClientResult.FromValue(AudioTranslation.FromResponse(result.GetRawResponse()), result.GetRawResponse());
325 }
326
327 /// <summary> Translates the input audio into English. </summary>
328 /// <param name="audio"> The audio stream to translate. </param>
329 /// <param name="audioFilename">
330 /// The filename associated with the audio stream. The filename's extension (for example: .mp3) will be used to
331 /// validate the format of the input audio. The request may fail if the filename's extension and the actual
332 /// format of the input audio do not match.
333 /// </param>
334 /// <param name="options"> The options to configure the audio translation. </param>
335 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
336 /// <exception cref="ArgumentNullException"> <paramref name="audio"/> or <paramref name="audioFilename"/> is null. </exception>
337 /// <exception cref="ArgumentException"> <paramref name="audioFilename"/> is an empty string, and was expected to be non-empty. </exception>
338 public virtual ClientResult<AudioTranslation> TranslateAudio(Stream audio, string audioFilename, AudioTranslationOptions options = null, CancellationToken cancellationToken = default)
339 {
340 Argument.AssertNotNull(audio, nameof(audio));
341 Argument.AssertNotNullOrEmpty(audioFilename, nameof(audioFilename));
342
343 options ??= new();
344 CreateAudioTranslationOptions(audio, audioFilename, ref options);
345
346 using MultiPartFormDataBinaryContent content = options.ToMultipartContent(audio, audioFilename);
347 ClientResult result = TranslateAudio(content, content.ContentType, cancellationToken.ToRequestOptions());
348 return ClientResult.FromValue(AudioTranslation.FromResponse(result.GetRawResponse()), result.GetRawResponse());
349 }
350
351 /// <summary> Translates the input audio into English. </summary>
352 /// <param name="audioFilePath">
353 /// The path of the audio file to translate. The provided file path's extension (for example: .mp3) will be
354 /// used to validate the format of the input audio. The request may fail if the file path's extension and the
355 /// actual format of the input audio do not match.
356 /// </param>
357 /// <param name="options"> The options to configure the audio translation. </param>
358 /// <exception cref="ArgumentNullException"> <paramref name="audioFilePath"/> was null. </exception>
359 /// <exception cref="ArgumentException"> <paramref name="audioFilePath"/> is an empty string, and was expected to be non-empty. </exception>
360 public virtual ClientResult<AudioTranslation> TranslateAudio(string audioFilePath, AudioTranslationOptions options = null)
361 {
362 Argument.AssertNotNullOrEmpty(audioFilePath, nameof(audioFilePath));
363
364 using FileStream audioStream = File.OpenRead(audioFilePath);
365 return TranslateAudio(audioStream, audioFilePath, options);
366 }
367
368 /// <summary> Translates the input audio into English. </summary>
369 /// <param name="audioFilePath">
370 /// The path of the audio file to translate. The provided file path's extension (for example: .mp3) will be
371 /// used to validate the format of the input audio. The request may fail if the file path's extension and the
372 /// actual format of the input audio do not match.
373 /// </param>
374 /// <param name="options"> The options to configure the audio translation. </param>
375 /// <exception cref="ArgumentNullException"> <paramref name="audioFilePath"/> was null. </exception>
376 /// <exception cref="ArgumentException"> <paramref name="audioFilePath"/> is an empty string, and was expected to be non-empty. </exception>
377 public virtual async Task<ClientResult<AudioTranslation>> TranslateAudioAsync(string audioFilePath, AudioTranslationOptions options = null)
378 {
379 Argument.AssertNotNull(audioFilePath, nameof(audioFilePath));
380
381 using FileStream audioStream = File.OpenRead(audioFilePath);
382 return await TranslateAudioAsync(audioStream, audioFilePath, options);
383 }
384
385 #endregion
386
387 private void CreateSpeechGenerationOptions(string text, GeneratedSpeechVoice voice, ref SpeechGenerationOptions options)
388 {
389 options.Input = text;
390 options.Voice = voice;
391 options.Model = _model;
392 }
393
394 internal virtual AudioTranscriptionOptions CreatePerCallTranscriptionOptions(AudioTranscriptionOptions userOptions, bool stream = false)
395 {
396 AudioTranscriptionOptions copiedOptions = userOptions is null ? new() : userOptions.GetClone();
397
398 copiedOptions.Model = _model;
399
400 if (stream)
401 {
402 copiedOptions.Stream = true;
403 }
404
405 return copiedOptions;
406 }
407
408 private void CreateAudioTranslationOptions(Stream audio, string audioFilename, ref AudioTranslationOptions options)
409 {
410 options.Model = _model;
411 }
412}