ai.muna.muna 0.0.44 → 0.0.45
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.
- package/Editor/MunaMenu.cs +11 -1
- package/Plugins/Android/Muna.aar +0 -0
- package/README.md +1 -1
- package/Runtime/API/DotNetClient.cs +0 -3
- package/Runtime/Beta/BetaClient.cs +14 -1
- package/Runtime/Beta/OpenAI/AudioService.cs +38 -0
- package/Runtime/Beta/OpenAI/AudioService.cs.meta +11 -0
- package/Runtime/Beta/OpenAI/ChatService.cs +38 -0
- package/Runtime/Beta/OpenAI/ChatService.cs.meta +11 -0
- package/Runtime/Beta/OpenAI/CompletionService.cs +117 -0
- package/Runtime/Beta/OpenAI/CompletionService.cs.meta +11 -0
- package/Runtime/Beta/OpenAI/EmbeddingService.cs +252 -0
- package/Runtime/Beta/OpenAI/EmbeddingService.cs.meta +11 -0
- package/Runtime/Beta/OpenAI/OpenAIClient.cs +50 -0
- package/Runtime/Beta/OpenAI/OpenAIClient.cs.meta +11 -0
- package/Runtime/Beta/OpenAI/SpeechService.cs +250 -0
- package/Runtime/Beta/OpenAI/SpeechService.cs.meta +11 -0
- package/Runtime/Beta/OpenAI/Types.cs +365 -0
- package/Runtime/Beta/OpenAI/Types.cs.meta +11 -0
- package/Runtime/Beta/OpenAI.meta +8 -0
- package/Runtime/Beta/Remote/RemotePredictionService.cs +45 -66
- package/Runtime/Beta/{Value.cs → Remote/Value.cs} +3 -4
- package/Runtime/C/Configuration.cs +1 -1
- package/Runtime/C/Function.cs +1 -1
- package/Runtime/C/Prediction.cs +1 -1
- package/Runtime/C/PredictionStream.cs +1 -1
- package/Runtime/C/Predictor.cs +1 -1
- package/Runtime/C/Value.cs +3 -2
- package/Runtime/C/ValueMap.cs +1 -1
- package/Runtime/Muna.cs +2 -2
- package/Runtime/Types/Parameter.cs +75 -0
- package/Runtime/Types/Parameter.cs.meta +11 -0
- package/Runtime/Types/Predictor.cs +0 -53
- package/Unity/API/PredictionCacheClient.cs +1 -1
- package/Unity/MunaUnity.cs +0 -1
- package/package.json +1 -1
- /package/Runtime/Beta/{Value.cs.meta → Remote/Value.cs.meta} +0 -0
|
@@ -0,0 +1,250 @@
|
|
|
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
|
+
// Build prediction input map
|
|
194
|
+
var inputMap = new Dictionary<string, object?> {
|
|
195
|
+
[inputParam.name] = input,
|
|
196
|
+
[voiceParam.name] = voice
|
|
197
|
+
};
|
|
198
|
+
if (speedParam != null)
|
|
199
|
+
inputMap[speedParam.name] = speed;
|
|
200
|
+
// Create prediction
|
|
201
|
+
var prediction = await CreatePrediction(
|
|
202
|
+
model,
|
|
203
|
+
inputs: inputMap,
|
|
204
|
+
acceleration: acceleration
|
|
205
|
+
);
|
|
206
|
+
// Check for error
|
|
207
|
+
if (prediction.error != null)
|
|
208
|
+
throw new InvalidOperationException(prediction.error);
|
|
209
|
+
// Check returned audio
|
|
210
|
+
var result = prediction.results![audioParamIdx]!;
|
|
211
|
+
if (!(result is Tensor<float> tensor))
|
|
212
|
+
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.");
|
|
213
|
+
if (tensor.shape.Length != 1 && tensor.shape.Length != 2) {
|
|
214
|
+
var shapeStr = "(" + string.Join(",", tensor.shape) + ")";
|
|
215
|
+
throw new InvalidOperationException($"{tag} cannot be used with OpenAI speech API because it returned an audio tensor with an invalid shape: {shapeStr}");
|
|
216
|
+
}
|
|
217
|
+
// Create response
|
|
218
|
+
var channels = tensor.shape.Length == 2 ? tensor.shape[0] : 1; // Assume planar
|
|
219
|
+
var mediaType = $"audio/pcm;rate={audioParam.sampleRate};channels={channels}";
|
|
220
|
+
var response = ToBinaryData(tensor, mediaType);
|
|
221
|
+
// Return
|
|
222
|
+
return response;
|
|
223
|
+
};
|
|
224
|
+
// Return
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
private Task<Prediction> CreatePrediction(
|
|
229
|
+
string tag,
|
|
230
|
+
Dictionary<string, object?> inputs,
|
|
231
|
+
object acceleration
|
|
232
|
+
) => acceleration switch {
|
|
233
|
+
Acceleration acc => predictions.Create(tag, inputs, acc),
|
|
234
|
+
RemoteAcceleration acc => remotePredictions.Create(tag, inputs, acc),
|
|
235
|
+
_ => throw new InvalidOperationException($"Cannot create {tag} prediction because acceleration is invalid: {acceleration}")
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
private static unsafe BinaryData ToBinaryData<T>(
|
|
239
|
+
Tensor<T> tensor,
|
|
240
|
+
string? mediaType = null
|
|
241
|
+
) where T : unmanaged {
|
|
242
|
+
var elementCount = tensor.shape.Aggregate(1, (a, b) => a * b);
|
|
243
|
+
var data = new byte[elementCount * sizeof(T)];
|
|
244
|
+
fixed (void* src = tensor, dst = data)
|
|
245
|
+
Buffer.MemoryCopy(src, dst, data.Length, data.Length);
|
|
246
|
+
return new BinaryData(data, mediaType);
|
|
247
|
+
}
|
|
248
|
+
#endregion
|
|
249
|
+
}
|
|
250
|
+
}
|
|
@@ -0,0 +1,365 @@
|
|
|
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.Runtime.Serialization;
|
|
12
|
+
using Newtonsoft.Json;
|
|
13
|
+
using Newtonsoft.Json.Converters;
|
|
14
|
+
|
|
15
|
+
/// <summary>
|
|
16
|
+
/// Binary data with an optional content type.
|
|
17
|
+
/// </summary>
|
|
18
|
+
public sealed class BinaryData {
|
|
19
|
+
|
|
20
|
+
/// <summary>
|
|
21
|
+
/// Whether this data is empty.
|
|
22
|
+
/// </summary>
|
|
23
|
+
public bool IsEmpty => data.Length == 0;
|
|
24
|
+
|
|
25
|
+
/// <summary>
|
|
26
|
+
/// Number of bytes of this data.
|
|
27
|
+
/// </summary>
|
|
28
|
+
public int Length => data.Length;
|
|
29
|
+
|
|
30
|
+
/// <summary>
|
|
31
|
+
/// MIME type of this data
|
|
32
|
+
/// </summary>
|
|
33
|
+
public string? MediaType { get; private set; }
|
|
34
|
+
|
|
35
|
+
/// <summary>
|
|
36
|
+
/// Convert the `BinaryData` to a byte array.
|
|
37
|
+
/// </summary>
|
|
38
|
+
/// <returns></returns>
|
|
39
|
+
public byte[] ToArray() => data;
|
|
40
|
+
|
|
41
|
+
/// <summary>
|
|
42
|
+
/// Gets the value of this instance as bytes without any further interpretation.
|
|
43
|
+
/// </summary>
|
|
44
|
+
public ReadOnlyMemory<byte> ToMemory() => new ReadOnlyMemory<byte>(data);
|
|
45
|
+
|
|
46
|
+
private readonly byte[] data;
|
|
47
|
+
|
|
48
|
+
public BinaryData(byte[] data, string? mediaType = null) {
|
|
49
|
+
this.data = data;
|
|
50
|
+
this.MediaType = mediaType;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/// <summary>
|
|
55
|
+
/// Embedding.
|
|
56
|
+
/// </summary>
|
|
57
|
+
public sealed class Embedding {
|
|
58
|
+
|
|
59
|
+
/// <summary>
|
|
60
|
+
/// The object type, which is always "embedding".
|
|
61
|
+
/// </summary>
|
|
62
|
+
[JsonProperty(@"object")]
|
|
63
|
+
#pragma warning disable 8618
|
|
64
|
+
public string Object;
|
|
65
|
+
#pragma warning restore 8618
|
|
66
|
+
|
|
67
|
+
/// <summary>
|
|
68
|
+
/// Embedding vector as number array.
|
|
69
|
+
/// </summary>
|
|
70
|
+
[JsonProperty(@"embedding")]
|
|
71
|
+
public float[]? Floats;
|
|
72
|
+
|
|
73
|
+
/// <summary>
|
|
74
|
+
/// Index of the embedding in the list of embeddings.
|
|
75
|
+
/// </summary>
|
|
76
|
+
[JsonProperty(@"index")]
|
|
77
|
+
public int Index;
|
|
78
|
+
|
|
79
|
+
/// <summary>
|
|
80
|
+
/// Embedding vector as a base64 string.
|
|
81
|
+
/// </summary>
|
|
82
|
+
[JsonIgnore]
|
|
83
|
+
public string? Base64;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public sealed class CreateEmbeddingResponse {
|
|
87
|
+
|
|
88
|
+
#pragma warning disable 8618
|
|
89
|
+
/// <summary>
|
|
90
|
+
/// The object type, which is always "list".
|
|
91
|
+
/// </summary>
|
|
92
|
+
[JsonProperty(@"object")]
|
|
93
|
+
public string Object;
|
|
94
|
+
|
|
95
|
+
/// <summary>
|
|
96
|
+
/// The name of the model used to generate the embedding.
|
|
97
|
+
/// </summary>
|
|
98
|
+
[JsonProperty(@"model")]
|
|
99
|
+
public string Model;
|
|
100
|
+
|
|
101
|
+
/// <summary>
|
|
102
|
+
/// The list of embeddings generated by the model.
|
|
103
|
+
/// </summary>
|
|
104
|
+
[JsonProperty(@"data")]
|
|
105
|
+
public Embedding[] Data;
|
|
106
|
+
#pragma warning restore 8618
|
|
107
|
+
|
|
108
|
+
/// <summary>
|
|
109
|
+
/// The usage information for the request.
|
|
110
|
+
/// </summary>
|
|
111
|
+
[JsonProperty(@"usage")]
|
|
112
|
+
public UsageInfo Usage;
|
|
113
|
+
|
|
114
|
+
/// <summary>
|
|
115
|
+
/// Usage information for the request.
|
|
116
|
+
/// </summary>
|
|
117
|
+
public struct UsageInfo {
|
|
118
|
+
|
|
119
|
+
/// <summary>
|
|
120
|
+
/// Number of tokens used by the prompt.
|
|
121
|
+
/// </summary>
|
|
122
|
+
[JsonProperty(@"prompt_tokens")]
|
|
123
|
+
public int PromptTokens;
|
|
124
|
+
|
|
125
|
+
/// <summary>
|
|
126
|
+
/// Total number of tokens used by the request.
|
|
127
|
+
/// </summary>
|
|
128
|
+
[JsonProperty(@"total_tokens")]
|
|
129
|
+
public int TotalTokens;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/// <summary>
|
|
134
|
+
/// Chat message.
|
|
135
|
+
/// </summary>
|
|
136
|
+
public sealed class ChatMessage {
|
|
137
|
+
|
|
138
|
+
/// <summary>
|
|
139
|
+
/// Message role.
|
|
140
|
+
/// </summary>
|
|
141
|
+
[JsonConverter(typeof(StringEnumConverter))]
|
|
142
|
+
public enum ChatRole {
|
|
143
|
+
/// <summary>
|
|
144
|
+
/// Assistant.
|
|
145
|
+
/// </summary>
|
|
146
|
+
[EnumMember(Value = @"assistant")]
|
|
147
|
+
Assistant = 1,
|
|
148
|
+
/// <summary>
|
|
149
|
+
/// User
|
|
150
|
+
/// </summary>
|
|
151
|
+
[EnumMember(Value = @"user")]
|
|
152
|
+
User = 2,
|
|
153
|
+
/// <summary>
|
|
154
|
+
/// Developer.
|
|
155
|
+
/// </summary>
|
|
156
|
+
[EnumMember(Value = @"developer")]
|
|
157
|
+
Developer = 3,
|
|
158
|
+
/// <summary>
|
|
159
|
+
/// System.
|
|
160
|
+
/// </summary>
|
|
161
|
+
[EnumMember(Value = @"system")]
|
|
162
|
+
System = 4,
|
|
163
|
+
/// <summary>
|
|
164
|
+
/// Tool.
|
|
165
|
+
/// </summary>
|
|
166
|
+
[EnumMember(Value = @"tool")]
|
|
167
|
+
Tool = 5,
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/// <summary>
|
|
171
|
+
/// Message role.
|
|
172
|
+
/// </summary>
|
|
173
|
+
[JsonProperty(@"role")]
|
|
174
|
+
public ChatRole Role;
|
|
175
|
+
|
|
176
|
+
/// <summary>
|
|
177
|
+
/// Message content.
|
|
178
|
+
/// </summary>
|
|
179
|
+
[JsonProperty(@"content")]
|
|
180
|
+
public string? Content;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/// <summary>
|
|
184
|
+
/// Chat completion.
|
|
185
|
+
/// </summary>
|
|
186
|
+
public sealed class ChatCompletion {
|
|
187
|
+
|
|
188
|
+
#pragma warning disable 8618
|
|
189
|
+
/// <summary>
|
|
190
|
+
/// The object type, which is always `chat.completion`.
|
|
191
|
+
/// </summary>
|
|
192
|
+
[JsonProperty(@"object")]
|
|
193
|
+
public string Object;
|
|
194
|
+
|
|
195
|
+
/// <summary>
|
|
196
|
+
/// Completion unique identifier.
|
|
197
|
+
/// </summary>
|
|
198
|
+
[JsonProperty(@"id")]
|
|
199
|
+
public string Id;
|
|
200
|
+
|
|
201
|
+
/// <summary>
|
|
202
|
+
/// Model that generated the chat completion.
|
|
203
|
+
/// </summary>
|
|
204
|
+
[JsonProperty(@"model")]
|
|
205
|
+
public string Model;
|
|
206
|
+
|
|
207
|
+
/// <summary>
|
|
208
|
+
/// Chat completion choices.
|
|
209
|
+
/// Can be more than one if `n` is greater than 1.
|
|
210
|
+
/// </summary>
|
|
211
|
+
[JsonProperty(@"choices")]
|
|
212
|
+
public Choice[] Choices;
|
|
213
|
+
|
|
214
|
+
/// <summary>
|
|
215
|
+
/// Date created as a unix timestamp (in seconds).
|
|
216
|
+
/// </summary>
|
|
217
|
+
[JsonProperty(@"created")]
|
|
218
|
+
public long Created;
|
|
219
|
+
|
|
220
|
+
/// <summary>
|
|
221
|
+
/// Usage statistics for the completion request.
|
|
222
|
+
/// </summary>
|
|
223
|
+
[JsonProperty(@"usage")]
|
|
224
|
+
public UsageInfo Usage;
|
|
225
|
+
|
|
226
|
+
public sealed class Choice {
|
|
227
|
+
|
|
228
|
+
/// <summary>
|
|
229
|
+
/// Index of this choice in the list of choices.
|
|
230
|
+
/// </summary>
|
|
231
|
+
[JsonProperty(@"index")]
|
|
232
|
+
public int Index;
|
|
233
|
+
|
|
234
|
+
/// <summary>
|
|
235
|
+
/// Completion message generated by the model.
|
|
236
|
+
/// </summary>
|
|
237
|
+
[JsonProperty(@"message")]
|
|
238
|
+
public ChatMessage Message;
|
|
239
|
+
|
|
240
|
+
/// <summary>
|
|
241
|
+
/// The reason the model stopped generating tokens. This will be:
|
|
242
|
+
///
|
|
243
|
+
/// `stop` if the model hit a natural stop point or a provided stop sequence.
|
|
244
|
+
/// `length` if the maximum number of tokens specified in the request was reached.
|
|
245
|
+
/// `content_filter` if content was omitted due to a flag from our content filters.
|
|
246
|
+
/// `tool_calls` if the model called a tool.
|
|
247
|
+
/// `function_call` (deprecated) if the model called a function.
|
|
248
|
+
/// </summary>
|
|
249
|
+
[JsonProperty(@"finish_reason")]
|
|
250
|
+
public string? FinishReason;
|
|
251
|
+
}
|
|
252
|
+
#pragma warning restore 8618
|
|
253
|
+
|
|
254
|
+
public struct UsageInfo {
|
|
255
|
+
|
|
256
|
+
/// <summary>
|
|
257
|
+
/// Number of tokens in the generated completion.
|
|
258
|
+
/// </summary>
|
|
259
|
+
[JsonProperty(@"completion_tokens")]
|
|
260
|
+
public int CompletionTokens;
|
|
261
|
+
|
|
262
|
+
/// <summary>
|
|
263
|
+
/// Number of tokens in the prompt.
|
|
264
|
+
/// </summary>
|
|
265
|
+
[JsonProperty(@"prompt_tokens")]
|
|
266
|
+
public int PromptTokens;
|
|
267
|
+
|
|
268
|
+
/// <summary>
|
|
269
|
+
/// Total number of tokens used in the request (prompt + completion).
|
|
270
|
+
/// </summary>
|
|
271
|
+
[JsonProperty(@"total_tokens")]
|
|
272
|
+
public int TotalTokens;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/// <summary>
|
|
277
|
+
/// Chat completion chunk.
|
|
278
|
+
/// </summary>
|
|
279
|
+
public sealed class ChatCompletionChunk {
|
|
280
|
+
|
|
281
|
+
#pragma warning disable 8618
|
|
282
|
+
/// <summary>
|
|
283
|
+
/// The object type, which is always `chat.completion.chunk`.
|
|
284
|
+
/// </summary>
|
|
285
|
+
[JsonProperty(@"object")]
|
|
286
|
+
public string Object;
|
|
287
|
+
|
|
288
|
+
/// <summary>
|
|
289
|
+
/// Completion unique identifier.
|
|
290
|
+
/// All chunks from a given completion share the same identifier.
|
|
291
|
+
/// </summary>
|
|
292
|
+
[JsonProperty(@"id")]
|
|
293
|
+
public string Id;
|
|
294
|
+
|
|
295
|
+
/// <summary>
|
|
296
|
+
/// Model that generated the chat completion.
|
|
297
|
+
/// </summary>
|
|
298
|
+
[JsonProperty(@"model")]
|
|
299
|
+
public string Model;
|
|
300
|
+
|
|
301
|
+
/// <summary>
|
|
302
|
+
/// Chat completion choices.
|
|
303
|
+
/// Can be more than one if `n` is greater than 1.
|
|
304
|
+
/// Can also be empty for the last chunk if you set `stream_options: {"include_usage": true}`.
|
|
305
|
+
/// </summary>
|
|
306
|
+
[JsonProperty(@"choices")]
|
|
307
|
+
public Choice[] Choices;
|
|
308
|
+
#pragma warning restore 8618
|
|
309
|
+
|
|
310
|
+
/// <summary>
|
|
311
|
+
/// Date created as a unix timestamp (in seconds).
|
|
312
|
+
/// All chunks from a given completion share the same creation timestamp.
|
|
313
|
+
/// </summary>
|
|
314
|
+
[JsonProperty(@"created")]
|
|
315
|
+
public long Created;
|
|
316
|
+
|
|
317
|
+
/// <summary>
|
|
318
|
+
/// Usage statistics for the completion request.
|
|
319
|
+
/// </summary>
|
|
320
|
+
[JsonProperty(@"usage")]
|
|
321
|
+
public ChatCompletion.UsageInfo? Usage;
|
|
322
|
+
|
|
323
|
+
public sealed class Choice {
|
|
324
|
+
|
|
325
|
+
/// <summary>
|
|
326
|
+
/// Index of this choice in the list of choices.
|
|
327
|
+
/// </summary>
|
|
328
|
+
[JsonProperty(@"index")]
|
|
329
|
+
public int Index;
|
|
330
|
+
|
|
331
|
+
/// <summary>
|
|
332
|
+
/// Completion message delta generated by the model when streaming.
|
|
333
|
+
/// </summary>
|
|
334
|
+
[JsonProperty(@"delta")]
|
|
335
|
+
public MessageDelta? Delta;
|
|
336
|
+
|
|
337
|
+
/// <summary>
|
|
338
|
+
/// The reason the model stopped generating tokens. This will be:
|
|
339
|
+
///
|
|
340
|
+
/// `stop` if the model hit a natural stop point or a provided stop sequence.
|
|
341
|
+
/// `length` if the maximum number of tokens specified in the request was reached.
|
|
342
|
+
/// `content_filter` if content was omitted due to a flag from our content filters.
|
|
343
|
+
/// `tool_calls` if the model called a tool.
|
|
344
|
+
/// `function_call` (deprecated) if the model called a function.
|
|
345
|
+
/// </summary>
|
|
346
|
+
[JsonProperty(@"finish_reason")]
|
|
347
|
+
public string? FinishReason;
|
|
348
|
+
|
|
349
|
+
public sealed class MessageDelta {
|
|
350
|
+
|
|
351
|
+
/// <summary>
|
|
352
|
+
/// Role of the author of this message.
|
|
353
|
+
/// </summary>
|
|
354
|
+
[JsonProperty(@"role")]
|
|
355
|
+
public ChatMessage.ChatRole? Role;
|
|
356
|
+
|
|
357
|
+
/// <summary>
|
|
358
|
+
/// Content of the message chunk.
|
|
359
|
+
/// </summary>
|
|
360
|
+
[JsonProperty(@"content")]
|
|
361
|
+
public string? Content;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|