openai/openai-dotnet

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
OpenAI_2.10.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

examples/Responses/Example04_FunctionCallingStreaming.cs

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