Skip to content

Commit 7d3b186

Browse files
authored
Openai examples (#1292)
* Moved OpenAI examples to dedicated folder. * Sending function output back. * OpenAI local function example working nicely. * Refactor.
1 parent ddc8ac2 commit 7d3b186

72 files changed

Lines changed: 2191 additions & 1421 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

examples/WebRTCExamples/WebRTCOpenAI/JsonConverters/BooleanStringConverter.cs renamed to examples/OpenAIExamples/OpenAI.Realtime/JsonConverters/BooleanStringConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// is only required for System.Text.Json as Newtonsoft already supports this.
66
//
77
// Author(s):
8-
// Aaron Clauson
8+
// Aaron Clauson ([email protected])
99
//
1010
// History:
1111
// 09 Jun 2024 Aaron Clauson Created, Dublin, Ireland.

examples/WebRTCExamples/WebRTCOpenAI/JsonSerializationOptions.cs renamed to examples/OpenAIExamples/OpenAI.Realtime/JsonConverters/JsonSerializationOptions.cs

File renamed without changes.

examples/WebRTCExamples/WebRTCOpenAIAliceAndBob/JsonConverters/JsonStringEnumMemberConverter.cs renamed to examples/OpenAIExamples/OpenAI.Realtime/JsonConverters/JsonStringEnumMemberConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// is only required for System.Text.Json as Newtonsoft already supports this.
77
//
88
// Author(s):
9-
// Aaron Clauson
9+
// Aaron Clauson ([email protected])
1010
//
1111
// History:
1212
// 09 Jun 2024 Aaron Clauson Created, Dublin, Ireland.

examples/WebRTCExamples/WebRTCOpenAI/JsonConverters/NumericConverter.cs renamed to examples/OpenAIExamples/OpenAI.Realtime/JsonConverters/NumericConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// is only required for System.Text.Json as Newtonsoft already supports this.
66
//
77
// Author(s):
8-
// Aaron Clauson
8+
// Aaron Clauson ([email protected])
99
//
1010
// History:
1111
// 09 Jun 2024 Aaron Clauson Created, Dublin, Ireland.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<LangVersion>12.0</LangVersion>
6+
<Nullable>enable</Nullable>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="LanguageExt.Core" Version="4.4.9" />
11+
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
12+
</ItemGroup>
13+
14+
</Project>
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
//-----------------------------------------------------------------------------
2+
// Filename: OpenAIRealtimeRestClient.cs
3+
//
4+
// Description:
5+
//
6+
// Author(s):
7+
// Aaron Clauson ([email protected])
8+
//
9+
// History:
10+
// 23 Jan 2025 Aaron Clauson Created, Dublin, Ireland.
11+
//
12+
// License:
13+
// MIT.
14+
//-----------------------------------------------------------------------------
15+
16+
using LanguageExt;
17+
using System.Net.Http.Headers;
18+
using System.Net.Http;
19+
using System.Text.Json;
20+
using System.Text;
21+
using System.Threading.Tasks;
22+
using LanguageExt.Common;
23+
24+
namespace demo;
25+
26+
public class OpenAIRealtimeRestClient
27+
{
28+
/// <summary>
29+
/// Completes the steps required to get an ephemeral key from the OpenAI REST server. The ephemeral key is needed
30+
/// to send an SDP offer, and get the SDP answer.
31+
/// </summary>
32+
public static async Task<Either<Error, string>> CreateEphemeralKeyAsync(string sessionsUrl, string openAIToken, string model, OpenAIVoicesEnum voice)
33+
=> (await SendHttpPostAsync(
34+
sessionsUrl,
35+
openAIToken,
36+
JsonSerializer.Serialize(
37+
new OpenAISession
38+
{
39+
Model = model,
40+
Voice = voice
41+
}, JsonOptions.Default),
42+
"application/json"))
43+
.Bind(responseContent =>
44+
JsonSerializer.Deserialize<JsonElement>(responseContent)
45+
.GetProperty("client_secret")
46+
.GetProperty("value")
47+
.GetString() ??
48+
Prelude.Left<Error, string>(Error.New("Failed to get ephemeral secret."))
49+
);
50+
51+
/// <summary>
52+
/// Attempts to get the SDP answer from the OpenAI REST server. This is the way OpenAI does the signalling. The
53+
/// ICE candidates will be returned in the SDP answer and are publicly accessible IP's.
54+
/// </summary>
55+
/// <remarks>
56+
/// See https://platform.openai.com/docs/guides/realtime-webrtc#creating-an-ephemeral-token.
57+
/// </remarks>
58+
public static Task<Either<Error, string>> GetOpenAIAnswerSdpAsync(string ephemeralKey, string openAIBaseUrl, string model, string offerSdp)
59+
=> SendHttpPostAsync(
60+
$"{openAIBaseUrl}?model={model}",
61+
ephemeralKey,
62+
offerSdp,
63+
"application/sdp");
64+
65+
/// <summary>
66+
/// Helper method to send an HTTP POST request with the required headers.
67+
/// </summary>
68+
public static async Task<Either<Error, string>> SendHttpPostAsync(
69+
string url,
70+
string token,
71+
string body,
72+
string contentType)
73+
{
74+
using var httpClient = new HttpClient();
75+
76+
httpClient.DefaultRequestHeaders.Clear();
77+
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
78+
79+
var content = new StringContent(body, Encoding.UTF8);
80+
content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
81+
82+
var response = await httpClient.PostAsync(url, content);
83+
84+
if (!response.IsSuccessStatusCode)
85+
{
86+
var errorBody = await response.Content.ReadAsStringAsync();
87+
return Error.New($"HTTP POST to {url} failed: {response.StatusCode}. Error body: {errorBody}");
88+
}
89+
90+
return await response.Content.ReadAsStringAsync();
91+
}
92+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace demo;
2+
3+
public enum OpenAIConversationAudioFormatsEnum
4+
{
5+
// "pcm16"
6+
Pcm16,
7+
8+
// "g711_ulaw"
9+
G711_Ulaw,
10+
11+
// "g711_alaw"
12+
G711Alaw
13+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace demo;
2+
3+
public enum OpenAIConversationConversationTypeEnum
4+
{
5+
message,
6+
7+
function_call,
8+
9+
function_call_output
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace demo;
2+
3+
public enum OpenAIResponseStatusEnum
4+
{
5+
Completed,
6+
Cancelled,
7+
Failed,
8+
Incomplete
9+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace demo;
2+
3+
public enum OpenAIToolChoiceEnum
4+
{
5+
Auto,
6+
None,
7+
Required
8+
}

0 commit comments

Comments
 (0)