openai/openai-dotnet

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
OpenAI_2.1.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

examples/Assistants/Example02b_FunctionCallingStreaming.cs

137lines · modecode

1using NUnit.Framework;
2using OpenAI.Assistants;
3using System;
4using System.ClientModel;
5using System.ClientModel.Primitives;
6using System.Collections.Generic;
7using System.Threading.Tasks;
8
9namespace OpenAI.Examples;
10
11public partial class AssistantExamples
12{
13 [Test]
14 public async Task Example02b_FunctionCallingStreaming()
15 {
16 // This example parallels the content at the following location:
17 // https://platform.openai.com/docs/assistants/tools/function-calling/function-calling-beta
18 #region Step 1 - Define Functions
19
20 // First, define the functions that the assistant will use in its defined tools.
21
22 FunctionToolDefinition getTemperatureTool = new()
23 {
24 FunctionName = "get_current_temperature",
25 Description = "Gets the current temperature at a specific location.",
26 Parameters = BinaryData.FromString("""
27 {
28 "type": "object",
29 "properties": {
30 "location": {
31 "type": "string",
32 "description": "The city and state, e.g., San Francisco, CA"
33 },
34 "unit": {
35 "type": "string",
36 "enum": ["Celsius", "Fahrenheit"],
37 "description": "The temperature unit to use. Infer this from the user's location."
38 }
39 }
40 }
41 """),
42 };
43
44 FunctionToolDefinition getRainProbabilityTool = new()
45 {
46 FunctionName = "get_current_rain_probability",
47 Description = "Gets the current forecasted probability of rain at a specific location,"
48 + " represented as a percent chance in the range of 0 to 100.",
49 Parameters = BinaryData.FromString("""
50 {
51 "type": "object",
52 "properties": {
53 "location": {
54 "type": "string",
55 "description": "The city and state, e.g., San Francisco, CA"
56 }
57 },
58 "required": ["location"]
59 }
60 """),
61 };
62
63 #endregion
64
65 // Assistants is a beta API and subject to change; acknowledge its experimental status by suppressing the matching warning.
66 AssistantClient client = new(Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
67
68 #region Create a new assistant with function tools
69 // Create an assistant that can call the function tools.
70 AssistantCreationOptions assistantOptions = new()
71 {
72 Name = "Example: Function Calling",
73 Instructions =
74 "Don't make assumptions about what values to plug into functions."
75 + " Ask for clarification if a user request is ambiguous.",
76 Tools = { getTemperatureTool, getRainProbabilityTool },
77 };
78
79 Assistant assistant = await client.CreateAssistantAsync("gpt-4-turbo", assistantOptions);
80 #endregion
81
82 #region Step 2 - Create a thread and add messages
83 AssistantThread thread = await client.CreateThreadAsync();
84 ThreadMessage message = await client.CreateMessageAsync(
85 thread.Id,
86 MessageRole.User,
87 [
88 "What's the weather in San Francisco today and the likelihood it'll rain?"
89 ]);
90 #endregion
91
92 #region Step 3 - Initiate a streaming run
93 AsyncCollectionResult<StreamingUpdate> asyncUpdates
94 = client.CreateRunStreamingAsync(thread.Id, assistant.Id);
95
96 ThreadRun currentRun = null;
97 do
98 {
99 currentRun = null;
100 List<ToolOutput> outputsToSubmit = [];
101 await foreach (StreamingUpdate update in asyncUpdates)
102 {
103 if (update is RequiredActionUpdate requiredActionUpdate)
104 {
105 if (requiredActionUpdate.FunctionName == getTemperatureTool.FunctionName)
106 {
107 outputsToSubmit.Add(new ToolOutput(requiredActionUpdate.ToolCallId, "57"));
108 }
109 else if (requiredActionUpdate.FunctionName == getRainProbabilityTool.FunctionName)
110 {
111 outputsToSubmit.Add(new ToolOutput(requiredActionUpdate.ToolCallId, "25%"));
112 }
113 }
114 else if (update is RunUpdate runUpdate)
115 {
116 currentRun = runUpdate;
117 }
118 else if (update is MessageContentUpdate contentUpdate)
119 {
120 Console.Write(contentUpdate.Text);
121 }
122 }
123 if (outputsToSubmit.Count > 0)
124 {
125 asyncUpdates = client.SubmitToolOutputsToRunStreamingAsync(currentRun.ThreadId, currentRun.Id, outputsToSubmit);
126 }
127 }
128 while (currentRun?.Status.IsTerminal == false);
129
130 #endregion
131
132 // Optionally, delete the resources for tidiness if no longer needed.
133 RequestOptions noThrowOptions = new() { ErrorOptions = ClientErrorBehaviors.NoThrow };
134 _ = await client.DeleteThreadAsync(thread.Id, noThrowOptions);
135 _ = await client.DeleteAssistantAsync(assistant.Id, noThrowOptions);
136 }
137}
138