Add executor of evaluation.
This commit is contained in:
parent
13e17acc76
commit
a4c1b56740
|
|
@ -32,13 +32,13 @@ Task OnFunctionExecuted(RoleDialogModel message);
|
||||||
Task OnResponseGenerated(RoleDialogModel message);
|
Task OnResponseGenerated(RoleDialogModel message);
|
||||||
|
|
||||||
// LLM detected the current task is completed.
|
// LLM detected the current task is completed.
|
||||||
Task CurrentTaskEnding(RoleDialogModel conversation);
|
Task OnCurrentTaskEnding(RoleDialogModel message);
|
||||||
|
|
||||||
// LLM detected the user's intention to end the conversation
|
// LLM detected the user's intention to end the conversation
|
||||||
Task ConversationEnding(RoleDialogModel conversation);
|
Task OnConversationEnding(RoleDialogModel message);
|
||||||
|
|
||||||
// LLM can't handle user's request or user requests human being to involve.
|
// LLM can't handle user's request or user requests human being to involve.
|
||||||
Task HumanInterventionNeeded(RoleDialogModel conversation);
|
Task OnHumanInterventionNeeded(RoleDialogModel message);
|
||||||
```
|
```
|
||||||
More information about conversation hook please go to [Conversation Hook](../conversation/hook.md).
|
More information about conversation hook please go to [Conversation Hook](../conversation/hook.md).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,4 +15,9 @@ public class AgentTemplate
|
||||||
Name = name;
|
Name = name;
|
||||||
Content = content;
|
Content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,17 +42,17 @@ public abstract class ConversationHookBase : IConversationHook
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Task ConversationEnding(RoleDialogModel message)
|
public virtual Task OnConversationEnding(RoleDialogModel message)
|
||||||
{
|
{
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Task CurrentTaskEnding(RoleDialogModel conversation)
|
public virtual Task OnCurrentTaskEnding(RoleDialogModel message)
|
||||||
{
|
{
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Task HumanInterventionNeeded(RoleDialogModel conversation)
|
public virtual Task OnHumanInterventionNeeded(RoleDialogModel message)
|
||||||
{
|
{
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
@ -77,7 +77,7 @@ public abstract class ConversationHookBase : IConversationHook
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Task OnConversationInitialized(Conversation conversation)
|
public virtual Task OnConversationInitialized(Conversation message)
|
||||||
{
|
{
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,19 +51,19 @@ public interface IConversationHook
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="conversation"></param>
|
/// <param name="conversation"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task CurrentTaskEnding(RoleDialogModel conversation);
|
Task OnCurrentTaskEnding(RoleDialogModel message);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// LLM detected the whole conversation is going to be end.
|
/// LLM detected the whole conversation is going to be end.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="conversation"></param>
|
/// <param name="conversation"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task ConversationEnding(RoleDialogModel conversation);
|
Task OnConversationEnding(RoleDialogModel message);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// LLM can't handle user's request or user requests human being to involve.
|
/// LLM can't handle user's request or user requests human being to involve.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="conversation"></param>
|
/// <param name="conversation"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task HumanInterventionNeeded(RoleDialogModel conversation);
|
Task OnHumanInterventionNeeded(RoleDialogModel message);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,18 +21,12 @@ public class RoleDialogModel
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
public string? FunctionArgs { get; set; }
|
public string? FunctionArgs { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Function execution result, this result will be seen by LLM.
|
|
||||||
/// </summary>
|
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
||||||
public string? ExecutionResult { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Function execution structured data, this data won't pass to LLM.
|
/// Function execution structured data, this data won't pass to LLM.
|
||||||
/// It's ideal to render in rich content in UI.
|
/// It's ideal to render in rich content in UI.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
public object ExecutionData { get; set; }
|
public object Data { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stop conversation completion
|
/// Stop conversation completion
|
||||||
|
|
@ -50,7 +44,7 @@ public class RoleDialogModel
|
||||||
{
|
{
|
||||||
if (Role == AgentRole.Function)
|
if (Role == AgentRole.Function)
|
||||||
{
|
{
|
||||||
return $"{Role}: {FunctionName} => {ExecutionResult}";
|
return $"{Role}: {FunctionName}({FunctionArgs}) => {Content}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,25 @@ namespace BotSharp.Abstraction.Evaluations;
|
||||||
|
|
||||||
public interface IEvaluatingService
|
public interface IEvaluatingService
|
||||||
{
|
{
|
||||||
Task<EvaluationResult> Evaluate(EvaluationRequest request);
|
/// <summary>
|
||||||
|
/// Execute task
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="task">Task template name</param>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <returns>Conversation</returns>
|
||||||
|
Task<Conversation> Execute(string task, EvaluationRequest request);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Review result
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<EvaluationResult> Review(string conversationId, EvaluationRequest request);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate evaluation report
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<EvaluationResult> Evaluate(string conversationId, EvaluationRequest request);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace BotSharp.Abstraction.Evaluations;
|
||||||
|
|
||||||
|
public interface IExecutionLogger
|
||||||
|
{
|
||||||
|
void Append(string conversationId, string context);
|
||||||
|
}
|
||||||
|
|
@ -3,5 +3,4 @@ namespace BotSharp.Abstraction.Evaluations.Models;
|
||||||
public class EvaluationRequest
|
public class EvaluationRequest
|
||||||
{
|
{
|
||||||
public string AgentId { get; set; }
|
public string AgentId { get; set; }
|
||||||
public string Task { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ using BotSharp.Core.Plugins;
|
||||||
using BotSharp.Abstraction.Evaluations.Settings;
|
using BotSharp.Abstraction.Evaluations.Settings;
|
||||||
using BotSharp.Abstraction.Evaluations;
|
using BotSharp.Abstraction.Evaluations;
|
||||||
using BotSharp.Core.Evaluatings;
|
using BotSharp.Core.Evaluatings;
|
||||||
|
using BotSharp.Core.Evaluations;
|
||||||
|
|
||||||
namespace BotSharp.Core;
|
namespace BotSharp.Core;
|
||||||
|
|
||||||
|
|
@ -76,7 +77,9 @@ public static class BotSharpServiceCollectionExtensions
|
||||||
config.Bind("Evaluator", evalSetting);
|
config.Bind("Evaluator", evalSetting);
|
||||||
services.AddSingleton((IServiceProvider x) => evalSetting);
|
services.AddSingleton((IServiceProvider x) => evalSetting);
|
||||||
|
|
||||||
|
services.AddScoped<IConversationHook, EvaluationConversationHook>();
|
||||||
services.AddScoped<IEvaluatingService, EvaluatingService>();
|
services.AddScoped<IEvaluatingService, EvaluatingService>();
|
||||||
|
services.AddScoped<IExecutionLogger, ExecutionLogger>();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,11 +34,16 @@ public partial class ConversationService
|
||||||
{
|
{
|
||||||
// Execute function
|
// Execute function
|
||||||
await fn.Execute(msg);
|
await fn.Execute(msg);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(msg.Content))
|
||||||
|
{
|
||||||
|
msg.Content = msg.Content ?? JsonSerializer.Serialize(msg.Data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
msg.ExecutionResult = ex.Message;
|
msg.Content = ex.Message;
|
||||||
_logger.LogError(msg.ExecutionResult);
|
_logger.LogError(msg.Content);
|
||||||
}
|
}
|
||||||
|
|
||||||
// After functions have been executed
|
// After functions have been executed
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
using BotSharp.Abstraction.Agents.Enums;
|
|
||||||
using BotSharp.Abstraction.Repositories;
|
using BotSharp.Abstraction.Repositories;
|
||||||
using BotSharp.Abstraction.Routing.Settings;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace BotSharp.Core.Conversations.Services;
|
namespace BotSharp.Core.Conversations.Services;
|
||||||
|
|
@ -36,7 +34,7 @@ public class ConversationStorage : IConversationStorage
|
||||||
|
|
||||||
sb.AppendLine($"{dialog.CreatedAt}|{dialog.Role}|{agentId}|{dialog.FunctionName}|{args}");
|
sb.AppendLine($"{dialog.CreatedAt}|{dialog.Role}|{agentId}|{dialog.FunctionName}|{args}");
|
||||||
|
|
||||||
var content = dialog.ExecutionResult ?? dialog.Content;
|
var content = dialog.Content;
|
||||||
content = content.Replace("\r", " ").Replace("\n", " ").Trim();
|
content = content.Replace("\r", " ").Replace("\n", " ").Trim();
|
||||||
if (string.IsNullOrEmpty(content))
|
if (string.IsNullOrEmpty(content))
|
||||||
{
|
{
|
||||||
|
|
@ -84,7 +82,7 @@ public class ConversationStorage : IConversationStorage
|
||||||
CurrentAgentId = currentAgentId,
|
CurrentAgentId = currentAgentId,
|
||||||
FunctionName = funcName,
|
FunctionName = funcName,
|
||||||
FunctionArgs = funcArgs,
|
FunctionArgs = funcArgs,
|
||||||
ExecutionResult = text,
|
Content = text,
|
||||||
CreatedAt = createdAt
|
CreatedAt = createdAt
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using BotSharp.Abstraction.Conversations.Models;
|
|
||||||
using BotSharp.Abstraction.Evaluations;
|
using BotSharp.Abstraction.Evaluations;
|
||||||
using BotSharp.Abstraction.Evaluations.Models;
|
using BotSharp.Abstraction.Evaluations.Models;
|
||||||
using BotSharp.Abstraction.Evaluations.Settings;
|
using BotSharp.Abstraction.Evaluations.Settings;
|
||||||
|
|
@ -17,11 +16,13 @@ public class EvaluatingService : IEvaluatingService
|
||||||
_settings = settings;
|
_settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<EvaluationResult> Evaluate(EvaluationRequest request)
|
public async Task<Conversation> Execute(string task, EvaluationRequest request)
|
||||||
{
|
{
|
||||||
var agentService = _services.GetRequiredService<IAgentService>();
|
var agentService = _services.GetRequiredService<IAgentService>();
|
||||||
var evaluator = await agentService.GetAgent(_settings.EvaluatorId);
|
var evaluator = await agentService.GetAgent(_settings.EvaluatorId);
|
||||||
var taskPrompt = evaluator.Templates.First(x => x.Name == $"task.{request.Task}").Content;
|
// Task execution mode
|
||||||
|
evaluator.Instruction = evaluator.Templates.First(x => x.Name == "instruction.executor").Content;
|
||||||
|
var taskPrompt = evaluator.Templates.First(x => x.Name == $"task.{task}").Content;
|
||||||
|
|
||||||
var render = _services.GetRequiredService<ITemplateRender>();
|
var render = _services.GetRequiredService<ITemplateRender>();
|
||||||
var prompt = render.Render(evaluator.Instruction, new Dictionary<string, object>
|
var prompt = render.Render(evaluator.Instruction, new Dictionary<string, object>
|
||||||
|
|
@ -70,7 +71,12 @@ public class EvaluatingService : IEvaluatingService
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Dialogs = dialogs;
|
result.Dialogs = dialogs;
|
||||||
return result;
|
return conv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<EvaluationResult> Evaluate(string conversationId, EvaluationRequest request)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<RoleDialogModel> SendMessage(string agentId, string conversationId, string text)
|
private async Task<RoleDialogModel> SendMessage(string agentId, string conversationId, string text)
|
||||||
|
|
@ -88,4 +94,9 @@ public class EvaluatingService : IEvaluatingService
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task<EvaluationResult> Review(string conversationId, EvaluationRequest request)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
using BotSharp.Abstraction.Evaluations;
|
||||||
|
|
||||||
|
namespace BotSharp.Core.Evaluations;
|
||||||
|
|
||||||
|
public class EvaluationConversationHook : ConversationHookBase
|
||||||
|
{
|
||||||
|
private readonly IExecutionLogger _logger;
|
||||||
|
|
||||||
|
public EvaluationConversationHook(IExecutionLogger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task OnMessageReceived(RoleDialogModel message)
|
||||||
|
{
|
||||||
|
_logger.Append(_conversation.Id, $"[{DateTime.Now}] {message.Role}: {message.Content}");
|
||||||
|
return base.OnMessageReceived(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task OnFunctionExecuted(RoleDialogModel message)
|
||||||
|
{
|
||||||
|
_logger.Append(_conversation.Id, $"[{DateTime.Now}] {message.Role}: {message.FunctionName}({message.FunctionArgs}) => {message.Content}");
|
||||||
|
return base.OnFunctionExecuted(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task OnResponseGenerated(RoleDialogModel message)
|
||||||
|
{
|
||||||
|
_logger.Append(_conversation.Id, $"[{DateTime.Now}] {message.Role}: {message.Content}");
|
||||||
|
return base.OnResponseGenerated(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task OnHumanInterventionNeeded(RoleDialogModel message)
|
||||||
|
{
|
||||||
|
_logger.Append(_conversation.Id, $"[{DateTime.Now}] {AgentRole.Function}: trigger event \"{message.FunctionName}\"");
|
||||||
|
return base.OnHumanInterventionNeeded(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task OnConversationEnding(RoleDialogModel message)
|
||||||
|
{
|
||||||
|
_logger.Append(_conversation.Id, $"[{DateTime.Now}] {AgentRole.Function}: trigger event \"{message.FunctionName}\"");
|
||||||
|
return base.OnConversationEnding(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
using BotSharp.Abstraction.Evaluations;
|
||||||
|
using BotSharp.Abstraction.Repositories;
|
||||||
|
using BotSharp.Abstraction.Utilities;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace BotSharp.Core.Evaluations;
|
||||||
|
|
||||||
|
public class ExecutionLogger : IExecutionLogger
|
||||||
|
{
|
||||||
|
private readonly BotSharpDatabaseSettings _dbSettings;
|
||||||
|
private readonly IServiceProvider _services;
|
||||||
|
public ExecutionLogger(
|
||||||
|
BotSharpDatabaseSettings dbSettings,
|
||||||
|
IServiceProvider services)
|
||||||
|
{
|
||||||
|
_dbSettings = dbSettings;
|
||||||
|
_services = services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Append(string conversationId, string content)
|
||||||
|
{
|
||||||
|
var file = GetStorageFile(conversationId);
|
||||||
|
File.AppendAllLines(file, new[] { content });
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetStorageFile(string conversationId)
|
||||||
|
{
|
||||||
|
var dir = Path.Combine(_dbSettings.FileRepository, "conversations", conversationId);
|
||||||
|
return Path.Combine(dir, "execution.log");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -36,8 +36,8 @@ public partial class InstructService
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
msg.ExecutionResult = ex.Message;
|
msg.Content = ex.Message;
|
||||||
_logger.LogError(msg.ExecutionResult);
|
_logger.LogError(msg.Content);
|
||||||
}
|
}
|
||||||
|
|
||||||
// After functions have been executed
|
// After functions have been executed
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ public partial class InstructService : IInstructService
|
||||||
},
|
},
|
||||||
async fn =>
|
async fn =>
|
||||||
{
|
{
|
||||||
response.Data = fn.ExecutionData;
|
response.Data = fn.Data;
|
||||||
await onFunctionExecuted(fn);
|
await onFunctionExecuted(fn);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -85,13 +85,13 @@ public partial class InstructService : IInstructService
|
||||||
await HandleFunctionMessage(fn, onFunctionExecuting, onFunctionExecuted);
|
await HandleFunctionMessage(fn, onFunctionExecuting, onFunctionExecuted);
|
||||||
|
|
||||||
// Function executed has exception
|
// Function executed has exception
|
||||||
if (fn.ExecutionResult == null || fn.StopCompletion)
|
if (fn.Content == null || fn.StopCompletion)
|
||||||
{
|
{
|
||||||
await onMessageReceived(new RoleDialogModel(AgentRole.Assistant, fn.Content));
|
await onMessageReceived(new RoleDialogModel(AgentRole.Assistant, fn.Content));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn.Content = fn.FunctionArgs.Replace("\r", " ").Replace("\n", " ").Trim() + " => " + fn.ExecutionResult;
|
fn.Content = fn.FunctionArgs.Replace("\r", " ").Replace("\n", " ").Trim() + " => " + fn.Content;
|
||||||
|
|
||||||
// Find response template
|
// Find response template
|
||||||
var templateService = _services.GetRequiredService<IResponseTemplateService>();
|
var templateService = _services.GetRequiredService<IResponseTemplateService>();
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ public class RouteToAgentFn : IFunctionCallback
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(args.AgentName))
|
if (string.IsNullOrEmpty(args.AgentName))
|
||||||
{
|
{
|
||||||
message.ExecutionResult = $"missing agent name";
|
message.Content = $"missing agent name";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -51,7 +51,7 @@ public class RouteToAgentFn : IFunctionCallback
|
||||||
var targetAgent = db.GetAgents(args.AgentName).FirstOrDefault();
|
var targetAgent = db.GetAgents(args.AgentName).FirstOrDefault();
|
||||||
if (targetAgent == null)
|
if (targetAgent == null)
|
||||||
{
|
{
|
||||||
message.ExecutionData = JsonSerializer.Deserialize<JsonElement>(message.FunctionArgs);
|
message.Data = JsonSerializer.Deserialize<JsonElement>(message.FunctionArgs);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,14 +66,14 @@ public class RouteToAgentFn : IFunctionCallback
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
message.CurrentAgentId = targetAgent.Id;
|
message.CurrentAgentId = targetAgent.Id;
|
||||||
message.ExecutionResult = $"Routing to {args.AgentName}";
|
message.Content = $"Routing to {args.AgentName}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_context.Push(message.CurrentAgentId);
|
_context.Push(message.CurrentAgentId);
|
||||||
|
|
||||||
// Set default execution data
|
// Set default execution data
|
||||||
message.ExecutionData = JsonSerializer.Deserialize<JsonElement>(message.FunctionArgs);
|
message.Data = JsonSerializer.Deserialize<JsonElement>(message.FunctionArgs);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,8 +130,7 @@ public class RouteToAgentFn : IFunctionCallback
|
||||||
{
|
{
|
||||||
// Add field to args
|
// Add field to args
|
||||||
message.FunctionArgs = AppendPropertyToArgs(message.FunctionArgs, "missing_fields", missingFields);
|
message.FunctionArgs = AppendPropertyToArgs(message.FunctionArgs, "missing_fields", missingFields);
|
||||||
message.ExecutionResult = $"missing some information: {string.Join(',', missingFields)}";
|
message.Content = $"missing some information: {string.Join(',', missingFields)}";
|
||||||
message.Content = message.ExecutionResult;
|
|
||||||
|
|
||||||
// Handle redirect
|
// Handle redirect
|
||||||
var routingRule = routingRules.FirstOrDefault(x => missingFields.Contains(x.Field));
|
var routingRule = routingRules.FirstOrDefault(x => missingFields.Contains(x.Field));
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ public class ConversationEndRoutingHandler : RoutingHandlerBase, IRoutingHandler
|
||||||
{
|
{
|
||||||
CurrentAgentId = _settings.RouterId,
|
CurrentAgentId = _settings.RouterId,
|
||||||
FunctionName = inst.Function,
|
FunctionName = inst.Function,
|
||||||
ExecutionData = inst
|
Data = inst
|
||||||
};
|
};
|
||||||
|
|
||||||
var hooks = _services.GetServices<IConversationHook>()
|
var hooks = _services.GetServices<IConversationHook>()
|
||||||
|
|
@ -39,7 +39,7 @@ public class ConversationEndRoutingHandler : RoutingHandlerBase, IRoutingHandler
|
||||||
|
|
||||||
foreach (var hook in hooks)
|
foreach (var hook in hooks)
|
||||||
{
|
{
|
||||||
await hook.ConversationEnding(result);
|
await hook.OnConversationEnding(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ public class HumanInterventionNeededHandler : RoutingHandlerBase, IRoutingHandle
|
||||||
{
|
{
|
||||||
CurrentAgentId = _settings.RouterId,
|
CurrentAgentId = _settings.RouterId,
|
||||||
FunctionName = inst.Function,
|
FunctionName = inst.Function,
|
||||||
ExecutionData = inst
|
Data = inst
|
||||||
};
|
};
|
||||||
|
|
||||||
var hooks = _services.GetServices<IConversationHook>()
|
var hooks = _services.GetServices<IConversationHook>()
|
||||||
|
|
@ -40,7 +40,7 @@ public class HumanInterventionNeededHandler : RoutingHandlerBase, IRoutingHandle
|
||||||
|
|
||||||
foreach (var hook in hooks)
|
foreach (var hook in hooks)
|
||||||
{
|
{
|
||||||
await hook.HumanInterventionNeeded(result);
|
await hook.OnHumanInterventionNeeded(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ public class ResponseToUserRoutingHandler : RoutingHandlerBase, IRoutingHandler
|
||||||
{
|
{
|
||||||
CurrentAgentId = _settings.RouterId,
|
CurrentAgentId = _settings.RouterId,
|
||||||
FunctionName = inst.Function,
|
FunctionName = inst.Function,
|
||||||
ExecutionData = inst,
|
Data = inst,
|
||||||
StopCompletion = true
|
StopCompletion = true
|
||||||
};
|
};
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler
|
||||||
|
|
||||||
var result = await routing.InvokeAgent(context.GetCurrentAgentId());
|
var result = await routing.InvokeAgent(context.GetCurrentAgentId());
|
||||||
// Keep last message data for debug
|
// Keep last message data for debug
|
||||||
result.ExecutionData = result.ExecutionData ?? message.ExecutionData;
|
result.Data = result.Data ?? message.Data;
|
||||||
result.FunctionName = result.FunctionName ?? message.FunctionName;
|
result.FunctionName = result.FunctionName ?? message.FunctionName;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ public class TaskEndRoutingHandler : RoutingHandlerBase, IRoutingHandler
|
||||||
{
|
{
|
||||||
CurrentAgentId = _settings.RouterId,
|
CurrentAgentId = _settings.RouterId,
|
||||||
FunctionName = inst.Function,
|
FunctionName = inst.Function,
|
||||||
ExecutionData = inst
|
Data = inst
|
||||||
};
|
};
|
||||||
|
|
||||||
var hooks = _services.GetServices<IConversationHook>()
|
var hooks = _services.GetServices<IConversationHook>()
|
||||||
|
|
@ -38,7 +38,7 @@ public class TaskEndRoutingHandler : RoutingHandlerBase, IRoutingHandler
|
||||||
|
|
||||||
foreach (var hook in hooks)
|
foreach (var hook in hooks)
|
||||||
{
|
{
|
||||||
await hook.CurrentTaskEnding(result);
|
await hook.OnCurrentTaskEnding(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -42,11 +42,6 @@ public partial class RoutingService
|
||||||
// Call functions
|
// Call functions
|
||||||
await conversationService.CallFunctions(response);
|
await conversationService.CallFunctions(response);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(response.Content))
|
|
||||||
{
|
|
||||||
response.Content = response.ExecutionResult ?? JsonSerializer.Serialize(response.ExecutionData);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dialogs.Add(response);
|
Dialogs.Add(response);
|
||||||
|
|
||||||
// Pass execution result to LLM to get response
|
// Pass execution result to LLM to get response
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,9 @@ public class ResponseTemplateService : IResponseTemplateService
|
||||||
ExtractArgs(JsonSerializer.Deserialize<JsonDocument>(message.FunctionArgs), dict);
|
ExtractArgs(JsonSerializer.Deserialize<JsonDocument>(message.FunctionArgs), dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.ExecutionData != null)
|
if (message.Data != null)
|
||||||
{
|
{
|
||||||
ExtractExecuteData(message.ExecutionData, dict);
|
ExtractExecuteData(message.Data, dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
var text = render.Render(template, dict);
|
var text = render.Render(template, dict);
|
||||||
|
|
@ -85,9 +85,9 @@ public class ResponseTemplateService : IResponseTemplateService
|
||||||
ExtractArgs(JsonSerializer.Deserialize<JsonDocument>(message.FunctionArgs), dict);
|
ExtractArgs(JsonSerializer.Deserialize<JsonDocument>(message.FunctionArgs), dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.ExecutionData != null)
|
if (message.Data != null)
|
||||||
{
|
{
|
||||||
ExtractExecuteData(message.ExecutionData, dict);
|
ExtractExecuteData(message.Data, dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
var text = render.Render(template, dict);
|
var text = render.Render(template, dict);
|
||||||
|
|
|
||||||
|
|
@ -65,11 +65,11 @@ public class ConversationController : ControllerBase, IApiAdapter
|
||||||
async fnExecuted =>
|
async fnExecuted =>
|
||||||
{
|
{
|
||||||
response.Function = fnExecuted.FunctionName;
|
response.Function = fnExecuted.FunctionName;
|
||||||
response.Data = fnExecuted.ExecutionData;
|
response.Data = fnExecuted.Data;
|
||||||
});
|
});
|
||||||
|
|
||||||
response.Text = string.Join("\r\n", stackMsg.Select(x => x.Content));
|
response.Text = string.Join("\r\n", stackMsg.Select(x => x.Content));
|
||||||
response.Data = response.Data ?? stackMsg.Last().ExecutionData;
|
response.Data = response.Data ?? stackMsg.Last().Data;
|
||||||
response.Function = stackMsg.Last().FunctionName;
|
response.Function = stackMsg.Last().FunctionName;
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using BotSharp.Abstraction.ApiAdapters;
|
using BotSharp.Abstraction.ApiAdapters;
|
||||||
|
using BotSharp.Abstraction.Conversations.Models;
|
||||||
using BotSharp.Abstraction.Evaluations;
|
using BotSharp.Abstraction.Evaluations;
|
||||||
using BotSharp.Abstraction.Evaluations.Models;
|
using BotSharp.Abstraction.Evaluations.Models;
|
||||||
|
|
||||||
|
|
@ -14,10 +15,24 @@ public class EvaluationController : ControllerBase, IApiAdapter
|
||||||
_services = services;
|
_services = services;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("/evaluation")]
|
[HttpPost("/evaluation/execute/{task}")]
|
||||||
public async Task<EvaluationResult> RunTask([FromBody] EvaluationRequest request)
|
public async Task<Conversation> Execute([FromRoute] string task, [FromBody] EvaluationRequest request)
|
||||||
{
|
{
|
||||||
var eval = _services.GetRequiredService<IEvaluatingService>();
|
var eval = _services.GetRequiredService<IEvaluatingService>();
|
||||||
return await eval.Evaluate(request);
|
return await eval.Execute(task, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("/evaluation/review/{conversationId}")]
|
||||||
|
public async Task<EvaluationResult> Review([FromRoute] string conversationId, [FromBody] EvaluationRequest request)
|
||||||
|
{
|
||||||
|
var eval = _services.GetRequiredService<IEvaluatingService>();
|
||||||
|
return await eval.Review(conversationId, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("/evaluation/evaluate/{conversationId}")]
|
||||||
|
public async Task<EvaluationResult> Evaluate([FromRoute] string conversationId, [FromBody] EvaluationRequest request)
|
||||||
|
{
|
||||||
|
var eval = _services.GetRequiredService<IEvaluatingService>();
|
||||||
|
return await eval.Evaluate(conversationId, request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -117,10 +117,10 @@ public class WebhookController : ControllerBase
|
||||||
}, async functionExecuted =>
|
}, async functionExecuted =>
|
||||||
{
|
{
|
||||||
// Render structured data
|
// Render structured data
|
||||||
if (functionExecuted.ExecutionData != null)
|
if (functionExecuted.Data != null)
|
||||||
{
|
{
|
||||||
// validate data format
|
// validate data format
|
||||||
var json = JsonSerializer.Serialize(functionExecuted.ExecutionData, jsonOpt);
|
var json = JsonSerializer.Serialize(functionExecuted.Data, jsonOpt);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,6 @@
|
||||||
"createdDateTime": "2023-08-18T14:39:32.2349685Z",
|
"createdDateTime": "2023-08-18T14:39:32.2349685Z",
|
||||||
"updatedDateTime": "2023-08-18T14:39:32.2349686Z",
|
"updatedDateTime": "2023-08-18T14:39:32.2349686Z",
|
||||||
"id": "b284db86-e9c2-4c25-a59e-4649797dd130",
|
"id": "b284db86-e9c2-4c25-a59e-4649797dd130",
|
||||||
"allowRouting": true
|
"allowRouting": true,
|
||||||
|
"isPublic": true
|
||||||
}
|
}
|
||||||
|
|
@ -4,5 +4,6 @@
|
||||||
"createdDateTime": "2023-07-26T02:29:25.123224Z",
|
"createdDateTime": "2023-07-26T02:29:25.123224Z",
|
||||||
"updatedDateTime": "2023-07-26T02:29:25.123274Z",
|
"updatedDateTime": "2023-07-26T02:29:25.123274Z",
|
||||||
"id": "c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd",
|
"id": "c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd",
|
||||||
"allowRouting": true
|
"allowRouting": true,
|
||||||
|
"isPublic": true
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
This is a model executing program, which interactive with model to complete a certain task based on the background information given to you.
|
||||||
|
|
||||||
|
{{ task_prompt }}
|
||||||
|
|
||||||
|
user: Hi!
|
||||||
|
assistant: Hello, How can I help you?
|
||||||
|
user:
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
You are a task reviewer. You analyze the user's intention through the [CONVERSAION] and then generate the corresponding information to verify the result.
|
||||||
|
|
||||||
|
[CONVERSAION]
|
||||||
|
{{ execution_log }}
|
||||||
|
|
||||||
|
Populate values to validate the result. Response in JSON format: {
|
||||||
|
"is_conversation_end": "True or False",
|
||||||
|
"validation_parameters: "fields used to call validation function"
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
"updatedDateTime": "2023-07-26T02:29:25.123274Z",
|
"updatedDateTime": "2023-07-26T02:29:25.123274Z",
|
||||||
"id": "fe8c60aa-b114-4ef3-93cb-a8efeac80f75",
|
"id": "fe8c60aa-b114-4ef3-93cb-a8efeac80f75",
|
||||||
"allowRouting": true,
|
"allowRouting": true,
|
||||||
|
"isPublic": true,
|
||||||
"routingRules": [
|
"routingRules": [
|
||||||
{
|
{
|
||||||
"field": "order_number",
|
"field": "order_number",
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ public class GetOrderStatusFn : IFunctionCallback
|
||||||
|
|
||||||
public async Task<bool> Execute(RoleDialogModel message)
|
public async Task<bool> Execute(RoleDialogModel message)
|
||||||
{
|
{
|
||||||
message.ExecutionResult = "ready to deliver, will arrived in about 15 minutes.";
|
message.Content = "ready to deliver, will arrived in about 15 minutes.";
|
||||||
message.ExecutionData = new
|
message.Data = new
|
||||||
{
|
{
|
||||||
Status = "Ready to deliver",
|
Status = "Ready to deliver",
|
||||||
EstimatedTime = "15 minuts"
|
EstimatedTime = "15 minuts"
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ public class GetPizzaPricesFn : IFunctionCallback
|
||||||
|
|
||||||
public async Task<bool> Execute(RoleDialogModel message)
|
public async Task<bool> Execute(RoleDialogModel message)
|
||||||
{
|
{
|
||||||
message.ExecutionData = new
|
message.Data = new
|
||||||
{
|
{
|
||||||
pepperoni_unit_price = 3.2,
|
pepperoni_unit_price = 3.2,
|
||||||
cheese_unit_price = 3.5,
|
cheese_unit_price = 3.5,
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ public class GetPizzaTypesFn : IFunctionCallback
|
||||||
|
|
||||||
public async Task<bool> Execute(RoleDialogModel message)
|
public async Task<bool> Execute(RoleDialogModel message)
|
||||||
{
|
{
|
||||||
message.ExecutionResult = "Pepperoni Pizza, Cheese Pizza, Margherita Pizza";
|
message.Content = "Pepperoni Pizza, Cheese Pizza, Margherita Pizza";
|
||||||
message.ExecutionData = new List<string>
|
message.Data = new List<string>
|
||||||
{
|
{
|
||||||
"Pepperoni Pizza",
|
"Pepperoni Pizza",
|
||||||
"Cheese Pizza",
|
"Cheese Pizza",
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ public class MakePaymentFn : IFunctionCallback
|
||||||
|
|
||||||
public async Task<bool> Execute(RoleDialogModel message)
|
public async Task<bool> Execute(RoleDialogModel message)
|
||||||
{
|
{
|
||||||
message.ExecutionResult = "Payment proceed successfully. Thank you for your business. Have a great day!";
|
message.Content = "Payment proceed successfully. Thank you for your business. Have a great day!";
|
||||||
message.ExecutionData = new
|
message.Data = new
|
||||||
{
|
{
|
||||||
Transaction = Guid.NewGuid().ToString(),
|
Transaction = Guid.NewGuid().ToString(),
|
||||||
Status = "Success"
|
Status = "Success"
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ public class PlaceOrderFn : IFunctionCallback
|
||||||
|
|
||||||
public async Task<bool> Execute(RoleDialogModel message)
|
public async Task<bool> Execute(RoleDialogModel message)
|
||||||
{
|
{
|
||||||
message.ExecutionResult = "The order number is P123-01";
|
message.Content = "The order number is P123-01";
|
||||||
var state = _service.GetRequiredService<IConversationStateService>();
|
var state = _service.GetRequiredService<IConversationStateService>();
|
||||||
state.SetState("order_number", "P123-01");
|
state.SetState("order_number", "P123-01");
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue