fix chat stream and websocket close

This commit is contained in:
Jicheng Lu 2025-09-23 13:11:31 -05:00
parent 3b692a958d
commit de08a34adb
10 changed files with 36 additions and 45 deletions

View file

@ -0,0 +1,14 @@
namespace BotSharp.Abstraction.MLTasks.Utilities;
public static class AiModelUtility
{
public static string? VerifyModelParameter(string? curVal, string? defaultVal, IEnumerable<string>? options = null)
{
if (options.IsNullOrEmpty())
{
return curVal.IfNullOrEmptyAs(defaultVal);
}
return options.Contains(curVal) ? curVal : defaultVal;
}
}

View file

@ -74,7 +74,7 @@ public class BotSharpRealtimeSession : IDisposable
return;
}
await _websocket.CloseAsync(WebSocketCloseStatus.Empty, null, CancellationToken.None);
await _websocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Normal Closure", CancellationToken.None);
}
public void Dispose()

View file

@ -111,7 +111,7 @@ public class LlmRealtimeSession : IDisposable
if (_webSocket.State == WebSocketState.Open)
{
await _webSocket.CloseAsync(WebSocketCloseStatus.Empty, null, CancellationToken.None);
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Normal Closure", CancellationToken.None);
}
}

View file

@ -10,7 +10,6 @@ public class ChatStreamMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ChatStreamMiddleware> _logger;
private BotSharpRealtimeSession _session;
public ChatStreamMiddleware(
RequestDelegate next,
@ -40,7 +39,6 @@ public class ChatStreamMiddleware
}
catch (Exception ex)
{
_session?.Dispose();
_logger.LogError(ex, $"Error when connecting Chat stream. ({ex.Message})");
}
return;
@ -52,8 +50,7 @@ public class ChatStreamMiddleware
private async Task HandleWebSocket(IServiceProvider services, string agentId, string conversationId, WebSocket webSocket)
{
_session?.Dispose();
_session = new BotSharpRealtimeSession(services, webSocket, new ChatSessionOptions
using var session = new BotSharpRealtimeSession(services, webSocket, new ChatSessionOptions
{
Provider = "BotSharp Chat Stream",
BufferSize = 1024 * 32,
@ -72,7 +69,7 @@ public class ChatStreamMiddleware
convService.SetConversationId(conversationId, []);
await convService.GetConversationRecordOrCreateNew(agentId);
await foreach (ChatSessionUpdate update in _session.ReceiveUpdatesAsync(CancellationToken.None))
await foreach (ChatSessionUpdate update in session.ReceiveUpdatesAsync(CancellationToken.None))
{
var receivedText = update?.RawResponse;
if (string.IsNullOrEmpty(receivedText))
@ -87,7 +84,7 @@ public class ChatStreamMiddleware
_logger.LogCritical($"Start chat stream connection for conversation ({conversationId})");
#endif
var request = InitRequest(data, conversationId);
await ConnectToModel(hub, webSocket, request?.States);
await ConnectToModel(hub, session, request?.States);
}
else if (eventType == "media")
{
@ -107,17 +104,16 @@ public class ChatStreamMiddleware
}
convService.SaveStates();
await _session.DisconnectAsync();
_session.Dispose();
await session.DisconnectAsync();
}
private async Task ConnectToModel(IRealtimeHub hub, WebSocket webSocket, List<MessageState>? states = null)
private async Task ConnectToModel(IRealtimeHub hub, BotSharpRealtimeSession session, List<MessageState>? states = null)
{
await hub.ConnectToModel(responseToUser: async data =>
{
if (_session != null)
if (session != null)
{
await _session.SendEventAsync(data);
await session.SendEventAsync(data);
}
}, initStates: states);
}

View file

@ -47,8 +47,8 @@ public class AudioTranscriptionProvider : IAudioTranscription
temperature = $"{settings.Temperature}";
}
responseFormat = settings?.ResponseFormat != null ? VerifyTranscriptionParameter(responseFormat, settings.ResponseFormat.Default, settings.ResponseFormat.Options) : null;
granularity = settings?.Granularity != null ? VerifyTranscriptionParameter(granularity, settings.Granularity.Default, settings.Granularity.Options) : null;
responseFormat = settings?.ResponseFormat != null ? AiModelUtility.VerifyModelParameter(responseFormat, settings.ResponseFormat.Default, settings.ResponseFormat.Options) : null;
granularity = settings?.Granularity != null ? AiModelUtility.VerifyModelParameter(granularity, settings.Granularity.Default, settings.Granularity.Options) : null;
var options = new AudioTranscriptionOptions
{
@ -131,14 +131,4 @@ public class AudioTranscriptionProvider : IAudioTranscription
return temperature;
}
private string? VerifyTranscriptionParameter(string? curVal, string? defaultVal, IEnumerable<string>? options = null)
{
if (options.IsNullOrEmpty())
{
return curVal.IfNullOrEmptyAs(defaultVal);
}
return options.Contains(curVal) ? curVal : defaultVal;
}
}

View file

@ -61,9 +61,9 @@ public partial class ImageCompletionProvider
var settings = settingsService.GetSetting(Provider, _model)?.Image?.Edit;
size = settings?.Size != null ? VerifyImageParameter(size, settings.Size.Default, settings.Size.Options) : null;
responseFormat = settings?.ResponseFormat != null ? VerifyImageParameter(responseFormat, settings.ResponseFormat.Default, settings.ResponseFormat.Options) : null;
background = settings?.Background != null ? VerifyImageParameter(background, settings.Background.Default, settings.Background.Options) : null;
size = settings?.Size != null ? AiModelUtility.VerifyModelParameter(size, settings.Size.Default, settings.Size.Options) : null;
responseFormat = settings?.ResponseFormat != null ? AiModelUtility.VerifyModelParameter(responseFormat, settings.ResponseFormat.Default, settings.ResponseFormat.Options) : null;
background = settings?.Background != null ? AiModelUtility.VerifyModelParameter(background, settings.Background.Default, settings.Background.Options) : null;
var options = new ImageEditOptions();
if (!string.IsNullOrEmpty(size))

View file

@ -42,11 +42,11 @@ public partial class ImageCompletionProvider
var settings = settingsService.GetSetting(Provider, _model)?.Image?.Generation;
size = settings?.Size != null ? VerifyImageParameter(size, settings.Size.Default, settings.Size.Options) : null;
quality = settings?.Quality != null ? VerifyImageParameter(quality, settings.Quality.Default, settings.Quality.Options) : null;
style = settings?.Style != null ? VerifyImageParameter(style, settings.Style.Default, settings.Style.Options) : null;
responseFormat = settings?.ResponseFormat != null ? VerifyImageParameter(responseFormat, settings.ResponseFormat.Default, settings.ResponseFormat.Options) : null;
background = settings?.Background != null ? VerifyImageParameter(background, settings.Background.Default, settings.Background.Options) : null;
size = settings?.Size != null ? AiModelUtility.VerifyModelParameter(size, settings.Size.Default, settings.Size.Options) : null;
quality = settings?.Quality != null ? AiModelUtility.VerifyModelParameter(quality, settings.Quality.Default, settings.Quality.Options) : null;
style = settings?.Style != null ? AiModelUtility.VerifyModelParameter(style, settings.Style.Default, settings.Style.Options) : null;
responseFormat = settings?.ResponseFormat != null ? AiModelUtility.VerifyModelParameter(responseFormat, settings.ResponseFormat.Default, settings.ResponseFormat.Options) : null;
background = settings?.Background != null ? AiModelUtility.VerifyModelParameter(background, settings.Background.Default, settings.Background.Options) : null;
var options = new ImageGenerationOptions();
if (!string.IsNullOrEmpty(size))

View file

@ -35,8 +35,8 @@ public partial class ImageCompletionProvider
var settings = settingsService.GetSetting(Provider, _model)?.Image?.Variation;
size = settings?.Size != null ? VerifyImageParameter(size, settings.Size.Default, settings.Size.Options) : null;
responseFormat = settings?.ResponseFormat != null ? VerifyImageParameter(responseFormat, settings.ResponseFormat.Default, settings.ResponseFormat.Options) : null;
size = settings?.Size != null ? AiModelUtility.VerifyModelParameter(size, settings.Size.Default, settings.Size.Options) : null;
responseFormat = settings?.ResponseFormat != null ? AiModelUtility.VerifyModelParameter(responseFormat, settings.ResponseFormat.Default, settings.ResponseFormat.Options) : null;
var options = new ImageVariationOptions();
if (!string.IsNullOrEmpty(size))

View file

@ -201,15 +201,5 @@ public partial class ImageCompletionProvider : IImageCompletion
}
return retCount;
}
private string? VerifyImageParameter(string? curVal, string? defaultVal, IEnumerable<string>? options = null)
{
if (options.IsNullOrEmpty())
{
return curVal.IfNullOrEmptyAs(defaultVal);
}
return options.Contains(curVal) ? curVal : defaultVal;
}
#endregion
}

View file

@ -26,6 +26,7 @@ global using BotSharp.Abstraction.Conversations.Enums;
global using BotSharp.Abstraction.Files.Utilities;
global using BotSharp.Abstraction.Functions.Models;
global using BotSharp.Abstraction.MLTasks.Settings;
global using BotSharp.Abstraction.MLTasks.Utilities;
global using BotSharp.Abstraction.Options;
global using BotSharp.Abstraction.Realtime;
global using BotSharp.Abstraction.Realtime.Models;