openai/openai-dotnet

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
joseharriaga/prompt-cache

Branches

Tags

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

Clone

HTTPS

Download ZIP

examples/Realtime/Example01_AudioFromFileWithToolsAsync.cs

262lines · modecode

1using NUnit.Framework;
2using OpenAI.Realtime;
3using System;
4using System.Collections.Generic;
5using System.IO;
6using System.Linq;
7using System.Threading.Tasks;
8
9namespace OpenAI.Examples;
10
11#pragma warning disable OPENAI002
12
13public partial class RealtimeExamples
14{
15 private static string GetCurrentWeather(string location, string unit = "celsius")
16 {
17 // Call the weather API here.
18 return $"31 {unit}";
19 }
20
21 private static readonly RealtimeFunctionTool getCurrentWeatherTool = new(functionName: nameof(GetCurrentWeather))
22 {
23 FunctionDescription = "gets the weather for a location",
24 FunctionParameters = BinaryData.FromString("""
25 {
26 "type": "object",
27 "properties": {
28 "location": {
29 "type": "string",
30 "description": "The city and state, e.g. Boston, MA"
31 },
32 "unit": {
33 "type": "string",
34 "enum": [ "celsius", "fahrenheit" ],
35 "description": "The temperature unit to use. Infer this from the specified location."
36 }
37 },
38 "required": [ "location" ]
39 }
40 """)
41 };
42
43 [Test]
44 public async Task Example01_AudioFromFileWithToolsAsync()
45 {
46 RealtimeClient client = new(apiKey: Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
47
48 using RealtimeSessionClient sessionClient = await client.StartConversationSessionAsync(model: "gpt-realtime");
49
50 RealtimeConversationSessionOptions sessionOptions = new()
51 {
52 Instructions = "You are a cheerful assistant that talks like a pirate. "
53 + "Always inform the user when you are about to call a tool. "
54 + "Prefer to call tools whenever applicable.",
55
56 Tools = { getCurrentWeatherTool },
57
58 AudioOptions = new()
59 {
60 InputAudioOptions = new()
61 {
62 // AudioFormat = new GARealtimePcmAudioFormat(),
63 AudioTranscriptionOptions = new()
64 {
65 Model = "gpt-4o-transcribe",
66 },
67 TurnDetection = new RealtimeServerVadTurnDetection(),
68 },
69 OutputAudioOptions = new()
70 {
71 // AudioFormat = new GARealtimePcmAudioFormat(),
72 Voice = RealtimeVoice.Alloy,
73 },
74 },
75 };
76
77 await sessionClient.ConfigureConversationSessionAsync(sessionOptions);
78
79 // The conversation history (if applicable) can be provided by adding messages to the
80 // conversation one by one. Note that adding a message will not automatically initiate
81 // a response from the model.
82 await sessionClient.AddItemAsync(RealtimeItem.CreateUserMessageItem("I'm trying to decide what to wear on my trip."));
83
84 string inputAudioFilePath = Path.Join("Assets", "realtime_whats_the_weather_pcm16_24khz_mono.wav");
85 using Stream inputAudioStream = File.OpenRead(inputAudioFilePath);
86 _ = sessionClient.SendInputAudioAsync(inputAudioStream);
87
88 string outputAudioFilePath = Path.Join("output.raw");
89 using Stream outputAudioStream = File.OpenWrite(outputAudioFilePath);
90
91 bool done = false;
92
93 await foreach (RealtimeServerUpdate update in sessionClient.ReceiveUpdatesAsync())
94 {
95 switch (update)
96 {
97 case RealtimeServerUpdateSessionCreated sessionCreatedUpdate:
98 {
99 Console.WriteLine($"[EVENT ID: {sessionCreatedUpdate.EventId}]");
100 Console.WriteLine($">> Session created.");
101 Console.WriteLine();
102 break;
103 }
104 case RealtimeServerUpdateSessionUpdated sessionUpdatedUpdate:
105 {
106 Console.WriteLine($"[EVENT ID: {sessionUpdatedUpdate.EventId}]");
107 Console.WriteLine($">> Session updated.");
108 Console.WriteLine();
109 break;
110 }
111 case RealtimeServerUpdateInputAudioBufferSpeechStarted inputAudioBufferSpeechStartedUpdate:
112 {
113 Console.WriteLine($"[EVENT ID: {inputAudioBufferSpeechStartedUpdate.EventId}]");
114 Console.WriteLine($">> Speech started at {inputAudioBufferSpeechStartedUpdate.AudioStartTime}.");
115 Console.WriteLine();
116 break;
117 }
118 case RealtimeServerUpdateInputAudioBufferSpeechStopped inputAudioBufferSpeechStoppedUpdate:
119 {
120 Console.WriteLine($"[EVENT ID: {inputAudioBufferSpeechStoppedUpdate.EventId}]");
121 Console.WriteLine($">> Speech stopped at {inputAudioBufferSpeechStoppedUpdate.AudioEndTime}.");
122 Console.WriteLine();
123 break;
124 }
125 case RealtimeServerUpdateConversationItemDone conversationItemDoneUpdate:
126 {
127 Console.WriteLine($"[EVENT ID: {conversationItemDoneUpdate.EventId}]");
128 Console.WriteLine($">> Conversation item done. Type: {conversationItemDoneUpdate.Item.Patch.GetString("$.type"u8)}.");
129
130 RealtimeMessageItem messageItem = conversationItemDoneUpdate.Item as RealtimeMessageItem;
131
132 if (messageItem != null)
133 {
134 foreach (RealtimeMessageContentPart contentPart in messageItem.Content)
135 {
136 switch (contentPart)
137 {
138 case RealtimeInputTextMessageContentPart inputTextPart:
139 {
140 Console.WriteLine();
141 Console.WriteLine($"++ [{messageItem.Role.ToString().ToUpperInvariant()}]:");
142 Console.WriteLine(inputTextPart.Text);
143 break;
144 }
145 case RealtimeOutputTextMessageContentPart outputTextPart:
146 {
147 Console.WriteLine();
148 Console.WriteLine($"++ [{messageItem.Role.ToString().ToUpperInvariant()}]:");
149 Console.WriteLine(outputTextPart.Text);
150 break;
151 }
152 }
153 }
154 }
155
156 Console.WriteLine();
157 break;
158 }
159 case RealtimeServerUpdateConversationItemInputAudioTranscriptionCompleted conversationItemInputAudioTranscriptionCompletedUpdate:
160 {
161 Console.WriteLine($"[EVENT ID: {conversationItemInputAudioTranscriptionCompletedUpdate.EventId}]");
162 Console.WriteLine($">> Conversation item input audio transcription completed.");
163
164 Console.WriteLine();
165 Console.WriteLine($"++ [USER]:");
166 Console.WriteLine($"{conversationItemInputAudioTranscriptionCompletedUpdate.Transcript}");
167 Console.WriteLine();
168 break;
169 }
170 case RealtimeServerUpdateResponseOutputAudioDelta responseOutputAudioDeltaUpdate:
171 {
172 Console.WriteLine($"[EVENT ID: {responseOutputAudioDeltaUpdate.EventId}]");
173 Console.WriteLine($">> Response output audio delta. Bytes: {responseOutputAudioDeltaUpdate.Delta.Length}.");
174
175 outputAudioStream.Write(responseOutputAudioDeltaUpdate.Delta);
176
177 break;
178 }
179 case RealtimeServerUpdateResponseOutputAudioDone responseOutputAudioDoneUpdate:
180 {
181 Console.WriteLine($"[EVENT ID: {responseOutputAudioDoneUpdate.EventId}]");
182 Console.WriteLine($">> Response output audio done. Bytes: {outputAudioStream.Length}.");
183 Console.WriteLine();
184 break;
185 }
186 case RealtimeServerUpdateResponseOutputAudioTranscriptDone responseOutputAudioTranscriptionDoneUpdate:
187 {
188 Console.WriteLine($"[EVENT ID: {responseOutputAudioTranscriptionDoneUpdate.EventId}]");
189 Console.WriteLine($">> Response output audio transcription done.");
190
191 Console.WriteLine();
192 Console.WriteLine($"++ [ASSISTANT]:");
193 Console.WriteLine($"{responseOutputAudioTranscriptionDoneUpdate.Transcript}");
194 Console.WriteLine();
195 break;
196 }
197 case RealtimeServerUpdateResponseDone responseDoneUpdate:
198 {
199 Console.WriteLine($"[EVENT ID: {responseDoneUpdate.EventId}]");
200 Console.WriteLine($">> Response done. Status: {responseDoneUpdate.Response.Status}.");
201
202 bool hasToolCalls = false;
203
204 List<RealtimeFunctionCallItem> functionCallItems = responseDoneUpdate.Response.OutputItems
205 .OfType<RealtimeFunctionCallItem>()
206 .ToList();
207
208 foreach (RealtimeFunctionCallItem functionCallItem in functionCallItems)
209 {
210 hasToolCalls = true;
211
212 Console.WriteLine($">> Calling {functionCallItem.FunctionName} function...");
213
214 string output = GetCurrentWeather(location: "San Francisco, CA");
215
216 RealtimeItem functionCallOutputItem = RealtimeItem.CreateFunctionCallOutputItem(
217 callId: functionCallItem.CallId,
218 functionOutput: output);
219
220 Console.WriteLine($">> Adding function call output item...");
221
222 await sessionClient.AddItemAsync(functionCallOutputItem);
223 }
224
225 if (hasToolCalls)
226 {
227 // If we need the model to process the output of a tool call, we instruct
228 // the server to create another responses.
229 Console.WriteLine($">> Requesting follow up response...");
230
231 await sessionClient.StartResponseAsync();
232 }
233 else
234 {
235 done = true;
236 break;
237 }
238
239 Console.WriteLine();
240 break;
241 }
242 case RealtimeServerUpdateError errorUpdate:
243 {
244 Console.WriteLine($"[EVENT ID: {errorUpdate.EventId}]");
245 Console.WriteLine($"Error: {errorUpdate.Error.Message}");
246
247 done = true;
248
249 Console.WriteLine();
250 break;
251 }
252 }
253
254 if (done)
255 {
256 break;
257 }
258 }
259 }
260}
261
262#pragma warning restore OPENAI002