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_FunctionCallingStreamingAsync.cs

112lines · modeblame

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