openai/openai-dotnet
Publicmirrored from https://github.com/openai/openai-dotnetAvailable
docs/MigrationGuide.md
341lines · modecode
| 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 |
| 51 | |Files | OpenAIFileClient |
| 52 | |Models | OpenAIModelClient |
| 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 |
| 342 | |