Skip to content

OpenAI

Nuget package dotnet License: MIT Discord CodeRabbit Pull Request Reviews

Features 🔥

  • Fully generated C# SDK based on official OpenAI OpenAPI specification using AutoSDK
  • Same day update to support new features
  • Updated and supported automatically if there are no breaking changes
  • Contains a supported list of constants such as current prices, models, and other
  • Source generator to define functions natively through C# interfaces
  • All modern .NET features - nullability, trimming, NativeAOT, etc.
  • Support .Net Framework/.Net Standard 2.0
  • Support all OpenAI API endpoints including completions, chat, embeddings, images, assistants and more.
  • Regularly tested for compatibility with popular custom providers like OpenRouter/DeepSeek/Ollama/LM Studio and many others

Documentation

Examples and documentation can be found here: https://tryagi.github.io/OpenAI/

Usage

 1  2  3  4  5  6  7  8  9 10 11 12 13 14
using var api = new OpenAiApi("API_KEY"); string response = await api.Chat.CreateChatCompletionAsync(  messages: ["Generate five random words."],  model: CreateChatCompletionRequestModel.Gpt4oMini); Console.WriteLine(response); // "apple, banana, cherry, date, elderberry" var enumerable = api.Chat.CreateChatCompletionAsStreamAsync(  messages: ["Generate five random words."],  model: CreateChatCompletionRequestModel.Gpt4oMini); await foreach (string response in enumerable) {  Console.WriteLine(response); } 
It uses three implicit conversions: - from string to ChatCompletionRequestUserMessage. It will always be converted to the user message. - from ChatCompletionResponseMessage to string . It will always contain the first choice message content. - from CreateChatCompletionStreamResponse to string . It will always contain the first delta content.

You still can use the full response objects if you need more information, just replace string response to var response.

Tools

 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
using OpenAI; using CSharpToJsonSchema; public enum Unit {  Celsius,  Fahrenheit, } public class Weather {  public string Location { get; set; } = string.Empty;  public double Temperature { get; set; }  public Unit Unit { get; set; }  public string Description { get; set; } = string.Empty; } [GenerateJsonSchema(Strict = true)] // false by default. You can't use parameters with default values in Strict mode. public interface IWeatherFunctions {  [Description("Get the current weather in a given location")]  public Task<Weather> GetCurrentWeatherAsync(  [Description("The city and state, e.g. San Francisco, CA")] string location,  Unit unit,  CancellationToken cancellationToken = default); } public class WeatherService : IWeatherFunctions {  public Task<Weather> GetCurrentWeatherAsync(string location, Unit unit = Unit.Celsius, CancellationToken cancellationToken = default)  {  return Task.FromResult(new Weather  {  Location = location,  Temperature = 22.0,  Unit = unit,  Description = "Sunny",  });  } } using var api = new OpenAiApi("API_KEY"); var service = new WeatherService(); var tools = service.AsTools().AsOpenAiTools(); var messages = new List<ChatCompletionRequestMessage> {  "You are a helpful weather assistant.".AsSystemMessage(),  "What is the current temperature in Dubai, UAE in Celsius?".AsUserMessage(), }; var model = CreateChatCompletionRequestModel.Gpt4oMini; var result = await api.Chat.CreateChatCompletionAsync(  messages,  model: model,  tools: tools); var resultMessage = result.Choices.First().Message; messages.Add(resultMessage.AsRequestMessage()); foreach (var call in resultMessage.ToolCalls) {  var json = await service.CallAsync(  functionName: call.Function.Name,  argumentsAsJson: call.Function.Arguments);  messages.Add(json.AsToolMessage(call.Id)); } var result = await api.Chat.CreateChatCompletionAsync(  messages,  model: model,  tools: tools); var resultMessage = result.Choices.First().Message; messages.Add(resultMessage.AsRequestMessage()); 
 1  2  3  4  5  6  7  8  9 10 11
> System: You are a helpful weather assistant. > User: What is the current temperature in Dubai, UAE in Celsius? > Assistant: call_3sptsiHzKnaxF8bs8BWxPo0B: GetCurrentWeather({"location":"Dubai, UAE","unit":"celsius"}) > Tool(call_3sptsiHzKnaxF8bs8BWxPo0B): {"location":"Dubai, UAE","temperature":22,"unit":"celsius","description":"Sunny"} > Assistant: The current temperature in Dubai, UAE is 22°C with sunny weather. 

Structured Outputs

 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19
using OpenAI; using var api = new OpenAiApi("API_KEY"); var response = await api.Chat.CreateChatCompletionAsAsync<Weather>(  messages: ["Generate random weather."],  model: CreateChatCompletionRequestModel.Gpt4oMini,  jsonSerializerOptions: new JsonSerializerOptions  {  Converters = {new JsonStringEnumConverter()},  }); // or (if you need trimmable/NativeAOT version) var response = await api.Chat.CreateChatCompletionAsAsync(  jsonTypeInfo: SourceGeneratedContext.Default.Weather,  messages: ["Generate random weather."],  model: CreateChatCompletionRequestModel.Gpt4oMini); // response.Value1 contains the structured output // response.Value2 contains the CreateChatCompletionResponse object 
1 2 3 4 5 6 7
Weather: Location: San Francisco, CA Temperature: 65 Unit: Fahrenheit Description: Partly cloudy with a light breeze and occasional sunshine. Raw Response: {"Location":"San Francisco, CA","Temperature":65,"Unit":"Fahrenheit","Description":"Partly cloudy with a light breeze and occasional sunshine."} 
Additional code for trimmable/NativeAOT version:
1 2 3
[JsonSourceGenerationOptions(Converters = [typeof(JsonStringEnumConverter<Unit>)])] [JsonSerializable(typeof(Weather))] public partial class SourceGeneratedContext : JsonSerializerContext; 

Custom providers

 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19
using OpenAI; using var api = CustomProviders.GitHubModels("GITHUB_TOKEN"); using var api = CustomProviders.Azure("API_KEY", "ENDPOINT"); using var api = CustomProviders.DeepInfra("API_KEY"); using var api = CustomProviders.Groq("API_KEY"); using var api = CustomProviders.XAi("API_KEY"); using var api = CustomProviders.DeepSeek("API_KEY"); using var api = CustomProviders.Fireworks("API_KEY"); using var api = CustomProviders.OpenRouter("API_KEY"); using var api = CustomProviders.Together("API_KEY"); using var api = CustomProviders.Perplexity("API_KEY"); using var api = CustomProviders.SambaNova("API_KEY"); using var api = CustomProviders.Mistral("API_KEY"); using var api = CustomProviders.Codestral("API_KEY"); using var api = CustomProviders.Cerebras("API_KEY"); using var api = CustomProviders.Cohere("API_KEY"); using var api = CustomProviders.Ollama(); using var api = CustomProviders.LmStudio(); 

Constants

All tryGetXXX methods return null if the value is not found.
There also non-try methods that throw an exception if the value is not found.

 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
using OpenAI; // You can try to get the enum from string using: var model = CreateChatCompletionRequestModelExtensions.ToEnum("gpt-4o") ?? throw new Exception("Invalid model"); // Chat var model = CreateChatCompletionRequestModel.Gpt4oMini; double? priceInUsd = model.TryGetPriceInUsd(  inputTokens: 500,  outputTokens: 500) double? priceInUsd = model.TryGetFineTunePriceInUsd(  trainingTokens: 500,  inputTokens: 500,  outputTokens: 500) int contextLength = model.TryGetContextLength() // 128_000 int outputLength = model.TryGetOutputLength() // 16_000 // Embeddings var model = CreateEmbeddingRequestModel.TextEmbedding3Small; int? maxInputTokens = model.TryGetMaxInputTokens() // 8191 double? priceInUsd = model.TryGetPriceInUsd(tokens: 500) // Images double? priceInUsd = CreateImageRequestModel.DallE3.TryGetPriceInUsd(  size: CreateImageRequestSize.x1024x1024,  quality: CreateImageRequestQuality.Hd) // Speech to Text double? priceInUsd = CreateTranscriptionRequestModel.Whisper1.TryGetPriceInUsd(  seconds: 60) // Text to Speech double? priceInUsd = CreateSpeechRequestModel.Tts1Hd.TryGetPriceInUsd(  characters: 1000) 

Support

Priority place for bugs: https://github.com/tryAGI/OpenAI/issues
Priority place for ideas and general questions: https://github.com/tryAGI/OpenAI/discussions
Discord: https://discord.gg/Ca2xhfBf3v

Acknowledgments

JetBrains logo

This project is supported by JetBrains through the Open Source Support Program.

CodeRabbit logo

This project is supported by CodeRabbit through the Open Source Support Program.