openai/openai-dotnet

Public

mirrored from https://github.com/openai/openai-dotnetAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
OpenAI_2.0.0-beta.8

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

examples/Chat/Example03_FunctionCallingAsync.cs

146lines · modecode

1using NUnit.Framework;
2using OpenAI.Chat;
3using System;
4using System.Collections.Generic;
5using System.Text.Json;
6using System.Threading.Tasks;
7
8namespace OpenAI.Examples;
9
10public partial class ChatExamples
11{
12 // See Example03_FunctionCalling.cs for the tool and function definitions.
13
14 [Test]
15 public async Task Example03_FunctionCallingAsync()
16 {
17 ChatClient client = new("gpt-4-turbo", Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
18
19 #region
20 List<ChatMessage> messages = [
21 new UserChatMessage("What's the weather like today?"),
22 ];
23
24 ChatCompletionOptions options = new()
25 {
26 Tools = { getCurrentLocationTool, getCurrentWeatherTool },
27 };
28 #endregion
29
30 #region
31 bool requiresAction;
32
33 do
34 {
35 requiresAction = false;
36 ChatCompletion chatCompletion = await client.CompleteChatAsync(messages, options);
37
38 switch (chatCompletion.FinishReason)
39 {
40 case ChatFinishReason.Stop:
41 {
42 // Add the assistant message to the conversation history.
43 messages.Add(new AssistantChatMessage(chatCompletion));
44 break;
45 }
46
47 case ChatFinishReason.ToolCalls:
48 {
49 // First, add the assistant message with tool calls to the conversation history.
50 messages.Add(new AssistantChatMessage(chatCompletion));
51
52 // Then, add a new tool message for each tool call that is resolved.
53 foreach (ChatToolCall toolCall in chatCompletion.ToolCalls)
54 {
55 switch (toolCall.FunctionName)
56 {
57 case nameof(GetCurrentLocation):
58 {
59 string toolResult = GetCurrentLocation();
60 messages.Add(new ToolChatMessage(toolCall.Id, toolResult));
61 break;
62 }
63
64 case nameof(GetCurrentWeather):
65 {
66 // The arguments that the model wants to use to call the function are specified as a
67 // stringified JSON object based on the schema defined in the tool definition. Note that
68 // the model may hallucinate arguments too. Consequently, it is important to do the
69 // appropriate parsing and validation before calling the function.
70 using JsonDocument argumentsJson = JsonDocument.Parse(toolCall.FunctionArguments);
71 bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location);
72 bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit);
73
74 if (!hasLocation)
75 {
76 throw new ArgumentNullException(nameof(location), "The location argument is required.");
77 }
78
79 string toolResult = hasUnit
80 ? GetCurrentWeather(location.GetString(), unit.GetString())
81 : GetCurrentWeather(location.GetString());
82 messages.Add(new ToolChatMessage(toolCall.Id, toolResult));
83 break;
84 }
85
86 default:
87 {
88 // Handle other unexpected calls.
89 throw new NotImplementedException();
90 }
91 }
92 }
93
94 requiresAction = true;
95 break;
96 }
97
98 case ChatFinishReason.Length:
99 throw new NotImplementedException("Incomplete model output due to MaxTokens parameter or token limit exceeded.");
100
101 case ChatFinishReason.ContentFilter:
102 throw new NotImplementedException("Omitted content due to a content filter flag.");
103
104 case ChatFinishReason.FunctionCall:
105 throw new NotImplementedException("Deprecated in favor of tool calls.");
106
107 default:
108 throw new NotImplementedException(chatCompletion.FinishReason.ToString());
109 }
110 } while (requiresAction);
111 #endregion
112
113 #region
114 foreach (ChatMessage requestMessage in messages)
115 {
116 switch (requestMessage)
117 {
118 case SystemChatMessage systemMessage:
119 Console.WriteLine($"[SYSTEM]:");
120 Console.WriteLine($"{systemMessage.Content[0].Text}");
121 Console.WriteLine();
122 break;
123
124 case UserChatMessage userMessage:
125 Console.WriteLine($"[USER]:");
126 Console.WriteLine($"{userMessage.Content[0].Text}");
127 Console.WriteLine();
128 break;
129
130 case AssistantChatMessage assistantMessage when assistantMessage.Content.Count > 0:
131 Console.WriteLine($"[ASSISTANT]:");
132 Console.WriteLine($"{assistantMessage.Content[0].Text}");
133 Console.WriteLine();
134 break;
135
136 case ToolChatMessage:
137 // Do not print any tool messages; let the assistant summarize the tool results instead.
138 break;
139
140 default:
141 break;
142 }
143 }
144 #endregion
145 }
146}
147