Merge pull request #188 from hchen2020/master

Add SelfId to IAgentHook.
This commit is contained in:
Haiping 2023-10-24 16:40:01 -05:00 committed by GitHub
commit 41a0b35b7b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 191 additions and 6 deletions

154
docs/channels/components.md Normal file
View file

@ -0,0 +1,154 @@
# Messaging Components
Conversations are a lot more than simple text messages when you are building a AI chatbot. In addition to text, the `BotSharp`` allows you to send rich-media, like audio, video, and images, and provides a set of structured messaging options in the form of message templates, quick replies, buttons and more. The UI rendering program can render components according to the returned data format.
## Text Messages
```json
{
"recipient":{
"id":"{{conversation_id}}"
},
"messaging_type": "RESPONSE",
"message":{
"text":"Hello, world!"
}
}
```
## Quick Replies
`content_type`: Text, Phone Number and Email
```json
{
"recipient":{
"id":"{{conversation_id}}"
},
"messaging_type": "RESPONSE",
"message":{
"text": "Pick a color:",
"quick_replies":[
{
"content_type":"text",
"title":"Red",
"payload":"<POSTBACK_PAYLOAD>",
"image_url":"http://example.com/img/red.png"
},{
"content_type":"text",
"title":"Green",
"payload":"<POSTBACK_PAYLOAD>",
"image_url":"http://example.com/img/green.png"
}
]
}
}
```
## Sender Actions
Setting expectations is crucial when creating a chatbot. Sender actions, a key tool, allow you to control typing and read receipt indicators. For instance, you can use them to show when a message has been seen or when a response is being typed, keeping users informed during interactions.
`sender_action`: mark_seen, typing_on and typing_off
```json
{
"recipient":{
"id":"{{conversation_id}}"
},
"sender_action":"typing_on"
}
```
## Message Templates
Message templates are structured message formats used for various purposes to present complex information in a tidy manner during conversations, preventing messy text. These templates also include buttons to enhance interactivity. It gives a way for you to offer a richer in-conversation experience than standard text messages by integrating buttons, images, lists, and more alongside text a single message. Templates can be use for many purposes, such as displaying product information, asking the message recipient to choose from a pre-determined set of options, and showing search results.
```json
{
"recipient":{
"id":"{{conversation_id}}"
},
"message":{
"attachment":{
"type":"template",
"payload":{
"template_type":"TEMPLATE-TYPE",
"elements":[
{
"title":"TEMPLATE-TITLE",
...
}
]
}
}
}
}
```
### Button template
The button template sends a text message with up to three attached buttons. This template is useful for offering the message recipient options to choose from, such as pre-determined responses to a question, or actions to take.
`type`: web_url, postback, phone_number, account_link (log in), account_unlink (log out)
```json
{
"template_type":"button",
"text":"What do you want to do next?",
"buttons":[
{
"type":"web_url",
"url":"https://www.github.com",
"title":"Visit Github"
},
{
"type":"postback",
"title":"Visit Github",
"payload": "<STRING_SENT_TO_WEBHOOK>"
},
{
"type":"phone_number",
"title":"<BUTTON_TEXT>",
"payload":"<PHONE_NUMBER>"
},
{
"type": "account_link",
"url": "<YOUR_LOGIN_URL>"
},
{
"type": "account_unlink"
}
]
}
```
### Generic template
The generic template is a simple structured message that includes a title, subtitle, image, and up to three buttons. You may also specify a `default_action` object that sets a URL that will be opened in the chat webview when the template is tapped.
```json
{
"template_type":"generic",
"elements":[
{
"title":"Welcome!",
"image_url":"https://raw.githubusercontent.com/fbsamples/original-coast-clothing/main/public/styles/male-work.jpg",
"subtitle":"We have the right hat for everyone.",
"default_action": {
"type": "web_url",
"url": "https://www.originalcoastclothing.com/",
"webview_height_ratio": "tall"
},
"buttons":[
{
"type":"web_url",
"url":"https://www.originalcoastclothing.com/",
"title":"View Website"
}
]
}
]
}
```
### Form template
Form template is used to collect information from the user side, and the UI allows users to fill in a structured form.
### Customer Feedback Template

View file

@ -66,6 +66,7 @@ The main documentation for the site is organized into the following sections:
:caption: Interactive Channels
channels/intro
channels/components
channels/messenger
channels/wechat

View file

@ -5,6 +5,8 @@ namespace BotSharp.Abstraction.Agents;
public abstract class AgentHookBase : IAgentHook
{
public virtual string SelfId => throw new NotImplementedException("Please set SelfId as agent id!");
protected Agent _agent;
public Agent Agent => _agent;

View file

@ -4,6 +4,10 @@ namespace BotSharp.Abstraction.Agents;
public interface IAgentHook
{
/// <summary>
/// Agent Id
/// </summary>
string SelfId { get; }
Agent Agent { get; }
void SetAget(Agent agent);

View file

@ -31,4 +31,8 @@
<PackageReference Include="System.Text.Json" Version="7.0.3" />
</ItemGroup>
<ItemGroup>
<Folder Include="Messaging\Models\" />
</ItemGroup>
</Project>

View file

@ -5,7 +5,7 @@ namespace BotSharp.Abstraction.Functions.Models;
public class FunctionParametersDef
{
[JsonPropertyName("type")]
public string Type { get; set; } = "object";
public string Type { get; set; } = "string";
/// <summary>
/// ParameterPropertyDef

View file

@ -13,7 +13,7 @@ public class RoutingRule
/// <summary>
/// Field type: string, number, object
/// </summary>
public string Type { get; set; }
public string Type { get; set; } = "string";
public bool Required { get; set; }

View file

@ -15,6 +15,11 @@ public partial class AgentService
// Before agent is loaded.
foreach (var hook in hooks)
{
if (!string.IsNullOrEmpty(hook.SelfId) && hook.SelfId != id)
{
continue;
}
hook.OnAgentLoading(ref id);
}
@ -30,6 +35,11 @@ public partial class AgentService
// After agent is loaded
foreach (var hook in hooks)
{
if (!string.IsNullOrEmpty(hook.SelfId) && hook.SelfId != id)
{
continue;
}
hook.SetAget(agent);
if (!string.IsNullOrEmpty(agent.Instruction))

View file

@ -31,13 +31,13 @@ public class EvaluationConversationHook : ConversationHookBase
public override Task OnHumanInterventionNeeded(RoleDialogModel message)
{
_logger.Append(_conversation.Id, $"[{DateTime.Now}] {AgentRole.Function}: trigger event \"{message.FunctionName}\"");
_logger.Append(_conversation.Id, $"[{DateTime.Now}] {AgentRole.Function}: trigger_event({{\"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}\"");
_logger.Append(_conversation.Id, $"[{DateTime.Now}] {AgentRole.Function}: trigger_event({{\"event\": \"{message.FunctionName}\"}})");
return base.OnConversationEnding(message);
}
}

View file

@ -1,5 +1,6 @@
using BotSharp.Abstraction.Evaluations;
using BotSharp.Abstraction.Repositories;
using System.Text.RegularExpressions;
namespace BotSharp.Core.Evaluations;
@ -17,6 +18,8 @@ public class ExecutionLogger : IExecutionLogger
public void Append(string conversationId, string content)
{
content = content.Replace("\r\n", " ").Replace("\n", " ");
content = Regex.Replace(content, @"\s+", " ");
var db = _services.GetRequiredService<IBotSharpRepository>();
db.AddExectionLogs(conversationId, new List<string> { content });
}

View file

@ -1,13 +1,18 @@
using BotSharp.Abstraction.Functions.Models;
using BotSharp.Abstraction.Routing;
using BotSharp.Abstraction.Routing.Settings;
namespace BotSharp.Core.Routing.Hooks;
public class RoutingAgentHook : AgentHookBase
{
public RoutingAgentHook(IServiceProvider services, AgentSettings settings)
private readonly RoutingSettings _routingSetting;
public override string SelfId => _routingSetting.RouterId;
public RoutingAgentHook(IServiceProvider services, AgentSettings settings, RoutingSettings routingSetting)
: base(services, settings)
{
_routingSetting = routingSetting;
}
public override bool OnInstructionLoaded(string template, Dictionary<string, object> dict)

View file

@ -1,4 +1,5 @@
using BotSharp.Abstraction.Agents.Models;
using BotSharp.Abstraction.MLTasks.Settings;
using BotSharp.Abstraction.Templating;
namespace BotSharp.Core.Routing;
@ -19,7 +20,8 @@ public partial class RoutingService
var agentService = _services.GetRequiredService<IAgentService>();
var agent = await agentService.LoadAgent(agentId);
var chatCompletion = CompletionProvider.GetChatCompletion(_services);
var settings = _services.GetRequiredService<ChatCompletionSetting>();
var chatCompletion = CompletionProvider.GetChatCompletion(_services, provider: settings.Provider, model: settings.Model);
RoleDialogModel response = chatCompletion.GetChatCompletions(agent, Dialogs);
if (response.Role == AgentRole.Function)