gpt4 book ai didi

c# - 在 Cosmos DB 中管理状态,而不是在内存中管理 Bot 到 Human 的切换场景

转载 作者:行者123 更新时间:2023-12-04 03:52:49 25 4
gpt4 key购买 nike

我正在开发一个具有人工切换功能(人-2-人聊天)的机器人,其中机器人负责整个通信。用户可以开始与 bot 的通信,如果他对 bot 的响应不满意,他可以向 Human 寻求进一步的帮助。

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

我已经创建了一个 API Controller 端点并作为回调 url 传递给这个系统。当代理发送消息时,系统会在此端点上发出通知。它是简单的 Web API Controller ,与 Bot Framework 没有直接关系。

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

  • Conversation Reference 有助于使用 ContinueConversationAsync 将代理消息从 bot 传递给用户。

  • TurnContext 有助于在 session 关闭等情况下管理和更新这些属性的状态。并且还可以使用它在自上次回合具有事件时间戳后的一段时间不活动后发送消息。

现在这两个都在内存中,这意味着随着新聊天 session 的创建和更多消息的交换,它们会被添加和删除。我现在想将其从内存中移出到共享缓存或低延迟 cosmos。这样我也可以在需要时使用自动扩展新的机器人服务实例的可能性。我目前正在使用应用服务。但是由于这种耦合,新实例无法访问内存中的数据,因此无法提供服务。我不认为为 Bot Scenarios 启用 AffinityCookie 实际上有效。

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

那么我怎样才能移动此代码以独立于实例上的单例 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);
}
}
//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);
}
}

任何想通的想法都将不胜感激。

最佳答案

对话引用包含事件中信息的子集,而事件只是回合上下文的一个属性,因此对话引用包含回合上下文中信息的子集。保存对话引用和转弯上下文是多余的,因为如果您保存转弯上下文,那么您已经拥有对话引用中的所有信息。

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

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

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

关于c# - 在 Cosmos DB 中管理状态,而不是在内存中管理 Bot 到 Human 的切换场景,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64206530/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com