Merge branch 'SciSharp:master' into master

This commit is contained in:
Haiping 2025-01-09 04:47:28 +00:00 committed by GitHub
commit 8e5b7cadf0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 120 additions and 38 deletions

View file

@ -2,12 +2,12 @@ namespace BotSharp.Abstraction.Agents.Models;
public class AgentRule
{
public string Name { get; set; }
[JsonPropertyName("trigger_name")]
public string TriggerName { get; set; }
[JsonPropertyName("disabled")]
public bool Disabled { get; set; }
[JsonPropertyName("event_name")]
public string EventName { get; set; }
[JsonPropertyName("entity_type")]
public string EntityType { get; set; }
[JsonPropertyName("criteria")]
public string Criteria { get; set; }
}

View file

@ -8,4 +8,5 @@ public class ConversationChannel
public const string Messenger = "messenger";
public const string Email = "email";
public const string Cron = "cron";
public const string Database = "database";
}

View file

@ -1,26 +1,85 @@
using BotSharp.Abstraction.Conversations;
using BotSharp.Abstraction.Conversations.Enums;
using BotSharp.Abstraction.Models;
using BotSharp.Abstraction.Repositories.Filters;
using BotSharp.Abstraction.Routing;
using BotSharp.Abstraction.Utilities;
using BotSharp.Core.Rules.Triggers;
using Microsoft.Extensions.Logging;
using System.Data;
namespace BotSharp.Core.Rules.Engines;
public class RuleEngine : IRuleEngine
{
private readonly IServiceProvider _services;
public RuleEngine(IServiceProvider services)
private readonly ILogger _logger;
public RuleEngine(IServiceProvider services, ILogger<RuleEngine> logger)
{
_services = services;
_logger = logger;
}
public async Task Triggered(IRuleTrigger trigger, string data)
{
// Pull all user defined rules
var agentService = _services.GetRequiredService<IAgentService>();
var agents = await agentService.GetAgents(new AgentFilter
{
Pager = new Pagination
{
Size = 1000
}
});
var preFilteredAgents = agents.Items.Where(x =>
x.Rules.Exists(r => r.TriggerName == trigger.Name &&
!x.Disabled)).ToList();
// Trigger the agents
var instructService = _services.GetRequiredService<IInstructService>();
var convService = _services.GetRequiredService<IConversationService>();
var userSay = $"===Input data===\r\n{data}\r\n\r\nWhen WO NTE is greater than 100, notify resident.";
foreach (var agent in preFilteredAgents)
{
var conv = await convService.NewConversation(new Conversation
{
AgentId = agent.Id
});
var result = await instructService.Execute(BuiltInAgentId.RulesInterpreter, new RoleDialogModel(AgentRole.User, data), "criteria_check", "#TEMPLATE#");
var message = new RoleDialogModel(AgentRole.User, data);
string[] rules = [];
// Check if meet the criteria
var states = new List<MessageState>
{
new("channel", ConversationChannel.Database),
new("channel_id", trigger.EntityId)
};
convService.SetConversationId(conv.Id, states);
await convService.SendMessage(agent.Id,
message,
null,
msg => Task.CompletedTask);
/*foreach (var rule in agent.Rules)
{
var userSay = $"===Input data with Before and After values===\r\n{data}\r\n\r\n===Trigger Criteria===\r\n{rule.Criteria}\r\n\r\nJust output 1 or 0 without explanation: ";
var result = await instructService.Execute(BuiltInAgentId.RulesInterpreter, new RoleDialogModel(AgentRole.User, userSay), "criteria_check", "#TEMPLATE#");
// Check if meet the criteria
if (result.Text == "1")
{
// Hit rule
_logger.LogInformation($"Hit rule {rule.TriggerName} {rule.EntityType} {rule.EventName}, {data}");
await convService.SendMessage(agent.Id,
new RoleDialogModel(AgentRole.User, $"The conversation was triggered by {rule.Criteria}"),
null,
msg => Task.CompletedTask);
}
}*/
}
}
}

View file

@ -4,7 +4,8 @@ public interface IRuleTrigger
{
string Channel => throw new NotImplementedException("Please set the channel of trigger");
string EventName { get; set; }
string Name { get; set; }
string EntityType { get; set; }
string EntityId { get; set; }

View file

@ -1,7 +1,7 @@
{
"id": "201e49a2-40b3-4ccd-b8cc-2476565a1b40",
"name": "Rules Agent",
"description": "Utility assistant that can be used to complete many different tasks",
"description": "Rules understands and converts user-defined rules into Triggers, Criterias and Actions",
"type": "static",
"createdDateTime": "2024-12-30T00:00:00Z",
"updatedDateTime": "2024-12-30T00:00:00Z",

View file

@ -1,4 +1,4 @@
You are a rule interpreter, analyze and respond according to the following steps:
1. Understand the rules customized by the user;
2. Determine whether the input data meets the user's action execution conditions;
3. If it meets the conditions, output "true", otherwise output "false"
3. If it meets the conditions, output number "1", otherwise output "0"

View file

@ -170,6 +170,6 @@ public class AgentController : ControllerBase
{
hook.AddRules(rules);
}
return rules.Where(x => !string.IsNullOrWhiteSpace(x.Name)).OrderBy(x => x.Name).ToList();
return rules.Where(x => !string.IsNullOrWhiteSpace(x.TriggerName)).OrderBy(x => x.TriggerName).ToList();
}
}

View file

@ -1,4 +1,5 @@
using BotSharp.Abstraction.Options;
using BotSharp.Abstraction.Repositories;
using BotSharp.Abstraction.Translation;
using BotSharp.OpenAPI.ViewModels.Translations;
@ -21,8 +22,8 @@ public class TranslationController : ControllerBase
[HttpPost("/translate")]
public async Task<TranslationResponseModel> Translate([FromBody] TranslationRequestModel model)
{
var agentService = _services.GetRequiredService<IAgentService>();
var agent = await agentService.LoadAgent(BuiltInAgentId.AIAssistant);
var db = _services.GetRequiredService<IBotSharpRepository>();
var agent = db.GetAgent(BuiltInAgentId.AIAssistant);
var translator = _services.GetRequiredService<ITranslationService>();
var states = _services.GetRequiredService<IConversationStateService>();
states.SetState("max_tokens", "8192");
@ -36,8 +37,8 @@ public class TranslationController : ControllerBase
[HttpPost("/translate/long-text")]
public async Task SendMessageSse([FromBody] TranslationLongTextRequestModel model)
{
var agentService = _services.GetRequiredService<IAgentService>();
var agent = await agentService.LoadAgent(BuiltInAgentId.AIAssistant);
var db = _services.GetRequiredService<IBotSharpRepository>();
var agent = db.GetAgent(BuiltInAgentId.AIAssistant);
var translator = _services.GetRequiredService<ITranslationService>();
Response.StatusCode = 200;

View file

@ -25,11 +25,11 @@ public class WelcomeHook : ConversationHookBase
public override async Task OnUserAgentConnectedInitially(Conversation conversation)
{
var agentService = _services.GetRequiredService<IAgentService>();
var agent = await agentService.LoadAgent(conversation.AgentId);
var db = _services.GetRequiredService<IBotSharpRepository>();
var agent = db.GetAgent(conversation.AgentId);
// Check if the Welcome template exists.
var welcomeTemplate = agent.Templates?.FirstOrDefault(x => x.Name == ".welcome");
var welcomeTemplate = agent?.Templates?.FirstOrDefault(x => x.Name == ".welcome");
if (welcomeTemplate != null)
{
// Render template

View file

@ -9,7 +9,7 @@ namespace BotSharp.Plugin.HttpHandler.Functions;
public class HandleHttpRequestFn : IFunctionCallback
{
public string Name => "util-http-handle_http_request";
public string Indication => "Handling http request";
public string Indication => "Give me a second, I'm taking care of it!";
private readonly IServiceProvider _services;
private readonly ILogger<HandleHttpRequestFn> _logger;

View file

@ -4,19 +4,17 @@ namespace BotSharp.Plugin.MongoStorage.Models;
public class AgentRuleMongoElement
{
public string Name { get; set; }
public string TriggerName { get; set; }
public bool Disabled { get; set; }
public string EventName { get; set; }
public string EntityType { get; set; }
public string Criteria { get; set; }
public static AgentRuleMongoElement ToMongoElement(AgentRule rule)
{
return new AgentRuleMongoElement
{
Name = rule.Name,
TriggerName = rule.TriggerName,
Disabled = rule.Disabled,
EventName = rule.EventName,
EntityType = rule.EntityType
Criteria = rule.Criteria
};
}
@ -24,10 +22,9 @@ public class AgentRuleMongoElement
{
return new AgentRule
{
Name = rule.Name,
TriggerName = rule.TriggerName,
Disabled = rule.Disabled,
EventName = rule.EventName,
EntityType = rule.EntityType
Criteria = rule.Criteria
};
}
}

View file

@ -1,5 +1,6 @@
using BotSharp.Abstraction.Files;
using BotSharp.Abstraction.Options;
using BotSharp.Abstraction.Routing;
using BotSharp.Core.Infrastructures;
using BotSharp.Plugin.Twilio.Interfaces;
using BotSharp.Plugin.Twilio.Models;
@ -49,10 +50,28 @@ namespace BotSharp.Plugin.Twilio.OutboundPhoneCallHandler.Functions
return false;
}
var convService = _services.GetRequiredService<IConversationService>();
var convStorage = _services.GetRequiredService<IConversationStorage>();
var routing = _services.GetRequiredService<IRoutingContext>();
var fileStorage = _services.GetRequiredService<IFileStorageService>();
var sessionManager = _services.GetRequiredService<ITwilioSessionManager>();
var convService = _services.GetRequiredService<IConversationService>();
var conversationId = convService.ConversationId;
// Fork conversation
var entryAgentId = routing.EntryAgentId;
var newConv = await convService.NewConversation(new Abstraction.Conversations.Models.Conversation
{
AgentId = entryAgentId,
Channel = ConversationChannel.Phone
});
var conversationId = newConv.Id;
convStorage.Append(conversationId, new RoleDialogModel(AgentRole.User, "Hi, I'm calling to check my work order quote status, please help me locate my work order number and let me know what to do next.")
{
CurrentAgentId = entryAgentId
});
convStorage.Append(conversationId, new RoleDialogModel(AgentRole.Assistant, args.InitialMessage)
{
CurrentAgentId = entryAgentId
});
// Generate audio
var completion = CompletionProvider.GetAudioCompletion(_services, "openai", "tts-1");
@ -72,7 +91,7 @@ namespace BotSharp.Plugin.Twilio.OutboundPhoneCallHandler.Functions
to: new PhoneNumber(args.PhoneNumber),
from: new PhoneNumber(_twilioSetting.PhoneNumber));
message.Content = $"The generated phone message: {args.InitialMessage}" ?? message.Content;
message.Content = $"The generated phone message: {args.InitialMessage}. \r\n[Conversation ID: {conversationId}]" ?? message.Content;
message.StopCompletion = true;
return true;
}

View file

@ -65,6 +65,7 @@ namespace BotSharp.Plugin.Twilio.Services
var httpContext = sp.GetRequiredService<IHttpContextAccessor>();
httpContext.HttpContext = new DefaultHttpContext();
httpContext.HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity());
httpContext.HttpContext.Request.Headers["X-Twilio-BotSharp"] = "LOST";
AssistantMessage reply = null;
var inputMsg = new RoleDialogModel(AgentRole.User, message.Content);
@ -75,8 +76,11 @@ namespace BotSharp.Plugin.Twilio.Services
var progressService = sp.GetRequiredService<IConversationProgressService>();
InitProgressService(message, sessionManager, progressService);
InitConversation(message, inputMsg, conv, routing);
var result = await conv.SendMessage(config.AgentId,
var conversation = await conv.GetConversation(message.ConversationId);
var agentId = string.IsNullOrWhiteSpace(conversation.AgentId) ? config.AgentId : conversation.AgentId;
var result = await conv.SendMessage(agentId,
inputMsg,
replyMessage: BuildPostbackMessageModel(conv, message),
async msg =>