diff --git a/Directory.Packages.props b/Directory.Packages.props
index 843e0899..b115ab6b 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -59,7 +59,7 @@
-
+
diff --git a/src/Infrastructure/BotSharp.Abstraction/MLTasks/IRealTimeCompletion.cs b/src/Infrastructure/BotSharp.Abstraction/MLTasks/IRealTimeCompletion.cs
index b3827c33..396ccf02 100644
--- a/src/Infrastructure/BotSharp.Abstraction/MLTasks/IRealTimeCompletion.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/MLTasks/IRealTimeCompletion.cs
@@ -16,14 +16,14 @@ public interface IRealTimeCompletion
Action> onModelResponseDone,
Action onConversationItemCreated,
Action onInputAudioTranscriptionCompleted,
- Action onUserInterrupted);
+ Action onInterruptionDetected);
Task AppenAudioBuffer(string message);
Task AppenAudioBuffer(ArraySegment data, int length);
Task SendEventToModel(object message);
Task Disconnect();
- Task UpdateSession(RealtimeHubConnection conn, bool interruptResponse = true);
+ Task UpdateSession(RealtimeHubConnection conn);
Task InsertConversationItem(RoleDialogModel message);
Task RemoveConversationItem(string itemId);
Task TriggerModelInference(string? instructions = null);
diff --git a/src/Infrastructure/BotSharp.Abstraction/Realtime/IRealtimeHub.cs b/src/Infrastructure/BotSharp.Abstraction/Realtime/IRealtimeHub.cs
index 37e58f12..7e3a840e 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Realtime/IRealtimeHub.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Realtime/IRealtimeHub.cs
@@ -1,6 +1,5 @@
using BotSharp.Abstraction.MLTasks;
using BotSharp.Abstraction.Realtime.Models;
-using System.Net.WebSockets;
namespace BotSharp.Abstraction.Realtime;
@@ -13,7 +12,6 @@ public interface IRealtimeHub
RealtimeHubConnection SetHubConnection(string conversationId);
IRealTimeCompletion Completer { get; }
- IRealTimeCompletion SetCompleter(string provider);
Task ConnectToModel(Func responseToUser);
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Realtime/Models/RealtimeHubConnection.cs b/src/Infrastructure/BotSharp.Abstraction/Realtime/Models/RealtimeHubConnection.cs
index e4f21b0e..b3132df7 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Realtime/Models/RealtimeHubConnection.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Realtime/Models/RealtimeHubConnection.cs
@@ -1,5 +1,3 @@
-using System.Collections.Concurrent;
-
namespace BotSharp.Abstraction.Realtime.Models;
public class RealtimeHubConnection
@@ -9,7 +7,6 @@ public class RealtimeHubConnection
public long LatestMediaTimestamp { get; set; }
public long? ResponseStartTimestamp { get; set; }
public string KeypadInputBuffer { get; set; } = string.Empty;
- public ConcurrentQueue MarkQueue { get; set; } = new();
public string CurrentAgentId { get; set; } = null!;
public string ConversationId { get; set; } = null!;
public Func OnModelReady { get; set; } = () => string.Empty;
@@ -19,7 +16,6 @@ public class RealtimeHubConnection
public void ResetResponseState()
{
- MarkQueue.Clear();
LastAssistantItemId = null;
ResponseStartTimestamp = null;
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Realtime/Models/RealtimeModelSettings.cs b/src/Infrastructure/BotSharp.Abstraction/Realtime/Models/RealtimeModelSettings.cs
index 2428bd5b..7ebe2c42 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Realtime/Models/RealtimeModelSettings.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Realtime/Models/RealtimeModelSettings.cs
@@ -2,11 +2,16 @@ namespace BotSharp.Abstraction.Realtime.Models;
public class RealtimeModelSettings
{
+ public string Provider { get; set; } = "openai";
+ public string Model { get; set; } = "gpt-4o-mini-realtime-preview";
+ public bool InterruptResponse { get; set; } = true;
public string InputAudioFormat { get; set; } = "g711_ulaw";
public string OutputAudioFormat { get; set; } = "g711_ulaw";
+ public bool InputAudioTranscribe { get; set; } = false;
public string Voice { get; set; } = "alloy";
public float Temperature { get; set; } = 0.8f;
public int MaxResponseOutputTokens { get; set; } = 512;
+ public int ModelResponseTimeout { get; set; } = 30;
public AudioTranscription InputAudioTranscription { get; set; } = new();
public ModelTurnDetection TurnDetection { get; set; } = new();
}
diff --git a/src/Infrastructure/BotSharp.Core.Realtime/Hooks/RealtimeConversationHook.cs b/src/Infrastructure/BotSharp.Core.Realtime/Hooks/RealtimeConversationHook.cs
index 9ff13082..bb019996 100644
--- a/src/Infrastructure/BotSharp.Core.Realtime/Hooks/RealtimeConversationHook.cs
+++ b/src/Infrastructure/BotSharp.Core.Realtime/Hooks/RealtimeConversationHook.cs
@@ -19,8 +19,11 @@ public class RealtimeConversationHook : ConversationHookBase, IConversationHook
return;
}
// Save states
- var states = _services.GetRequiredService();
- states.SaveStateByArgs(message.FunctionArgs?.JsonContent() ?? JsonDocument.Parse("{}"));
+ if (message.FunctionArgs != null && message.FunctionArgs.Length > 3)
+ {
+ var states = _services.GetRequiredService();
+ states.SaveStateByArgs(message.FunctionArgs?.JsonContent());
+ }
}
public async Task OnFunctionExecuted(RoleDialogModel message)
diff --git a/src/Infrastructure/BotSharp.Core.Realtime/RealtimePlugin.cs b/src/Infrastructure/BotSharp.Core.Realtime/RealtimePlugin.cs
index 5ed76aa3..5e1f1478 100644
--- a/src/Infrastructure/BotSharp.Core.Realtime/RealtimePlugin.cs
+++ b/src/Infrastructure/BotSharp.Core.Realtime/RealtimePlugin.cs
@@ -23,6 +23,6 @@ public class RealtimePlugin : IBotSharpPlugin
services.AddScoped();
services.AddScoped();
- services.AddScoped();
+ services.AddScoped();
}
}
diff --git a/src/Infrastructure/BotSharp.Core.Realtime/Services/RealtimeHub.cs b/src/Infrastructure/BotSharp.Core.Realtime/Services/RealtimeHub.cs
index 0e11e841..294d77d7 100644
--- a/src/Infrastructure/BotSharp.Core.Realtime/Services/RealtimeHub.cs
+++ b/src/Infrastructure/BotSharp.Core.Realtime/Services/RealtimeHub.cs
@@ -47,6 +47,9 @@ public class RealtimeHub : IRealtimeHub
routing.Context.SetMessageId(_conn.ConversationId, dialogs.Last().MessageId);
var states = _services.GetRequiredService();
+ var settings = _services.GetRequiredService();
+
+ _completer = _services.GetServices().First(x => x.Provider == settings.Provider);
await _completer.Connect(_conn,
onModelReady: async () =>
@@ -101,9 +104,7 @@ public class RealtimeHub : IRealtimeHub
await HookEmitter.Emit(_services, async hook => await hook.OnRoutingInstructionReceived(instruction, message));
}
- var delay = Task.Delay(1000);
- routing.InvokeFunction(message.FunctionName, message);
- await delay;
+ await routing.InvokeFunction(message.FunctionName, message);
}
else
{
@@ -140,13 +141,16 @@ public class RealtimeHub : IRealtimeHub
await hook.OnMessageReceived(message);
}
},
- onUserInterrupted: async () =>
+ onInterruptionDetected: async () =>
{
- // Reset states
- _conn.ResetResponseState();
+ if (settings.InterruptResponse)
+ {
+ // Reset states
+ _conn.ResetResponseState();
- var data = _conn.OnModelUserInterrupted();
- await responseToUser(data);
+ var data = _conn.OnModelUserInterrupted();
+ await responseToUser(data);
+ }
});
}
@@ -159,10 +163,4 @@ public class RealtimeHub : IRealtimeHub
return _conn;
}
-
- public IRealTimeCompletion SetCompleter(string provider)
- {
- _completer = _services.GetServices().First(x => x.Provider == provider);
- return _completer;
- }
}
diff --git a/src/Infrastructure/BotSharp.Core.Realtime/Services/WaveStremChannel.cs b/src/Infrastructure/BotSharp.Core.Realtime/Services/WaveStreamChannel.cs
similarity index 96%
rename from src/Infrastructure/BotSharp.Core.Realtime/Services/WaveStremChannel.cs
rename to src/Infrastructure/BotSharp.Core.Realtime/Services/WaveStreamChannel.cs
index f07bd73c..8f7767f4 100644
--- a/src/Infrastructure/BotSharp.Core.Realtime/Services/WaveStremChannel.cs
+++ b/src/Infrastructure/BotSharp.Core.Realtime/Services/WaveStreamChannel.cs
@@ -4,7 +4,7 @@ using NAudio.Wave;
namespace BotSharp.Core.Realtime.Services;
-public class WaveStremChannel : IStreamChannel
+public class WaveStreamChannel : IStreamChannel
{
private readonly IServiceProvider _services;
private WaveInEvent _waveIn;
@@ -13,7 +13,7 @@ public class WaveStremChannel : IStreamChannel
private readonly ConcurrentQueue _audioBufferQueue = [];
private readonly ILogger _logger;
- public WaveStremChannel(IServiceProvider services, ILogger logger)
+ public WaveStreamChannel(IServiceProvider services, ILogger logger)
{
_services = services;
_logger = logger;
diff --git a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Realtime/RealTimeCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Realtime/RealTimeCompletionProvider.cs
index f630f5da..dcadd25d 100644
--- a/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Realtime/RealTimeCompletionProvider.cs
+++ b/src/Plugins/BotSharp.Plugin.GoogleAI/Providers/Realtime/RealTimeCompletionProvider.cs
@@ -1,10 +1,8 @@
-using BotSharp.Abstraction.MLTasks.Settings;
using GenerativeAI;
using GenerativeAI.Core;
using GenerativeAI.Live;
using GenerativeAI.Live.Extensions;
using GenerativeAI.Types;
-using System;
namespace BotSharp.Plugin.GoogleAi.Providers.Realtime;
@@ -66,8 +64,8 @@ public class GoogleRealTimeProvider : IRealTimeCompletion
this.onInputAudioTranscriptionCompleted = onInputAudioTranscriptionCompleted;
this.onUserInterrupted = onUserInterrupted;
- var llmProviderService = _services.GetRequiredService();
- _model = llmProviderService.GetProviderModel(Provider, "gemini-2.0", modelType: LlmModelType.Realtime).Name;
+ var realtimeModelSettings = _services.GetRequiredService();
+ _model = realtimeModelSettings.Model;
var client = ProviderHelper.GetGeminiClient(Provider, _model, _services);
_chatClient = client.CreateGenerativeModel(_model);
@@ -235,7 +233,7 @@ public class GoogleRealTimeProvider : IRealTimeCompletion
//todo Send Audio Chunks to Model, Botsharp RealTime Implementation seems to be incomplete
}
- public async Task UpdateSession(RealtimeHubConnection conn, bool interruptResponse = true)
+ public async Task UpdateSession(RealtimeHubConnection conn)
{
var convService = _services.GetRequiredService();
var conv = await convService.GetConversation(conn.ConversationId);
diff --git a/src/Plugins/BotSharp.Plugin.MicrosoftExtensionsAI/MicrosoftExtensionsAIChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.MicrosoftExtensionsAI/MicrosoftExtensionsAIChatCompletionProvider.cs
index 6ee77772..d32fbece 100644
--- a/src/Plugins/BotSharp.Plugin.MicrosoftExtensionsAI/MicrosoftExtensionsAIChatCompletionProvider.cs
+++ b/src/Plugins/BotSharp.Plugin.MicrosoftExtensionsAI/MicrosoftExtensionsAIChatCompletionProvider.cs
@@ -38,7 +38,7 @@ public sealed class MicrosoftExtensionsAIChatCompletionProvider : IChatCompletio
IServiceProvider services)
{
_client = client;
- _model = _client.GetService()?.ModelId;
+ _model = _client.GetService()?.DefaultModelId;
_logger = logger;
_services = services;
}
@@ -180,7 +180,7 @@ public sealed class MicrosoftExtensionsAIChatCompletionProvider : IChatCompletio
public override JsonElement JsonSchema => schema;
- protected override Task