refine chat event

This commit is contained in:
Jicheng Lu 2025-08-01 14:41:17 -05:00
parent e32d820440
commit 20de3f7565
10 changed files with 103 additions and 30 deletions

View file

@ -98,6 +98,7 @@
<None Remove="data\plugins\config.json" />
<None Remove="data\agents\01e2fc5c-2c89-4ec7-8470-7688608b496c\functions\get_weather.json" />
<None Remove="data\agents\01e2fc5c-2c89-4ec7-8470-7688608b496c\functions\get_fun_events.json" />
</ItemGroup>
<ItemGroup>
@ -211,6 +212,9 @@
<Content Include="data\agents\01e2fc5c-2c89-4ec7-8470-7688608b496c\functions\get_weather.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="data\agents\01e2fc5c-2c89-4ec7-8470-7688608b496c\functions\get_fun_events.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
@ -242,5 +246,4 @@
<Pack>true</Pack>
</Content>
</ItemGroup>
</Project>

View file

@ -21,7 +21,7 @@ using Microsoft.Extensions.Configuration;
namespace BotSharp.Core.Conversations;
public class ConversationPlugin : IBotSharpPlugin, IBotSharpAppPlugin
public class ConversationPlugin : IBotSharpPlugin
{
public string Id => "99e9b971-a9f1-4273-84da-876d2873d192";
public string Name => "Conversation";
@ -48,6 +48,7 @@ public class ConversationPlugin : IBotSharpPlugin, IBotSharpAppPlugin
return settingService.Bind<GoogleApiSettings>("GoogleApi");
});
// Observer and observable
services.AddSingleton<MessageHub<HubObserveData<RoleDialogModel>>>();
services.AddScoped<ObserverSubscriptionContainer<HubObserveData<RoleDialogModel>>>();
services.AddScoped<IBotSharpObserver<HubObserveData<RoleDialogModel>>, ConversationObserver>();
@ -75,9 +76,4 @@ public class ConversationPlugin : IBotSharpPlugin, IBotSharpAppPlugin
menu.Add(new PluginMenuDef("Conversation", link: "page/conversation", icon: "bx bx-conversation", weight: section.Weight + 5));
return true;
}
public void Configure(IApplicationBuilder app)
{
}
}

View file

@ -0,0 +1,51 @@
using BotSharp.Abstraction.Functions;
using BotSharp.Core.MessageHub;
using System.Text.Json.Serialization;
namespace BotSharp.Core.Demo.Functions;
public class GetFunEventsFn : IFunctionCallback
{
private readonly IServiceProvider _services;
public GetFunEventsFn(IServiceProvider services)
{
_services = services;
}
public string Name => "get_fun_events";
public string Indication => "Searching fun events";
public async Task<bool> Execute(RoleDialogModel message)
{
var args = JsonSerializer.Deserialize<WeatherLocation>(message.FunctionArgs);
var conv = _services.GetRequiredService<IConversationService>();
var messageHub = _services.GetRequiredService<MessageHub<HubObserveData<RoleDialogModel>>>();
await Task.Delay(1000);
message.Indication = $"Start querying event data in {args?.City}";
messageHub.Push(new()
{
EventName = ChatEvent.OnIndicationReceived,
Data = message,
RefId = conv.ConversationId
});
await Task.Delay(1500);
message.Indication = $"Still searching in {args?.City}";
messageHub.Push(new()
{
EventName = ChatEvent.OnIndicationReceived,
Data = message,
RefId = conv.ConversationId
});
await Task.Delay(1500);
message.Content = $"Here in {args?.City}, there are a lot of fun events in summer.";
message.StopCompletion = true;
return true;
}
}

View file

@ -1,4 +1,6 @@
using BotSharp.Abstraction.Functions;
using BotSharp.Abstraction.Models;
using BotSharp.Abstraction.SideCar;
using BotSharp.Core.MessageHub;
using System.Text.Json.Serialization;
@ -46,6 +48,22 @@ public class GetWeatherFn : IFunctionCallback
message.Content = $"It is a sunny day!";
message.StopCompletion = false;
#if DEBUG
var sidecar = _services.GetService<IConversationSideCar>();
if (sidecar != null)
{
var text = $"I want to know fun events in {args?.City}";
var states = new List<MessageState>
{
new() { Key = "channel", Value = "email" }
};
var msg = await sidecar.SendMessage(message.CurrentAgentId, text, states: states);
message.Content = $"{message.Content} {msg.Content}";
}
#endif
return true;
}
}

View file

@ -66,7 +66,10 @@ public class ObserverService : IObserverService
foreach (var sub in subscriptions)
{
if (!sub.Observer.Active) continue;
sub.UnSubscribe();
}
container.Remove(names);
}
}

View file

@ -0,0 +1,15 @@
{
"name": "get_fun_events",
"description": "Get fun events information for user.",
"visibility_expression": "{% if states.channel == 'email' %}visible{% endif %}",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "The city where user wants to find fun events."
}
},
"required": [ "city" ]
}
}

View file

@ -1,6 +1,7 @@
{
"name": "get_weather",
"description": "Get weather information for user.",
"visibility_expression": "{% if states.channel != 'email' %}visible{% endif %}",
"parameters": {
"type": "object",
"properties": {

View file

@ -13,7 +13,7 @@ namespace BotSharp.Plugin.ChatHub;
/// <summary>
/// The dialogue channel connects users, AI assistants and customer service representatives.
/// </summary>
public class ChatHubPlugin : IBotSharpPlugin, IBotSharpAppPlugin
public class ChatHubPlugin : IBotSharpPlugin
{
public string Id => "6e52d42d-1e23-406b-8599-36af36c83209";
public string Name => "Chat Hub";
@ -36,9 +36,4 @@ public class ChatHubPlugin : IBotSharpPlugin, IBotSharpAppPlugin
services.AddScoped<IContentGeneratingHook, StreamingLogHook>();
services.AddScoped<ICrontabHook, ChatHubCrontabHook>();
}
public void Configure(IApplicationBuilder app)
{
}
}

View file

@ -113,16 +113,13 @@ public class ChatHubConversationHook : ConversationHookBase
};
// Send typing-off to client
if (!message.IsStreaming)
var action = new ConversationSenderActionModel
{
var action = new ConversationSenderActionModel
{
ConversationId = conv.ConversationId,
SenderAction = SenderActionEnum.TypingOff
};
await SendEvent(ChatEvent.OnSenderActionGenerated, conv.ConversationId, action);
}
ConversationId = conv.ConversationId,
SenderAction = SenderActionEnum.TypingOff
};
await SendEvent(ChatEvent.OnSenderActionGenerated, conv.ConversationId, action);
await SendEvent(ChatEvent.OnMessageReceivedFromAssistant, conv.ConversationId, data);
await base.OnResponseGenerated(message);
}

View file

@ -99,14 +99,6 @@ public class ChatHubObserver : BotSharpObserverBase<HubObserveData<RoleDialogMod
Role = AgentRole.Assistant
}
};
action = new ConversationSenderActionModel
{
ConversationId = conv.ConversationId,
SenderAction = SenderActionEnum.TypingOff
};
SendEvent(ChatEvent.OnSenderActionGenerated, conv.ConversationId, action);
break;
case ChatEvent.OnIndicationReceived:
model = new ChatResponseDto
@ -122,7 +114,9 @@ public class ChatHubObserver : BotSharpObserverBase<HubObserveData<RoleDialogMod
}
};
#if DEBUG
_logger.LogCritical($"Receiving {value.EventName} ({value.Data.Indication}) in {nameof(ChatHubObserver)} - {conv.ConversationId}");
#endif
break;
}