openai/openai-dotnet

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
OpenAI_2.0.0-beta.10

Branches

Tags

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

Clone

HTTPS

Download ZIP

examples/Assistants/Example04_AllTheTools.cs

206lines · modecode

1using NUnit.Framework;
2using OpenAI.Assistants;
3using OpenAI.Files;
4using System;
5using System.ClientModel;
6using System.Collections.Generic;
7using System.Text.Json;
8using System.Threading;
9
10namespace OpenAI.Examples;
11
12public partial class AssistantExamples
13{
14 [Test]
15 public void Example04_AllTheTools()
16 {
17#pragma warning disable OPENAI001
18
19 #region Define a function tool
20 static string GetNameOfFamilyMember(string relation)
21 => relation switch
22 {
23 { } when relation.Contains("father") => "John Doe",
24 { } when relation.Contains("mother") => "Jane Doe",
25 _ => throw new ArgumentException(relation, nameof(relation))
26 };
27
28 FunctionToolDefinition getNameOfFamilyMemberTool = new()
29 {
30 FunctionName = nameof(GetNameOfFamilyMember),
31 Description = "Provided a family relation type like 'father' or 'mother', "
32 + "gets the name of the related person from the user.",
33 Parameters = BinaryData.FromString("""
34 {
35 "type": "object",
36 "properties": {
37 "relation": {
38 "type": "string",
39 "description": "The relation to the user to query, e.g. 'mother' or 'father'"
40 }
41 },
42 "required": [ "relation" ]
43 }
44 """),
45 };
46
47 #region Upload a mock file for use with file search
48 FileClient fileClient = new(Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
49 OpenAIFileInfo favoriteNumberFile = fileClient.UploadFile(
50 BinaryData.FromString("""
51 This file contains the favorite numbers for individuals.
52
53 John Doe: 14
54 Bob Doe: 32
55 Jane Doe: 44
56 """).ToStream(),
57 "favorite_numbers.txt",
58 FileUploadPurpose.Assistants);
59 #endregion
60
61 #region Create an assistant with functions, file search, and code interpreter all enabled
62 AssistantClient client = new(Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
63 Assistant assistant = client.CreateAssistant("gpt-4-turbo", new AssistantCreationOptions()
64 {
65 Instructions = "Use functions to resolve family relations into the names of people. Use file search to "
66 + " look up the favorite numbers of people. Use code interpreter to create graphs of lines.",
67 Tools = { getNameOfFamilyMemberTool, new FileSearchToolDefinition(), new CodeInterpreterToolDefinition() },
68 ToolResources = new()
69 {
70 FileSearch = new()
71 {
72 NewVectorStores =
73 {
74 new VectorStoreCreationHelper([favoriteNumberFile.Id]),
75 },
76 },
77 },
78 });
79 #endregion
80
81 #region Create a new thread and start a run
82 AssistantThread thread = client.CreateThread(new ThreadCreationOptions()
83 {
84 InitialMessages =
85 {
86 "Create a graph of a line with a slope that's my father's favorite number "
87 + "and an offset that's my mother's favorite number.",
88 "Include people's names in your response and cite where you found them."
89 }
90 });
91
92 ThreadRun run = client.CreateRun(thread, assistant);
93 #endregion
94
95 #region Complete the run, calling functions as needed
96 // Poll the run until it is no longer queued or in progress.
97 while (!run.Status.IsTerminal)
98 {
99 Thread.Sleep(TimeSpan.FromSeconds(1));
100 run = client.GetRun(run.ThreadId, run.Id);
101
102 // If the run requires action, resolve them.
103 if (run.Status == RunStatus.RequiresAction)
104 {
105 List<ToolOutput> toolOutputs = [];
106
107 foreach (RequiredAction action in run.RequiredActions)
108 {
109 switch (action.FunctionName)
110 {
111 case nameof(GetNameOfFamilyMember):
112 {
113 using JsonDocument argumentsDocument = JsonDocument.Parse(action.FunctionArguments);
114 string relation = argumentsDocument.RootElement.TryGetProperty("relation", out JsonElement relationProperty)
115 ? relationProperty.GetString()
116 : null;
117 string toolResult = GetNameOfFamilyMember(relation);
118 toolOutputs.Add(new ToolOutput(action.ToolCallId, toolResult));
119 break;
120 }
121
122 default:
123 {
124 // Handle other or unexpected calls.
125 throw new NotImplementedException();
126 }
127 }
128 }
129
130 // Submit the tool outputs to the assistant, which returns the run to the queued state.
131 run = client.SubmitToolOutputsToRun(run.ThreadId, run.Id, toolOutputs);
132 }
133 }
134 #endregion
135
136 #region
137 // With the run complete, list the messages and display their content
138 if (run.Status == RunStatus.Completed)
139 {
140 PageCollection<ThreadMessage> messagePages
141 = client.GetMessages(run.ThreadId, new MessageCollectionOptions() { Order = ListOrder.OldestFirst });
142 IEnumerable<ThreadMessage> messages = messagePages.GetAllValues();
143
144 foreach (ThreadMessage message in messages)
145 {
146 Console.WriteLine($"[{message.Role.ToString().ToUpper()}]: ");
147 foreach (MessageContent contentItem in message.Content)
148 {
149 Console.WriteLine($"{contentItem.Text}");
150
151 if (contentItem.ImageFileId is not null)
152 {
153 Console.WriteLine($" <Image File ID> {contentItem.ImageFileId}");
154 }
155
156 // Include annotations, if any.
157 if (contentItem.TextAnnotations.Count > 0)
158 {
159 Console.WriteLine();
160 foreach (TextAnnotation annotation in contentItem.TextAnnotations)
161 {
162 Console.WriteLine($"* File ID used by file_search: {annotation.InputFileId}");
163 Console.WriteLine($"* File ID created by code_interpreter: {annotation.OutputFileId}");
164 Console.WriteLine($"* Text to replace: {annotation.TextToReplace}");
165 Console.WriteLine($"* Message content index range: {annotation.StartIndex}-{annotation.EndIndex}");
166 }
167 }
168
169 }
170 Console.WriteLine();
171 }
172 #endregion
173
174 #region List run steps for details about tool calls
175 PageCollection<RunStep> runSteps = client.GetRunSteps(
176 run, new RunStepCollectionOptions()
177 {
178 Order = ListOrder.OldestFirst
179 });
180 foreach (RunStep step in runSteps.GetAllValues())
181 {
182 Console.WriteLine($"Run step: {step.Status}");
183 foreach (RunStepToolCall toolCall in step.Details.ToolCalls)
184 {
185 Console.WriteLine($" --> Tool call: {toolCall.ToolKind}");
186 foreach (RunStepCodeInterpreterOutput output in toolCall.CodeInterpreterOutputs)
187 {
188 Console.WriteLine($" --> Output: {output.ImageFileId}");
189 }
190 }
191 }
192 #endregion
193 }
194 else
195 {
196 throw new NotImplementedException(run.Status.ToString());
197 }
198 #endregion
199
200 #region Clean up any temporary resources that are no longer needed
201 _ = client.DeleteThread(thread);
202 _ = client.DeleteAssistant(assistant);
203 _ = fileClient.DeleteFile(favoriteNumberFile.Id);
204 #endregion
205 }
206}