{"id":23908917,"url":"https://github.com/rodion-m/chatgpt_api_dotnet","last_synced_at":"2025-04-09T18:19:06.086Z","repository":{"id":95979307,"uuid":"608422041","full_name":"rodion-m/ChatGPT_API_dotnet","owner":"rodion-m","description":"OpenAI, Azure OpenAI and OpenRouter Chat Completions (ChatGPT) .NET integration with DI, persistence and streaming support","archived":false,"fork":false,"pushed_at":"2024-07-28T20:16:37.000Z","size":1843,"stargazers_count":87,"open_issues_count":1,"forks_count":14,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-09T18:19:04.767Z","etag":null,"topics":["api-client","aspnetcore","azure","azureopenai","chatgpt","chatgpt-api","csharp","dependency-injection","entity-framework-core","gpt-3","gpt-4","openai","openrouter"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rodion-m.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-02T01:26:20.000Z","updated_at":"2025-04-01T16:24:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"4ef4ecb9-2941-44ee-94bb-3f9b098aa941","html_url":"https://github.com/rodion-m/ChatGPT_API_dotnet","commit_stats":{"total_commits":20,"total_committers":1,"mean_commits":20.0,"dds":0.0,"last_synced_commit":"2083216e09150b00bee9089ad124466cb19b489b"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rodion-m%2FChatGPT_API_dotnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rodion-m%2FChatGPT_API_dotnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rodion-m%2FChatGPT_API_dotnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rodion-m%2FChatGPT_API_dotnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rodion-m","download_url":"https://codeload.github.com/rodion-m/ChatGPT_API_dotnet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248085325,"owners_count":21045139,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-client","aspnetcore","azure","azureopenai","chatgpt","chatgpt-api","csharp","dependency-injection","entity-framework-core","gpt-3","gpt-4","openai","openrouter"],"created_at":"2025-01-05T05:14:21.163Z","updated_at":"2025-04-09T18:19:06.062Z","avatar_url":"https://github.com/rodion-m.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![example gif...](assets/chatgpt_console_spectre_example.gif)](samples/ChatGpt.SpectreConsoleExample/Program.cs)\n# ChatGPT integration for .NET (+DI)\n[![Nuget](https://img.shields.io/nuget/v/OpenAI.ChatGPT.EntityFrameworkCore)](https://www.nuget.org/packages/OpenAI.ChatGPT.EntityFrameworkCore/)[![.NET](https://github.com/rodion-m/ChatGPT_API_dotnet/actions/workflows/dotnet.yml/badge.svg)](https://github.com/rodion-m/ChatGPT_API_dotnet/actions/workflows/dotnet.yml) \\\nOpenAI Chat Completions API (ChatGPT) integration with DI and EF Core support. It allows you to use the API in your .NET applications. Also, the client supports streaming responses (like ChatGPT) via async streams.\n\n## Changelog\n\n### 2024.8\n\n* Add OpenRouter and Azure OpenAI support\n* Add support for GPT-4-o, GPT-4-o-mini\n* Improve JSON mode support\n* BREAKING CHANGES: `AddChatGptEntityFrameworkIntegration` now requires `builder.Configuration` as a mandatory parameter.\n* Add a [setup example](https://github.com/buddy-ai-team/buddy_language_backend/blob/69ee02988878c89b897c293cc192c5ea8c65b888/src/infrastructure/BuddyLanguage.Infrastructure/BuddyLanguageDependencyInjection.cs#L65)\n\n### 2023.11\n\n* Add GPT-4-Turbo \n* Add JSON mode support\n* `StructuredResponse` module allows you to get structured responses from the API as C# object. See: [StructuredResponse](#structuredresponse) section.\n\n## Content\n\u003c!-- TOC --\u003e\n* [ChatGPT integration for .NET (+DI)](#chatgpt-integration-for-net-di)\n  * [Changelog](#changelog)\n    * [2024.8](#20248)\n    * [2023.11](#202311)\n  * [Content](#content)\n  * [Preparation](#preparation)\n  * [Installation](#installation)\n  * [Usage](#usage)\n  * [Exceptions](#exceptions)\n  * [Thread safety and async](#thread-safety-and-async)\n  * [Retries, timeouts and other policies](#retries-timeouts-and-other-policies)\n  * [Modules](#modules)\n    * [StructuredResponse](#structuredresponse)\n    * [Translator](#translator)\n  * [Examples](#examples)\n  * [API Parameters](#api-parameters)\n    * [Model](#model)\n    * [MaxTokens](#maxtokens)\n    * [Temperature](#temperature)\n* [Using raw client without DI](#using-raw-client-without-di)\n  * [Simple usage of the Chat Completions API (raw client)](#simple-usage-of-the-chat-completions-api-raw-client)\n  * [Streaming response with async streams (like ChatGPT)](#streaming-response-with-async-streams-like-chatgpt)\n  * [Continue dialog with ChatGPT (message history)](#continue-dialog-with-chatgpt-message-history)\n\u003c!-- TOC --\u003e\n\n## Preparation\nFirst, you need to create an OpenAI account and get an API key (or OpenRouter or Azure OpenAI). You can do this at https://platform.openai.com/account/api-keys.\n\n## Installation\nThe easiest way to use ChatGPT service in your .NET project with DI and persistence (EF Core) supporting is to install the NuGet package [OpenAI.ChatGPT.EntityFrameworkCore](https://www.nuget.org/packages/OpenAI.ChatGPT.EntityFrameworkCore/):\n```\nInstall-Package OpenAI.ChatGPT.EntityFrameworkCore\n```\nIf you don't want to use EF Core, you can install the package [OpenAI.ChatGPT.AspNetCore](https://www.nuget.org/packages/OpenAI.ChatGPT.AspNetCore/) and implement your own storage for chat history, using `IChatHistoryStorage` interface.\n\n## Usage\n\nTL;DR: See [an example in a reference project](https://github.com/buddy-ai-team/buddy_language_backend/blob/69ee02988878c89b897c293cc192c5ea8c65b888/src/infrastructure/BuddyLanguage.Infrastructure/BuddyLanguageDependencyInjection.cs#L65).\n\n1. Set the OpenAI API key or even host (optional) in your project user secrets, or the `appsettings.json` file (not safe):\n```json\n{\n  \"AIProvider\": \"openai\", // or openrouter or azure_openai\n  \"OpenAICredentials\": { //optional\n    \"ApiKey\": \"your-api-key-from-openai\",\n    \"ApiHost\": \"https://api.openai.com/v1/\"\n  },\n  \"AzureOpenAICredentials\": { //optional\n    \"ApiKey\": \"your-api-key-from-azure-openai\",\n    \"ApiHost\": \"https://{your-host}.openai.azure.com/\",\n    \"DeploymentName\": \"gpt-4-turbo-preview\"\n  },\n  \"OpenRouterCredentials\": { //optional\n    \"ApiKey\": \"your-api-key-from-openrouter\",\n    \"ApiHost\": \"https://openrouter.ai/api/v1\"\n  }\n}\n```\nAlso, you can specify OpenAI API key as environment variable `ASPNETCORE_OpenAICredentials:ApiKey`.\n\n2. Add ChatGPT integration with EF to your DI container:\n```csharp\nbuilder.Services.AddChatGptEntityFrameworkIntegration(\n    builder.Configuration,\n    options =\u003e options.UseSqlite(\"Data Source=chats.db\"));\n```\nInstead of `options.UseSqlite(\"Data Source=chats.db\")` use your own db and connection string.\n\n3. Inject `ChatGPTFactory` to your service and use it to create `ChatGPT` instance:\n```csharp\npublic class YourService\n{\n    private readonly ChatGPTFactory _chatGptFactory;\n\n    public YourService(ChatGPTFactory chatGptFactory)\n    {\n        _chatGptFactory = chatGptFactory;\n    }\n\n    public async Task\u003cstring\u003e GetAnswer(string text)\n    {\n        ChatGPT chatGpt = await _chatGptFactory.Create(userId);\n        var chatService = await chatGpt.ContinueOrStartNewTopic();\n        response = await _chatService.GetNextMessageResponse(_prompt);\n        return response;\n    }\n}\n```\nSee [Blazor Example](samples/ChatGpt.BlazorExample/Pages/Index.razor).\n\nIf you want to configure request parameters, you can do it in `appsettings.json` configuration or in `ChatGPTFactory.Create` or in `ChatGPT.CreateChat` methods.\n```json\n{\n  \"ChatGPTConfig\": {\n      \"InitialSystemMessage\": \"You are a helpful and kind assistant.\",\n      \"InitialUserMessage\": null,\n      \"MaxTokens\": null,\n      \"Model\": null,\n      \"Temperature\": null,\n      \"PassUserIdToOpenAiRequests\": true\n  }\n}\n```\nSee parameters description inside [ChatGPTConfig](OpenAI.ChatGpt/Models/ChatGPTConfig.cs).\n\n## Exceptions\nIf the server response is not a success status code, the client will throw a [NotExpectedResponseException](OpenAI.ChatGpt/Exceptions/NotExpectedResponseException.cs). The exception will contain the error message from the OpenAI API. \\\nBy default, requesting cancellation or `ChatService.Stop()` method calling will throw `OperationCanceledException`. If you don't want to throw it (relevant for streaming responses), you can set `throwOnCancellation` parameter to `false`:\n```csharp\nawait foreach (string chunk in chatService.StreamNextMessageResponse(text, throwOnCancellation: false))\n{\n    //...\n}\n```\n\n## Thread safety and async\n`ChatGPTFactory`, `ChatGPT` classes thread-safety is depend on the `IChatHistoryStorage` implementation. If you use `ChatGPTFactory` with entity framework, it's NOT thread-safe. `ChatService` class is not thread-safe. \\\nAnyways, these services are designed to be used safely with DI, so you don't need to worry about it. \\\nAll the methods from all the packages are designed to be used in async context and use `ConfigureAwait(false)` (thanks for the `ConfigureAwait.Fody` package).\n\n## Retries, timeouts and other policies\nSince `ChatGPTFactory` depends on `IHttpClientFactory`, you can easily use any of the available policies for it, like `Polly`.\n\n## Modules\n### StructuredResponse\nThis module allows you to get structured responses from the API as C# object. It's useful if you want to use the API for something more than just chat.\n\n```csharp\nrecord City(string Name, int YearOfFoundation, string Country);\n\nvar message = Dialog\n    .StartAsSystem(\"Return requested data.\")\n    .ThenUser(\"I need info about Almaty city\");\nCity almaty = await _client.GetStructuredResponse\u003cCity\u003e(message, model: ChatCompletionModels.Gpt4Turbo);\nConsole.WriteLine(almaty); // Name: \"Almaty\", Country: \"Kazakhstan\", YearOfFoundation: 1854\n```\nUnder the hood, it uses the new [json mode](https://platform.openai.com/docs/guides/text-generation/json-mode) of the API for GPT4Turbo and for the `gpt-3.5-turbo-1106`. Regular GPT4 and GPT3.5Turbo models are also supported, but GPT3.5 responses may be unstable (for GPT3.5 it's strictly recommended to provide `examples` parameter).\n\nMore complex examples with arrays, nested objects and enums are available in tests: https://github.com/rodion-m/ChatGPT_API_dotnet/blob/f50d386f0b65a4ba8c1041a28bab2a1a475c2296/tests/OpenAI.ChatGpt.IntegrationTests/OpenAiClientTests/OpenAiClient_GetStructuredResponse.cs#L1\n\nNuGet: https://www.nuget.org/packages/OpenAI.ChatGPT.Modules.StructuredResponse\n\n### Translator\nThis module allows you to translate messages from one language to another.\n```csharp\nstring textToTranslate = \"Hello, world!\";\nstring translatedText = await _client.TranslateText(textToTranslate, \"English\", \"Russian\");\nConsole.WriteLine(translatedText); // \"Привет, мир!\"\n```\nAlso, it's possible to translate entire object in pair with `StructuredResponse` module:\n```csharp\nvar objectToTranslate = new Order(\n    new List\u003cOrder.Item\u003e \n    {\n        new(1,\"Book\", 5),\n        new(2,\"Pen\", 10),\n        new(3,\"Notebook\", 3)\n    }\n);\nOrder translatedObject = await _client.TranslateObject(objectToTranslate, \"English\", \"Russian\");\n```\n\nSee full example in tests: https://github.com/rodion-m/ChatGPT_API_dotnet/blob/11658b76b497b9cc4ac74621c91c5e22cd724f2e/tests/OpenAI.ChatGpt.IntegrationTests/ChatGptTranslatorServiceTests.cs#L36\n\nNuGet: https://www.nuget.org/packages/OpenAI.ChatGPT.Modules.Translator\n\n## Examples\n* [Blazor Example](samples/ChatGpt.BlazorExample)\n* [Console Example](samples/ChatGpt.ConsoleExample/Program.cs) (simple)\n* [Spectre Console Example](samples/ChatGpt.SpectreConsoleExample/Program.cs) (advanced)\n\n## API Parameters\nHere is a list of the main parameters that can be used in the ChatCompletions (ChatGPT) API request (OpenAI.ChatGpt/Models/ChatCompletion/ChatCompletionRequest.cs).\nSome of them are taken from this article: https://towardsdatascience.com/gpt-3-parameters-and-prompt-design-1a595dc5b405 \\\nBelow listed parameters for ChatCompletions API.\n\n### Model\nThe prediction-generating AI model is specified by the engine parameter. The available models are described below: https://platform.openai.com/docs/models\n\n| C# Model                                   | API Model              |\n|--------------------------------------------|------------------------|\n| ChatCompletionModels.Gpt4Turbo             | gpt-4-1106-preview     |\n| ChatCompletionModels.Gpt4                  | gpt-4                  |\n| ChatCompletionModels.Gpt4_0613             | gpt-4-0613             |\n| ChatCompletionModels.Gpt4_32k              | gpt-4-32k              |\n| ChatCompletionModels.Gpt4_32k_0613         | gpt-4-32k-0613         |\n| ChatCompletionModels.Gpt3_5_Turbo          | gpt-3.5-turbo          |\n| ChatCompletionModels.Gpt3_5_Turbo_1106     | gpt-3.5-turbo-1106     |\n| ChatCompletionModels.Gpt3_5_Turbo_16k      | gpt-3.5-turbo-16k      |\n| ChatCompletionModels.Gpt3_5_Turbo_0613     | gpt-3.5-turbo-0613     |\n| ChatCompletionModels.Gpt3_5_Turbo_16k_0613 | gpt-3.5-turbo-16k-0613 |\n| ChatCompletionModels.Gpt4_0314             | gpt-4-0314             |\n| ChatCompletionModels.Gpt4_32k_0314         | gpt-4-32k-0314         |\n| ChatCompletionModels.Gpt3_5_Turbo_0301     | gpt-3.5-turbo-0301     |\n\n### MaxTokens\nThe maximum number of tokens allowed for the generated answer. Defaults to `ChatCompletionRequest.MaxTokensDefault` (64).\n* This value is validated and limited with `ChatCompletionModels.GetMaxTokensLimitForModel` method.\n* It's possible to calculate approximately tokens count using `ChatCompletionMessage.CalculateApproxTotalTokenCount` method\n* The number of tokens can be retrieved from the API response: `ChatCompletionResponse.Usage.TotalTokens`.\n  As a rule of thumb for English, 1 token is around 4 characters (so 100 tokens ≈ 75 words). See tokenizer from OpenAI: https://platform.openai.com/tokenizer\n* Encoding algorithm can be found here: https://github.com/latitudegames/GPT-3-Encoder\n\n### Temperature\nWhat sampling temperature to use, between 0 and 2.\n* Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n* Predefined values are available in `ChatCompletionTemperatures`.\n* Default value is: `ChatCompletionTemperatures.Balanced` (0.5).\n\nDescription:\nBefore being mapped into probabilities, the model outputs unnormalized values (logits). The logits are typically used with a function such as softmax to convert them into probabilities.\n\nBut, before applying the softmax function, we can use a trick inspired by thermodynamics and scale the logits with the temperature parameter, i.e. softmax(logits/temperature).\n\nA temperature parameter close to 1 would mean that the logits are passed through the softmax function without modification. If the temperature is close to zero, the highest probable tokens will become very likely compared to the other tokens, i.e. the model becomes more deterministic and will always output the same set of tokens after a given sequence of words.\n\nMore parameters description can be found here: Some of them are taken from this article: https://towardsdatascience.com/gpt-3-parameters-and-prompt-design-1a595dc5b405\n\n# Using raw client without DI\nIf you don't need DI and chat history, you can use only the NuGet package [OpenAI.ChatGPT](https://www.nuget.org/packages/OpenAI.ChatGPT):\n```\nInstall-Package OpenAI.ChatGPT\n```\nThen create an instance of `OpenAIClient`:\n```csharp\n_client = new OpenAiClient(\"{YOUR_OPENAI_API_KEY}\");\n```\n\n## Simple usage of the Chat Completions API (raw client)\n```csharp\nstring text = \"Who are you?\";\nstring response = await _client.GetChatCompletions(new UserMessage(text), maxTokens: 80);\nConsole.WriteLine(response);\n```\n\n## Streaming response with async streams (like ChatGPT)\n```csharp\nvar text = \"Write the world top 3 songs of Soul genre\";\nawait foreach (string chunk in _client.StreamChatCompletions(new UserMessage(text), maxTokens: 80))\n{\n    Console.Write(chunk);\n}\n```\n\n## Continue dialog with ChatGPT (message history)\nUse `ThenAssistant` and `ThenUser` methods to create a dialog:\n```csharp\nvar dialog = Dialog.StartAsUser(\"How many meters are in a kilometer? Write just the number.\") //the message from user\n          .ThenAssistant(\"1000\") // response from the assistant\n          .ThenUser(\"Convert it to hex. Write just the number.\"); // the next message from user\n\nawait foreach (var chunk in _client.StreamChatCompletions(dialog, maxTokens: 80))\n{\n    Console.Write(chunk);\n}\n```\nOr just send message history as a collection.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frodion-m%2Fchatgpt_api_dotnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frodion-m%2Fchatgpt_api_dotnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frodion-m%2Fchatgpt_api_dotnet/lists"}