Skip to content

Commit 5519a5f

Browse files
committed
Renewal transcription API implementation
1 parent 71b66fb commit 5519a5f

20 files changed

+423
-237
lines changed

Assets/Mochineko/Whisper_API.Samples/Mochineko.Whisper_API.Samples.asmdef

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
"rootNamespace": "",
44
"references": [
55
"GUID:12e7ae99596e14eef8970a67eb588899",
6+
"GUID:2620e54ab6edb48f48d55966fd5662fb",
7+
"GUID:51d11816546934d4a937e4a420478ce5",
68
"GUID:f51ebe6a0ceec4240a699833d6309b23"
79
],
810
"includePlatforms": [],
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#nullable enable
2+
using System;
3+
using Mochineko.Relent.Resilience;
4+
using Mochineko.Relent.Resilience.Bulkhead;
5+
using Mochineko.Relent.Resilience.Retry;
6+
using Mochineko.Relent.Resilience.Timeout;
7+
using Mochineko.Relent.Resilience.Wrap;
8+
9+
namespace Mochineko.Whisper_API.Samples
10+
{
11+
internal static class PolicyFactory
12+
{
13+
private const float TotalTimeoutSeconds = 60f;
14+
private const int MaxRetryCount = 10;
15+
private const double ExponentialBackoffFactor = 0.1d;
16+
private const double ExponentialBackoffBaseNumber = 2d;
17+
private const int MaxParallelization = 1;
18+
19+
public static IPolicy<string> Build()
20+
{
21+
var totalTimeout = TimeoutFactory.Timeout<string>(
22+
timeout: TimeSpan.FromSeconds(TotalTimeoutSeconds));
23+
24+
var retry = RetryFactory.RetryWithExponentialBackoff<string>(
25+
MaxRetryCount,
26+
factor: ExponentialBackoffFactor,
27+
baseNumber: ExponentialBackoffBaseNumber);
28+
29+
var bulkheadPolicy = BulkheadFactory.Bulkhead<string>(
30+
MaxParallelization);
31+
32+
return totalTimeout
33+
.Wrap(retry)
34+
.Wrap(bulkheadPolicy);
35+
}
36+
}
37+
}

Assets/Mochineko/Whisper_API.Samples/PolicyFactory.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 60 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
#nullable enable
2-
using System;
32
using System.Net.Http;
3+
using System.Threading;
44
using Cysharp.Threading.Tasks;
5+
using Mochineko.Relent.Resilience;
6+
using Mochineko.Relent.UncertainResult;
57
using UnityEngine;
6-
using UnityEngine.Assertions;
78

89
namespace Mochineko.Whisper_API.Samples
910
{
@@ -15,64 +16,76 @@ public sealed class TranscriptionSample : MonoBehaviour
1516
/// <summary>
1617
/// API key generated by OpenAPI.
1718
/// </summary>
18-
[SerializeField] private string apiKey = string.Empty;
19+
[SerializeField]
20+
private string apiKey = string.Empty;
1921

2022
/// <summary>
2123
/// File path of speech audio.
2224
/// </summary>
23-
[SerializeField] private string filePath = string.Empty;
25+
[SerializeField]
26+
private string filePath = string.Empty;
2427

2528
private static readonly HttpClient httpClient = new();
26-
27-
private void Start()
28-
{
29-
// API Key must be set.
30-
Assert.IsNotNull(apiKey);
3129

32-
// If you want to specify response format, language, etc..., please use other initialization:
33-
// connection = new WhisperTranscriptionConnection(apiKey, new APIRequestBody(
34-
// file: "",
35-
// model: "whisper-1",
36-
// prompt: "Some prompts",
37-
// responseFormat: "json",
38-
// temperature: 1f,
39-
// language: "ja"));
40-
}
30+
private readonly TranscriptionRequestBody requestBody = new(
31+
file: string.Empty,
32+
Model.Whisper1);
33+
34+
private readonly IPolicy<string> policy = PolicyFactory.Build();
4135

4236
[ContextMenu(nameof(Transcribe))]
43-
public async void Transcribe()
37+
public void Transcribe()
4438
{
45-
// Validations
46-
if (string.IsNullOrEmpty(filePath))
47-
{
48-
Debug.LogError($"[Whisper_API.Transcription.Samples] File path is null or empty.");
49-
return;
50-
}
39+
TranscribeAsync(this.GetCancellationTokenOnDestroy())
40+
.Forget();
41+
}
5142

52-
string result;
53-
try
54-
{
55-
// Transcribe speech into text by Whisper transcription API.
56-
result = await Transcription
57-
.TranscribeFromFileAsync(
58-
apiKey,
59-
httpClient,
60-
filePath,
61-
Model.Whisper1,
62-
this.GetCancellationTokenOnDestroy());
63-
}
64-
catch (Exception e)
65-
{
66-
// Exceptions should be caught.
67-
Debug.LogException(e);
68-
return;
69-
}
43+
private async UniTask TranscribeAsync(CancellationToken cancellationToken)
44+
{
45+
requestBody.File = filePath;
7046

71-
// Default text response format is JSON.
72-
var text = TranscriptionResponseBody.FromJson(result)?.Text;
47+
await UniTask.SwitchToThreadPool();
7348

74-
// Log text result.
75-
Debug.Log($"[Whisper_API.Transcription.Samples] Result:\n{text}");
49+
// Transcribe speech into text by Whisper transcription API.
50+
var result = await policy
51+
.ExecuteAsync(async innerCancellationToken
52+
=> await TranscriptionAPI
53+
.TranscribeFromFileAsync(
54+
apiKey,
55+
httpClient,
56+
filePath,
57+
requestBody,
58+
innerCancellationToken),
59+
cancellationToken);
60+
61+
await UniTask.SwitchToMainThread(cancellationToken);
62+
63+
switch (result)
64+
{
65+
// Success
66+
case IUncertainSuccessResult<string> success:
67+
{
68+
// Default text response format is JSON.
69+
var text = TranscriptionResponseBody.FromJson(success.Result)?.Text;
70+
// Log text result.
71+
Debug.Log($"[Whisper_API.Transcription.Samples] Succeeded to transcribe into: {text}.");
72+
break;
73+
}
74+
// Retryable failure
75+
case IUncertainRetryableResult<string> retryable:
76+
{
77+
Debug.LogError($"[Whisper_API.Transcription.Samples] Failed to transcribe because -> {retryable.Message}.");
78+
break;
79+
}
80+
// Failure
81+
case IUncertainFailureResult<string> failure:
82+
{
83+
Debug.LogError($"[Whisper_API.Transcription.Samples] Failed to transcribe because -> {failure.Message}.");
84+
break;
85+
}
86+
default:
87+
throw new UncertainResultPatternMatchException(nameof(result));
88+
}
7689
}
7790
}
7891
}

Assets/Mochineko/Whisper_API.Samples/TranslationSample.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ public sealed class TranslationSample : MonoBehaviour
2121
/// </summary>
2222
[SerializeField] private string filePath = string.Empty;
2323

24-
private Translation? connection;
24+
private TranslationAPI? connection;
2525

2626
private void Start()
2727
{
2828
// API Key must be set.
2929
Assert.IsNotNull(apiKey);
3030

3131
// Create instance of WhisperTranscriptionConnection.
32-
connection = new Translation(apiKey);
32+
connection = new TranslationAPI(apiKey);
3333

3434
// If you want to specify response format, etc..., please use other initialization:
3535
// connection = new WhisperTranslationConnection(apiKey, new APIRequestBody(

Assets/Mochineko/Whisper_API.Tests/Mochineko.Whisper_API.Tests.asmdef

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"GUID:0acc523941302664db1f4e527237feb3",
77
"GUID:e372c541aba5148868e12aa078ca7c20",
88
"GUID:12e7ae99596e14eef8970a67eb588899",
9-
"GUID:f51ebe6a0ceec4240a699833d6309b23"
9+
"GUID:f51ebe6a0ceec4240a699833d6309b23",
10+
"GUID:2620e54ab6edb48f48d55966fd5662fb"
1011
],
1112
"includePlatforms": [
1213
"Editor"

Assets/Mochineko/Whisper_API.Tests/TranscriptionTest.cs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using System.IO;
33
using System.Threading;
44
using System.Threading.Tasks;
5-
using FluentAssertions;
5+
using Mochineko.Relent.UncertainResult;
66
using NUnit.Framework;
77
using UnityEngine;
88
using UnityEngine.TestTools;
@@ -29,19 +29,33 @@ public async Task Transcribe()
2929

3030
using var httpClient = new System.Net.Http.HttpClient();
3131

32-
var result = await Transcription
32+
var result = await TranscriptionAPI
3333
.TranscribeFromFileAsync(
3434
apiKey,
3535
httpClient,
3636
filePath,
37-
Model.Whisper1,
37+
new TranscriptionRequestBody(
38+
file: filePath,
39+
Model.Whisper1),
3840
CancellationToken.None);
39-
40-
string.IsNullOrEmpty(result).Should().BeFalse();
41-
42-
var json = TranscriptionResponseBody.FromJson(result);
43-
44-
Debug.Log($"Result:\n{json?.Text}");
41+
switch (result)
42+
{
43+
case IUncertainSuccessResult<string> success:
44+
var json = TranscriptionResponseBody.FromJson(success.Result);
45+
Debug.Log($"Result:\n{json?.Text}");
46+
break;
47+
48+
case IUncertainRetryableResult<string> retryable:
49+
Debug.LogError($"Retryable error -> {retryable.Message}");
50+
break;
51+
52+
case IUncertainFailureResult<string> failure:
53+
Debug.LogError($"Failure error -> {failure.Message}");
54+
break;
55+
56+
default:
57+
throw new UncertainResultPatternMatchException(nameof(result));
58+
}
4559
}
4660
}
4761
}

Assets/Mochineko/Whisper_API.Tests/TranslationTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public async Task Translate()
2727
Application.dataPath,
2828
"Mochineko/Whisper_API.Tests/test.wav");
2929

30-
var connection = new Translation(apiKey, Model.Whisper1);
30+
var connection = new TranslationAPI(apiKey, Model.Whisper1);
3131

3232
var result = await connection.TranslateFromFileAsync(filePath, CancellationToken.None);
3333

Assets/Mochineko/Whisper_API/Mochineko.Whisper_API.asmdef

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"name": "Mochineko.Whisper_API",
33
"rootNamespace": "",
44
"references": [
5+
"GUID:2620e54ab6edb48f48d55966fd5662fb",
56
"GUID:f51ebe6a0ceec4240a699833d6309b23"
67
],
78
"includePlatforms": [],
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#nullable enable
2+
using Mochineko.Relent.UncertainResult;
3+
4+
namespace Mochineko.Whisper_API
5+
{
6+
public sealed class RateLimitExceededResult<T>
7+
: IUncertainRetryableResult<T>
8+
{
9+
public bool Success => false;
10+
public bool Retryable => false;
11+
public bool Failure => true;
12+
public string Message { get; }
13+
14+
public RateLimitExceededResult(string message)
15+
{
16+
Message = message;
17+
}
18+
}
19+
}

0 commit comments

Comments
 (0)