| File: OpenAIRealtimeClient.cs | |
| Project: ..\..\..\src\Libraries\Microsoft.Extensions.AI.OpenAI\Microsoft.Extensions.AI.OpenAI.csproj (Microsoft.Extensions.AI.OpenAI) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; using OpenAI.Realtime; #pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. #pragma warning disable OPENAI002 // OpenAI Realtime API is experimental namespace Microsoft.Extensions.AI; /// <summary>Represents an <see cref="IRealtimeClient"/> for the OpenAI Realtime API.</summary> [Experimental(DiagnosticIds.Experiments.AIRealTime, UrlFormat = DiagnosticIds.UrlFormat)] public sealed class OpenAIRealtimeClient : IRealtimeClient { /// <summary>The OpenAI Realtime client.</summary> private readonly RealtimeClient _realtimeClient; /// <summary>The model to use for realtime sessions.</summary> private readonly string _model; /// <summary>Metadata about this client's provider and model, used for OpenTelemetry.</summary> private readonly ChatClientMetadata _metadata; /// <summary>Initializes a new instance of the <see cref="OpenAIRealtimeClient"/> class.</summary> /// <param name="apiKey">The API key used for authentication.</param> /// <param name="model">The model to use for realtime sessions.</param> /// <exception cref="ArgumentNullException"><paramref name="apiKey"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentNullException"><paramref name="model"/> is <see langword="null"/>.</exception> public OpenAIRealtimeClient(string apiKey, string model) { _realtimeClient = new RealtimeClient(Throw.IfNull(apiKey)); _model = Throw.IfNull(model); _metadata = new("openai", defaultModelId: _model); } /// <summary>Initializes a new instance of the <see cref="OpenAIRealtimeClient"/> class.</summary> /// <param name="realtimeClient">The OpenAI Realtime client to use.</param> /// <param name="model">The model to use for realtime sessions.</param> /// <exception cref="ArgumentNullException"><paramref name="realtimeClient"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentNullException"><paramref name="model"/> is <see langword="null"/>.</exception> public OpenAIRealtimeClient(RealtimeClient realtimeClient, string model) { _realtimeClient = Throw.IfNull(realtimeClient); _model = Throw.IfNull(model); _metadata = new("openai", defaultModelId: _model); } /// <inheritdoc /> public async Task<IRealtimeClientSession> CreateSessionAsync(RealtimeSessionOptions? options = null, CancellationToken cancellationToken = default) { var sessionClient = options?.SessionKind == RealtimeSessionKind.Transcription ? await _realtimeClient.StartTranscriptionSessionAsync(cancellationToken: cancellationToken).ConfigureAwait(false) : await _realtimeClient.StartConversationSessionAsync(_model, cancellationToken: cancellationToken).ConfigureAwait(false); var session = new OpenAIRealtimeClientSession(sessionClient, _model); try { if (options is not null) { await session.SendAsync(new SessionUpdateRealtimeClientMessage(options), cancellationToken).ConfigureAwait(false); } return session; } catch { await session.DisposeAsync().ConfigureAwait(false); throw; } } /// <inheritdoc /> object? IRealtimeClient.GetService(Type serviceType, object? serviceKey) { _ = Throw.IfNull(serviceType); return serviceKey is not null ? null : serviceType == typeof(ChatClientMetadata) ? _metadata : serviceType.IsInstanceOfType(this) ? this : serviceType.IsInstanceOfType(_realtimeClient) ? _realtimeClient : null; } /// <inheritdoc /> public void Dispose() { // Client itself has no resources to dispose. // Sessions are disposed independently. } }