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/Assistants/Example02b_FunctionCallingStreaming.cs

141lines · modeblame

9f9f2936Jose Arriaga Maldonado2 years ago1using NUnit.Framework;
2using OpenAI.Assistants;
3using System;
4using System.ClientModel;
5using System.ClientModel.Primitives;
6using System.Collections.Generic;
7using System.Threading.Tasks;
8
8cc6643fJose Arriaga Maldonado2 years ago9namespace OpenAI.Examples;
74848f8dJose Arriaga Maldonado2 years ago10
5dce104aJose Arriaga Maldonado1 years ago11// 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
8cc6643fJose Arriaga Maldonado2 years ago15public partial class AssistantExamples
9f9f2936Jose Arriaga Maldonado2 years ago16{
17[Test]
8cc6643fJose Arriaga Maldonado2 years ago18public async Task Example02b_FunctionCallingStreaming()
9f9f2936Jose Arriaga Maldonado2 years ago19{
8cc6643fJose Arriaga Maldonado2 years ago20// This example parallels the content at the following location:
9f9f2936Jose Arriaga Maldonado2 years ago21// https://platform.openai.com/docs/assistants/tools/function-calling/function-calling-beta
22#region Step 1 - Define Functions
b0f9e5c3Jose Arriaga Maldonado1 years ago23
9f9f2936Jose Arriaga Maldonado2 years ago24// First, define the functions that the assistant will use in its defined tools.
25
86407c80Jose Arriaga Maldonado1 years ago26FunctionToolDefinition getTemperatureTool = new("get_current_temperature")
9f9f2936Jose Arriaga Maldonado2 years ago27{
28Description = "Gets the current temperature at a specific location.",
29Parameters = BinaryData.FromString("""
30{
31"type": "object",
32"properties": {
33"location": {
34"type": "string",
35"description": "The city and state, e.g., San Francisco, CA"
36},
37"unit": {
38"type": "string",
39"enum": ["Celsius", "Fahrenheit"],
40"description": "The temperature unit to use. Infer this from the user's location."
41}
42}
43}
44"""),
45};
46
86407c80Jose Arriaga Maldonado1 years ago47FunctionToolDefinition getRainProbabilityTool = new("get_current_rain_probability")
9f9f2936Jose Arriaga Maldonado2 years ago48{
49Description = "Gets the current forecasted probability of rain at a specific location,"
50+ " represented as a percent chance in the range of 0 to 100.",
51Parameters = BinaryData.FromString("""
52{
53"type": "object",
54"properties": {
55"location": {
56"type": "string",
57"description": "The city and state, e.g., San Francisco, CA"
58}
59},
60"required": ["location"]
61}
62"""),
63};
64
65#endregion
66
67// Assistants is a beta API and subject to change; acknowledge its experimental status by suppressing the matching warning.
68AssistantClient client = new(Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
69
70#region Create a new assistant with function tools
71// Create an assistant that can call the function tools.
72AssistantCreationOptions assistantOptions = new()
73{
8cc6643fJose Arriaga Maldonado2 years ago74Name = "Example: Function Calling",
9f9f2936Jose Arriaga Maldonado2 years ago75Instructions =
76"Don't make assumptions about what values to plug into functions."
77+ " Ask for clarification if a user request is ambiguous.",
78Tools = { getTemperatureTool, getRainProbabilityTool },
79};
80
81Assistant assistant = await client.CreateAssistantAsync("gpt-4-turbo", assistantOptions);
82#endregion
83
84#region Step 2 - Create a thread and add messages
85AssistantThread thread = await client.CreateThreadAsync();
86ThreadMessage message = await client.CreateMessageAsync(
a330c2e7Jose Arriaga Maldonado1 years ago87thread.Id,
d665b61fTravis Wilson2 years ago88MessageRole.User,
9f9f2936Jose Arriaga Maldonado2 years ago89[
90"What's the weather in San Francisco today and the likelihood it'll rain?"
91]);
92#endregion
93
94#region Step 3 - Initiate a streaming run
7bdecfd8Anne Thompson2 years ago95AsyncCollectionResult<StreamingUpdate> asyncUpdates
a330c2e7Jose Arriaga Maldonado1 years ago96= client.CreateRunStreamingAsync(thread.Id, assistant.Id);
9f9f2936Jose Arriaga Maldonado2 years ago97
98ThreadRun currentRun = null;
99do
100{
101currentRun = null;
102List<ToolOutput> outputsToSubmit = [];
103await foreach (StreamingUpdate update in asyncUpdates)
104{
a330c2e7Jose Arriaga Maldonado1 years ago105if (update is RequiredActionUpdate requiredActionUpdate)
9f9f2936Jose Arriaga Maldonado2 years ago106{
107if (requiredActionUpdate.FunctionName == getTemperatureTool.FunctionName)
108{
109outputsToSubmit.Add(new ToolOutput(requiredActionUpdate.ToolCallId, "57"));
110}
111else if (requiredActionUpdate.FunctionName == getRainProbabilityTool.FunctionName)
112{
113outputsToSubmit.Add(new ToolOutput(requiredActionUpdate.ToolCallId, "25%"));
114}
115}
a330c2e7Jose Arriaga Maldonado1 years ago116else if (update is RunUpdate runUpdate)
117{
118currentRun = runUpdate;
119}
9f9f2936Jose Arriaga Maldonado2 years ago120else if (update is MessageContentUpdate contentUpdate)
121{
122Console.Write(contentUpdate.Text);
123}
124}
125if (outputsToSubmit.Count > 0)
126{
a330c2e7Jose Arriaga Maldonado1 years ago127asyncUpdates = client.SubmitToolOutputsToRunStreamingAsync(currentRun.ThreadId, currentRun.Id, outputsToSubmit);
9f9f2936Jose Arriaga Maldonado2 years ago128}
129}
130while (currentRun?.Status.IsTerminal == false);
131
132#endregion
133
134// Optionally, delete the resources for tidiness if no longer needed.
135RequestOptions noThrowOptions = new() { ErrorOptions = ClientErrorBehaviors.NoThrow };
136_ = await client.DeleteThreadAsync(thread.Id, noThrowOptions);
137_ = await client.DeleteAssistantAsync(assistant.Id, noThrowOptions);
138}
139}
5dce104aJose Arriaga Maldonado1 years ago140
141#pragma warning restore OPENAI001