Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在Cosmos DB中管理状态,而不是在内存中管理机器人到人的切换场景_C#_.net Core_Botframework - Fatal编程技术网

C# 在Cosmos DB中管理状态,而不是在内存中管理机器人到人的切换场景

C# 在Cosmos DB中管理状态,而不是在内存中管理机器人到人的切换场景,c#,.net-core,botframework,C#,.net Core,Botframework,我正在开发一个具有人工切换功能(人机对话)的机器人,机器人负责整个通信。用户可以启动与bot的通信,如果他对bot的响应不满意,他可以请求人工的进一步帮助 Bot能够使用第三方系统将用户连接到实时代理。Bot将对话框中的消息与回调url一起转发到此系统的API端点。此第三方系统使用回调机制传递代理在此指定url上编写的消息 我已经创建了一个API控制器端点,并将其作为回调url传递到此系统。当代理发送消息时,系统将通知此端点。它是一个简单的WebAPI控制器,与Bot框架没有直接联系 虽然我在C

我正在开发一个具有人工切换功能(人机对话)的机器人,机器人负责整个通信。用户可以启动与bot的通信,如果他对bot的响应不满意,他可以请求人工的进一步帮助

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

我已经创建了一个API控制器端点,并将其作为回调url传递到此系统。当代理发送消息时,系统将通知此端点。它是一个简单的WebAPI控制器,与Bot框架没有直接联系

虽然我在Cosmos DB中维护了机器人的对话和用户状态,并且它有一些属性包含聊天连接状态,比如(ChatConnected、ChatClosed等)。现在,为了将这些消息通知传递给bot,我维护了两个并发字典,一个用于会话引用,另一个用于上下文

  • 会话引用有助于使用ContinueConversationAsync将代理消息从bot传递给用户

  • TurnContext有助于在会话关闭时管理和更新这些属性的状态等,还可以使用它在某个非活动期后发送消息,因为最后一个回合有活动时间戳

现在这两个都在内存中,这意味着它们会随着新聊天会话的创建和更多消息的交换而被添加和删除。我现在想把它从内存中转移到共享缓存或低延迟宇宙中。因此,我还可以在需要时使用自动扩展bot服务的新实例的可能性。我现在正在使用appservices。但由于这种耦合,新实例无法访问内存中的数据,因此无法提供服务。我不认为为机器人场景启用AffinityCookie实际上是可行的

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

那么,如何在实例上使这段代码独立于singleton ConcurrentDictionary呢-

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);
            }
        }

任何需要仔细思考的想法都将受到欢迎。

会话引用包含活动中信息的子集,而活动只是回合上下文的一个属性,因此会话引用包含回合上下文中信息的子集。保存会话引用和话轮上下文是多余的,因为如果保存话轮上下文,那么您就已经拥有了会话引用中的所有信息

也就是说,试图保存回合上下文是一个非常糟糕的主意。如果您需要一些不在会话引用中的信息,只需保存这些特定信息即可。例如,您可以创建自己的类,该类包含一个对话引用和一个时间戳,该时间戳表示来自该对话的最后一条消息的时间

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

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

h2h的意思是“人与人”还是“移交给人”还是什么?@KyleDelaney,它的意思是“人与人”,但“移交给人”也是正确的。@KyleDelaney,如果我的问题需要澄清或不清楚的话。请随意评论,我会改正的。谢谢谢谢你编辑你的问题。现在有点清楚了,但仍然很长。我不认为TJ能够看到你提到他的地方,因为他没有对这个问题发表评论,向特定的人寻求帮助通常不是一个好主意。谢谢你的回答。我知道保持turncontext并不是最好的做法,但问题是我需要更新需要turncontext的状态。这是错误的。保存状态所需的所有信息都在对话引用中。我建议你投票并接受这个答案,然后问一个新问题,解释为什么你认为你需要保存一个回合上下文来更新状态,并询问你如何在没有回合上下文的情况下更新状态。我认为ConversationReference包含使用Continue Conversation发送消息的相关信息,因为它服务URL等,但TurnContext具有实际的TurnState字典,该字典将更新并持久保存到Cosmos。另外,我不需要写一个新的状态属性或新的文档,这通常和直接写Cosmos一样好。文档中有一些例子。但是我必须在实际的bot状态下获取和更新属性,我使用自定义ConversationDataModel添加了一些附加属性。所以不要认为没有TurnContext是可能的。我今天添加了一个新的。一旦我有了一个通俗易懂的答案,我会接受去造福他人。谢谢,有一段时间我对这项工作分心了,但又回到了这项工作中。我已经实现了创建一个带有ConversationReference的模型类的建议,以及我需要从Activity类中获得的一些附加属性。因此,它变得重量轻,可串行化以存储在Cosmos DB中。谢谢。
//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);
                                }
                            }
public class ConversationInfo
{
    [JsonProperty(PropertyName = "conversationReference")]
    public ConversationReference ConversationReference { get; set; }

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