Add onFunctionExecuted to reflect UI progress.
This commit is contained in:
parent
883ef65d2a
commit
0da5bd36f7
|
|
@ -2,5 +2,6 @@ namespace BotSharp.Abstraction.Agents;
|
|||
|
||||
public interface IAgentRouting
|
||||
{
|
||||
Task<Agent> LoadRouter();
|
||||
Task<Agent> LoadCurrentAgent();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace BotSharp.Abstraction.Agents.Models;
|
||||
|
||||
public class AgentRoutingArgs
|
||||
{
|
||||
[JsonPropertyName("agent_id")]
|
||||
public string AgentId { get; set; }
|
||||
}
|
||||
|
|
@ -20,12 +20,14 @@ public interface IConversationService
|
|||
/// <param name="lastDalog"></param>
|
||||
/// <param name="onMessageReceived"></param>
|
||||
/// <param name="onFunctionExecuting">This delegate is useful when you want to report progress on UI</param>
|
||||
/// <param name="onFunctionExecuted">This delegate is useful when you want to report progress on UI</param>
|
||||
/// <returns></returns>
|
||||
Task<bool> SendMessage(string agentId,
|
||||
string conversationId,
|
||||
RoleDialogModel lastDalog,
|
||||
Func<RoleDialogModel, Task> onMessageReceived,
|
||||
Func<RoleDialogModel, Task> onFunctionExecuting);
|
||||
Func<RoleDialogModel, Task> onFunctionExecuting,
|
||||
Func<RoleDialogModel, Task> onFunctionExecuted);
|
||||
|
||||
List<RoleDialogModel> GetDialogHistory(string conversationId, int lastCount = 20);
|
||||
Task CleanHistory(string agentId);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Abstraction.Agents.Models;
|
||||
|
||||
namespace BotSharp.Core.Agents.Services;
|
||||
|
|
@ -17,11 +18,18 @@ public class AgentRouter : IAgentRouting
|
|||
_settings = settings;
|
||||
}
|
||||
|
||||
public async Task<Agent> LoadRouter()
|
||||
{
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(_settings.RouterId);
|
||||
return agent;
|
||||
}
|
||||
|
||||
public async Task<Agent> LoadCurrentAgent()
|
||||
{
|
||||
// Load current agent from state
|
||||
var state = _services.GetRequiredService<IConversationStateService>();
|
||||
var currentAgentId = state.GetState("agentId");
|
||||
var currentAgentId = state.GetState("agent_id");
|
||||
if (string.IsNullOrEmpty(currentAgentId))
|
||||
{
|
||||
currentAgentId = _settings.RouterId;
|
||||
|
|
@ -30,7 +38,7 @@ public class AgentRouter : IAgentRouting
|
|||
var agent = await agentService.LoadAgent(currentAgentId);
|
||||
|
||||
// Set agent and trigger state changed
|
||||
state.SetState("agentId", currentAgentId);
|
||||
state.SetState("agent_id", currentAgentId);
|
||||
|
||||
return agent;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Colorful.Console" Version="1.2.15" />
|
||||
<PackageReference Include="EntityFrameworkCore.BootKit" Version="6.2.1" />
|
||||
<PackageReference Include="Fluid.Core" Version="2.4.0" />
|
||||
<PackageReference Include="TensorFlow.Keras" Version="0.11.2" />
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ public static class BotSharpServiceCollectionExtensions
|
|||
services.AddScoped<IAgentRouting, AgentRouter>();
|
||||
|
||||
services.AddScoped<IFunctionCallback, GoToRouterFn>();
|
||||
services.AddScoped<IFunctionCallback, RouteToAgentFn>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ public partial class ConversationService
|
|||
Agent agent,
|
||||
List<RoleDialogModel> wholeDialogs,
|
||||
Func<RoleDialogModel, Task> onMessageReceived,
|
||||
Func<RoleDialogModel, Task> onFunctionExecuting)
|
||||
Func<RoleDialogModel, Task> onFunctionExecuting,
|
||||
Func<RoleDialogModel, Task> onFunctionExecuted)
|
||||
{
|
||||
currentRecursiveDepth++;
|
||||
if (currentRecursiveDepth > maxRecursiveDepth)
|
||||
|
|
@ -38,7 +39,7 @@ public partial class ConversationService
|
|||
{
|
||||
var preAgentId = agent.Id;
|
||||
|
||||
await HandleFunctionMessage(fn, onFunctionExecuting);
|
||||
await HandleFunctionMessage(fn, onFunctionExecuting, onFunctionExecuted);
|
||||
|
||||
// Function executed has exception
|
||||
if (fn.ExecutionResult == null)
|
||||
|
|
@ -58,10 +59,6 @@ public partial class ConversationService
|
|||
var agentSettings = _services.GetRequiredService<AgentSettings>();
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
agent = await agentService.LoadAgent(fn.CurrentAgentId);
|
||||
|
||||
// Set state to make next conversation will go to this agent directly
|
||||
// var state = _services.GetRequiredService<IConversationStateService>();
|
||||
// state.SetState("agentId", fn.CurrentAgentId);
|
||||
}
|
||||
|
||||
// Add to dialog history
|
||||
|
|
@ -70,7 +67,13 @@ public partial class ConversationService
|
|||
// After function is executed, pass the result to LLM to get a natural response
|
||||
wholeDialogs.Add(fn);
|
||||
|
||||
await GetChatCompletionsAsyncRecursively(chatCompletion, conversationId, agent, wholeDialogs, onMessageReceived, onFunctionExecuting);
|
||||
await GetChatCompletionsAsyncRecursively(chatCompletion,
|
||||
conversationId,
|
||||
agent,
|
||||
wholeDialogs,
|
||||
onMessageReceived,
|
||||
onFunctionExecuting,
|
||||
onFunctionExecuted);
|
||||
});
|
||||
|
||||
return result;
|
||||
|
|
@ -89,7 +92,9 @@ public partial class ConversationService
|
|||
await onMessageReceived(msg);
|
||||
}
|
||||
|
||||
private async Task HandleFunctionMessage(RoleDialogModel msg, Func<RoleDialogModel, Task> onFunctionExecuting)
|
||||
private async Task HandleFunctionMessage(RoleDialogModel msg,
|
||||
Func<RoleDialogModel, Task> onFunctionExecuting,
|
||||
Func<RoleDialogModel, Task> onFunctionExecuted)
|
||||
{
|
||||
// Save states
|
||||
SaveStateByArgs(msg.FunctionArgs);
|
||||
|
|
@ -97,5 +102,6 @@ public partial class ConversationService
|
|||
// Call functions
|
||||
await onFunctionExecuting(msg);
|
||||
await CallFunctions(msg);
|
||||
await onFunctionExecuted(msg);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ public partial class ConversationService
|
|||
public async Task<bool> SendMessage(string agentId, string conversationId,
|
||||
RoleDialogModel lastDialog,
|
||||
Func<RoleDialogModel, Task> onMessageReceived,
|
||||
Func<RoleDialogModel, Task> onFunctionExecuting)
|
||||
Func<RoleDialogModel, Task> onFunctionExecuting,
|
||||
Func<RoleDialogModel, Task> onFunctionExecuted)
|
||||
{
|
||||
var converation = await GetConversation(conversationId);
|
||||
|
||||
|
|
@ -29,7 +30,7 @@ public partial class ConversationService
|
|||
stateService.Load();
|
||||
|
||||
var router = _services.GetRequiredService<IAgentRouting>();
|
||||
var agent = await router.LoadCurrentAgent();
|
||||
var agent = await router.LoadRouter();
|
||||
|
||||
_logger.LogInformation($"[{agent.Name}] {lastDialog.Role}: {lastDialog.Content}");
|
||||
|
||||
|
|
@ -67,7 +68,8 @@ public partial class ConversationService
|
|||
agent,
|
||||
wholeDialogs,
|
||||
onMessageReceived,
|
||||
onFunctionExecuting);
|
||||
onFunctionExecuting,
|
||||
onFunctionExecuted);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
36
src/Infrastructure/BotSharp.Core/Functions/RouteToAgentFn.cs
Normal file
36
src/Infrastructure/BotSharp.Core/Functions/RouteToAgentFn.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Conversations.Models;
|
||||
using BotSharp.Abstraction.Functions;
|
||||
using BotSharp.Abstraction.Functions.Models;
|
||||
|
||||
namespace BotSharp.Core.Functions;
|
||||
|
||||
public class RouteToAgentFn : IFunctionCallback
|
||||
{
|
||||
public string Name => "route_to_agent";
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public RouteToAgentFn(IServiceProvider services)
|
||||
{
|
||||
_services = services;
|
||||
}
|
||||
|
||||
public async Task<bool> Execute(RoleDialogModel message)
|
||||
{
|
||||
var args = JsonSerializer.Deserialize<AgentRoutingArgs>(message.FunctionArgs);
|
||||
|
||||
if (string.IsNullOrEmpty(args.AgentId))
|
||||
{
|
||||
var result = new FunctionExecutionValidationResult("false", "agent_id can't be parsed.");
|
||||
message.ExecutionResult = JsonSerializer.Serialize(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = new FunctionExecutionValidationResult("true");
|
||||
message.ExecutionResult = JsonSerializer.Serialize(result);
|
||||
message.CurrentAgentId = args.AgentId;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ using Microsoft.Extensions.Configuration;
|
|||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Console = Colorful.Console;
|
||||
|
||||
namespace BotSharp.Core.Plugins;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
using BotSharp.Abstraction.ApiAdapters;
|
||||
using BotSharp.Abstraction.Conversations.Models;
|
||||
using BotSharp.OpenAPI.ViewModels.Conversations;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace BotSharp.OpenAPI.Controllers;
|
||||
|
||||
|
|
@ -52,9 +50,17 @@ public class ConversationController : ControllerBase, IApiAdapter
|
|||
await conv.SendMessage(agentId, conversationId,
|
||||
new RoleDialogModel("user", input.Text),
|
||||
async msg =>
|
||||
stackMsg.Add(msg),
|
||||
async fn
|
||||
=> await Task.CompletedTask);
|
||||
{
|
||||
stackMsg.Add(msg);
|
||||
},
|
||||
async fnExecuting =>
|
||||
{
|
||||
|
||||
},
|
||||
async fnExecuted =>
|
||||
{
|
||||
response.Json = JsonSerializer.Deserialize<object>(fnExecuted.ExecutionResult);
|
||||
});
|
||||
|
||||
response.Text = string.Join("\r\n", stackMsg.Select(x => x.Content));
|
||||
return response;
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@ namespace BotSharp.OpenAPI.ViewModels.Conversations;
|
|||
public class MessageResponseModel
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public object Json { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,6 +75,8 @@ public class ChatbotUiController : ControllerBase, IApiAdapter
|
|||
async msg =>
|
||||
await OnChunkReceived(outputStream, msg),
|
||||
async fn
|
||||
=> await Task.CompletedTask,
|
||||
async fn
|
||||
=> await Task.CompletedTask);
|
||||
|
||||
await OnEventCompleted(outputStream);
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ public class WebhookController : ControllerBase
|
|||
|
||||
}
|
||||
content = msg.Content;
|
||||
}, async fn =>
|
||||
}, async functionExecuting =>
|
||||
{
|
||||
/*await messenger.SendMessage(setting.ApiVersion, setting.PageId, new SendingMessageRequest
|
||||
{
|
||||
|
|
@ -113,13 +113,15 @@ public class WebhookController : ControllerBase
|
|||
Recipient = JsonSerializer.Serialize(new { Id = sessionId }, jsonOpt),
|
||||
Message = JsonSerializer.Serialize(new { Text = "I'm pulling the relevent information, please wait a second ..." }, jsonOpt)
|
||||
});*/
|
||||
|
||||
await messenger.SendMessage(setting.ApiVersion, setting.PageId, new SendingMessageRequest
|
||||
}, async functionExecuted =>
|
||||
{
|
||||
// Render structured data
|
||||
/*await messenger.SendMessage(setting.ApiVersion, setting.PageId, new SendingMessageRequest
|
||||
{
|
||||
AccessToken = setting.PageAccessToken,
|
||||
Recipient = JsonSerializer.Serialize(new { Id = senderId }, jsonOpt),
|
||||
SenderAction = SenderActionEnum.TypingOn
|
||||
});
|
||||
});*/
|
||||
});
|
||||
|
||||
// Response to user
|
||||
|
|
|
|||
|
|
@ -59,7 +59,10 @@ namespace BotSharp.Plugin.WeChat
|
|||
var result = await conversationService.SendMessage(AgentId, latestConversationId, new RoleDialogModel("user", message), async msg =>
|
||||
{
|
||||
await ReplyTextMessageAsync(openid, msg.Content);
|
||||
}, async fn =>
|
||||
}, async functionExecuting =>
|
||||
{
|
||||
|
||||
}, async functionExecuted =>
|
||||
{
|
||||
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue