openai/openai-dotnet
Publicmirrored from https://github.com/openai/openai-dotnetAvailable
docs/MigrationGuide.md
341lines · modeblame
f150666cCaio Saldanha2 years ago | 1 | # Guide for migrating to OpenAI 2.0.0-beta.1 or higher from OpenAI 1.11.0 |
| 2 | | |
| 3 | This guide is intended to assist in the migration to the official OpenAI library (2.0.0-beta.1 or higher) from [OpenAI 1.11.0][openai_1110], focusing on side-by-side comparisons for similar operations between libraries. Version 2.0.0-beta.1 will be used for comparison with 1.11.0 but this guide can still be safely used when migrating to higher versions. | |
| 4 | | |
| 5 | Prior to 2.0.0-beta.1, the OpenAI package was a community library not officially supported by OpenAI. See the [CHANGELOG][changelog] for more details. | |
| 6 | | |
| 7 | Familiarity with the OpenAI 1.11.0 package is assumed. For those new to any OpenAI library for .NET, see the [README][readme] rather than this guide. | |
| 8 | | |
| 9 | ## Table of contents | |
| 10 | - [Client usage](#client-usage) | |
| 11 | - [Authentication](#authentication) | |
| 12 | - [Highlighted scenarios](#highlighted-scenarios) | |
| 13 | - [Chat Completions: Text generation](#chat-completions-text-generation) | |
| 14 | - [Chat Completions: Streaming](#chat-completions-streaming) | |
| 15 | - [Chat Completions: JSON mode](#chat-completions-json-mode) | |
| 16 | - [Chat Completions: Vision](#chat-completions-vision) | |
| 17 | - [Audio: Speech-to-text](#audio-speech-to-text) | |
| 18 | - [Audio: Text-to-speech](#audio-text-to-speech) | |
| 19 | - [Image: Image generation](#image-image-generation) | |
| 20 | - [Additional examples](#additional-examples) | |
| 21 | | |
| 22 | ## Client usage | |
| 23 | | |
| 24 | The client usage has considerably changed between libraries. While the OpenAI 1.11.0 had a single client, `OpenAIAPI`, from which multiple APIs could be accessed, OpenAI 2.0.0-beta.1 keeps a separate client per API. The following snippets illustrate this difference when invoking the image generation capability from the Image API: | |
| 25 | | |
| 26 | OpenAI 1.11.0: | |
| 27 | ```cs | |
| 28 | OpenAIAPI api = new OpenAIAPI("<api-key>"); | |
| 29 | ImageResult result = await api.ImageGenerations.CreateImageAsync("Draw a quick brown fox jumping over a lazy dog.", Model.DALLE3); | |
| 30 | ``` | |
| 31 | | |
| 32 | OpenAI 2.0.0-beta.1: | |
| 33 | ```cs | |
| 34 | ImageClient client = new ImageClient("dall-e-3", "<api-key>"); | |
| 35 | ClientResult<GeneratedImage> result = await client.GenerateImageAsync("Draw a quick brown fox jumping over a lazy dog."); | |
| 36 | ``` | |
| 37 | | |
| 38 | Another major difference highlighted in the snippets above is that OpenAI 2.0.0-beta.1 requires the model to be explicitly set during client instantiation, while the `OpenAIAPI` client allows a model to be specified per call. | |
| 39 | | |
| 40 | The table below illustrates to which client each endpoint of `OpenAIAPI` was ported. Note that the deprecated Completions API is not supported in 2.0.0-beta.1: | |
| 41 | | |
| 42 | Old library's endpoint|New library's client | |
| 43 | |-|- | |
| 44 | |Chat | ChatClient | |
| 45 | |ImageGenerations | ImageClient | |
| 46 | |TextToSpeech | AudioClient | |
| 47 | |Transcriptions | AudioClient | |
| 48 | |Translations | AudioClient | |
| 49 | |Moderation | ModerationClient | |
| 50 | |Embeddings | EmbeddingClient | |
31c2ba63Jose Arriaga Maldonado1 years ago | 51 | |Files | OpenAIFileClient |
| 52 | |Models | OpenAIModelClient | |
f150666cCaio Saldanha2 years ago | 53 | |Completions | Not supported |
| 54 | | |
| 55 | ## Authentication | |
| 56 | | |
| 57 | To authenticate to OpenAI, you must set an API key when creating a client. | |
| 58 | | |
| 59 | OpenAI 1.11.0 allowed setting the API key in 3 different ways: | |
| 60 | - Directly from a string | |
| 61 | - From an environment variable | |
| 62 | - From a configuration file | |
| 63 | | |
| 64 | ```cs | |
| 65 | OpenAIAPI api; | |
| 66 | | |
| 67 | // Sets the API key directly from a string. | |
| 68 | api = new OpenAIAPI("<api-key>"); | |
| 69 | | |
| 70 | // Attempts to load the API key from environment variables OPENAI_KEY and OPENAI_API_KEY. | |
| 71 | api = new OpenAIAPI(APIAuthentication.LoadFromEnv()); | |
| 72 | | |
| 73 | // Attempts to load the API key from a configuration file. | |
| 74 | api = new OpenAIAPI(APIAuthentication.LoadFromPath("<directory>", "<filename>")); | |
| 75 | ``` | |
| 76 | | |
| 77 | OpenAI 2.0.0-beta.1 only supports setting it from a string or from an environment variable. The following snippet illustrates the behavior with the `ChatClient`, but other clients behave the same: | |
| 78 | | |
| 79 | ```cs | |
| 80 | ChatClient client; | |
| 81 | | |
| 82 | // Sets the API key directly from a string. | |
| 83 | client = new ChatClient("gpt-3.5-turbo", "<api-key>"); | |
| 84 | | |
| 85 | // When no API key string is specified, attempts to load the API key from the environment variable OPENAI_API_KEY. | |
| 86 | client = new ChatClient("gpt-3.5-turbo"); | |
| 87 | ``` | |
| 88 | | |
| 89 | Note that, unlike the OpenAI 1.11.0, OpenAI 2.0.0-beta.1 will never attempt to load the API key from the `OPENAI_KEY` environment variable. Only `OPENAI_API_KEY` is supported. | |
| 90 | | |
| 91 | ## Highlighted scenarios | |
| 92 | | |
| 93 | The following sections illustrate side-by-side comparisons for similar operations between the two libraries, highlighting common scenarios. | |
| 94 | | |
| 95 | ### Chat Completions: Text generation | |
| 96 | | |
| 97 | OpenAI 1.11.0: | |
| 98 | ```cs | |
| 99 | OpenAIAPI api = new OpenAIAPI("<api-key>"); | |
| 100 | Conversation conversation = api.Chat.CreateConversation(); | |
| 101 | | |
| 102 | conversation.Model = Model.ChatGPTTurbo; | |
| 103 | conversation.AppendSystemMessage("You are a helpful assistant."); | |
| 104 | conversation.AppendUserInput("When was the Nobel Prize founded?"); | |
| 105 | | |
| 106 | await conversation.GetResponseFromChatbotAsync(); | |
| 107 | | |
| 108 | conversation.AppendUserInput("Who was the first person to be awarded one?"); | |
| 109 | | |
| 110 | await conversation.GetResponseFromChatbotAsync(); | |
| 111 | | |
| 112 | foreach (ChatMessage message in conversation.Messages) | |
| 113 | { | |
| 114 | Console.WriteLine($"{message.Role}: {message.TextContent}"); | |
| 115 | } | |
| 116 | ``` | |
| 117 | | |
| 118 | OpenAI 2.0.0-beta.1: | |
| 119 | ```cs | |
| 120 | ChatClient client = new ChatClient("gpt-3.5-turbo", "<api-key>"); | |
| 121 | List<ChatMessage> messages = new List<ChatMessage>() | |
| 122 | { | |
| 123 | new SystemChatMessage("You are a helpful assistant."), | |
| 124 | new UserChatMessage("When was the Nobel Prize founded?") | |
| 125 | }; | |
| 126 | | |
| 127 | ClientResult<ChatCompletion> result = await client.CompleteChatAsync(messages); | |
| 128 | | |
| 129 | messages.Add(new AssistantChatMessage(result)); | |
| 130 | messages.Add(new UserChatMessage("Who was the first person to be awarded one?")); | |
| 131 | | |
| 132 | result = await client.CompleteChatAsync(messages); | |
| 133 | | |
| 134 | messages.Add(new AssistantChatMessage(result)); | |
| 135 | | |
| 136 | foreach (ChatMessage message in messages) | |
| 137 | { | |
| 138 | string role = message.GetType().Name; | |
| 139 | string text = message.Content[0].Text; | |
| 140 | | |
| 141 | Console.WriteLine($"{role}: {text}"); | |
| 142 | } | |
| 143 | ``` | |
| 144 | | |
| 145 | ### Chat Completions: Streaming | |
| 146 | | |
| 147 | OpenAI 1.11.0: | |
| 148 | ```cs | |
| 149 | OpenAIAPI api = new OpenAIAPI("<api-key>"); | |
| 150 | Conversation conversation = api.Chat.CreateConversation(); | |
| 151 | | |
| 152 | conversation.Model = Model.ChatGPTTurbo; | |
| 153 | conversation.AppendUserInput("Give me a list of Nobel Prize winners of the last 5 years."); | |
| 154 | | |
| 155 | await foreach (string response in conversation.StreamResponseEnumerableFromChatbotAsync()) | |
| 156 | { | |
| 157 | Console.Write(response); | |
| 158 | } | |
| 159 | ``` | |
| 160 | | |
| 161 | OpenAI 2.0.0-beta.1: | |
| 162 | ```cs | |
| 163 | ChatClient client = new ChatClient("gpt-3.5-turbo", "<api-key>"); | |
| 164 | List<ChatMessage> messages = new List<ChatMessage>() | |
| 165 | { | |
| 166 | new UserChatMessage("Give me a list of Nobel Prize winners of the last 5 years.") | |
| 167 | }; | |
| 168 | | |
| 169 | await foreach (StreamingChatCompletionUpdate chatUpdate in client.CompleteChatStreamingAsync(messages)) | |
| 170 | { | |
| 171 | if (chatUpdate.ContentUpdate.Count > 0) | |
| 172 | { | |
| 173 | Console.Write(chatUpdate.ContentUpdate[0].Text); | |
| 174 | } | |
| 175 | } | |
| 176 | ``` | |
| 177 | | |
| 178 | ### Chat Completions: JSON mode | |
| 179 | | |
| 180 | OpenAI 1.11.0: | |
| 181 | ```cs | |
| 182 | OpenAIAPI api = new OpenAIAPI("<api-key>"); | |
| 183 | ChatRequest request = new ChatRequest() | |
| 184 | { | |
| 185 | Model = Model.ChatGPTTurbo, | |
| 186 | ResponseFormat = request.ResponseFormats.JsonObject, | |
| 187 | Messages = new List<ChatMessage>() | |
| 188 | { | |
| 189 | new ChatMessage(ChatMessageRole.System, "You are a helpful assistant designed to output JSON."), | |
| 190 | new ChatMessage(ChatMessageRole.User, "Give me a JSON object listing Nobel Prize winners of the last 5 years.") | |
| 191 | } | |
| 192 | }; | |
| 193 | | |
| 194 | ChatResult result = await api.Chat.CreateChatCompletionAsync(request); | |
| 195 | | |
| 196 | Console.WriteLine(result); | |
| 197 | ``` | |
| 198 | | |
| 199 | OpenAI 2.0.0-beta.1: | |
| 200 | ```cs | |
| 201 | ChatClient client = new ChatClient("gpt-3.5-turbo", "<api-key>"); | |
| 202 | List<ChatMessage> messages = new List<ChatMessage>() | |
| 203 | { | |
| 204 | new SystemChatMessage("You are a helpful assistant designed to output JSON."), | |
| 205 | new UserChatMessage("Give me a JSON object listing Nobel Prize winners of the last 5 years.") | |
| 206 | }; | |
| 207 | ChatCompletionOptions options = new ChatCompletionOptions() | |
| 208 | { | |
| 209 | ResponseFormat = ChatResponseFormat.JsonObject | |
| 210 | }; | |
| 211 | | |
| 212 | ClientResult<ChatCompletion> result = await client.CompleteChatAsync(messages, options); | |
| 213 | string text = result.Value.Content[0].Text; | |
| 214 | | |
| 215 | Console.WriteLine(text); | |
| 216 | ``` | |
| 217 | | |
| 218 | ### Chat Completions: Vision | |
| 219 | | |
| 220 | OpenAI 1.11.0: | |
| 221 | ```cs | |
| 222 | OpenAIAPI api = new OpenAIAPI("<api-key>"); | |
| 223 | Conversation conversation = api.Chat.CreateConversation(); | |
| 224 | byte[] imageData = await File.ReadAllBytesAsync("<file-path>"); | |
| 225 | | |
| 226 | conversation.Model = Model.GPT4_Vision; | |
| 227 | conversation.AppendUserInput("Describe this image.", ImageInput.FromImageBytes(imageData)); | |
| 228 | | |
| 229 | string response = await conversation.GetResponseFromChatbotAsync(); | |
| 230 | | |
| 231 | Console.WriteLine(response); | |
| 232 | ``` | |
| 233 | | |
| 234 | OpenAI 2.0.0-beta.1: | |
| 235 | ```cs | |
| 236 | ChatClient client = new ChatClient("gpt-4-vision-preview", "<api-key>"); | |
| 237 | using FileStream file = File.OpenRead("<file-path>"); | |
| 238 | BinaryData imageData = await BinaryData.FromStreamAsync(file); | |
| 239 | List<ChatMessage> messages = new List<ChatMessage>() | |
| 240 | { | |
| 241 | new UserChatMessage( | |
| 242 | ChatMessageContentPart.CreateTextMessageContentPart("Describe this image."), | |
| 243 | ChatMessageContentPart.CreateImageMessageContentPart(imageData, "image/png")) | |
| 244 | }; | |
| 245 | | |
| 246 | ClientResult<ChatCompletion> result = await client.CompleteChatAsync(messages); | |
| 247 | string text = result.Value.Content[0].Text; | |
| 248 | | |
| 249 | Console.WriteLine(text); | |
| 250 | ``` | |
| 251 | | |
| 252 | ### Audio: Speech-to-text | |
| 253 | | |
| 254 | OpenAI 1.11.0: | |
| 255 | ```cs | |
| 256 | OpenAIAPI api = new OpenAIAPI("<api-key>"); | |
| 257 | string result = await api.Transcriptions.GetTextAsync("<file-path>", "fr"); | |
| 258 | | |
| 259 | Console.WriteLine(result); | |
| 260 | ``` | |
| 261 | | |
| 262 | OpenAI 2.0.0-beta.1: | |
| 263 | ```cs | |
| 264 | AudioClient client = new AudioClient("whisper-1", "<api-key>"); | |
| 265 | AudioTranscriptionOptions options = new AudioTranscriptionOptions() | |
| 266 | { | |
| 267 | Language = "fr" | |
| 268 | }; | |
| 269 | | |
| 270 | ClientResult<AudioTranscription> result = await client.TranscribeAudioAsync("<file-path>", options); | |
| 271 | string text = result.Value.Text; | |
| 272 | | |
| 273 | Console.WriteLine(text); | |
| 274 | ``` | |
| 275 | | |
| 276 | ### Audio: Text-to-speech | |
| 277 | | |
| 278 | OpenAI 1.11.0: | |
| 279 | ```cs | |
| 280 | OpenAIAPI api = new OpenAIAPI("<api-key>"); | |
| 281 | TextToSpeechRequest request = new TextToSpeechRequest() | |
| 282 | { | |
| 283 | Input = "Hasta la vista, baby.", | |
| 284 | Model = Model.TTS_Speed, | |
| 285 | Voice = "alloy" | |
| 286 | }; | |
| 287 | | |
| 288 | await api.TextToSpeech.SaveSpeechToFileAsync(request, "<file-path>"); | |
| 289 | ``` | |
| 290 | | |
| 291 | OpenAI 2.0.0-beta.1: | |
| 292 | ```cs | |
| 293 | AudioClient client = new AudioClient("tts-1", "<api-key>"); | |
| 294 | | |
| 295 | ClientResult<BinaryData> result = await client.GenerateSpeechFromTextAsync("Hasta la vista, baby.", GeneratedSpeechVoice.Alloy); | |
| 296 | BinaryData data = result.Value; | |
| 297 | | |
| 298 | await File.WriteAllBytesAsync("<file-path>", data.ToArray()); | |
| 299 | ``` | |
| 300 | | |
| 301 | ### Image: Image generation | |
| 302 | | |
| 303 | OpenAI 1.11.0: | |
| 304 | ```cs | |
| 305 | OpenAIAPI api = new OpenAIAPI("<api-key>"); | |
| 306 | ImageGenerationRequest request = new ImageGenerationRequest() | |
| 307 | { | |
| 308 | Prompt = "Draw a quick brown fox jumping over a lazy dog.", | |
| 309 | Model = Model.DALLE3, | |
| 310 | Quality = "standard", | |
| 311 | Size = ImageSize._1024 | |
| 312 | }; | |
| 313 | | |
| 314 | ImageResult result = await api.ImageGenerations.CreateImageAsync(request); | |
| 315 | | |
| 316 | Console.WriteLine(result.Data[0].Url); | |
| 317 | ``` | |
| 318 | | |
| 319 | OpenAI 2.0.0-beta.1: | |
| 320 | ```cs | |
| 321 | ImageClient client = new ImageClient("dall-e-3", "<api-key>"); | |
| 322 | ImageGenerationOptions options = new ImageGenerationOptions() | |
| 323 | { | |
| 324 | Quality = GeneratedImageQuality.Standard, | |
| 325 | Size = GeneratedImageSize.W1024xH1024 | |
| 326 | }; | |
| 327 | | |
| 328 | ClientResult<GeneratedImage> result = await client.GenerateImageAsync("Draw a quick brown fox jumping over a lazy dog.", options); | |
| 329 | Uri imageUri = result.Value.ImageUri; | |
| 330 | | |
| 331 | Console.WriteLine(imageUri.AbsoluteUri); | |
| 332 | ``` | |
| 333 | | |
| 334 | ## Additional examples | |
| 335 | | |
| 336 | For additional examples, see [OpenAI Examples][examples]. | |
| 337 | | |
| 338 | [readme]: https://github.com/openai/openai-dotnet/blob/main/README.md | |
| 339 | [changelog]: https://github.com/openai/openai-dotnet/blob/main/CHANGELOG.md | |
| 340 | [examples]: https://github.com/openai/openai-dotnet/tree/main/examples | |
| 341 | [openai_1110]: https://aka.ms/openai1110 |