Merge branch 'master' into human_agent

This commit is contained in:
Haiping Chen 2024-04-22 15:47:35 -05:00
commit 9d1525837b
20 changed files with 122 additions and 15 deletions

View file

@ -34,23 +34,28 @@ public class DialogElement
{
public DialogMetaData MetaData { get; set; }
public string Content { get; set; }
public string? SecondaryContent { get; set; }
public string? RichContent { get; set; }
public string? SecondaryRichContent { get; set; }
public DialogElement()
{
}
public DialogElement(DialogMetaData meta, string content, string? richContent = null)
public DialogElement(DialogMetaData meta, string content, string? richContent = null,
string? secondaryContent = null, string? secondaryRichContent = null)
{
MetaData = meta;
Content = content;
RichContent = richContent;
SecondaryContent = secondaryContent;
SecondaryRichContent = secondaryRichContent;
}
public override string ToString()
{
return $"{MetaData.Role}: {Content} [{MetaData.CreateTime}]";
return $"{MetaData.Role}: {Content} [{MetaData?.CreateTime}]";
}
}

View file

@ -26,6 +26,8 @@ public class RoleDialogModel : ITrackableMessage
public string Content { get; set; }
public string? SecondaryContent { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string CurrentAgentId { get; set; }
@ -57,6 +59,9 @@ public class RoleDialogModel : ITrackableMessage
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public RichContent<IRichMessage>? RichContent { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public RichContent<IRichMessage>? SecondaryRichContent { get; set; }
/// <summary>
/// Stop conversation completion
/// </summary>

View file

@ -1,12 +1,15 @@
using BotSharp.Abstraction.Messaging.Enums;
using Newtonsoft.Json;
namespace BotSharp.Abstraction.Messaging;
public interface IRichMessage
{
[JsonPropertyName("text")]
[JsonProperty("text")]
string Text { get; set; }
[JsonPropertyName("rich_type")]
[JsonProperty("rich_type")]
string RichType => RichTypeEnum.Text;
}

View file

@ -1,7 +1,10 @@
using Newtonsoft.Json;
namespace BotSharp.Abstraction.Messaging;
public interface ITemplateMessage
{
[JsonPropertyName("template_type")]
[JsonProperty("template_type")]
string TemplateType => string.Empty;
}

View file

@ -1,3 +1,6 @@
using Newtonsoft.Json;
using JsonIgnoreAttribute = System.Text.Json.Serialization.JsonIgnoreAttribute;
namespace BotSharp.Abstraction.Messaging.Models.RichContent;
public class ElementAction
@ -8,6 +11,7 @@ public class ElementAction
public string Url { get; set; }
[JsonPropertyName("webview_height_ratio")]
[JsonProperty("webview_height_ratio")]
public string WebViewHeightRatio { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]

View file

@ -1,3 +1,6 @@
using Newtonsoft.Json;
using JsonIgnoreAttribute = System.Text.Json.Serialization.JsonIgnoreAttribute;
namespace BotSharp.Abstraction.Messaging.Models.RichContent;
/// <summary>
@ -16,11 +19,14 @@ public class ElementButton
public string Payload { get; set; }
[JsonPropertyName("is_primary")]
[JsonProperty("is_primary")]
public bool IsPrimary { get; set; }
[JsonPropertyName("is_secondary")]
[JsonProperty("is_secondary")]
public bool IsSecondary { get; set; }
[JsonPropertyName("post_action_disclaimer")]
[JsonProperty("post_action_disclaimer")]
public string? PostActionDisclaimer { get; set; }
}

View file

@ -1,3 +1,6 @@
using Newtonsoft.Json;
using JsonIgnoreAttribute = System.Text.Json.Serialization.JsonIgnoreAttribute;
namespace BotSharp.Abstraction.Messaging.Models.RichContent;
public class QuickReplyElement
@ -9,6 +12,7 @@ public class QuickReplyElement
public string? Payload { get; set; }
[JsonPropertyName("image_url")]
[JsonProperty("image_url")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? ImageUrl { get; set; }
}

View file

@ -1,13 +1,16 @@
using BotSharp.Abstraction.Messaging.Enums;
using Newtonsoft.Json;
namespace BotSharp.Abstraction.Messaging.Models.RichContent;
public class QuickReplyMessage : IRichMessage
{
[JsonPropertyName("rich_type")]
[JsonProperty("rich_type")]
public string RichType => RichTypeEnum.QuickReply;
public string Text { get; set; } = string.Empty;
[JsonPropertyName("quick_replies")]
[JsonProperty("quick_replies")]
public List<QuickReplyElement> QuickReplies { get; set; } = new List<QuickReplyElement>();
}

View file

@ -1,4 +1,5 @@
using BotSharp.Abstraction.Messaging.Enums;
using Newtonsoft.Json;
namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template;
@ -8,17 +9,22 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template;
public class ButtonTemplateMessage : IRichMessage, ITemplateMessage
{
[JsonPropertyName("rich_type")]
[JsonProperty("rich_type")]
public string RichType => RichTypeEnum.ButtonTemplate;
[JsonPropertyName("text")]
[JsonProperty("text")]
public string Text { get; set; } = string.Empty;
[JsonPropertyName("template_type")]
[JsonProperty("template_type")]
public string TemplateType => TemplateTypeEnum.Button;
[JsonPropertyName("buttons")]
[JsonProperty("buttons")]
public ElementButton[] Buttons { get; set; } = new ElementButton[0];
[JsonPropertyName("is_horizontal")]
[JsonProperty("is_horizontal")]
public bool IsHorizontal { get; set; }
}

View file

@ -1,4 +1,5 @@
using BotSharp.Abstraction.Messaging.Enums;
using Newtonsoft.Json;
namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template;
@ -9,30 +10,40 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template;
public class CouponTemplateMessage : IRichMessage, ITemplateMessage
{
[JsonPropertyName("rich_type")]
[JsonProperty("rich_type")]
public string RichType => RichTypeEnum.CouponTemplate;
[JsonPropertyName("text")]
[JsonProperty("text")]
public string Text { get; set; }
public string Title { get; set; }
public string Subtitle { get; set; }
[JsonPropertyName("template_type")]
[JsonProperty("template_type")]
public string TemplateType => TemplateTypeEnum.Coupon;
[JsonPropertyName("coupon_code")]
[JsonProperty("coupon_code")]
public string CouponCode { get; set; }
[JsonPropertyName("coupon_url")]
[JsonProperty("coupon_url")]
public string CouponUrl { get; set; }
[JsonPropertyName("coupon_url_button_title")]
[JsonProperty("coupon_url_button_title")]
public string CouponUrlButtonTitle { get; set; } = "Shop now";
[JsonPropertyName("coupon_pre_message")]
[JsonProperty("coupon_pre_message")]
public string CouponPreMessage { get; set; } = "Here's a deal just for you!";
[JsonPropertyName("image_url")]
[JsonProperty("image_url")]
public string ImageUrl { get; set; }
[JsonPropertyName("payload")]
[JsonProperty("payload")]
public string Payload { get; set; }
}

View file

@ -1,28 +1,36 @@
using BotSharp.Abstraction.Messaging.Enums;
using Newtonsoft.Json;
namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template;
public class GenericTemplateMessage<T> : IRichMessage, ITemplateMessage
{
[JsonPropertyName("rich_type")]
[JsonProperty("rich_type")]
public string RichType => RichTypeEnum.GenericTemplate;
[JsonPropertyName("text")]
[JsonProperty("text")]
public string Text { get; set; } = string.Empty;
[JsonPropertyName("template_type")]
[JsonProperty("template_type")]
public virtual string TemplateType { get; set; } = TemplateTypeEnum.Generic;
[JsonPropertyName("elements")]
[JsonProperty("elements")]
public List<T> Elements { get; set; } = new List<T>();
[JsonPropertyName("is_horizontal")]
[JsonProperty("is_horizontal")]
public bool IsHorizontal { get; set; }
[JsonPropertyName("is_popup")]
[JsonProperty("is_popup")]
public bool IsPopup { get; set; }
[JsonPropertyName("element_type")]
[JsonProperty("element_type")]
public string ElementType => typeof(T).Name;
}
@ -30,9 +38,13 @@ public class GenericElement
{
public string Title { get; set; }
public string Subtitle { get; set; }
[JsonPropertyName("image_url")]
[JsonProperty("image_url")]
public string ImageUrl { get; set; }
[JsonPropertyName("default_action")]
[JsonProperty("default_action")]
public ElementAction DefaultAction { get; set; }
public ElementButton[] Buttons { get; set; }
}

View file

@ -1,21 +1,28 @@
using BotSharp.Abstraction.Messaging.Enums;
using Newtonsoft.Json;
namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template;
public class MultiSelectTemplateMessage : IRichMessage, ITemplateMessage
{
[JsonPropertyName("rich_type")]
[JsonProperty("rich_type")]
public string RichType => RichTypeEnum.MultiSelectTemplate;
[JsonPropertyName("text")]
[JsonProperty("text")]
public string Text { get; set; } = string.Empty;
[JsonPropertyName("template_type")]
[JsonProperty("template_type")]
public string TemplateType => TemplateTypeEnum.MultiSelect;
[JsonPropertyName("options")]
[JsonProperty("options")]
public List<OptionElement> Options { get; set; } = new List<OptionElement>();
[JsonPropertyName("is_horizontal")]
[JsonProperty("is_horizontal")]
public bool IsHorizontal { get; set; }
}

View file

@ -1,16 +1,20 @@
using BotSharp.Abstraction.Messaging.Enums;
using Newtonsoft.Json;
namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template;
public class ProductTemplateMessage : IRichMessage, ITemplateMessage
{
[JsonPropertyName("rich_type")]
[JsonProperty("rich_type")]
public string RichType => RichTypeEnum.GenericTemplate;
[JsonPropertyName("text")]
[JsonProperty("text")]
public string Text { get; set; } = string.Empty;
[JsonPropertyName("template_type")]
[JsonProperty("template_type")]
public string TemplateType => TemplateTypeEnum.Product;
}

View file

@ -1,10 +1,12 @@
using BotSharp.Abstraction.Messaging.Enums;
using Newtonsoft.Json;
namespace BotSharp.Abstraction.Messaging.Models.RichContent;
public class TextMessage : IRichMessage
{
[JsonPropertyName("rich_type")]
[JsonProperty("rich_type")]
public string RichType => RichTypeEnum.Text;
public string Text { get; set; } = string.Empty;

View file

@ -50,7 +50,7 @@ public class ConversationStorage : IConversationStorage
{
return;
}
dialogElements.Add(new DialogElement(meta, content));
dialogElements.Add(new DialogElement(meta, content, dialog.SecondaryContent));
}
else
{
@ -71,7 +71,8 @@ public class ConversationStorage : IConversationStorage
}
var richContent = dialog.RichContent != null ? JsonSerializer.Serialize(dialog.RichContent, _options.JsonSerializerOptions) : null;
dialogElements.Add(new DialogElement(meta, content, richContent));
var secondaryRichContent = dialog.SecondaryRichContent != null ? JsonSerializer.Serialize(dialog.SecondaryRichContent, _options.JsonSerializerOptions) : null;
dialogElements.Add(new DialogElement(meta, content, richContent, dialog.SecondaryContent, secondaryRichContent));
}
db.AppendConversationDialogs(conversationId, dialogElements);
@ -88,6 +89,7 @@ public class ConversationStorage : IConversationStorage
{
var meta = dialog.MetaData;
var content = dialog.Content;
var secondaryContent = dialog.SecondaryContent;
var role = meta.Role;
var currentAgentId = meta.AgentId;
var messageId = meta.MessageId;
@ -96,6 +98,8 @@ public class ConversationStorage : IConversationStorage
var createdAt = meta.CreateTime;
var richContent = !string.IsNullOrEmpty(dialog.RichContent) ?
JsonSerializer.Deserialize<RichContent<IRichMessage>>(dialog.RichContent, _options.JsonSerializerOptions) : null;
var secondaryRichContent = !string.IsNullOrEmpty(dialog.SecondaryRichContent) ?
JsonSerializer.Deserialize<RichContent<IRichMessage>>(dialog.SecondaryRichContent, _options.JsonSerializerOptions) : null;
var record = new RoleDialogModel(role, content)
{
@ -104,7 +108,9 @@ public class ConversationStorage : IConversationStorage
CreatedAt = createdAt,
SenderId = senderId,
FunctionName = function,
RichContent = richContent
RichContent = richContent,
SecondaryContent = secondaryContent,
SecondaryRichContent = secondaryRichContent,
};
results.Add(record);

View file

@ -5,7 +5,6 @@ using System.Drawing;
using System.IO;
using System.Reflection;
using System.Xml;
using BotSharp.Abstraction.Repositories;
namespace BotSharp.Core.Plugins;

View file

@ -506,11 +506,14 @@ namespace BotSharp.Core.Repository
var rawDialogs = File.ReadAllLines(dialogDir);
if (!rawDialogs.IsNullOrEmpty())
{
for (int i = 0; i < rawDialogs.Count(); i += 2)
for (int i = 0; i < rawDialogs.Count(); i += 5)
{
var blocks = rawDialogs[i].Split("|");
var content = rawDialogs[i + 1];
var trimmed = content.Substring(4);
var content = rawDialogs[i + 2];
var trimmedContent = content.Substring(4);
var secondaryContent = rawDialogs[i + 4];
var trimmedSecondaryContent = secondaryContent.Substring(4);
var meta = new DialogMetaData
{
Role = blocks[1],
@ -521,8 +524,9 @@ namespace BotSharp.Core.Repository
CreateTime = DateTime.Parse(blocks[0])
};
var richContent = blocks.Count() > 6 ? DecodeRichContent(blocks[6]) : null;
dialogs.Add(new DialogElement(meta, trimmed, richContent));
var richContent = DecodeRichContent(rawDialogs[i + 1]);
var secondaryRichContent = DecodeRichContent(rawDialogs[i + 3]);
dialogs.Add(new DialogElement(meta, trimmedContent, richContent, trimmedSecondaryContent, secondaryRichContent));
}
}
return dialogs;
@ -538,10 +542,17 @@ namespace BotSharp.Core.Repository
var meta = element.MetaData;
var createTime = meta.CreateTime.ToString("MM/dd/yyyy hh:mm:ss.ffffff tt", CultureInfo.InvariantCulture);
var encodedRichContent = EncodeRichContent(element.RichContent);
var metaStr = $"{createTime}|{meta.Role}|{meta.AgentId}|{meta.MessageId}|{meta.SenderId}|{meta.FunctionName}|{encodedRichContent}";
var encodedSecondaryRichContent = EncodeRichContent(element.SecondaryRichContent);
var metaStr = $"{createTime}|{meta.Role}|{meta.AgentId}|{meta.MessageId}|{meta.SenderId}|{meta.FunctionName}";
dialogTexts.Add(metaStr);
dialogTexts.Add(encodedRichContent);
var content = $" - {element.Content}";
dialogTexts.Add(content);
dialogTexts.Add(encodedSecondaryRichContent);
var secondaryContent = $" - {element.SecondaryContent}";
dialogTexts.Add(secondaryContent);
}
return dialogTexts;

View file

@ -84,6 +84,7 @@ public class ConversationController : ControllerBase
MessageId = message.MessageId,
CreatedAt = message.CreatedAt,
Text = message.Content,
SecondaryText = message.SecondaryContent,
Data = message.Data,
Sender = UserViewModel.FromUser(user)
});
@ -97,6 +98,7 @@ public class ConversationController : ControllerBase
MessageId = message.MessageId,
CreatedAt = message.CreatedAt,
Text = message.Content,
SecondaryText = message.SecondaryContent,
Function = message.FunctionName,
Data = message.Data,
Sender = new UserViewModel
@ -104,7 +106,8 @@ public class ConversationController : ControllerBase
FirstName = agent.Name,
Role = message.Role,
},
RichContent = message.RichContent
RichContent = message.RichContent,
SecondaryRichContent = message.SecondaryRichContent
});
}
}

View file

@ -21,6 +21,9 @@ public class ChatResponseModel : InstructResult
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public FunctionCallFromLlm? Instruction { get; set; }
[JsonPropertyName("secondary_text")]
public string? SecondaryText { get; set; }
/// <summary>
/// Rich message for UI rendering
/// </summary>
@ -28,6 +31,10 @@ public class ChatResponseModel : InstructResult
[JsonPropertyName("rich_content")]
public RichContent<IRichMessage>? RichContent { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("secondary_rich_content")]
public RichContent<IRichMessage>? SecondaryRichContent { get; set; }
[JsonPropertyName("created_at")]
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}

View file

@ -6,7 +6,9 @@ public class DialogMongoElement
{
public DialogMetaDataMongoElement MetaData { get; set; }
public string Content { get; set; }
public string? SecondaryContent { get; set; }
public string? RichContent { get; set; }
public string? SecondaryRichContent { get; set; }
public DialogMongoElement()
{
@ -19,7 +21,9 @@ public class DialogMongoElement
{
MetaData = DialogMetaDataMongoElement.ToMongoElement(dialog.MetaData),
Content = dialog.Content,
RichContent = dialog.RichContent
SecondaryContent = dialog.SecondaryContent,
RichContent = dialog.RichContent,
SecondaryRichContent = dialog.SecondaryRichContent
};
}
@ -29,7 +33,9 @@ public class DialogMongoElement
{
MetaData = DialogMetaDataMongoElement.ToDomainElement(dialog.MetaData),
Content = dialog.Content,
RichContent = dialog.RichContent
SecondaryContent = dialog.SecondaryContent,
RichContent = dialog.RichContent,
SecondaryRichContent = dialog.SecondaryRichContent
};
}
}