openai/openai-dotnet

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
mailinhphan/clientOptions

Branches

Tags

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

Clone

HTTPS

Download ZIP

OpenAI/src/Custom/Chat/ChatClient.cs

459lines · modecode

1using Microsoft.TypeSpec.Generator.Customizations;
2using OpenAI.Telemetry;
3using System;
4using System.ClientModel;
5using System.ClientModel.Primitives;
6using System.Collections.Generic;
7using System.Diagnostics.CodeAnalysis;
8using System.Linq;
9using System.Threading;
10using System.Threading.Tasks;
11
12namespace OpenAI.Chat;
13
14// CUSTOM:
15// - Renamed.
16// - Suppressed constructor that takes endpoint parameter; endpoint is now a property in the options class.
17// - Suppressed methods that only take the options parameter.
18/// <summary> The service client for OpenAI chat operations. </summary>
19[CodeGenType("Chat")]
20[CodeGenSuppress("ChatClient", typeof(ClientPipeline), typeof(Uri))]
21[CodeGenSuppress("CompleteChat", typeof(ChatCompletionOptions), typeof(CancellationToken))]
22[CodeGenSuppress("CompleteChatAsync", typeof(ChatCompletionOptions), typeof(CancellationToken))]
23public partial class ChatClient
24{
25 private readonly string _model;
26 private readonly OpenTelemetrySource _telemetry;
27 private static readonly InternalChatCompletionStreamOptions s_includeUsageStreamOptions = new(includeUsage: true, patch: default);
28
29 // CUSTOM: Added as a convenience.
30 /// <summary> Initializes a new instance of <see cref="ChatClient"/>. </summary>
31 /// <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>
32 /// <param name="apiKey"> The API key to authenticate with the service. </param>
33 /// <exception cref="ArgumentNullException"> <paramref name="model"/> or <paramref name="apiKey"/> is null. </exception>
34 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
35 public ChatClient(string model, string apiKey) : this(model, new ApiKeyCredential(apiKey), new OpenAIClientOptions())
36 {
37 }
38
39 // CUSTOM:
40 // - Added `model` parameter.
41 // - Used a custom pipeline.
42 // - Demoted the endpoint parameter to be a property in the options class.
43 /// <summary> Initializes a new instance of <see cref="ChatClient"/>. </summary>
44 /// <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>
45 /// <param name="credential"> The <see cref="ApiKeyCredential"/> to authenticate with the service. </param>
46 /// <exception cref="ArgumentNullException"> <paramref name="model"/> or <paramref name="credential"/> is null. </exception>
47 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
48 public ChatClient(string model, ApiKeyCredential credential) : this(model, credential, new OpenAIClientOptions())
49 {
50 }
51
52 // CUSTOM:
53 // - Added `model` parameter.
54 // - Used a custom pipeline.
55 // - Demoted the endpoint parameter to be a property in the options class.
56 // - Added telemetry support.
57 /// <summary> Initializes a new instance of <see cref="ChatClient"/>. </summary>
58 /// <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>
59 /// <param name="credential"> The <see cref="ApiKeyCredential"/> to authenticate with the service. </param>
60 /// <param name="options"> The options to configure the client. </param>
61 /// <exception cref="ArgumentNullException"> <paramref name="model"/> or <paramref name="credential"/> is null. </exception>
62 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
63 public ChatClient(string model, ApiKeyCredential credential, OpenAIClientOptions options) : this(model, OpenAIClient.CreateApiKeyAuthenticationPolicy(credential), options)
64 {
65 }
66
67 // CUSTOM: Added as a convenience.
68 /// <summary> Initializes a new instance of <see cref="ChatClient"/>. </summary>
69 /// <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>
70 /// <param name="authenticationPolicy"> The authentication policy used to authenticate with the service. </param>
71 /// <exception cref="ArgumentNullException"> <paramref name="model"/> or <paramref name="authenticationPolicy"/> is null. </exception>
72 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
73 [Experimental("OPENAI001")]
74 public ChatClient(string model, AuthenticationPolicy authenticationPolicy) : this(model, authenticationPolicy, new OpenAIClientOptions())
75 {
76 }
77
78 // CUSTOM: Added as a convenience.
79 /// <summary> Initializes a new instance of <see cref="ChatClient"/>. </summary>
80 /// <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>
81 /// <param name="authenticationPolicy"> The authentication policy used to authenticate with the service. </param>
82 /// <param name="options"> The options to configure the client. </param>
83 /// <exception cref="ArgumentNullException"> <paramref name="model"/> or <paramref name="authenticationPolicy"/> is null. </exception>
84 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
85 [Experimental("OPENAI001")]
86 public ChatClient(string model, AuthenticationPolicy authenticationPolicy, OpenAIClientOptions options)
87 {
88 Argument.AssertNotNullOrEmpty(model, nameof(model));
89 Argument.AssertNotNull(authenticationPolicy, nameof(authenticationPolicy));
90 options ??= new OpenAIClientOptions();
91
92 _model = model;
93 Pipeline = OpenAIClient.CreatePipeline(authenticationPolicy, options);
94 _endpoint = OpenAIClient.GetEndpoint(options);
95 _telemetry = new OpenTelemetrySource(model, _endpoint);
96 }
97
98 // CUSTOM:
99 // - Added `model` parameter.
100 // - Used a custom pipeline.
101 // - Demoted the endpoint parameter to be a property in the options class.
102 // - Added telemetry support.
103 // - Made protected.
104 /// <summary> Initializes a new instance of <see cref="ChatClient"/>. </summary>
105 /// <param name="pipeline"> The HTTP pipeline to send and receive REST requests and responses. </param>
106 /// <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>
107 /// <param name="options"> The options to configure the client. </param>
108 /// <exception cref="ArgumentNullException"> <paramref name="pipeline"/> or <paramref name="model"/> is null. </exception>
109 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
110 protected internal ChatClient(ClientPipeline pipeline, string model, OpenAIClientOptions options)
111 {
112 Argument.AssertNotNull(pipeline, nameof(pipeline));
113 Argument.AssertNotNullOrEmpty(model, nameof(model));
114 options ??= new OpenAIClientOptions();
115
116 _model = model;
117 Pipeline = pipeline;
118 _endpoint = OpenAIClient.GetEndpoint(options);
119 _telemetry = new OpenTelemetrySource(model, _endpoint);
120 }
121
122 /// <summary> Initializes a new instance of <see cref="ChatClient"/>. </summary>
123 /// <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>
124 /// <param name="credential"> The <see cref="ApiKeyCredential"/> to authenticate with the service. </param>
125 /// <param name="options"> The options to configure the client. </param>
126 /// <exception cref="ArgumentNullException"> <paramref name="model"/> or <paramref name="credential"/> is null. </exception>
127 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
128 [Experimental("OPENAI001")]
129 public ChatClient(string model, ApiKeyCredential credential, ChatClientOptions options) : this(model, OpenAIClient.CreateApiKeyAuthenticationPolicy(credential), options)
130 {
131 }
132
133 /// <summary> Initializes a new instance of <see cref="ChatClient"/>. </summary>
134 /// <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>
135 /// <param name="authenticationPolicy"> The authentication policy used to authenticate with the service. </param>
136 /// <param name="options"> The options to configure the client. </param>
137 /// <exception cref="ArgumentNullException"> <paramref name="model"/> or <paramref name="authenticationPolicy"/> is null. </exception>
138 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
139 [Experimental("OPENAI001")]
140 public ChatClient(string model, AuthenticationPolicy authenticationPolicy, ChatClientOptions options)
141 {
142 Argument.AssertNotNullOrEmpty(model, nameof(model));
143 Argument.AssertNotNull(authenticationPolicy, nameof(authenticationPolicy));
144 options ??= new ChatClientOptions();
145
146 _model = model;
147 Pipeline = OpenAIClientUtilities.CreatePipeline(authenticationPolicy, options, options.UserAgentApplicationId, options.OrganizationId, options.ProjectId);
148 _endpoint = OpenAIClientUtilities.GetEndpoint(options.Endpoint);
149 _telemetry = new OpenTelemetrySource(model, _endpoint);
150 }
151
152 /// <summary> Initializes a new instance of <see cref="ChatClient"/>. </summary>
153 /// <param name="pipeline"> The HTTP pipeline to send and receive REST requests and responses. </param>
154 /// <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>
155 /// <param name="options"> The options to configure the client. </param>
156 /// <exception cref="ArgumentNullException"> <paramref name="pipeline"/> or <paramref name="model"/> is null. </exception>
157 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
158 [Experimental("OPENAI001")]
159 protected internal ChatClient(ClientPipeline pipeline, string model, ChatClientOptions options)
160 {
161 Argument.AssertNotNull(pipeline, nameof(pipeline));
162 Argument.AssertNotNullOrEmpty(model, nameof(model));
163 options ??= new ChatClientOptions();
164
165 _model = model;
166 Pipeline = pipeline;
167 _endpoint = OpenAIClientUtilities.GetEndpoint(options.Endpoint);
168 _telemetry = new OpenTelemetrySource(model, _endpoint);
169 }
170
171 [Experimental("SCME0002")]
172 public ChatClient(ChatClientSettings settings)
173 : this(settings?.Model, AuthenticationPolicy.Create(settings), settings?.Options)
174 {
175 }
176
177 /// <summary>
178 /// Gets the name of the model used in requests sent to the service.
179 /// </summary>
180 [Experimental("OPENAI001")]
181 public string Model => _model;
182
183 /// <summary>
184 /// Gets the endpoint URI for the service.
185 /// </summary>
186 [Experimental("OPENAI001")]
187 public Uri Endpoint => _endpoint;
188
189 /// <summary> Generates a completion for the given chat. </summary>
190 /// <param name="messages"> The messages comprising the chat so far. </param>
191 /// <param name="options"> The options to configure the chat completion. </param>
192 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
193 /// <exception cref="ArgumentNullException"> <paramref name="messages"/> is null. </exception>
194 /// <exception cref="ArgumentException"> <paramref name="messages"/> is an empty collection, and was expected to be non-empty. </exception>
195 public virtual Task<ClientResult<ChatCompletion>> CompleteChatAsync(IEnumerable<ChatMessage> messages, ChatCompletionOptions options = null, CancellationToken cancellationToken = default)
196 {
197 return CompleteChatAsync(messages, options, cancellationToken.ToRequestOptions() ?? new RequestOptions());
198 }
199
200 internal async Task<ClientResult<ChatCompletion>> CompleteChatAsync(IEnumerable<ChatMessage> messages, ChatCompletionOptions options, RequestOptions requestOptions)
201 {
202 Argument.AssertNotNullOrEmpty(messages, nameof(messages));
203 Argument.AssertNotNull(requestOptions, nameof(requestOptions));
204 if (requestOptions.BufferResponse is false)
205 {
206 throw new InvalidOperationException("'requestOptions.BufferResponse' must be 'true' when calling 'CompleteChatAsync'.");
207 }
208
209 options ??= new();
210 var clonedOptions = CreateChatCompletionOptions(messages, options);
211 using OpenTelemetryScope scope = _telemetry.StartChatScope(clonedOptions);
212
213 try
214 {
215 using BinaryContent content = clonedOptions.ToBinaryContent();
216
217 ClientResult result = await CompleteChatAsync(content, requestOptions).ConfigureAwait(false);
218 ChatCompletion chatCompletion = (ChatCompletion)result;
219 scope?.RecordChatCompletion(chatCompletion);
220 return ClientResult.FromValue(chatCompletion, result.GetRawResponse());
221 }
222 catch (Exception ex)
223 {
224 scope?.RecordException(ex);
225 throw;
226 }
227 }
228
229 /// <summary> Generates a completion for the given chat. </summary>
230 /// <param name="messages"> The messages comprising the chat so far. </param>
231 /// <param name="options"> The options to configure the chat completion. </param>
232 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
233 /// <exception cref="ArgumentNullException"> <paramref name="messages"/> is null. </exception>
234 /// <exception cref="ArgumentException"> <paramref name="messages"/> is an empty collection, and was expected to be non-empty. </exception>
235 public virtual ClientResult<ChatCompletion> CompleteChat(IEnumerable<ChatMessage> messages, ChatCompletionOptions options = null, CancellationToken cancellationToken = default)
236 {
237 Argument.AssertNotNullOrEmpty(messages, nameof(messages));
238
239 options ??= new();
240 var clonedOptions = CreateChatCompletionOptions(messages, options);
241 using OpenTelemetryScope scope = _telemetry.StartChatScope(clonedOptions);
242
243 try
244 {
245 using BinaryContent content = clonedOptions.ToBinaryContent();
246 ClientResult result = CompleteChat(content, cancellationToken.ToRequestOptions());
247 ChatCompletion chatCompletion = (ChatCompletion)result;
248
249 scope?.RecordChatCompletion(chatCompletion);
250 return ClientResult.FromValue(chatCompletion, result.GetRawResponse());
251 }
252 catch (Exception ex)
253 {
254 scope?.RecordException(ex);
255 throw;
256 }
257 }
258
259 /// <summary> Generates a completion for the given chat. </summary>
260 /// <param name="messages"> The messages comprising the chat so far. </param>
261 /// <exception cref="ArgumentNullException"> <paramref name="messages"/> is null. </exception>
262 /// <exception cref="ArgumentException"> <paramref name="messages"/> is an empty collection, and was expected to be non-empty. </exception>
263 public virtual async Task<ClientResult<ChatCompletion>> CompleteChatAsync(params ChatMessage[] messages)
264 => await CompleteChatAsync(messages, default(ChatCompletionOptions)).ConfigureAwait(false);
265
266 /// <summary> Generates a completion for the given chat. </summary>
267 /// <param name="messages"> The messages comprising the chat so far. </param>
268 /// <exception cref="ArgumentNullException"> <paramref name="messages"/> is null. </exception>
269 /// <exception cref="ArgumentException"> <paramref name="messages"/> is an empty collection, and was expected to be non-empty. </exception>
270 public virtual ClientResult<ChatCompletion> CompleteChat(params ChatMessage[] messages)
271 => CompleteChat(messages, default(ChatCompletionOptions));
272
273 /// <summary>
274 /// Generates a completion for the given chat. The completion is streamed back token by token as it is being
275 /// generated by the model instead of waiting for it to be finished first.
276 /// </summary>
277 /// <remarks>
278 /// <see cref="AsyncCollectionResult{T}"/> implements the <see cref="IAsyncEnumerable{T}"/> interface and can be
279 /// enumerated over using the <c>await foreach</c> pattern.
280 /// </remarks>
281 /// <param name="messages"> The messages comprising the chat so far. </param>
282 /// <param name="options"> The options to configure the chat completion. </param>
283 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
284 /// <exception cref="ArgumentNullException"> <paramref name="messages"/> is null. </exception>
285 /// <exception cref="ArgumentException"> <paramref name="messages"/> is an empty collection, and was expected to be non-empty. </exception>
286 public virtual AsyncCollectionResult<StreamingChatCompletionUpdate> CompleteChatStreamingAsync(IEnumerable<ChatMessage> messages, ChatCompletionOptions options = null, CancellationToken cancellationToken = default)
287 {
288 return CompleteChatStreamingAsync(messages, options, cancellationToken.ToRequestOptions(streaming: true));
289 }
290
291 internal AsyncCollectionResult<StreamingChatCompletionUpdate> CompleteChatStreamingAsync(IEnumerable<ChatMessage> messages, ChatCompletionOptions options, RequestOptions requestOptions)
292 {
293 Argument.AssertNotNull(messages, nameof(messages));
294 Argument.AssertNotNull(requestOptions, nameof(requestOptions));
295 if (requestOptions.BufferResponse is true)
296 {
297 throw new InvalidOperationException("'requestOptions.BufferResponse' must be 'false' when calling 'CompleteChatStreamingAsync'.");
298 }
299
300 options ??= new();
301 var clonedOptions = CreateChatCompletionOptions(messages, options, stream: true);
302
303 using BinaryContent content = clonedOptions.ToBinaryContent();
304 return new AsyncSseUpdateCollection<StreamingChatCompletionUpdate>(
305 async () => await CompleteChatAsync(content, requestOptions).ConfigureAwait(false),
306 StreamingChatCompletionUpdate.DeserializeStreamingChatCompletionUpdate,
307 requestOptions.CancellationToken);
308 }
309
310 /// <summary>
311 /// Generates a completion for the given chat. The completion is streamed back token by token as it is being
312 /// generated by the model instead of waiting for it to be finished first.
313 /// </summary>
314 /// <remarks>
315 /// <see cref="CollectionResult{T}"/> implements the <see cref="IEnumerable{T}"/> interface and can be
316 /// enumerated over using the <c>await foreach</c> pattern.
317 /// </remarks>
318 /// <param name="messages"> The messages comprising the chat so far. </param>
319 /// <param name="options"> The options to configure the chat completion. </param>
320 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
321 /// <exception cref="ArgumentNullException"> <paramref name="messages"/> is null. </exception>
322 /// <exception cref="ArgumentException"> <paramref name="messages"/> is an empty collection, and was expected to be non-empty. </exception>
323 public virtual CollectionResult<StreamingChatCompletionUpdate> CompleteChatStreaming(IEnumerable<ChatMessage> messages, ChatCompletionOptions options = null, CancellationToken cancellationToken = default)
324 {
325 Argument.AssertNotNull(messages, nameof(messages));
326
327 options ??= new();
328 var clonedOptions = CreateChatCompletionOptions(messages, options, stream: true);
329
330 using BinaryContent content = clonedOptions.ToBinaryContent();
331 return new SseUpdateCollection<StreamingChatCompletionUpdate>(
332 () => CompleteChat(content, cancellationToken.ToRequestOptions(streaming: true)),
333 StreamingChatCompletionUpdate.DeserializeStreamingChatCompletionUpdate,
334 cancellationToken);
335 }
336
337 /// <summary>
338 /// Generates a completion for the given chat. The completion is streamed back token by token as it is being
339 /// generated by the model instead of waiting for it to be finished first.
340 /// </summary>
341 /// <remarks>
342 /// <see cref="AsyncCollectionResult{T}"/> implements the <see cref="IAsyncEnumerable{T}"/> interface and can be
343 /// enumerated over using the <c>await foreach</c> pattern.
344 /// </remarks>
345 /// <param name="messages"> The messages comprising the chat so far. </param>
346 /// <exception cref="ArgumentNullException"> <paramref name="messages"/> is null. </exception>
347 /// <exception cref="ArgumentException"> <paramref name="messages"/> is an empty collection, and was expected to be non-empty. </exception>
348 public virtual AsyncCollectionResult<StreamingChatCompletionUpdate> CompleteChatStreamingAsync(params ChatMessage[] messages)
349 => CompleteChatStreamingAsync(messages, default(ChatCompletionOptions));
350
351 /// <summary>
352 /// Generates a completion for the given chat. The completion is streamed back token by token as it is being
353 /// generated by the model instead of waiting for it to be finished first.
354 /// </summary>
355 /// <remarks>
356 /// <see cref="CollectionResult{T}"/> implements the <see cref="IEnumerable{T}"/> interface and can be
357 /// enumerated over using the <c>await foreach</c> pattern.
358 /// </remarks>
359 /// <param name="messages"> The messages comprising the chat so far. </param>
360 /// <exception cref="ArgumentNullException"> <paramref name="messages"/> is null. </exception>
361 /// <exception cref="ArgumentException"> <paramref name="messages"/> is an empty collection, and was expected to be non-empty. </exception>
362 public virtual CollectionResult<StreamingChatCompletionUpdate> CompleteChatStreaming(params ChatMessage[] messages)
363 => CompleteChatStreaming(messages, default(ChatCompletionOptions));
364
365 // CUSTOM:
366 // - Added Experimental attribute.
367 // - Call FromClientResult.
368 [Experimental("OPENAI001")]
369 public virtual async Task<ClientResult<ChatCompletion>> GetChatCompletionAsync(string completionId, CancellationToken cancellationToken = default)
370 {
371 Argument.AssertNotNullOrEmpty(completionId, nameof(completionId));
372
373 ClientResult result = await GetChatCompletionAsync(completionId, cancellationToken.CanBeCanceled ? new RequestOptions { CancellationToken = cancellationToken } : null).ConfigureAwait(false);
374 return ClientResult.FromValue((ChatCompletion)result, result.GetRawResponse());
375 }
376
377 // CUSTOM:
378 // - Added Experimental attribute.
379 // - Call FromClientResult.
380 [Experimental("OPENAI001")]
381 public virtual ClientResult<ChatCompletion> GetChatCompletion(string completionId, CancellationToken cancellationToken = default)
382 {
383 Argument.AssertNotNullOrEmpty(completionId, nameof(completionId));
384
385 ClientResult result = GetChatCompletion(completionId, cancellationToken.CanBeCanceled ? new RequestOptions { CancellationToken = cancellationToken } : null);
386 return ClientResult.FromValue((ChatCompletion)result, result.GetRawResponse());
387 }
388
389 // CUSTOM:
390 // - Call FromClientResult.
391 [Experimental("OPENAI001")]
392 public virtual ClientResult<ChatCompletion> UpdateChatCompletion(string completionId, IDictionary<string, string> metadata, CancellationToken cancellationToken = default)
393 {
394 Argument.AssertNotNullOrEmpty(completionId, nameof(completionId));
395 Argument.AssertNotNull(metadata, nameof(metadata));
396
397 InternalUpdateChatCompletionRequest spreadModel = new InternalUpdateChatCompletionRequest(metadata, null);
398 ClientResult result = this.UpdateChatCompletion(completionId, spreadModel, cancellationToken.CanBeCanceled ? new RequestOptions { CancellationToken = cancellationToken } : null);
399 return ClientResult.FromValue((ChatCompletion)result, result.GetRawResponse());
400 }
401
402 // CUSTOM:
403 // - Call FromClientResult.
404 [Experimental("OPENAI001")]
405 public virtual async Task<ClientResult<ChatCompletion>> UpdateChatCompletionAsync(string completionId, IDictionary<string, string> metadata, CancellationToken cancellationToken = default)
406 {
407 Argument.AssertNotNullOrEmpty(completionId, nameof(completionId));
408 Argument.AssertNotNull(metadata, nameof(metadata));
409
410 InternalUpdateChatCompletionRequest spreadModel = new InternalUpdateChatCompletionRequest(metadata, null);
411 ClientResult result = await this.UpdateChatCompletionAsync(completionId, spreadModel, cancellationToken.CanBeCanceled ? new RequestOptions { CancellationToken = cancellationToken } : null).ConfigureAwait(false);
412 return ClientResult.FromValue((ChatCompletion)result, result.GetRawResponse());
413 }
414
415 // CUSTOM:
416 // - Added Experimental attribute.
417 // - Call FromClientResult.
418 [Experimental("OPENAI001")]
419 public virtual async Task<ClientResult<ChatCompletionDeletionResult>> DeleteChatCompletionAsync(string completionId, CancellationToken cancellationToken = default)
420 {
421 Argument.AssertNotNullOrEmpty(completionId, nameof(completionId));
422
423 ClientResult result = await DeleteChatCompletionAsync(completionId, cancellationToken.CanBeCanceled ? new RequestOptions { CancellationToken = cancellationToken } : null).ConfigureAwait(false);
424 return ClientResult.FromValue((ChatCompletionDeletionResult)result, result.GetRawResponse());
425 }
426
427 // CUSTOM:
428 // - Added Experimental attribute.
429 // - Call FromClientResult.
430 [Experimental("OPENAI001")]
431 public virtual ClientResult<ChatCompletionDeletionResult> DeleteChatCompletion(string completionId, CancellationToken cancellationToken = default)
432 {
433 Argument.AssertNotNullOrEmpty(completionId, nameof(completionId));
434
435 ClientResult result = DeleteChatCompletion(completionId, cancellationToken.CanBeCanceled ? new RequestOptions { CancellationToken = cancellationToken } : null);
436 return ClientResult.FromValue((ChatCompletionDeletionResult)result, result.GetRawResponse());
437 }
438
439 private ChatCompletionOptions CreateChatCompletionOptions(IEnumerable<ChatMessage> messages, ChatCompletionOptions options, bool stream = false)
440 {
441 var clonedOptions = options.Clone();
442 foreach (var message in messages)
443 {
444 clonedOptions.Messages.Add(message);
445 }
446 clonedOptions.Model ??= _model;
447 if (stream)
448 {
449 clonedOptions.Stream = true;
450 clonedOptions.StreamOptions = s_includeUsageStreamOptions;
451 }
452 else
453 {
454 clonedOptions.Stream = null;
455 clonedOptions.StreamOptions = null;
456 }
457 return clonedOptions;
458 }
459}