openai/openai-dotnet

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
copilot/update-dotnet-version-to-10

Branches

Tags

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

Clone

HTTPS

Download ZIP

examples/Responses/Example04_FunctionCallingStreaming.cs

113lines · 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 ResponsesClient client = new(model: "gpt-5", apiKey: 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 PrintMessageItems(inputItems.OfType<MessageResponseItem>());
30
31 bool requiresAction;
32
33 do
34 {
35 requiresAction = false;
36
37 CreateResponseOptions options = new(inputItems)
38 {
39 Tools = { getCurrentLocationTool, getCurrentWeatherTool },
40 StreamingEnabled = true,
41 };
42
43 CollectionResult<StreamingResponseUpdate> responseUpdates = client.CreateResponseStreaming(options);
44
45 foreach (StreamingResponseUpdate update in responseUpdates)
46 {
47 if (update is StreamingResponseOutputItemAddedUpdate outputItemAddedUpdated)
48 {
49 if (outputItemAddedUpdated.Item is MessageResponseItem message && message.Role == MessageRole.Assistant)
50 {
51 Console.WriteLine($"[ASSISTANT]:");
52 }
53 }
54
55 if (update is StreamingResponseOutputTextDeltaUpdate outputTextUpdate)
56 {
57 Console.Write(outputTextUpdate.Delta);
58 }
59
60 if (update is StreamingResponseOutputItemDoneUpdate outputItemDoneUpdate)
61 {
62 inputItems.Add(outputItemDoneUpdate.Item);
63
64 if (outputItemDoneUpdate.Item is FunctionCallResponseItem functionCall)
65 {
66 switch (functionCall.FunctionName)
67 {
68 case nameof(GetCurrentLocation):
69 {
70 string functionOutput = GetCurrentLocation();
71 inputItems.Add(new FunctionCallOutputResponseItem(functionCall.CallId, functionOutput));
72 break;
73 }
74
75 case nameof(GetCurrentWeather):
76 {
77 // The arguments that the model wants to use to call the function are specified as a
78 // stringified JSON object based on the schema defined in the tool definition. Note that
79 // the model may hallucinate arguments too. Consequently, it is important to do the
80 // appropriate parsing and validation before calling the function.
81 using JsonDocument argumentsJson = JsonDocument.Parse(functionCall.FunctionArguments);
82 bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location);
83 bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit);
84
85 if (!hasLocation)
86 {
87 throw new ArgumentNullException(nameof(location), "The location argument is required.");
88 }
89
90 string functionOutput = hasUnit
91 ? GetCurrentWeather(location.GetString(), unit.GetString())
92 : GetCurrentWeather(location.GetString());
93 inputItems.Add(new FunctionCallOutputResponseItem(functionCall.CallId, functionOutput));
94 break;
95 }
96
97 default:
98 {
99 // Handle other unexpected calls.
100 throw new NotImplementedException();
101 }
102 }
103
104 requiresAction = true;
105 break;
106 }
107 }
108 }
109 } while (requiresAction);
110 }
111}
112
113#pragma warning restore OPENAI001