Bot Framework V4中发送首条消息前如何访问用户/对话状态?
在Bot Framework V4 Directline场景下,发送首条消息前访问用户状态的实现方案
要在Directline接收消息的环节(发送首条响应前)访问用户的语言设置状态,核心是关联用户ID与存储的状态数据,并通过Bot Framework的状态管理机制读取。下面是具体的实现步骤和代码示例:
1. 先确保状态访问器已配置
首先你需要在项目中配置好用户状态(UserState)和对应的状态访问器,用来存储和读取用户的语言偏好:
// 定义存储用户语言设置的实体类 public class UserLanguageSettings { public string PreferredLanguage { get; set; } } // 状态访问器类,用于封装状态操作 public class LanguageSettingAccessor { public IStatePropertyAccessor<UserLanguageSettings> LanguageSettings { get; } public LanguageSettingAccessor(UserState userState) { // 注册名为"UserLanguageSettings"的用户状态属性 LanguageSettings = userState.CreateProperty<UserLanguageSettings>("UserLanguageSettings"); } } // 在Startup.cs中注入状态服务 services.AddSingleton<IStorage, MemoryStorage>(); // 生产环境建议用BlobStorage等持久化存储 services.AddSingleton<UserState>(); services.AddSingleton<LanguageSettingAccessor>();
2. 在消息接收方法中读取用户状态
在你的OnMessageReceive方法所在的类中,注入LanguageSettingAccessor和UserState,然后按以下步骤处理:
private readonly LanguageSettingAccessor _languageAccessor; private readonly UserState _userState; // 通过构造函数注入依赖 public YourMessageHandler(LanguageSettingAccessor languageAccessor, UserState userState) { _languageAccessor = languageAccessor; _userState = userState; } private async Task OnMessageReceive(SocketMessage socketMessage) { // 第一步:从Directline消息中提取用户唯一ID(关键,状态与用户ID绑定) var userId = socketMessage.From?.Id; if (string.IsNullOrEmpty(userId)) { // 处理用户ID为空的异常情况 return; } // 第二步:创建临时TurnContext,用于读取用户状态 // 这里用NullAdapter是因为我们仅需读取状态,无需实际发送消息 var tempActivity = new Activity { From = new ChannelAccount(userId) }; var tempTurnContext = new TurnContext(new NullAdapter(), tempActivity); // 第三步:读取用户的语言设置(如果是首次交互,会返回默认初始化的实例) var userLangSettings = await _languageAccessor.LanguageSettings.GetAsync( tempTurnContext, () => new UserLanguageSettings { PreferredLanguage = "en" } // 默认语言,可根据需求调整 ); // 第四步:检查输入语言与用户偏好是否匹配 if (IsLanguageMatch(socketMessage, userLangSettings.PreferredLanguage)) { await channel.SendMessageAsync(response); } } // 调整语言匹配方法,传入用户偏好语言 private bool IsLanguageMatch(SocketMessage socketMessage, string preferredLanguage) { // 这里实现你的语言检测逻辑:比如从消息文本识别语言,或读取消息自带的语言标识 var inputLanguage = DetectInputLanguage(socketMessage); // 替换为你的实际检测逻辑 return inputLanguage.Equals(preferredLanguage, StringComparison.OrdinalIgnoreCase); }
关键注意事项
- 用户ID的准确性:Directline消息中的
From.Id是用户的唯一标识,必须确保正确获取,否则会读取错误的状态数据。 - 首次交互的默认值:当用户第一次发送消息时,状态存储中没有数据,所以
GetAsync的第二个参数会返回你定义的默认语言设置。 - 持久化存储:示例中用
MemoryStorage仅适合开发测试,生产环境请使用BlobStorage或CosmosDbStorage来保证状态不会丢失。 - 状态更新:如果后续需要修改用户的语言设置,记得调用
await _userState.SaveChangesAsync(tempTurnContext);来持久化更新后的状态。
内容的提问来源于stack exchange,提问作者kemakino
相关产品推荐
相关产品推荐

