openai/openai-dotnet

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
typespec/update-http-client-csharp-1.0.0-alpha.20260516.1

Branches

Tags

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

Clone

HTTPS

Download ZIP

examples/Responses/Example03_FunctionCalling.cs

166lines · modecode

1using NUnit.Framework;
2using OpenAI.Responses;
3using System;
4using System.Collections.Generic;
5using System.Linq;
6using System.Text.Json;
7
8namespace OpenAI.Examples;
9
10// This example uses experimental APIs which are subject to change. To use experimental APIs,
11// please acknowledge their experimental status by suppressing the corresponding warning.
12#pragma warning disable OPENAI001
13
14public partial class ResponseExamples
15{
16 #region
17 private static string GetCurrentLocation()
18 {
19 // Call the location API here.
20 return "San Francisco";
21 }
22
23 private static string GetCurrentWeather(string location, string unit = "celsius")
24 {
25 // Call the weather API here.
26 return $"31 {unit}";
27 }
28 #endregion
29
30 #region
31 private static readonly FunctionTool getCurrentLocationTool = ResponseTool.CreateFunctionTool(
32 functionName: nameof(GetCurrentLocation),
33 functionDescription: "Get the user's current location",
34 functionParameters: null,
35 strictModeEnabled: false
36 );
37
38 private static readonly FunctionTool getCurrentWeatherTool = ResponseTool.CreateFunctionTool(
39 functionName: nameof(GetCurrentWeather),
40 functionDescription: "Get the current weather in a given location",
41 functionParameters: BinaryData.FromBytes("""
42 {
43 "type": "object",
44 "properties": {
45 "location": {
46 "type": "string",
47 "description": "The city and state, e.g. Boston, MA"
48 },
49 "unit": {
50 "type": "string",
51 "enum": [ "celsius", "fahrenheit" ],
52 "description": "The temperature unit to use. Infer this from the specified location."
53 }
54 },
55 "required": [ "location" ]
56 }
57 """u8.ToArray()),
58 strictModeEnabled: false
59 );
60 #endregion
61
62 [Test]
63 public void Example03_FunctionCalling()
64 {
65 ResponsesClient client = new(apiKey: Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
66
67 List<ResponseItem> inputItems =
68 [
69 ResponseItem.CreateUserMessageItem("What's the weather like today for my current location?"),
70 ];
71
72 PrintMessageItems(inputItems.OfType<MessageResponseItem>());
73
74 bool requiresAction;
75
76 do
77 {
78 requiresAction = false;
79
80 CreateResponseOptions options = new("gpt-5-mini", inputItems)
81 {
82 Tools = { getCurrentLocationTool, getCurrentWeatherTool },
83 };
84
85 ResponseResult response = client.CreateResponse(options);
86
87 inputItems.AddRange(response.OutputItems);
88
89 foreach (ResponseItem outputItem in response.OutputItems)
90 {
91 if (outputItem is FunctionCallResponseItem functionCall)
92 {
93 switch (functionCall.FunctionName)
94 {
95 case nameof(GetCurrentLocation):
96 {
97 string functionOutput = GetCurrentLocation();
98 inputItems.Add(new FunctionCallOutputResponseItem(functionCall.CallId, functionOutput));
99 break;
100 }
101
102 case nameof(GetCurrentWeather):
103 {
104 // The arguments that the model wants to use to call the function are specified as a
105 // stringified JSON object based on the schema defined in the tool definition. Note that
106 // the model may hallucinate arguments too. Consequently, it is important to do the
107 // appropriate parsing and validation before calling the function.
108 using JsonDocument argumentsJson = JsonDocument.Parse(functionCall.FunctionArguments);
109 bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location);
110 bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit);
111
112 if (!hasLocation)
113 {
114 throw new ArgumentNullException(nameof(location), "The location argument is required.");
115 }
116
117 string functionOutput = hasUnit
118 ? GetCurrentWeather(location.GetString(), unit.GetString())
119 : GetCurrentWeather(location.GetString());
120 inputItems.Add(new FunctionCallOutputResponseItem(functionCall.CallId, functionOutput));
121 break;
122 }
123
124 default:
125 {
126 // Handle other unexpected calls.
127 throw new NotImplementedException();
128 }
129 }
130
131 requiresAction = true;
132 break;
133 }
134 }
135
136 PrintMessageItems(response.OutputItems.OfType<MessageResponseItem>());
137
138 } while (requiresAction);
139 }
140
141 private void PrintMessageItems(IEnumerable<ResponseItem> messageItems)
142 {
143 foreach (MessageResponseItem messageItem in messageItems)
144 {
145 switch (messageItem.Role)
146 {
147 case MessageRole.User:
148 Console.WriteLine($"[USER]:");
149 Console.WriteLine($"{messageItem.Content[0].Text}");
150 Console.WriteLine();
151 break;
152
153 case MessageRole.Assistant:
154 Console.WriteLine($"[ASSISTANT]:");
155 Console.WriteLine($"{messageItem.Content[0].Text}");
156 Console.WriteLine();
157 break;
158
159 default:
160 break;
161 }
162 }
163 }
164}
165
166#pragma warning restore OPENAI001