openai/openai-dotnet

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
achandmsft-patch-1

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/Custom/Embeddings/EmbeddingClient.cs

266lines · modecode

1using System;
2using System.ClientModel;
3using System.ClientModel.Primitives;
4using System.Collections.Generic;
5using System.IO;
6using System.Linq;
7using System.Text.Json;
8using System.Threading;
9using System.Threading.Tasks;
10
11namespace OpenAI.Embeddings;
12
13// CUSTOM:
14// - Renamed.
15// - Suppressed constructor that takes endpoint parameter; endpoint is now a property in the options class.
16// - Suppressed methods that only take the options parameter.
17/// <summary> The service client for OpenAI embedding operations. </summary>
18[CodeGenType("Embeddings")]
19[CodeGenSuppress("EmbeddingClient", typeof(ClientPipeline), typeof(Uri))]
20[CodeGenSuppress("CreateEmbeddingAsync", typeof(EmbeddingGenerationOptions), typeof(CancellationToken))]
21[CodeGenSuppress("CreateEmbedding", typeof(EmbeddingGenerationOptions), typeof(CancellationToken))]
22public partial class EmbeddingClient
23{
24 private readonly string _model;
25
26 // CUSTOM: Added as a convenience.
27 /// <summary> Initializes a new instance of <see cref="EmbeddingClient"/>. </summary>
28 /// <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>
29 /// <param name="apiKey"> The API key to authenticate with the service. </param>
30 /// <exception cref="ArgumentNullException"> <paramref name="model"/> or <paramref name="apiKey"/> is null. </exception>
31 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
32 public EmbeddingClient(string model, string apiKey) : this(model, new ApiKeyCredential(apiKey), new OpenAIClientOptions())
33 {
34 }
35
36 // CUSTOM:
37 // - Added `model` parameter.
38 // - Used a custom pipeline.
39 // - Demoted the endpoint parameter to be a property in the options class.
40 /// <summary> Initializes a new instance of <see cref="EmbeddingClient"/>. </summary>
41 /// <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>
42 /// <param name="credential"> The API key to authenticate with the service. </param>
43 /// <exception cref="ArgumentNullException"> <paramref name="model"/> or <paramref name="credential"/> is null. </exception>
44 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
45 public EmbeddingClient(string model, ApiKeyCredential credential) : this(model, credential, new OpenAIClientOptions())
46 {
47 }
48
49 // CUSTOM:
50 // - Added `model` parameter.
51 // - Used a custom pipeline.
52 // - Demoted the endpoint parameter to be a property in the options class.
53 /// <summary> Initializes a new instance of <see cref="EmbeddingClient"/>. </summary>
54 /// <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>
55 /// <param name="credential"> The API key to authenticate with the service. </param>
56 /// <param name="options"> The options to configure the client. </param>
57 /// <exception cref="ArgumentNullException"> <paramref name="model"/> or <paramref name="credential"/> is null. </exception>
58 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
59 public EmbeddingClient(string model, ApiKeyCredential credential, OpenAIClientOptions options)
60 {
61 Argument.AssertNotNullOrEmpty(model, nameof(model));
62 Argument.AssertNotNull(credential, nameof(credential));
63 options ??= new OpenAIClientOptions();
64
65 _model = model;
66 Pipeline = OpenAIClient.CreatePipeline(credential, options);
67 _endpoint = OpenAIClient.GetEndpoint(options);
68 }
69
70 // CUSTOM:
71 // - Added `model` parameter.
72 // - Used a custom pipeline.
73 // - Demoted the endpoint parameter to be a property in the options class.
74 // - Made protected.
75 /// <summary> Initializes a new instance of <see cref="EmbeddingClient"/>. </summary>
76 /// <param name="pipeline"> The HTTP pipeline to send and receive REST requests and responses. </param>
77 /// <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>
78 /// <param name="options"> The options to configure the client. </param>
79 /// <exception cref="ArgumentNullException"> <paramref name="pipeline"/> or <paramref name="model"/> is null. </exception>
80 /// <exception cref="ArgumentException"> <paramref name="model"/> is an empty string, and was expected to be non-empty. </exception>
81 protected internal EmbeddingClient(ClientPipeline pipeline, string model, OpenAIClientOptions options)
82 {
83 Argument.AssertNotNull(pipeline, nameof(pipeline));
84 Argument.AssertNotNullOrEmpty(model, nameof(model));
85 options ??= new OpenAIClientOptions();
86
87 _model = model;
88 Pipeline = pipeline;
89 _endpoint = OpenAIClient.GetEndpoint(options);
90 }
91
92 // CUSTOM: Added to simplify generating a single embedding from a string input.
93 /// <summary> Generates an embedding representing the text input. </summary>
94 /// <param name="input"> The text input to generate an embedding for. </param>
95 /// <param name="options"> The options to configure the embedding generation. </param>
96 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
97 /// <exception cref="ArgumentNullException"> <paramref name="input"/> is null. </exception>
98 /// <exception cref="ArgumentException"> <paramref name="input"/> is an empty string, and was expected to be non-empty. </exception>
99 public virtual async Task<ClientResult<OpenAIEmbedding>> GenerateEmbeddingAsync(string input, EmbeddingGenerationOptions options = null, CancellationToken cancellationToken = default)
100 {
101 Argument.AssertNotNullOrEmpty(input, nameof(input));
102
103 options ??= new();
104 CreateEmbeddingGenerationOptions(input, ref options);
105
106 using BinaryContent content = options;
107 ClientResult result = await GenerateEmbeddingsAsync(content, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
108 return ClientResult.FromValue(((OpenAIEmbeddingCollection)result).FirstOrDefault(), result.GetRawResponse());
109 }
110
111 // CUSTOM: Added to simplify generating a single embedding from a string input.
112 /// <summary> Generates an embedding representing the text input. </summary>
113 /// <param name="input"> The text input to generate an embedding for. </param>
114 /// <param name="options"> The options to configure the embedding generation. </param>
115 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
116 /// <exception cref="ArgumentNullException"> <paramref name="input"/> is null. </exception>
117 /// <exception cref="ArgumentException"> <paramref name="input"/> is an empty string, and was expected to be non-empty. </exception>
118 public virtual ClientResult<OpenAIEmbedding> GenerateEmbedding(string input, EmbeddingGenerationOptions options = null, CancellationToken cancellationToken = default)
119 {
120 Argument.AssertNotNullOrEmpty(input, nameof(input));
121
122 options ??= new();
123 CreateEmbeddingGenerationOptions(input, ref options);
124
125 using BinaryContent content = options;
126 ClientResult result = GenerateEmbeddings(content, cancellationToken.ToRequestOptions());
127 return ClientResult.FromValue(((OpenAIEmbeddingCollection)result).FirstOrDefault(), result.GetRawResponse());
128 }
129
130 // CUSTOM: Added to simplify passing the input as a collection of strings instead of BinaryData.
131 /// <summary> Generates embeddings representing the text inputs. </summary>
132 /// <param name="inputs"> The text inputs to generate embeddings for. </param>
133 /// <param name="options"> The options to configure the embedding generation. </param>
134 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
135 /// <exception cref="ArgumentNullException"> <paramref name="inputs"/> is null. </exception>
136 /// <exception cref="ArgumentException"> <paramref name="inputs"/> is an empty collection, and was expected to be non-empty. </exception>
137 public virtual async Task<ClientResult<OpenAIEmbeddingCollection>> GenerateEmbeddingsAsync(IEnumerable<string> inputs, EmbeddingGenerationOptions options = null, CancellationToken cancellationToken = default)
138 {
139 Argument.AssertNotNullOrEmpty(inputs, nameof(inputs));
140
141 options ??= new();
142 CreateEmbeddingGenerationOptions(inputs, ref options);
143
144 using BinaryContent content = options;
145 ClientResult result = await GenerateEmbeddingsAsync(content, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
146 return ClientResult.FromValue((OpenAIEmbeddingCollection)result, result.GetRawResponse());
147
148 }
149
150 // CUSTOM: Added to simplify passing the input as a collection of strings instead of BinaryData.
151 /// <summary> Generates embeddings representing the text inputs. </summary>
152 /// <param name="inputs"> The text inputs to generate embeddings for. </param>
153 /// <param name="options"> The options to configure the embedding generation. </param>
154 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
155 /// <exception cref="ArgumentNullException"> <paramref name="inputs"/> is null. </exception>
156 /// <exception cref="ArgumentException"> <paramref name="inputs"/> is an empty collection, and was expected to be non-empty. </exception>
157 public virtual ClientResult<OpenAIEmbeddingCollection> GenerateEmbeddings(IEnumerable<string> inputs, EmbeddingGenerationOptions options = null, CancellationToken cancellationToken = default)
158 {
159 Argument.AssertNotNullOrEmpty(inputs, nameof(inputs));
160
161 options ??= new();
162 CreateEmbeddingGenerationOptions(inputs, ref options);
163
164 using BinaryContent content = options;
165 ClientResult result = GenerateEmbeddings(content, cancellationToken.ToRequestOptions());
166 return ClientResult.FromValue((OpenAIEmbeddingCollection)result, result.GetRawResponse());
167 }
168
169 // CUSTOM: Added to simplify passing the input as a collection of ReadOnlyMemory tokens instead of BinaryData.
170 /// <summary> Generates embeddings representing the tokenized text inputs. </summary>
171 /// <param name="inputs"> The tokenized text inputs to generate embeddings for. </param>
172 /// <param name="options"> The options to configure the embedding generation. </param>
173 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
174 /// <exception cref="ArgumentNullException"> <paramref name="inputs"/> is null. </exception>
175 /// <exception cref="ArgumentException"> <paramref name="inputs"/> is an empty collection, and was expected to be non-empty. </exception>
176 public virtual async Task<ClientResult<OpenAIEmbeddingCollection>> GenerateEmbeddingsAsync(IEnumerable<ReadOnlyMemory<int>> inputs, EmbeddingGenerationOptions options = null, CancellationToken cancellationToken = default)
177 {
178 Argument.AssertNotNullOrEmpty(inputs, nameof(inputs));
179
180 options ??= new();
181 CreateEmbeddingGenerationOptions(inputs, ref options);
182
183 using BinaryContent content = options;
184 ClientResult result = await GenerateEmbeddingsAsync(content, cancellationToken.ToRequestOptions()).ConfigureAwait(false);
185 return ClientResult.FromValue((OpenAIEmbeddingCollection)result, result.GetRawResponse());
186 }
187
188 // CUSTOM: Added to simplify passing the input as a collection of ReadOnlyMemory of tokens instead of BinaryData.
189 /// <summary> Generates embeddings representing the tokenized text inputs. </summary>
190 /// <param name="inputs"> The tokenized text inputs to generate embeddings for. </param>
191 /// <param name="options"> The options to configure the embedding generation. </param>
192 /// <param name="cancellationToken"> A token that can be used to cancel this method call. </param>
193 /// <exception cref="ArgumentNullException"> <paramref name="inputs"/> is null. </exception>
194 /// <exception cref="ArgumentException"> <paramref name="inputs"/> is an empty collection, and was expected to be non-empty. </exception>
195 public virtual ClientResult<OpenAIEmbeddingCollection> GenerateEmbeddings(IEnumerable<ReadOnlyMemory<int>> inputs, EmbeddingGenerationOptions options = null, CancellationToken cancellationToken = default)
196 {
197 Argument.AssertNotNullOrEmpty(inputs, nameof(inputs));
198
199 options ??= new();
200 CreateEmbeddingGenerationOptions(inputs, ref options);
201
202 using BinaryContent content = options;
203 ClientResult result = GenerateEmbeddings(content, cancellationToken.ToRequestOptions());
204 return ClientResult.FromValue((OpenAIEmbeddingCollection)result, result.GetRawResponse());
205 }
206
207 private void CreateEmbeddingGenerationOptions(string input, ref EmbeddingGenerationOptions options)
208 {
209 using MemoryStream stream = new();
210 using Utf8JsonWriter writer = new(stream);
211
212 writer.WriteStringValue(input);
213 writer.Flush();
214
215 options.Input = BinaryData.FromBytes(stream.ToArray());
216 options.Model = _model;
217 options.EncodingFormat = InternalCreateEmbeddingRequestEncodingFormat.Base64;
218 }
219
220 private void CreateEmbeddingGenerationOptions(IEnumerable<string> inputs, ref EmbeddingGenerationOptions options)
221 {
222 using MemoryStream stream = new();
223 using Utf8JsonWriter writer = new(stream);
224
225 writer.WriteStartArray();
226
227 foreach (string input in inputs)
228 {
229 writer.WriteStringValue(input);
230 }
231
232 writer.WriteEndArray();
233 writer.Flush();
234
235 options.Input = BinaryData.FromBytes(stream.ToArray());
236 options.Model = _model;
237 options.EncodingFormat = InternalCreateEmbeddingRequestEncodingFormat.Base64;
238 }
239
240 private void CreateEmbeddingGenerationOptions(IEnumerable<ReadOnlyMemory<int>> inputs, ref EmbeddingGenerationOptions options)
241 {
242 using MemoryStream stream = new();
243 using Utf8JsonWriter writer = new(stream);
244
245 writer.WriteStartArray();
246
247 foreach (ReadOnlyMemory<int> input in inputs)
248 {
249 writer.WriteStartArray();
250
251 foreach (int tokenId in input.ToArray())
252 {
253 writer.WriteNumberValue(tokenId);
254 }
255
256 writer.WriteEndArray();
257 }
258
259 writer.WriteEndArray();
260 writer.Flush();
261
262 options.Input = BinaryData.FromBytes(stream.ToArray());
263 options.Model = _model;
264 options.EncodingFormat = InternalCreateEmbeddingRequestEncodingFormat.Base64;
265 }
266}
267