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

tests/Audio/TranscriptionTests.cs

325lines · modecode

1using NUnit.Framework;
2using OpenAI.Audio;
3using OpenAI.Tests.Utility;
4using System;
5using System.ClientModel;
6using System.ClientModel.Primitives;
7using System.Collections.Generic;
8using System.IO;
9using System.Text;
10using System.Threading.Tasks;
11using System.Transactions;
12using static OpenAI.Tests.TestHelpers;
13
14namespace OpenAI.Tests.Audio;
15
16[TestFixture(true)]
17[TestFixture(false)]
18[Parallelizable(ParallelScope.All)]
19[Category("Audio")]
20public partial class TranscriptionTests : SyncAsyncTestBase
21{
22 public TranscriptionTests(bool isAsync) : base(isAsync)
23 {
24 }
25
26 public enum AudioSourceKind
27 {
28 UsingStream,
29 UsingFilePath,
30 }
31
32 [Test]
33 [TestCase(AudioSourceKind.UsingStream)]
34 [TestCase(AudioSourceKind.UsingFilePath)]
35 public async Task TranscriptionWorks(AudioSourceKind audioSourceKind)
36 {
37 AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_Whisper);
38 string filename = "audio_hello_world.mp3";
39 string path = Path.Combine("Assets", filename);
40 AudioTranscription transcription = null;
41
42 if (audioSourceKind == AudioSourceKind.UsingStream)
43 {
44 using FileStream inputStream = File.OpenRead(path);
45
46 transcription = IsAsync
47 ? await client.TranscribeAudioAsync(inputStream, filename)
48 : client.TranscribeAudio(inputStream, filename);
49 }
50 else if (audioSourceKind == AudioSourceKind.UsingFilePath)
51 {
52 transcription = IsAsync
53 ? await client.TranscribeAudioAsync(path)
54 : client.TranscribeAudio(path);
55 }
56
57 Assert.That(transcription, Is.Not.Null);
58 Assert.That(transcription.Text.ToLowerInvariant(), Contains.Substring("hello"));
59 }
60
61 [Test]
62 [TestCase(AudioTimestampGranularities.Default)]
63 [TestCase(AudioTimestampGranularities.Word)]
64 [TestCase(AudioTimestampGranularities.Segment)]
65 [TestCase(AudioTimestampGranularities.Word | AudioTimestampGranularities.Segment)]
66 public async Task TimestampsWork(AudioTimestampGranularities granularityFlags)
67 {
68 AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_Whisper);
69
70 using FileStream inputStream = File.OpenRead(Path.Combine("Assets", "audio_hello_world.mp3"));
71
72 AudioTranscriptionOptions options = new()
73 {
74 ResponseFormat = AudioTranscriptionFormat.Verbose,
75 Temperature = 0.4f,
76 TimestampGranularities = granularityFlags,
77 };
78
79 ClientResult<AudioTranscription> transcriptionResult = IsAsync
80 ? await client.TranscribeAudioAsync(inputStream, "audio_hello_world.mp3", options)
81 : client.TranscribeAudio(inputStream, "audio_hello_world.mp3", options);
82
83 PipelineResponse rawResponse = transcriptionResult.GetRawResponse();
84 Assert.That(rawResponse.Content.ToString(), Is.Not.Null.And.Not.Empty);
85
86 AudioTranscription transcription = transcriptionResult;
87 Assert.That(transcription, Is.Not.Null);
88
89 IReadOnlyList<TranscribedWord> words = transcription.Words;
90 IReadOnlyList<TranscribedSegment> segments = transcription.Segments;
91
92 bool wordTimestampsPresent = words?.Count > 0;
93 bool segmentTimestampsPresent = segments?.Count > 0;
94
95 bool wordTimestampsExpected = granularityFlags.HasFlag(AudioTimestampGranularities.Word);
96 bool segmentTimestampsExpected = granularityFlags.HasFlag(AudioTimestampGranularities.Segment)
97 || granularityFlags == AudioTimestampGranularities.Default;
98
99 Assert.That(wordTimestampsPresent, Is.EqualTo(wordTimestampsExpected));
100 Assert.That(segmentTimestampsPresent, Is.EqualTo(segmentTimestampsExpected));
101
102 for (int i = 0; i < (words?.Count ?? 0); i++)
103 {
104 if (i > 0)
105 {
106 Assert.That(words[i].StartTime, Is.GreaterThanOrEqualTo(words[i - 1].EndTime));
107 }
108 Assert.That(words[i].EndTime, Is.GreaterThan(words[i].StartTime));
109 Assert.That(string.IsNullOrEmpty(words[i].Word), Is.False);
110 }
111
112 for (int i = 0; i < (segments?.Count ?? 0); i++)
113 {
114 if (i > 0)
115 {
116 Assert.That(segments[i].Id, Is.GreaterThan(segments[i - 1].Id));
117 Assert.That(segments[i].SeekOffset, Is.GreaterThan(0));
118 Assert.That(segments[i].StartTime, Is.GreaterThanOrEqualTo(segments[i - 1].EndTime));
119 }
120 Assert.That(segments[i].EndTime, Is.GreaterThan(segments[i].StartTime));
121 Assert.That(string.IsNullOrEmpty(segments[i].Text), Is.False);
122 Assert.That(segments[i].TokenIds.Span.Length, Is.GreaterThan(0));
123 foreach (int tokenId in segments[i].TokenIds.ToArray())
124 {
125 Assert.That(tokenId, Is.GreaterThanOrEqualTo(0));
126 }
127 Assert.That(segments[i].Temperature, Is.LessThan(-0.001f).Or.GreaterThan(0.001f));
128 Assert.That(segments[i].AverageLogProbability, Is.LessThan(-0.001f).Or.GreaterThan(0.001f));
129 Assert.That(segments[i].CompressionRatio, Is.LessThan(-0.001f).Or.GreaterThan(0.001f));
130 Assert.That(segments[i].NoSpeechProbability, Is.LessThan(-0.001f).Or.GreaterThan(0.001f));
131 }
132 }
133
134 [Test]
135 [TestCase("text")]
136 [TestCase("json")]
137 [TestCase("verbose_json")]
138 [TestCase("srt")]
139 [TestCase("vtt")]
140 [TestCase(null)]
141 public async Task TranscriptionFormatsWork(string responseFormat)
142 {
143 AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_Whisper);
144 string path = Path.Combine("Assets", "audio_hello_world.mp3");
145
146 AudioTranscriptionOptions options = new()
147 {
148 ResponseFormat = responseFormat switch
149 {
150 "text" => AudioTranscriptionFormat.Text,
151 "json" => AudioTranscriptionFormat.Simple,
152 "verbose_json" => AudioTranscriptionFormat.Verbose,
153 "srt" => AudioTranscriptionFormat.Srt,
154 "vtt" => AudioTranscriptionFormat.Vtt,
155 _ => (AudioTranscriptionFormat?)null
156 }
157 };
158
159 AudioTranscription transcription = IsAsync
160 ? await client.TranscribeAudioAsync(path, options)
161 : client.TranscribeAudio(path, options);
162
163 Assert.That(transcription?.Text?.ToLowerInvariant(), Does.Contain("hello"));
164
165
166 if (options.ResponseFormat == AudioTranscriptionFormat.Verbose)
167 {
168 Assert.That(transcription.Language, Is.EqualTo("english"));
169 Assert.That(transcription.Duration, Is.GreaterThan(TimeSpan.Zero));
170 Assert.That(transcription.Segments, Is.Not.Empty);
171
172 for (int i = 0; i < transcription.Segments.Count; i++)
173 {
174 TranscribedSegment segment = transcription.Segments[i];
175
176 if (i > 0)
177 {
178 Assert.That(segment.StartTime, Is.GreaterThanOrEqualTo(transcription.Segments[i - 1].EndTime));
179 }
180
181 Assert.That(segment.Id, Is.EqualTo(i));
182 Assert.That(segment.EndTime, Is.GreaterThanOrEqualTo(segment.StartTime));
183 Assert.That(segment.TokenIds, Is.Not.Null);
184 Assert.That(segment.TokenIds.Length, Is.GreaterThan(0));
185
186 Assert.That(segment.AverageLogProbability, Is.LessThan(-0.001f).Or.GreaterThan(0.001f));
187 Assert.That(segment.CompressionRatio, Is.LessThan(-0.001f).Or.GreaterThan(0.001f));
188 Assert.That(segment.NoSpeechProbability, Is.LessThan(-0.001f).Or.GreaterThan(0.001f));
189 }
190 }
191 else
192 {
193 Assert.That(transcription.Duration, Is.Null);
194 Assert.That(transcription.Language, Is.Null);
195 Assert.That(transcription.Segments, Is.Not.Null.And.Empty);
196 Assert.That(transcription.Words, Is.Not.Null.And.Empty);
197 }
198 }
199
200 [Test]
201 public async Task IncludesWork()
202 {
203 AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_Gpt_4o_Mini_Transcribe);
204 string filename = "audio_hello_world.mp3";
205 string path = Path.Combine("Assets", filename);
206
207 AudioTranscription transcription = await client.TranscribeAudioAsync(path, new AudioTranscriptionOptions()
208 {
209 Includes = AudioTranscriptionIncludes.Logprobs,
210 });
211
212 Assert.That(transcription.TranscriptionTokenLogProbabilities, Has.Count.GreaterThan(0));
213 Assert.That(transcription.TranscriptionTokenLogProbabilities[0].Token, Is.Not.Null.And.Not.Empty);
214 Assert.That(transcription.TranscriptionTokenLogProbabilities[0].LogProbability, Is.Not.EqualTo(0));
215 Assert.That(transcription.TranscriptionTokenLogProbabilities[0].Utf8Bytes.ToArray(), Is.Not.Null.And.Not.Empty);
216 }
217
218 [Test]
219 public async Task StreamingIncludesWork()
220 {
221 AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_Gpt_4o_Mini_Transcribe);
222 string filename = "audio_hello_world.mp3";
223 string path = Path.Combine("Assets", filename);
224
225 List<AudioTokenLogProbabilityDetails> streamedDeltaLogProbs = [];
226
227 await foreach (StreamingAudioTranscriptionUpdate update
228 in client.TranscribeAudioStreamingAsync(
229 path,
230 new AudioTranscriptionOptions()
231 {
232 Includes = AudioTranscriptionIncludes.Logprobs,
233 }))
234 {
235 if (update is StreamingAudioTranscriptionTextDeltaUpdate deltaUpdate)
236 {
237 Assert.That(deltaUpdate.TranscriptionTokenLogProbabilities, Is.Not.Null);
238 streamedDeltaLogProbs.AddRange(deltaUpdate.TranscriptionTokenLogProbabilities);
239 }
240 else if (update is StreamingAudioTranscriptionTextDoneUpdate doneUpdate)
241 {
242 Assert.That(doneUpdate.TranscriptionTokenLogProbabilities, Has.Count.GreaterThan(0));
243 Assert.That(doneUpdate.TranscriptionTokenLogProbabilities.Count, Is.EqualTo(streamedDeltaLogProbs.Count));
244 Assert.That(doneUpdate.TranscriptionTokenLogProbabilities[0].Token, Is.Not.Null.And.Not.Empty);
245 Assert.That(doneUpdate.TranscriptionTokenLogProbabilities[0].Token, Is.EqualTo(streamedDeltaLogProbs[0].Token));
246 }
247 }
248
249 Assert.That(streamedDeltaLogProbs, Has.Count.GreaterThan(0));
250 }
251
252 [Test]
253 public async Task BadTranscriptionRequest()
254 {
255 AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_Whisper);
256
257 string path = Path.Combine("Assets", "audio_hello_world.mp3");
258
259 AudioTranscriptionOptions options = new AudioTranscriptionOptions()
260 {
261 Language = "this should cause an error"
262 };
263
264 Exception caughtException = null;
265
266 try
267 {
268 _ = IsAsync
269 ? await client.TranscribeAudioAsync(path, options)
270 : client.TranscribeAudio(path, options);
271 }
272 catch (Exception ex)
273 {
274 caughtException = ex;
275 }
276
277 Assert.That(caughtException, Is.InstanceOf<ClientResultException>());
278 Assert.That(caughtException.Message?.ToLower(), Contains.Substring("invalid language"));
279 }
280
281 [Test]
282 [TestCase(AudioSourceKind.UsingStream)]
283 [TestCase(AudioSourceKind.UsingFilePath)]
284 public async Task StreamingTranscriptionWorks(AudioSourceKind audioSourceKind)
285 {
286 AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_Gpt_4o_Mini_Transcribe);
287 string filename = "audio_hello_world.mp3";
288 string path = Path.Combine("Assets", filename);
289
290 FileStream inputStream = null;
291
292 AsyncCollectionResult<StreamingAudioTranscriptionUpdate> streamingUpdates = null;
293
294 if (audioSourceKind == AudioSourceKind.UsingStream)
295 {
296 inputStream = File.OpenRead(path);
297 streamingUpdates = client.TranscribeAudioStreamingAsync(inputStream, filename);
298 }
299 else if (audioSourceKind == AudioSourceKind.UsingFilePath)
300 {
301 streamingUpdates = client.TranscribeAudioStreamingAsync(path);
302 }
303
304 StringBuilder deltaBuilder = new();
305
306 await foreach (StreamingAudioTranscriptionUpdate update in streamingUpdates)
307 {
308 if (update is StreamingAudioTranscriptionTextDeltaUpdate deltaUpdate)
309 {
310 deltaBuilder.Append(deltaUpdate.Delta);
311 Assert.That(deltaUpdate.TranscriptionTokenLogProbabilities, Has.Count.EqualTo(0));
312 }
313 else if (update is StreamingAudioTranscriptionTextDoneUpdate doneUpdate)
314 {
315 Assert.That(doneUpdate.Text, Is.Not.Null.And.Not.Empty);
316 Assert.That(doneUpdate.Text, Is.EqualTo(deltaBuilder.ToString()));
317 Assert.That(doneUpdate.TranscriptionTokenLogProbabilities, Has.Count.EqualTo(0));
318 }
319 }
320
321 Assert.That(deltaBuilder.ToString().ToLower(), Does.Contain("hello world"));
322
323 inputStream?.Dispose();
324 }
325}
326