如何让含qnaid与context的Bot卡片实现QnA测试门户同款功能?
实现与QnA测试门户一致的机器人后续提示逻辑
我之前正好处理过类似的需求,要让机器人实现和QnA测试门户一模一样的按钮触发效果,核心就是要让点击按钮时把对应的qnaId和提示文本一起传给QnA Maker服务,而不是像官方的Bot-qnamaker-prompting示例那样只传纯文本。下面是具体的实现步骤:
第一步:给按钮带上qnaId的结构化数据
生成后续提示按钮的时候,别只传提示文本,要把qnaId和文本一起封装成JSON字符串放到按钮的value字段里。这样点击按钮时,机器人就能拿到完整的提示信息。
举个C#(Bot Framework)的例子:
// 生成提示按钮时,把qnaId和文本一起封装 var promptButton = new HeroCardButton { Text = prompt.DisplayText, // 按钮上显示的文本 Value = JsonConvert.SerializeObject(new { Question = prompt.DisplayText, QnaId = prompt.QnaId }) };
如果是Node.js版本,写法类似:
const promptButton = { type: 'imBack', title: prompt.displayText, value: JSON.stringify({ question: prompt.displayText, qnaId: prompt.qnaId }) };
第二步:修改QnA查询逻辑,优先用qnaId查答案
在处理用户消息的代码里,先判断收到的是不是按钮传来的结构化数据:
- 尝试把消息内容解析成JSON对象
- 如果解析成功且里面有
qnaId,就直接调用QnA Maker的「按ID查答案」接口(C#里是GetAnswersByIdAsync,Node.js是getAnswersById) - 如果解析失败,再走原来的按文本查询的逻辑
还是以C#为例:
var userInput = turnContext.Activity.Text; QnAMakerResults qnaResults = null; try { // 尝试解析成带qnaId的结构化数据 var promptData = JsonConvert.DeserializeObject<PromptData>(userInput); if (promptData != null && promptData.QnaId > 0) { // 直接用qnaId精准查询答案 qnaResults = await _qnaMaker.GetAnswersByIdAsync(turnContext, new List<int> { promptData.QnaId }); } } catch (JsonException) { // 不是结构化数据,走常规文本查询 qnaResults = await _qnaMaker.GetAnswersAsync(turnContext); } // 后续处理返回的答案即可
这里需要一个简单的实体类来接收解析后的数据:
public class PromptData { public string Question { get; set; } public int QnaId { get; set; } }
第三步:确保从QnA结果里正确拿到qnaId
从QnA Maker获取初始答案时,要记得把后续提示(Prompts)里的qnaId一起提取出来——这个字段在QnA返回的结果里是自带的,官方示例可能只取了displayText,你要把qnaId也拿到手,这样才能传给按钮。
比如C#里提取提示的代码:
var firstAnswer = qnaResults.Answers.FirstOrDefault(); if (firstAnswer?.Context?.Prompts != null) { foreach (var prompt in firstAnswer.Context.Prompts) { // 这里能拿到prompt.QnaId,用来生成上面的按钮 } }
第四步:测试验证
改完之后,点击按钮时可以抓个包看看机器人向QnA Maker发送的请求,确认是否携带了qnaId参数,并且返回的是对应ID的精准答案,而不是上下文匹配的模糊结果。
这样调整后,你的机器人就能实现和QnA测试门户完全一致的效果了,点击按钮直接触发对应qnaId的答案查询,再也不会出现文本匹配不准的问题。
内容的提问来源于stack exchange,提问作者feili
相关产品推荐
相关产品推荐

