在Cosmos DB中管理状态,而不是在Bot到Human切换场景的内存中进行管理 [英] Manage state in Cosmos DB instead of in-memory for Bot to Human handover scenario

查看:34
本文介绍了在Cosmos DB中管理状态,而不是在Bot到Human切换场景的内存中进行管理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个具有人类交接功能(人类2到人类聊天)的机器人,该机器人负责整个通信.用户可以开始与bot通信,如果他对bot的响应不满意,可以向Human寻求进一步的帮助.

I am working on a bot with human handover features (Human-2-Human chat), where bot is in charge of whole communication. The user can start the communication with bot and if he is not satisfied by bot's responses, he can ask for further assistance from Human.

Bot可以使用第三方系统将用户连接到实时代理.Bot将消息从对话框与回调URL一起从对话框转发到该系统的API端点.该第三方系统使用回调机制来传递代理在此指定的url上编写的消息.

Bot is able to connect the user to a live Agent using a Third Party System. Bot forwards the message from a dialog to an API endpoint of this system along with a callback url. This third party system uses a callback mechanism to pass the message written by agent on this specified url.

我创建了一个API Controller端点,并将其作为回调URL传递给该系统.当代理发送消息时,系统会在此端点上进行通知.它是简单的Web API控制器,与Bot Framework没有直接关联.

I have created an API Controller endpoint and pass to this system as callback url. When agent sends a message the system notifies on this endpoint. It is simple Web API controller with no direct affiliation to Bot Framework.

尽管我在Cosmos DB中维护该机器人的对话和用户状态,并且它具有某些属性,其中包含聊天连接的状态,例如(ChatConnected,ChatClosed等).现在要将这些消息通知传递给bot,我维护两个并发字典,一个用于会话引用",另一个用于"TurnContext".

Although I maintain a Conversation and User State of the bot in Cosmos DB and it has certain properties that contain status of chat connection like (ChatConnected, ChatClosed etc). Now to pass these message notifications to bot I maintain two concurrent dictionary one for Conversation Reference and second for TurnContext.

  • 对话参考有助于使用ContinueConversationAsync将代理消息从机器人传递给用户.

  • Conversation Reference helps to pass the agent message from bot to user using ContinueConversationAsync.

TurnContext有助于在会话关闭等情况下管理和更新这些属性的状态.由于上一回合具有活动时间戳记,因此在闲置一定时间后还可以使用它来发送消息.

TurnContext helps to manage and update the state of these properties when session closed etc. And also use it to send message after certain period of inactivity since last turn has activity timestamp.

现在这两个都在内存中,这意味着它们在创建新的聊天会话和交换更多消息时被添加和删除.我现在想将其从内存中移到共享缓存或低延迟的宇宙中.这样,我还可以在需要时使用自动缩放新的bot服务实例的可能性.我正在使用appservices.但是由于这种耦合,新实例无法访问内存中的数据,因此无法使用.我认为为Bot情景启用AffinityCookie确实不起作用.

Now both of these are in-memory, which means they are added and removed as new chat sessions are created and as more messages are exchanged. I now want to move this out from in-memory to a shared cache or low latency cosmos. So that I can also use the possibility of auto-scaling new instances of bot service when required. I am using appservices currenly. But due to this coupling new instances don't have access to in-memory data, and therefore can not service. I don't think that enabling AffinityCookie for Bot Scenarios actually works.

我能够序列化ConversationReference对象(通过NewtonSoft),但是由于对象内部循环,序列化TurnContext会引发JSON序列化异常.我试图通过SerilizationSettings忽略循环来缓解这种情况,但是在调试期间VS堆栈溢出异常,它甚至无法在VS中工作.

I am able to serialize the ConversationReference object (through NewtonSoft), but serializing TurnContext throws JSON serialization exception due to internal loop in object. I tried to mitigate that with SerilizationSettings to ignore loop but it does not even works in VS during debugging throws VS stack overflow exception.

那么我该如何移动代码以使其独立于实例上的单例ConcurrentDictionary-

So how can I move this code to become independent of singleton ConcurrentDictionary on an instance-

private readonly ConcurrentDictionary<string, ITurnContext> TurnContextReferences;


private void AddTurnContext(ITurnContext turnContext, string sessionId)
        {
            if (turnContext != null && !string.IsNullOrWhiteSpace(sessionId))
            {
                //Add the Session Id and TurnContext to dictionary
                TurnContextReferences.AddOrUpdate(sessionId, turnContext, (key, newValue) => turnContext);
            }
        }

//Using above method inside a function
//Trim the incoming message
                    var userMessage = messageActivity.Text.Trim();
                    if (!string.IsNullOrWhiteSpace(userMessage))
                    {
                        //send the incoming message from client to Agent
                        await TPSystem.SendMessageAsync(messageActivity.Conversation.Id, conversationData.SessionId, messageActivity.Text.Trim());
                        
                    }
                    //Add to Turn context Dictionary
                    AddTurnContext(stepContext.Context, conversationData.SessionId);

//Inside API Controller
 //Get the TurnContext from the Dictionary
                            TurnContextReferences.TryGetValue(sessionStateChangedEventData.SessionId, out ITurnContext turnContext);

                            if (turnContext != null)
                            {
                                var conversationData = await BotStateAccessors.ConversationStateAccessor.GetAsync(turnContext, () => new ConversationStateDataModel());
                                if (!conversationData.LiveAgentChatClosed)
                                {
                                    conversationData.LiveAgentChatClosed = true;
                                    await BotStateAccessors.ConversationStateAccessor.SetAsync(turnContext, conversationData);
                                    await BotConversationState.SaveChangesAsync(turnContext);
                                }
                            }

任何需要深思的想法都会受到赞赏.

Any ideas to think through would be appreciated.

推荐答案

对话参考包含活动中信息的子集,而活动只是转弯上下文的一个属性,因此对话参考中包含信息的子集在转弯的背景下.同时保存对话引用和转弯上下文是多余的,因为如果保存转弯上下文,则您将已经获得了对话引用中的所有信息.

Conversation references contain a subset of the information in activities, and an activity is just one property of a turn context, so a conversation reference contains a subset of the information in a turn context. It's redundant to be saving both conversation references and turn contexts because if you save turn contexts then you'll already have all the information from the conversation references.

也就是说,尝试保存转弯上下文是一个非常糟糕的主意.如果您需要对话参考中未包含的某些信息,则只需保存该特定信息即可.例如,您可以创建自己的类,其中包含对话引用和时间戳,该时间戳表示该对话中最后一条消息的时间.

That said, it's a very bad idea to try to save turn contexts. If you need some pieces of information that aren't in the conversation references then just save that specific information. For example, you can create your own class that contains a conversation reference and a timestamp that signifies the time of the last message from that conversation.

public class ConversationInfo
{
    [JsonProperty(PropertyName = "conversationReference")]
    public ConversationReference ConversationReference { get; set; }

    [JsonProperty(PropertyName = "timestamp")]
    public DateTimeOffset Timestamp { get; set; }
}

这篇关于在Cosmos DB中管理状态,而不是在Bot到Human切换场景的内存中进行管理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆