Skip to content

Commit a6e34b8

Browse files
authored
Merge pull request #348 from iceljc/features/add-botsharp-json-option
add botsharp options
2 parents 4309a2c + a6eee91 commit a6e34b8

File tree

11 files changed

+111
-60
lines changed

11 files changed

+111
-60
lines changed

src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFramework>netstandard2.1</TargetFramework>

src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,4 @@ public override void Write(Utf8JsonWriter writer, IRichMessage value, JsonSerial
4747
{
4848
JsonSerializer.Serialize(writer, value, value.GetType(), options);
4949
}
50-
}
50+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using BotSharp.Abstraction.Messaging.JsonConverters;
2+
using System.Text.Json;
3+
4+
namespace BotSharp.Abstraction.Options;
5+
6+
public class BotSharpOptions
7+
{
8+
private readonly static JsonSerializerOptions defaultJsonOptions = new JsonSerializerOptions()
9+
{
10+
PropertyNameCaseInsensitive = true,
11+
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
12+
AllowTrailingCommas = true,
13+
WriteIndented = true
14+
};
15+
16+
private JsonSerializerOptions _jsonSerializerOptions;
17+
18+
public JsonSerializerOptions JsonSerializerOptions
19+
{
20+
get
21+
{
22+
return _jsonSerializerOptions ?? defaultJsonOptions;
23+
}
24+
set
25+
{
26+
if (value == null)
27+
{
28+
_jsonSerializerOptions = defaultJsonOptions;
29+
}
30+
else
31+
{
32+
_jsonSerializerOptions = value;
33+
}
34+
}
35+
}
36+
37+
38+
public BotSharpOptions()
39+
{
40+
41+
}
42+
}

src/Infrastructure/BotSharp.Core/BotSharpCoreExtensions.cs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
using BotSharp.Abstraction.Functions;
2-
using BotSharp.Abstraction.Repositories;
32
using Microsoft.AspNetCore.Builder;
43
using Microsoft.Extensions.Configuration;
5-
using BotSharp.Abstraction.Routing;
64
using BotSharp.Core.Plugins;
75
using BotSharp.Abstraction.Settings;
6+
using BotSharp.Abstraction.Options;
7+
using BotSharp.Abstraction.Messaging;
8+
using System.Text.Json.Serialization;
9+
using Microsoft.Extensions.Options;
10+
using BotSharp.Abstraction.Messaging.JsonConverters;
811

912
namespace BotSharp.Core;
1013

1114
public static class BotSharpCoreExtensions
1215
{
13-
public static IServiceCollection AddBotSharpCore(this IServiceCollection services, IConfiguration config)
16+
public static IServiceCollection AddBotSharpCore(this IServiceCollection services, IConfiguration config, Action<BotSharpOptions>? configOptions = null)
1417
{
1518
services.AddScoped<ISettingService, SettingService>();
1619
services.AddScoped<IUserService, UserService>();
1720

1821
RegisterPlugins(services, config);
22+
ConfigureBotSharpOptions(services, configOptions);
1923
return services;
2024
}
2125

@@ -53,6 +57,24 @@ public static IApplicationBuilder UseBotSharp(this IApplicationBuilder app)
5357
return app;
5458
}
5559

60+
private static void ConfigureBotSharpOptions(IServiceCollection services, Action<BotSharpOptions>? configure)
61+
{
62+
var options = new BotSharpOptions();
63+
if (configure != null)
64+
{
65+
configure(options);
66+
}
67+
68+
AddDefaultJsonConverters(options);
69+
services.AddSingleton(options);
70+
}
71+
72+
private static void AddDefaultJsonConverters(BotSharpOptions options)
73+
{
74+
options.JsonSerializerOptions.Converters.Add(new RichContentJsonConverter());
75+
options.JsonSerializerOptions.Converters.Add(new TemplateMessageJsonConverter());
76+
}
77+
5678
public static void RegisterPlugins(IServiceCollection services, IConfiguration config)
5779
{
5880
var pluginSettings = new PluginSettings();

src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using BotSharp.Abstraction.Agents.Models;
21
using BotSharp.Abstraction.Messaging;
32
using BotSharp.Abstraction.Messaging.Models.RichContent;
43
using BotSharp.Abstraction.Routing.Settings;

src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStorage.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using BotSharp.Abstraction.Messaging;
22
using BotSharp.Abstraction.Messaging.JsonConverters;
33
using BotSharp.Abstraction.Messaging.Models.RichContent;
4+
using BotSharp.Abstraction.Options;
45
using BotSharp.Abstraction.Repositories;
56
using System;
67
using System.IO;
@@ -15,6 +16,7 @@ public class ConversationStorage : IConversationStorage
1516

1617
public ConversationStorage(
1718
BotSharpDatabaseSettings dbSettings,
19+
BotSharpOptions options,
1820
IServiceProvider services)
1921
{
2022
_dbSettings = dbSettings;
@@ -64,6 +66,7 @@ public void Append(string conversationId, RoleDialogModel dialog)
6466
AgentId = agentId,
6567
MessageId = dialog.MessageId,
6668
SenderId = dialog.SenderId,
69+
FunctionName = dialog.FunctionName,
6770
CreateTime = dialog.CreatedAt
6871
};
6972

@@ -93,7 +96,7 @@ public List<RoleDialogModel> GetDialogs(string conversationId)
9396
var role = meta.Role;
9497
var currentAgentId = meta.AgentId;
9598
var messageId = meta.MessageId;
96-
var function = role == AgentRole.Function ? meta.FunctionName : null;
99+
var function = meta.FunctionName;
97100
var senderId = role == AgentRole.Function ? currentAgentId : meta.SenderId;
98101
var createdAt = meta.CreateTime;
99102
var richContent = !string.IsNullOrEmpty(dialog.RichContent) ?

src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -408,16 +408,12 @@ private List<DialogElement> CollectDialogElements(string dialogDir)
408408
Role = blocks[1],
409409
AgentId = blocks[2],
410410
MessageId = blocks[3],
411-
FunctionName = blocks[1] == AgentRole.Function ? blocks[4] : null,
412-
SenderId = blocks[1] == AgentRole.Function ? null : blocks[4],
411+
SenderId = !string.IsNullOrWhiteSpace(blocks[4]) ? blocks[4] : null,
412+
FunctionName = !string.IsNullOrWhiteSpace(blocks[5]) ? blocks[5] : null,
413413
CreateTime = DateTime.Parse(blocks[0])
414414
};
415415

416-
string? richContent = null;
417-
if (blocks.Count() > 5)
418-
{
419-
richContent = blocks[5];
420-
}
416+
var richContent = blocks.Count() > 6 ? blocks[6] : null;
421417
dialogs.Add(new DialogElement(meta, trimmed, richContent));
422418
}
423419
}
@@ -433,8 +429,7 @@ private List<string> ParseDialogElements(List<DialogElement> dialogs)
433429
{
434430
var meta = element.MetaData;
435431
var createTime = meta.CreateTime.ToString("MM/dd/yyyy hh:mm:ss.fff tt", CultureInfo.InvariantCulture);
436-
var source = meta.FunctionName ?? meta.SenderId;
437-
var metaStr = $"{createTime}|{meta.Role}|{meta.AgentId}|{meta.MessageId}|{source}|{element.RichContent}";
432+
var metaStr = $"{createTime}|{meta.Role}|{meta.AgentId}|{meta.MessageId}|{meta.SenderId}|{meta.FunctionName}|{element.RichContent}";
438433
dialogTexts.Add(metaStr);
439434
var content = $" - {element.Content}";
440435
dialogTexts.Add(content);

src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using BotSharp.Abstraction.Messaging.Enums;
2-
using BotSharp.Abstraction.Messaging.JsonConverters;
2+
using BotSharp.Abstraction.Options;
33
using Microsoft.AspNetCore.SignalR;
44

55
namespace BotSharp.Plugin.ChatHub.Hooks;
@@ -9,24 +9,16 @@ public class ChatHubConversationHook : ConversationHookBase
99
private readonly IServiceProvider _services;
1010
private readonly IHubContext<SignalRHub> _chatHub;
1111
private readonly IUserIdentity _user;
12-
private readonly JsonSerializerOptions _serializerOptions;
12+
private readonly BotSharpOptions _options;
1313
public ChatHubConversationHook(IServiceProvider services,
1414
IHubContext<SignalRHub> chatHub,
15+
BotSharpOptions options,
1516
IUserIdentity user)
1617
{
1718
_services = services;
1819
_chatHub = chatHub;
1920
_user = user;
20-
21-
_serializerOptions = new JsonSerializerOptions
22-
{
23-
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
24-
Converters =
25-
{
26-
new RichContentJsonConverter(),
27-
new TemplateMessageJsonConverter(),
28-
}
29-
};
21+
_options = options;
3022
}
3123

3224
public override async Task OnConversationInitialized(Conversation conversation)
@@ -67,6 +59,11 @@ public override async Task OnMessageReceived(RoleDialogModel message)
6759
await base.OnMessageReceived(message);
6860
}
6961

62+
public override async Task OnPostbackMessageReceived(RoleDialogModel message, PostbackMessageModel replyMsg)
63+
{
64+
await this.OnMessageReceived(message);
65+
}
66+
7067
public override async Task OnResponseGenerated(RoleDialogModel message)
7168
{
7269
var conv = _services.GetRequiredService<IConversationService>();
@@ -84,7 +81,7 @@ public override async Task OnResponseGenerated(RoleDialogModel message)
8481
LastName = "Assistant",
8582
Role = AgentRole.Assistant
8683
}
87-
}, _serializerOptions);
84+
}, _options.JsonSerializerOptions);
8885

8986
// Send typing-off to client
9087
await _chatHub.Clients.User(_user.Id).SendAsync("OnSenderActionGenerated", new ConversationSenderActionModel

src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using BotSharp.Abstraction.Loggers;
44
using BotSharp.Abstraction.Loggers.Enums;
55
using BotSharp.Abstraction.Loggers.Models;
6+
using BotSharp.Abstraction.Options;
67
using BotSharp.Abstraction.Repositories;
78
using BotSharp.Abstraction.Routing;
89
using Microsoft.AspNetCore.SignalR;
@@ -12,7 +13,7 @@ namespace BotSharp.Plugin.ChatHub.Hooks;
1213
public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook, IRoutingHook
1314
{
1415
private readonly ConversationSetting _convSettings;
15-
private readonly JsonSerializerOptions _serializerOptions;
16+
private readonly BotSharpOptions _options;
1617
private readonly IServiceProvider _services;
1718
private readonly IHubContext<SignalRHub> _chatHub;
1819
private readonly IConversationStateService _state;
@@ -22,6 +23,7 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook, IR
2223

2324
public StreamingLogHook(
2425
ConversationSetting convSettings,
26+
BotSharpOptions options,
2527
IServiceProvider serivces,
2628
IHubContext<SignalRHub> chatHub,
2729
IConversationStateService state,
@@ -30,19 +32,13 @@ public StreamingLogHook(
3032
IRoutingContext routingCtx)
3133
{
3234
_convSettings = convSettings;
35+
_options = options;
3336
_services = serivces;
3437
_chatHub = chatHub;
3538
_state = state;
3639
_user = user;
3740
_agentService = agentService;
3841
_routingCtx = routingCtx;
39-
_serializerOptions = new JsonSerializerOptions
40-
{
41-
PropertyNameCaseInsensitive = true,
42-
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
43-
AllowTrailingCommas = true,
44-
WriteIndented = true,
45-
};
4642
}
4743

4844
public override async Task OnMessageReceived(RoleDialogModel message)
@@ -63,7 +59,7 @@ public override async Task OnPostbackMessageReceived(RoleDialogModel message, Po
6359
{
6460
var conversationId = _state.GetConversationId();
6561
var log = $"{message.Content}";
66-
var replyContent = JsonSerializer.Serialize(replyMsg, _serializerOptions);
62+
var replyContent = JsonSerializer.Serialize(replyMsg, _options.JsonSerializerOptions);
6763
log += $"\r\n```json\r\n{replyContent}\r\n```";
6864

6965
var input = new ContentLogInputModel(conversationId, message)
@@ -90,7 +86,7 @@ public override async Task OnFunctionExecuted(RoleDialogModel message)
9086
var conversationId = _state.GetConversationId();
9187
var agent = await _agentService.LoadAgent(message.CurrentAgentId);
9288
message.FunctionArgs = message.FunctionArgs ?? "{}";
93-
var args = JsonSerializer.Serialize(JsonDocument.Parse(message.FunctionArgs), _serializerOptions);
89+
var args = JsonSerializer.Serialize(JsonDocument.Parse(message.FunctionArgs), _options.JsonSerializerOptions);
9490
var log = $"*{message.FunctionName}*\r\n```json\r\n{args}\r\n```\r\n=> {message.Content?.Trim()}";
9591

9692
var input = new ContentLogInputModel(conversationId, message)
@@ -145,7 +141,7 @@ public override async Task OnResponseGenerated(RoleDialogModel message)
145141
var log = $"{message.Content}";
146142
if (message.RichContent != null && message.RichContent.Message.RichType != "text")
147143
{
148-
var richContent = JsonSerializer.Serialize(message.RichContent, _serializerOptions);
144+
var richContent = JsonSerializer.Serialize(message.RichContent, _options.JsonSerializerOptions);
149145
log += $"\r\n```json\r\n{richContent}\r\n```";
150146
}
151147

@@ -248,7 +244,7 @@ public async Task OnRoutingInstructionReceived(FunctionCallFromLlm instruct, Rol
248244
{
249245
var conversationId = _state.GetConversationId();
250246
var agent = await _agentService.LoadAgent(message.CurrentAgentId);
251-
var log = JsonSerializer.Serialize(instruct, _serializerOptions);
247+
var log = JsonSerializer.Serialize(instruct, _options.JsonSerializerOptions);
252248
log = $"```json\r\n{log}\r\n```";
253249

254250
var input = new ContentLogInputModel(conversationId, message)
@@ -293,7 +289,7 @@ private string BuildContentLog(ContentLogInputModel input)
293289
CreateTime = DateTime.UtcNow
294290
};
295291

296-
var json = JsonSerializer.Serialize(output, _serializerOptions);
292+
var json = JsonSerializer.Serialize(output, _options.JsonSerializerOptions);
297293

298294
var convSettings = _services.GetRequiredService<ConversationSetting>();
299295
if (convSettings.EnableContentLog)
@@ -322,6 +318,6 @@ private string BuildStateLog(string conversationId, Dictionary<string, string> s
322318
db.SaveConversationStateLog(log);
323319
}
324320

325-
return JsonSerializer.Serialize(log, _serializerOptions);
321+
return JsonSerializer.Serialize(log, _options.JsonSerializerOptions);
326322
}
327323
}

src/Plugins/BotSharp.Plugin.ChatHub/Hooks/WelcomeHook.cs

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
using BotSharp.Abstraction.Messaging.Models.RichContent;
22
using BotSharp.Abstraction.Messaging;
33
using BotSharp.Abstraction.Templating;
4-
using BotSharp.Abstraction.Messaging.JsonConverters;
54
using Microsoft.AspNetCore.SignalR;
5+
using BotSharp.Abstraction.Options;
66

77
namespace BotSharp.Plugin.ChatHub.Hooks;
88

@@ -12,26 +12,19 @@ public class WelcomeHook : ConversationHookBase
1212
private readonly IHubContext<SignalRHub> _chatHub;
1313
private readonly IUserIdentity _user;
1414
private readonly IConversationStorage _storage;
15-
private readonly JsonSerializerOptions _serializerOptions;
15+
private readonly BotSharpOptions _options;
16+
1617
public WelcomeHook(IServiceProvider services,
1718
IHubContext<SignalRHub> chatHub,
1819
IUserIdentity user,
19-
IConversationStorage storage)
20+
IConversationStorage storage,
21+
BotSharpOptions options)
2022
{
2123
_services = services;
2224
_chatHub = chatHub;
2325
_user = user;
2426
_storage = storage;
25-
26-
_serializerOptions = new JsonSerializerOptions
27-
{
28-
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
29-
Converters =
30-
{
31-
new RichContentJsonConverter(),
32-
new TemplateMessageJsonConverter(),
33-
}
34-
};
27+
_options = options;
3528
}
3629

3730
public override async Task OnUserAgentConnectedInitially(Conversation conversation)
@@ -66,7 +59,7 @@ public override async Task OnUserAgentConnectedInitially(Conversation conversati
6659
LastName = "",
6760
Role = AgentRole.Assistant
6861
}
69-
}, _serializerOptions);
62+
}, _options.JsonSerializerOptions);
7063

7164
await Task.Delay(300);
7265

0 commit comments

Comments
 (0)