Support Messenger quick reply.

This commit is contained in:
hchen 2023-08-20 17:53:53 -05:00
parent b402aa9e91
commit b68c311acb
9 changed files with 85 additions and 26 deletions

View file

@ -24,7 +24,8 @@ public partial class ConversationService
_logger.LogError($"Exceed max current recursive depth.");
await HandleAssistantMessage(new RoleDialogModel(AgentRole.Assistant, "System has exception, please try later.")
{
CurrentAgentId = agent.Id
CurrentAgentId = agent.Id,
Channel = wholeDialogs.Last().Channel
}, onMessageReceived);
return false;
}
@ -46,7 +47,8 @@ public partial class ConversationService
{
await HandleAssistantMessage(new RoleDialogModel(AgentRole.Assistant, fn.Content)
{
CurrentAgentId = fn.CurrentAgentId
CurrentAgentId = fn.CurrentAgentId,
Channel = fn.Channel
}, onMessageReceived);
return;
}

View file

@ -28,6 +28,7 @@ public partial class ConversationService
var stateService = _services.GetRequiredService<IConversationStateService>();
stateService.SetConversation(conversationId);
stateService.Load();
stateService.SetState("channel", lastDialog.Channel);
var router = _services.GetRequiredService<IAgentRouting>();
var agent = await router.LoadRouter();
@ -35,9 +36,11 @@ public partial class ConversationService
_logger.LogInformation($"[{agent.Name}] {lastDialog.Role}: {lastDialog.Content}");
lastDialog.CurrentAgentId = agent.Id;
_storage.Append(conversationId, agent.Id, lastDialog);
var wholeDialogs = GetDialogHistory(conversationId);
wholeDialogs.Add(lastDialog);
_storage.Append(conversationId, agent.Id, lastDialog);
// Get relevant domain knowledge
/*if (_settings.EnableKnowledgeBase)

View file

@ -48,7 +48,10 @@ public class ConversationController : ControllerBase, IApiAdapter
var stackMsg = new List<RoleDialogModel>();
await conv.SendMessage(agentId, conversationId,
new RoleDialogModel("user", input.Text),
new RoleDialogModel("user", input.Text)
{
Channel = "webapi"
},
async msg =>
{
stackMsg.Add(msg);

View file

@ -104,7 +104,8 @@ public class ChatCompletionProvider : IChatCompletion
{
CurrentAgentId = agent.Id,
FunctionName = message.FunctionCall.Name,
FunctionArgs = message.FunctionCall.Arguments
FunctionArgs = message.FunctionCall.Arguments,
Channel = conversations.Last().Channel
};
// Execute functions
@ -116,7 +117,8 @@ public class ChatCompletionProvider : IChatCompletion
var msg = new RoleDialogModel(AgentRole.Assistant, message.Content)
{
CurrentAgentId= agent.Id
CurrentAgentId= agent.Id,
Channel = conversations.Last().Channel
};
// Text response received

View file

@ -64,7 +64,10 @@ public class ChatbotUiController : ControllerBase, IApiAdapter
var conversation = input.Messages
.Where(x => x.Role == AgentRole.User)
.Select(x => new RoleDialogModel(x.Role, x.Content))
.Select(x => new RoleDialogModel(x.Role, x.Content)
{
Channel = "webchat"
})
.Last();
var conversationService = _services.GetRequiredService<IConversationService>();

View file

@ -15,7 +15,7 @@ using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Refit;
using BotSharp.Abstraction.Agents.Enums;
using Microsoft.Extensions.Logging;
namespace BotSharp.Plugin.MetaMessenger.Controllers;
@ -27,10 +27,12 @@ namespace BotSharp.Plugin.MetaMessenger.Controllers;
public class WebhookController : ControllerBase
{
private readonly IServiceProvider _services;
private readonly ILogger _logger;
public WebhookController(IServiceProvider services)
public WebhookController(IServiceProvider services, ILogger<WebhookController> logger)
{
_services = services;
_logger = logger;
}
[HttpGet("/messenger/webhook/{agentId}")]
@ -67,7 +69,7 @@ public class WebhookController : ControllerBase
{
var conv = _services.GetRequiredService<IConversationService>();
string content = "";
var reply = new QuickReplyMessage();
var senderId = req.Entry[0].Messaging[0].Sender.Id;
var input = req.Entry[0].Messaging[0].Message.Text;
@ -78,11 +80,13 @@ public class WebhookController : ControllerBase
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
var recipient = JsonSerializer.Serialize(new { Id = senderId }, jsonOpt);
// Marking seen
await messenger.SendMessage(setting.ApiVersion, setting.PageId, new SendingMessageRequest
{
AccessToken = setting.PageAccessToken,
Recipient = JsonSerializer.Serialize(new { Id = senderId }, jsonOpt),
Recipient = recipient,
SenderAction = SenderActionEnum.MarkSeen
});
@ -90,7 +94,7 @@ public class WebhookController : ControllerBase
await messenger.SendMessage(setting.ApiVersion, setting.PageId, new SendingMessageRequest
{
AccessToken = setting.PageAccessToken,
Recipient = JsonSerializer.Serialize(new { Id = senderId }, jsonOpt),
Recipient = recipient,
SenderAction = SenderActionEnum.TypingOn
});
@ -100,11 +104,7 @@ public class WebhookController : ControllerBase
Channel = "messenger"
}, async msg =>
{
if (msg.Role == AgentRole.Function)
{
}
content = msg.Content;
reply.Text = msg.Content;
}, async functionExecuting =>
{
/*await messenger.SendMessage(setting.ApiVersion, setting.PageId, new SendingMessageRequest
@ -116,27 +116,36 @@ public class WebhookController : ControllerBase
}, async functionExecuted =>
{
// Render structured data
/*await messenger.SendMessage(setting.ApiVersion, setting.PageId, new SendingMessageRequest
if (functionExecuted.ExecutionData != null)
{
AccessToken = setting.PageAccessToken,
Recipient = JsonSerializer.Serialize(new { Id = senderId }, jsonOpt),
SenderAction = SenderActionEnum.TypingOn
});*/
// validate data format
var json = JsonSerializer.Serialize(functionExecuted.ExecutionData, jsonOpt);
try
{
var parsed = JsonSerializer.Deserialize<QuickReplyMessageItem[]>(json, jsonOpt);
reply.QuickReplies = parsed;
}
catch(Exception ex)
{
_logger.LogError(ex, ex.Message);
}
}
});
// Response to user
await messenger.SendMessage(setting.ApiVersion, setting.PageId, new SendingMessageRequest
{
AccessToken = setting.PageAccessToken,
Recipient = JsonSerializer.Serialize(new { Id = senderId }, jsonOpt),
Message = JsonSerializer.Serialize(new { Text = content }, jsonOpt)
Recipient = recipient,
Message = JsonSerializer.Serialize(reply, jsonOpt)
});
// Typing off
await messenger.SendMessage(setting.ApiVersion, setting.PageId, new SendingMessageRequest
{
AccessToken = setting.PageAccessToken,
Recipient = JsonSerializer.Serialize(new { Id = senderId }, jsonOpt),
Recipient = recipient,
SenderAction = SenderActionEnum.TypingOff
});
}

View file

@ -0,0 +1,16 @@
using System.Text.Json.Serialization;
namespace BotSharp.Plugin.MetaMessenger.MessagingModels;
/// <summary>
/// Quick Replies
/// https://developers.facebook.com/docs/messenger-platform/send-messages/quick-replies
/// </summary>
public class QuickReplyMessage
{
[JsonPropertyName("text")]
public string Text { get; set; }
[JsonPropertyName("quick_replies")]
public QuickReplyMessageItem[] QuickReplies { get; set; }
}

View file

@ -0,0 +1,18 @@
using System.Text.Json.Serialization;
namespace BotSharp.Plugin.MetaMessenger.MessagingModels;
public class QuickReplyMessageItem
{
[JsonPropertyName("content_type")]
public string ContentType { get; set; } = "text";
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("payload")]
public string Payload { get; set; }
[JsonPropertyName("image_url")]
public string ImageUrl { get; set; }
}

View file

@ -1,3 +1,4 @@
using BotSharp.Plugin.MetaMessenger.MessagingModels;
using System;
using System.Collections.Generic;
using System.Text;
@ -10,4 +11,6 @@ public class WebhookMessageBody
[JsonPropertyName("mid")]
public string Id { get;set; }
public string Text { get;set; }
[JsonPropertyName("quick_reply")]
public QuickReplyMessageItem QuickReply { get;set; }
}