diff --git a/OpenAI_API/Embedding/EmbeddingEndpoint.cs b/OpenAI_API/Embedding/EmbeddingEndpoint.cs index 6796b07..617af78 100644 --- a/OpenAI_API/Embedding/EmbeddingEndpoint.cs +++ b/OpenAI_API/Embedding/EmbeddingEndpoint.cs @@ -1,77 +1,59 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Security.Authentication; -using System.Text; -using System.Threading.Tasks; +using System.Threading.Tasks; namespace OpenAI_API.Embedding { - /// - /// OpenAI’s text embeddings measure the relatedness of text strings by generating an embedding, which is a vector (list) of floating point numbers. The distance between two vectors measures their relatedness. Small distances suggest high relatedness and large distances suggest low relatedness. - /// - public class EmbeddingEndpoint - { - OpenAIAPI Api; - /// - /// This allows you to send request to the recommended model without needing to specify. Every request uses the model - /// - public EmbeddingRequest DefaultEmbeddingRequestArgs { get; set; } = new EmbeddingRequest() { Model = Model.AdaTextEmbedding }; - - /// - /// Constructor of the api endpoint. Rather than instantiating this yourself, access it through an instance of as . - /// - /// - internal EmbeddingEndpoint(OpenAIAPI api) - { - this.Api = api; - } - - /// - /// Ask the API to embedd text using the default embedding model - /// - /// Text to be embedded - /// Asynchronously returns the embedding result. Look in its property of to find the vector of floating point numbers - public async Task CreateEmbeddingAsync(string input) - { - DefaultEmbeddingRequestArgs.Input = input; - return await CreateEmbeddingAsync(DefaultEmbeddingRequestArgs); - } - - /// - /// Ask the API to embedd text using a custom request - /// - /// Request to be send - /// Asynchronously returns the embedding result. Look in its property of to find the vector of floating point numbers - public async Task CreateEmbeddingAsync(EmbeddingRequest request) - { - if (Api.Auth?.ApiKey is null) - { - throw new AuthenticationException("You must provide API authentication. Please refer to https://github.com/OkGoDoIt/OpenAI-API-dotnet#authentication for details."); - } - - HttpClient client = new HttpClient(); - client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", Api.Auth.ApiKey); - client.DefaultRequestHeaders.Add("User-Agent", "okgodoit/dotnet_openai_api"); - - string jsonContent = JsonConvert.SerializeObject(request, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore }); - var stringContent = new StringContent(jsonContent, Encoding.UTF8, "application/json"); - - var response = await client.PostAsync($"https://api.openai.com/v1/embeddings", stringContent); - if (response.IsSuccessStatusCode) - { - string resultAsString = await response.Content.ReadAsStringAsync(); - - var res = JsonConvert.DeserializeObject(resultAsString); - - return res; - } - else - { - throw new HttpRequestException("Error calling OpenAi API to get completion. HTTP status code: " + response.StatusCode.ToString() + ". Request body: " + jsonContent); - } - } - - } + /// + /// OpenAI’s text embeddings measure the relatedness of text strings by generating an embedding, which is a vector (list) of floating point numbers. The distance between two vectors measures their relatedness. Small distances suggest high relatedness and large distances suggest low relatedness. + /// + public class EmbeddingEndpoint : EndpointBase + { + /// + /// This allows you to send request to the recommended model without needing to specify. Every request uses the model + /// + public EmbeddingRequest DefaultEmbeddingRequestArgs { get; set; } = new EmbeddingRequest() { Model = Model.AdaTextEmbedding }; + + /// + /// The name of the endpoint, which is the final path segment in the API URL. For example, "embeddings". + /// + protected override string Endpoint { get { return "embeddings"; } } + + /// + /// Constructor of the api endpoint. Rather than instantiating this yourself, access it through an instance of as . + /// + /// + internal EmbeddingEndpoint(OpenAIAPI api) : base(api) { } + + /// + /// Ask the API to embedd text using the default embedding model + /// + /// Text to be embedded + /// Asynchronously returns the embedding result. Look in its property of to find the vector of floating point numbers + public async Task CreateEmbeddingAsync(string input) + { + EmbeddingRequest req = new EmbeddingRequest(DefaultEmbeddingRequestArgs.Model, input); + return await CreateEmbeddingAsync(req); + } + + /// + /// Ask the API to embedd text using a custom request + /// + /// Request to be send + /// Asynchronously returns the embedding result. Look in its property of to find the vector of floating point numbers + public async Task CreateEmbeddingAsync(EmbeddingRequest request) + { + return await HttpPost(postData: request); + } + + /// + /// Ask the API to embedd text using the default embedding model + /// + /// Text to be embedded + /// Asynchronously returns the first embedding result as an array of floats. + public async Task GetEmbeddingsAsync(string input) + { + EmbeddingRequest req = new EmbeddingRequest(DefaultEmbeddingRequestArgs.Model, input); + var embeddingResult = await CreateEmbeddingAsync(req); + return embeddingResult?.Data?[0]?.Embedding; + } + } } diff --git a/OpenAI_API/Embedding/EmbeddingRequest.cs b/OpenAI_API/Embedding/EmbeddingRequest.cs index a08b738..0ffb12f 100644 --- a/OpenAI_API/Embedding/EmbeddingRequest.cs +++ b/OpenAI_API/Embedding/EmbeddingRequest.cs @@ -1,50 +1,51 @@ using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Text; namespace OpenAI_API.Embedding { - /// - /// Represents a request to the Completions API. Matches with the docs at the OpenAI docs - /// - public class EmbeddingRequest - { - /// - /// ID of the model to use. You can use to see all of your available models, or use a standard model like . - /// - [JsonIgnore] - public Model Model { get; set; } + /// + /// Represents a request to the Completions API. Matches with the docs at the OpenAI docs + /// + public class EmbeddingRequest + { + /// + /// ID of the model to use. You can use to see all of your available models, or use a standard model like . + /// + [JsonProperty("model")] + public string Model { get; set; } - /// - /// The id/name of the model - /// - [JsonProperty("model")] - public string ModelName => Model.ModelID; + /// + /// Main text to be embedded + /// + [JsonProperty("input")] + public string Input { get; set; } - /// - /// Main text to be embedded - /// - [JsonProperty("input")] - public string Input { get; set; } + /// + /// Cretes a new, empty + /// + public EmbeddingRequest() + { - /// - /// Cretes a new, empty - /// - public EmbeddingRequest() - { + } - } + /// + /// Creates a new with the specified parameters + /// + /// The model to use. You can use to see all of your available models, or use a standard model like . + /// The prompt to transform + public EmbeddingRequest(Model model, string input) + { + Model = model; + this.Input = input; + } - /// - /// Creates a new with the specified parameters - /// - /// The model to use. You can use to see all of your available models, or use a standard model like . - /// The prompt to transform - public EmbeddingRequest(Model model, string input) - { - Model = model; - this.Input = input; - } - } + /// + /// Creates a new with the specified input and the model. + /// + /// The prompt to transform + public EmbeddingRequest(string input) + { + Model = OpenAI_API.Model.AdaTextEmbedding; + this.Input = input; + } + } } diff --git a/OpenAI_API/Embedding/EmbeddingResult.cs b/OpenAI_API/Embedding/EmbeddingResult.cs index 7dcceb6..2801ef2 100644 --- a/OpenAI_API/Embedding/EmbeddingResult.cs +++ b/OpenAI_API/Embedding/EmbeddingResult.cs @@ -1,84 +1,78 @@ using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Text; +using System.Linq; namespace OpenAI_API.Embedding { - /// - /// Represents an embedding result returned by the Embedding API. - /// - public class EmbeddingResult - { - /// - /// Type of the response. In case of embeddings, this will be "list" - /// - [JsonProperty("object")] + /// + /// Represents an embedding result returned by the Embedding API. + /// + public class EmbeddingResult : ApiResultBase + { + /// + /// List of results of the embedding + /// + [JsonProperty("data")] + public Data[] Data { get; set; } - public string Object { get; set; } + /// + /// Usage statistics of how many tokens have been used for this request + /// + [JsonProperty("usage")] + public Usage Usage { get; set; } - /// - /// List of results of the embedding - /// - [JsonProperty("data")] - public Data[] Data { get; set; } + /// + /// Allows an EmbeddingResult to be implicitly cast to the array of floats repsresenting the first ebmedding result + /// + /// The to cast to an array of floats. + public static implicit operator float[](EmbeddingResult embeddingResult) + { + return embeddingResult.Data.FirstOrDefault()?.Embedding; + } + } - /// - /// Name of the model used to generate this embedding - /// - [JsonProperty("model")] - public string Model { get; set; } + /// + /// Data returned from the Embedding API. + /// + public class Data + { + /// + /// Type of the response. In case of Data, this will be "embedding" + /// + [JsonProperty("object")] - /// - /// Usage statistics of how many tokens have been used for this request - /// - [JsonProperty("usage")] - public Usage Usage { get; set; } - } + public string Object { get; set; } - /// - /// Data returned from the Embedding API. - /// - public class Data - { - /// - /// Type of the response. In case of Data, this will be "embedding" - /// - [JsonProperty("object")] + /// + /// The input text represented as a vector (list) of floating point numbers + /// + [JsonProperty("embedding")] + public float[] Embedding { get; set; } - public string Object { get; set; } + /// + /// Index + /// + [JsonProperty("index")] + public int Index { get; set; } - /// - /// The input text represented as a vector (list) of floating point numbers - /// - [JsonProperty("embedding")] - public float[] Embedding { get; set; } + } - /// - /// Index - /// - [JsonProperty("index")] - public int Index { get; set; } + /// + /// Usage statistics of how many tokens have been used for this request. + /// + public class Usage + { + /// + /// How many tokens did the prompt consist of + /// + [JsonProperty("prompt_tokens")] + public int PromptTokens { get; set; } - } + /// + /// How many tokens did the request consume total + /// + [JsonProperty("total_tokens")] + public int TotalTokens { get; set; } - /// - /// Usage statistics of how many tokens have been used for this request. - /// - public class Usage - { - /// - /// How many tokens did the prompt consist of - /// - [JsonProperty("prompt_tokens")] - public int PromptTokens { get; set; } - - /// - /// How many tokens did the request consume total - /// - [JsonProperty("total_tokens")] - public int TotalTokens { get; set; } - - } + } } diff --git a/OpenAI_API/OpenAIAPI.cs b/OpenAI_API/OpenAIAPI.cs index d764408..93f21e0 100644 --- a/OpenAI_API/OpenAIAPI.cs +++ b/OpenAI_API/OpenAIAPI.cs @@ -10,6 +10,11 @@ namespace OpenAI_API /// public class OpenAIAPI { + /// + /// Base url for OpenAI + /// + public string ApiUrlBase = "https://api.openai.com/v1/"; + /// /// The API authentication information to use for API calls /// @@ -24,7 +29,7 @@ public OpenAIAPI(APIAuthentication apiKeys = null) this.Auth = apiKeys.ThisOrDefault(); Completions = new CompletionEndpoint(this); Models = new ModelsEndpoint(this); - Search = new SearchEndpoint(this); + //Search = new SearchEndpoint(this); Embeddings = new EmbeddingEndpoint(this); } diff --git a/OpenAI_Tests/EmbeddingEndpointTests.cs b/OpenAI_Tests/EmbeddingEndpointTests.cs index 93eb110..982a91b 100644 --- a/OpenAI_Tests/EmbeddingEndpointTests.cs +++ b/OpenAI_Tests/EmbeddingEndpointTests.cs @@ -2,9 +2,7 @@ using OpenAI_API; using OpenAI_API.Embedding; using System; -using System.Collections.Generic; using System.Linq; -using System.Text; namespace OpenAI_Tests { @@ -30,7 +28,6 @@ public void GetBasicEmbedding() Assert.That(results.Data.First().Embedding.Length == 1536); } - [Test] public void GetSimpleEmbedding() { @@ -38,11 +35,9 @@ public void GetSimpleEmbedding() Assert.IsNotNull(api.Embeddings); - var results = api.Embeddings.CreateEmbeddingAsync("A test text for embedding").Result; + var results = api.Embeddings.GetEmbeddingsAsync("A test text for embedding").Result; Assert.IsNotNull(results); - Assert.NotNull(results.Object); - Assert.NotZero(results.Data.Length); - Assert.That(results.Data.First().Embedding.Length == 1536); + Assert.That(results.Length == 1536); } } }