如何用C#获取Microsoft QnA Maker多轮对话的isContextOnly标签?
解决QnA Maker isContextOnly标签在Bot Builder Dialogs中无法获取的问题
我之前也碰到过一模一样的问题——明明知识库配置了isContextOnly,但用C#的Bot Builder SDK就是拿不到这个属性。后来折腾了好一阵,总结了几个可行的方案,你可以根据自己的场景选:
方案一:自定义模型手动反序列化(最可靠)
默认的QueryResult类并没有映射isContextOnly字段,所以我们可以自己扩展这个类,然后手动处理API响应的反序列化:
- 定义扩展的查询结果类:
using System.Text.Json.Serialization; using Microsoft.Bot.Builder.AI.QnA; public class ExtendedQueryResult : QueryResult { [JsonPropertyName("isContextOnly")] public bool IsContextOnly { get; set; } }
- 绕过SDK的默认解析,直接调用QnA Maker API并反序列化到自定义类:
using System.Net.Http; using System.Text.Json; using System.Threading.Tasks; public async Task<ExtendedQueryResult[]> GetQnAAnswersWithContextOnlyAsync(string question, string qnaEndpoint, string qnaSubscriptionKey) { var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", $"EndpointKey {qnaSubscriptionKey}"); var requestBody = new { question = question, top = 1 }; var content = new StringContent(JsonSerializer.Serialize(requestBody), System.Text.Encoding.UTF8, "application/json"); var response = await client.PostAsync($"{qnaEndpoint}/knowledgebases/your-kb-id/generateAnswer", content); var responseJson = await response.Content.ReadAsStringAsync(); var qnaResponse = JsonSerializer.Deserialize<QnaResponse>(responseJson); return qnaResponse.Answers; } // 辅助类用于反序列化整体响应 public class QnaResponse { [JsonPropertyName("answers")] public ExtendedQueryResult[] Answers { get; set; } }
这样就能直接拿到IsContextOnly属性了。
方案二:利用Metadata字段间接传递(最灵活)
如果不想改代码调用方式,可以在QnA Maker知识库中,给需要标记isContextOnly的问答对添加元数据,比如新增键值对isContextOnly: true。然后在代码里从Metadata中读取:
var qnaResponse = await _qnaMaker.GetAnswersAsync(turnContext); if (qnaResponse.Any()) { var contextOnlyMeta = qnaResponse.First().Metadata.FirstOrDefault(m => m.Name == "isContextOnly"); bool isContextOnly = contextOnlyMeta != null && bool.Parse(contextOnlyMeta.Value); // 这里处理你的业务逻辑 }
这个方法不依赖SDK的内部实现,就算SDK更新也不会受影响,非常稳妥。
方案三:尝试升级SDK版本
部分旧版本的Microsoft.Bot.Builder.AI.QnA包确实没有包含isContextOnly的映射。你可以尝试把这个NuGet包升级到最新稳定版,然后检查QueryResult类是否已经有IsContextOnly属性。如果有的话,直接用response.Answers[0].IsContextOnly就能获取了。
方案四:反射临时取值(不推荐长期使用)
如果以上方案都不适用,你可以用反射临时获取这个属性,但要注意这依赖于SDK的内部实现,后续版本更新可能失效:
var firstAnswer = response.Answers[0]; var isContextOnlyProp = firstAnswer.GetType().GetProperty("isContextOnly", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); if (isContextOnlyProp != null) { bool isContextOnly = (bool)isContextOnlyProp.GetValue(firstAnswer); // 处理逻辑 }
内容的提问来源于stack exchange,提问作者domac
相关产品推荐
相关产品推荐

