ai.muna.muna 0.0.44 → 0.0.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/Editor/MunaMenu.cs +17 -7
  2. package/Plugins/Android/Muna.aar +0 -0
  3. package/Plugins/macOS/Function.dylib.meta +26 -25
  4. package/README.md +1 -1
  5. package/Runtime/API/DotNetClient.cs +0 -3
  6. package/Runtime/Beta/BetaClient.cs +14 -1
  7. package/Runtime/Beta/OpenAI/AudioService.cs +38 -0
  8. package/Runtime/Beta/OpenAI/AudioService.cs.meta +11 -0
  9. package/Runtime/Beta/OpenAI/ChatService.cs +38 -0
  10. package/Runtime/Beta/OpenAI/ChatService.cs.meta +11 -0
  11. package/Runtime/Beta/OpenAI/CompletionService.cs +117 -0
  12. package/Runtime/Beta/OpenAI/CompletionService.cs.meta +11 -0
  13. package/Runtime/Beta/OpenAI/EmbeddingService.cs +252 -0
  14. package/Runtime/Beta/OpenAI/EmbeddingService.cs.meta +11 -0
  15. package/Runtime/Beta/OpenAI/OpenAIClient.cs +50 -0
  16. package/Runtime/Beta/OpenAI/OpenAIClient.cs.meta +11 -0
  17. package/Runtime/Beta/OpenAI/SpeechService.cs +256 -0
  18. package/Runtime/Beta/OpenAI/SpeechService.cs.meta +11 -0
  19. package/Runtime/Beta/OpenAI/Types.cs +364 -0
  20. package/Runtime/Beta/OpenAI/Types.cs.meta +11 -0
  21. package/Runtime/Beta/OpenAI.meta +8 -0
  22. package/Runtime/Beta/Remote/RemotePredictionService.cs +50 -70
  23. package/Runtime/Beta/{Value.cs → Types/Value.cs} +3 -4
  24. package/Runtime/Beta/Types.meta +8 -0
  25. package/Runtime/C/Configuration.cs +1 -1
  26. package/Runtime/C/Function.cs +1 -1
  27. package/Runtime/C/Prediction.cs +1 -1
  28. package/Runtime/C/PredictionStream.cs +1 -1
  29. package/Runtime/C/Predictor.cs +1 -1
  30. package/Runtime/C/Value.cs +3 -2
  31. package/Runtime/C/ValueMap.cs +1 -1
  32. package/Runtime/Muna.cs +2 -2
  33. package/Runtime/Types/Parameter.cs +75 -0
  34. package/Runtime/Types/Parameter.cs.meta +11 -0
  35. package/Runtime/Types/Predictor.cs +0 -53
  36. package/Unity/API/PredictionCacheClient.cs +1 -1
  37. package/Unity/Converters/Color.cs +46 -0
  38. package/Unity/Converters/Color.cs.meta +2 -0
  39. package/Unity/Converters/Rect.cs +230 -0
  40. package/Unity/Converters/Rect.cs.meta +2 -0
  41. package/Unity/Converters/Vector2.cs +44 -0
  42. package/Unity/Converters/Vector2.cs.meta +2 -0
  43. package/Unity/Converters/Vector3.cs +45 -0
  44. package/Unity/Converters/Vector3.cs.meta +2 -0
  45. package/Unity/Converters/Vector4.cs +46 -0
  46. package/Unity/Converters/Vector4.cs.meta +2 -0
  47. package/Unity/Converters.meta +8 -0
  48. package/Unity/MunaUnity.cs +67 -19
  49. package/package.json +1 -1
  50. /package/Runtime/Beta/{Value.cs.meta → Types/Value.cs.meta} +0 -0
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: 6ebe58906d9ce43c1bf3ca9d8bbc32e2
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
@@ -0,0 +1,50 @@
1
+ /*
2
+ * Muna
3
+ * Copyright © 2025 NatML Inc. All rights reserved.
4
+ */
5
+
6
+ #nullable enable
7
+
8
+ namespace Muna.Beta.OpenAI {
9
+
10
+ using Services;
11
+ using PredictorService = global::Muna.Services.PredictorService;
12
+ using EdgePredictionService = global::Muna.Services.PredictionService;
13
+
14
+ /// <summary>
15
+ /// Mock OpenAI client.
16
+ /// </summary>
17
+ public sealed class OpenAIClient {
18
+
19
+ #region --Client API--
20
+ /// <summary>
21
+ /// Create chat conversations.
22
+ /// </summary>
23
+ public readonly ChatService Chat;
24
+
25
+ /// <summary>
26
+ /// Create embedding vectors.
27
+ /// </summary>
28
+ public readonly EmbeddingService Embeddings;
29
+
30
+ /// <summary>
31
+ /// Create speech and transcriptions.
32
+ /// </summary>
33
+ public readonly AudioService Audio;
34
+ #endregion
35
+
36
+
37
+ #region --Operations--
38
+
39
+ internal OpenAIClient(
40
+ PredictorService predictors,
41
+ EdgePredictionService predictions,
42
+ RemotePredictionService remotePredictions
43
+ ) {
44
+ Chat = new ChatService(predictors, predictions, remotePredictions);
45
+ Embeddings = new EmbeddingService(predictors, predictions, remotePredictions);
46
+ Audio = new AudioService(predictors, predictions, remotePredictions);
47
+ }
48
+ #endregion
49
+ }
50
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: bd6e39d27020a4ed98e3a33bba356c3a
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
@@ -0,0 +1,256 @@
1
+ /*
2
+ * Muna
3
+ * Copyright © 2025 NatML Inc. All rights reserved.
4
+ */
5
+
6
+ #nullable enable
7
+
8
+ namespace Muna.Beta.OpenAI {
9
+
10
+ using System;
11
+ using System.Collections.Generic;
12
+ using System.Linq;
13
+ using System.Runtime.Serialization;
14
+ using System.Threading.Tasks;
15
+ using Newtonsoft.Json;
16
+ using Newtonsoft.Json.Converters;
17
+ using Services;
18
+ using PredictorService = global::Muna.Services.PredictorService;
19
+ using EdgePredictionService = global::Muna.Services.PredictionService;
20
+
21
+ /// <summary>
22
+ /// Create speech.
23
+ /// </summary>
24
+ public sealed class SpeechService {
25
+
26
+ #region --Client API--
27
+ /// <summary>
28
+ /// Audio output format.
29
+ /// </summary>
30
+ [JsonConverter(typeof(StringEnumConverter))]
31
+ public enum ResponseFormat {
32
+ /// <summary>
33
+ /// MP3 audio.
34
+ /// </summary>
35
+ [EnumMember(Value = @"mp3")]
36
+ MP3 = 1,
37
+ /// <summary>
38
+ /// Opus.
39
+ /// </summary>
40
+ [EnumMember(Value = @"opus")]
41
+ Opus = 2,
42
+ /// <summary>
43
+ /// AAC.
44
+ /// </summary>
45
+ [EnumMember(Value = @"aac")]
46
+ AAC = 3,
47
+ /// <summary>
48
+ /// FLAC losseless audio.
49
+ /// </summary>
50
+ [EnumMember(Value = @"flac")]
51
+ FLAC = 4,
52
+ /// <summary>
53
+ /// Waveform audio.
54
+ /// </summary>
55
+ [EnumMember(Value = @"wav")]
56
+ WAV = 5,
57
+ /// <summary>
58
+ /// Linear PCM audio.
59
+ /// </summary>
60
+ [EnumMember(Value = @"pcm")]
61
+ PCM = 6,
62
+ }
63
+
64
+ /// <summary>
65
+ /// The format to stream the audio in.
66
+ /// </summary>
67
+ [JsonConverter(typeof(StringEnumConverter))]
68
+ public enum StreamFormat {
69
+ /// <summary>
70
+ /// Raw audio.
71
+ /// </summary>
72
+ Audio = 1,
73
+ /// <summary>
74
+ /// Server-sent events.
75
+ /// </summary>
76
+ SSE = 2,
77
+ }
78
+
79
+ /// <summary>
80
+ /// Generate audio from the input text.
81
+ /// </summary>
82
+ /// <param name="model">Speech generation predictor tag.</param>
83
+ /// <param name="input">The text to generate audio for.</param>
84
+ /// <param name="voice">The voice to use when generating the audio.</param>
85
+ /// <param name="speed">The speed of the generated audio. Defaults to 1.0.</param>
86
+ /// <param name="responseFormat">The format to return audio in. Currently only `ResponseFormat.PCM` is supported.</param>
87
+ /// <param name="streamFormat">The format to stream the audio in. Currently only `StreamFormat.Audio` is supported.</param>
88
+ /// <param name="acceleration">Prediction acceleration. Must be `Acceleration` or `RemoteAcceleration` instance.</param>
89
+ /// <returns>Generated audio.</returns>
90
+ public async Task<BinaryData> Create(
91
+ string model,
92
+ string input,
93
+ string voice,
94
+ float speed = 1f,
95
+ ResponseFormat responseFormat = ResponseFormat.MP3,
96
+ StreamFormat streamFormat = StreamFormat.Audio,
97
+ object? acceleration = null
98
+ ) {
99
+ // Ensure we have a delegate
100
+ if (!cache.ContainsKey(model)) {
101
+ var @delegate = await CreateSpeechDelegate(model);
102
+ cache.Add(model, @delegate);
103
+ }
104
+ // Make prediction
105
+ var handler = cache[model];
106
+ var result = await handler(
107
+ model,
108
+ input,
109
+ voice,
110
+ speed,
111
+ responseFormat,
112
+ streamFormat,
113
+ acceleration: acceleration ?? Acceleration.Auto
114
+ );
115
+ // Return
116
+ return result;
117
+ }
118
+ #endregion
119
+
120
+
121
+ #region --Operations--
122
+ private readonly PredictorService predictors;
123
+ private readonly EdgePredictionService predictions;
124
+ private readonly RemotePredictionService remotePredictions;
125
+ private readonly Dictionary<string, SpeechDelegate> cache;
126
+ private delegate Task<BinaryData> SpeechDelegate(
127
+ string model,
128
+ string input,
129
+ string voice,
130
+ float speed,
131
+ ResponseFormat responseFormat,
132
+ StreamFormat streamFormat,
133
+ object acceleration
134
+ );
135
+
136
+ internal SpeechService(
137
+ PredictorService predictors,
138
+ EdgePredictionService predictions,
139
+ RemotePredictionService remotePredictions
140
+ ) {
141
+ this.predictors = predictors;
142
+ this.predictions = predictions;
143
+ this.remotePredictions = remotePredictions;
144
+ this.cache = new();
145
+ }
146
+
147
+ private async Task<SpeechDelegate> CreateSpeechDelegate(string tag) {
148
+ // Retrieve predictor
149
+ var predictor = await predictors.Retrieve(tag);
150
+ if (predictor == null)
151
+ throw new ArgumentException($"{tag} cannot be used for OpenAI speech API because the predictor could not be found.");
152
+ // Get required inputs
153
+ var signature = predictor.signature!;
154
+ var requiredInputParams = signature.inputs.Where(parameter => parameter.optional == false).ToArray();
155
+ if (requiredInputParams.Length != 2)
156
+ throw new InvalidOperationException($"${tag} cannot be used with OpenAI speech API because it does not have exactly two required input parameters.");
157
+ // Get the text input parameter
158
+ var inputParam = requiredInputParams.FirstOrDefault(parameter => parameter.type == Dtype.String);
159
+ if (inputParam == null)
160
+ throw new InvalidOperationException($"${tag} cannot be used with OpenAI speech API because it does not have the required speech input parameter.");
161
+ // Get the voice input parameter
162
+ var voiceParam = requiredInputParams.FirstOrDefault(parameter =>
163
+ parameter.type == Dtype.String &&
164
+ parameter.denotation == "audio.voice"
165
+ );
166
+ if (voiceParam == null)
167
+ throw new InvalidOperationException($"${tag} cannot be used with OpenAI speech API because it does not have the required speech voice parameter.");
168
+ // Get the speed input parameter (optional)
169
+ var speedParam = signature.inputs.FirstOrDefault(parameter =>
170
+ new[] { Dtype.Float32, Dtype.Float64 }.Contains((Dtype)parameter.type!) &&
171
+ parameter.denotation == "audio.speed"
172
+ );
173
+ // Get the audio output parameter
174
+ var (audioParamIdx, audioParam) = signature.outputs
175
+ .Select((parameter, idx) => (idx, parameter))
176
+ .Where(pair =>
177
+ pair.parameter.type == Dtype.Float32 &&
178
+ pair.parameter.denotation == "audio"
179
+ )
180
+ .FirstOrDefault();
181
+ if (audioParam == null)
182
+ throw new InvalidOperationException($"{tag} cannot be used with OpenAI speech API because it has no outputs with an `audio` denotation.");
183
+ // Create delegate
184
+ SpeechDelegate result = async(
185
+ string model,
186
+ string input,
187
+ string voice,
188
+ float speed,
189
+ ResponseFormat responseFormat,
190
+ StreamFormat streamFormat,
191
+ object acceleration
192
+ ) => {
193
+ // Check response format
194
+ if (responseFormat != ResponseFormat.PCM)
195
+ throw new ArgumentException($"Cannot create speech with response format {responseFormat} because only `ResponseFormat.PCM` is supported.");
196
+ // Check stream format
197
+ if (streamFormat != StreamFormat.Audio)
198
+ throw new ArgumentException($"Cannot create speech with stream format {streamFormat} because only `StreamFormat.Audio` is supported.");
199
+ // Build prediction input map
200
+ var inputMap = new Dictionary<string, object?> {
201
+ [inputParam.name] = input,
202
+ [voiceParam.name] = voice
203
+ };
204
+ if (speedParam != null)
205
+ inputMap[speedParam.name] = speed;
206
+ // Create prediction
207
+ var prediction = await CreatePrediction(
208
+ model,
209
+ inputs: inputMap,
210
+ acceleration: acceleration
211
+ );
212
+ // Check for error
213
+ if (prediction.error != null)
214
+ throw new InvalidOperationException(prediction.error);
215
+ // Check returned audio
216
+ var result = prediction.results![audioParamIdx]!;
217
+ if (!(result is Tensor<float> tensor))
218
+ throw new InvalidOperationException($"{tag} cannot be used with OpenAI speech API because it returned an object of type {result.GetType()} instead of an audio tensor.");
219
+ if (tensor.shape.Length != 1 && tensor.shape.Length != 2) {
220
+ var shapeStr = "(" + string.Join(",", tensor.shape) + ")";
221
+ throw new InvalidOperationException($"{tag} cannot be used with OpenAI speech API because it returned an audio tensor with an invalid shape: {shapeStr}");
222
+ }
223
+ // Create response
224
+ var channels = tensor.shape.Length == 2 ? tensor.shape[0] : 1; // Assume planar
225
+ var mediaType = $"audio/pcm;rate={audioParam.sampleRate};channels={channels}";
226
+ var response = ToBinaryData(tensor, mediaType);
227
+ // Return
228
+ return response;
229
+ };
230
+ // Return
231
+ return result;
232
+ }
233
+
234
+ private Task<Prediction> CreatePrediction(
235
+ string tag,
236
+ Dictionary<string, object?> inputs,
237
+ object acceleration
238
+ ) => acceleration switch {
239
+ Acceleration acc => predictions.Create(tag, inputs, acc),
240
+ RemoteAcceleration acc => remotePredictions.Create(tag, inputs, acc),
241
+ _ => throw new InvalidOperationException($"Cannot create {tag} prediction because acceleration is invalid: {acceleration}")
242
+ };
243
+
244
+ private static unsafe BinaryData ToBinaryData<T>(
245
+ Tensor<T> tensor,
246
+ string? mediaType = null
247
+ ) where T : unmanaged {
248
+ var elementCount = tensor.shape.Aggregate(1, (a, b) => a * b);
249
+ var data = new byte[elementCount * sizeof(T)];
250
+ fixed (void* src = tensor, dst = data)
251
+ Buffer.MemoryCopy(src, dst, data.Length, data.Length);
252
+ return new BinaryData(data, mediaType);
253
+ }
254
+ #endregion
255
+ }
256
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: aa80e003d14a045c59c487cf206d4f95
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant: