openai/openai-dotnet

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
OpenAI_2.6.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

examples/Responses/Example04_FunctionCallingStreaming.cs

111lines · modecode

1using NUnit.Framework;
2using OpenAI.Responses;
3using System;
4using System.ClientModel;
5using System.Collections.Generic;
6using System.Linq;
7using System.Text.Json;
8
9namespace OpenAI.Examples;
10
11// This example uses experimental APIs which are subject to change. To use experimental APIs,
12// please acknowledge their experimental status by suppressing the corresponding warning.
13#pragma warning disable OPENAI001
14
15public partial class ResponseExamples
16{
17 // See Example03_FunctionCalling.cs for the tool and function definitions.
18
19 [Test]
20 public void Example04_FunctionCallingStreaming()
21 {
22 OpenAIResponseClient client = new("gpt-5", Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
23
24 List<ResponseItem> inputItems =
25 [
26 ResponseItem.CreateUserMessageItem("What's the weather like today for my current location?"),
27 ];
28
29 ResponseCreationOptions options = new()
30 {
31 Tools = { getCurrentLocationTool, getCurrentWeatherTool },
32 };
33
34 PrintMessageItems(inputItems.OfType<MessageResponseItem>());
35
36 bool requiresAction;
37
38 do
39 {
40 requiresAction = false;
41 CollectionResult<StreamingResponseUpdate> responseUpdates = client.CreateResponseStreaming(inputItems, options);
42
43 foreach (StreamingResponseUpdate update in responseUpdates)
44 {
45 if (update is StreamingResponseOutputItemAddedUpdate outputItemAddedUpdated)
46 {
47 if (outputItemAddedUpdated.Item is MessageResponseItem message && message.Role == MessageRole.Assistant)
48 {
49 Console.WriteLine($"[ASSISTANT]:");
50 }
51 }
52
53 if (update is StreamingResponseOutputTextDeltaUpdate outputTextUpdate)
54 {
55 Console.Write(outputTextUpdate.Delta);
56 }
57
58 if (update is StreamingResponseOutputItemDoneUpdate outputItemDoneUpdate)
59 {
60 inputItems.Add(outputItemDoneUpdate.Item);
61
62 if (outputItemDoneUpdate.Item is FunctionCallResponseItem functionCall)
63 {
64 switch (functionCall.FunctionName)
65 {
66 case nameof(GetCurrentLocation):
67 {
68 string functionOutput = GetCurrentLocation();
69 inputItems.Add(new FunctionCallOutputResponseItem(functionCall.CallId, functionOutput));
70 break;
71 }
72
73 case nameof(GetCurrentWeather):
74 {
75 // The arguments that the model wants to use to call the function are specified as a
76 // stringified JSON object based on the schema defined in the tool definition. Note that
77 // the model may hallucinate arguments too. Consequently, it is important to do the
78 // appropriate parsing and validation before calling the function.
79 using JsonDocument argumentsJson = JsonDocument.Parse(functionCall.FunctionArguments);
80 bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location);
81 bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit);
82
83 if (!hasLocation)
84 {
85 throw new ArgumentNullException(nameof(location), "The location argument is required.");
86 }
87
88 string functionOutput = hasUnit
89 ? GetCurrentWeather(location.GetString(), unit.GetString())
90 : GetCurrentWeather(location.GetString());
91 inputItems.Add(new FunctionCallOutputResponseItem(functionCall.CallId, functionOutput));
92 break;
93 }
94
95 default:
96 {
97 // Handle other unexpected calls.
98 throw new NotImplementedException();
99 }
100 }
101
102 requiresAction = true;
103 break;
104 }
105 }
106 }
107 } while (requiresAction);
108 }
109}
110
111#pragma warning restore OPENAI001