BotFramework 从提示验证器传递结果
BotFramework passing results from prompt Validator
我正在使用 python botframework 的 sdk 来设计我的机器人。我在对话设计中使用瀑布式对话。
我的机器人通过询问用户开始对话:"I can show documents for topic A, B, C. Of what topic you would like to see documents?"
为了验证用户是否提交了正确的主题,我使用自定义验证器并使用 luis 验证用户是否输入了正确的主题。
在对话的瀑布步骤中,我使用用户输入的主题向他展示各自的主题。但在这里我也必须再次点击 luis 服务以从用户消息中提取主题,然后使用主题列表中的实体过滤器。
我的问题是:是否可以将值从 promptValidatorContext 传递到当前步骤上下文或瀑布对话框集中的下一个对话框。
正如您在下面的示例代码中看到的那样,我使用相同的用户消息两次访问 luis 应用程序,如果可以在 promptValidatorContext 和 dialogContext 之间共享值,这将帮助我避免两次访问 luis 服务并且可以做同样的工作,打一次。
示例代码:
class MainDialog(ComponentDialog):
def __init__(self, dialog_id, luis_app):
self.dialog_id = dialog_id
self.luis_app = luis_app
self.add_dialog(TextPrompt('topic', self.TopicValidator))
self.add_dialog(WaterFallDialog('wf_dialog', [self.Welcome, self.Topic, self.FinalStep])
async def Welcome(self, step_context):
return await step_context.prompt(
'topic',
options = PromptOptions(
prompt = MessageFactory.text('Welcome to the bot, I can show you documents of topic Math, English, Science'),
retry_prompt = MessageFactory.text("I am sorry I didn't understand please try again with different wording")
)
)
async def TopicValidator(self, prompt_context: PromptValidatorContext):
for_luis = prompt_context.recognized.value
#hit the luis app to get the topic name
topic_name = self.luis_app(for_luis)
if topic_name in ['Math', 'Science', 'English']:
return True
else:
return False
async def Topic(self, step_context):
topic_name = self.luis_app(step_context.context.activity.text) #using the same user message as used in Validator function
#filter documents based on topics with custom function filter_doc
docs = filter_doc(topic_name)
return await step_context.prompt('docs', options = PromptOptions(prompt = docs))
async def FinalStep(self, step_context):
#code for final step
我真的想重申我认为你应该使用选择提示。选择提示比您想象的要灵活得多。选择识别确实非常先进,它能够识别短语中间的选择,您甚至可以像在 LUIS 列表实体中一样提供同义词。对话框库中有一个 entire folder 专用于选择识别。你认为你通过使用 LUIS 为用户提供了更好的体验,但实际上你给了他们更糟糕的体验,因为他们无法输入像 1 或 2 这样的序数作为他们的选择。根据你告诉我的情况,我确信选择提示是最适合你的选择。
话虽这么说,这是您要的信息。
通常的做法是每轮只调用一次任何给定的 LUIS 端点。如果您的 LUIS 模型对于您的机器人来说是全局的,那么在该对话框之外调用它会更有意义,因此我假设此 LUIS 模型特定于此对话框。
最明显的解决方案是将 LUIS 结果存储在转弯状态中。你可以这样存储它:
prompt_context.context.turn_state[MY_KEY] = self.luis_app(for_luis);
您可以像这样检索值:
topic_name = step_context.context.turn_state[MY_KEY];
另一个想法是使 luis_app
成为 memoized function(缓存其自身结果的函数)。由于其缓存的最佳位置是转向状态,因此这与第一个想法并没有太大不同。主要区别在于您将更改 luis_app
代码并保持对话代码不变。
另一个想法是将您的 LUIS 结果放入提示结果中。您可以随意修改验证器中的识别值。
prompt_context.recognized.value = self.luis_app(prompt_context.recognized.value);
在瀑布的下一步中使用 step_context.result
访问该值。我应该提一下,您还可以修改传入 activity 的文本 属性,但这可能被认为是不好的做法。
最后,您可以创建自己的提示 class,它会自动使用 LUIS 实体作为其识别值。也许你可以称它为 EntityPrompt
或其他名称。
我正在使用 python botframework 的 sdk 来设计我的机器人。我在对话设计中使用瀑布式对话。
我的机器人通过询问用户开始对话:"I can show documents for topic A, B, C. Of what topic you would like to see documents?"
为了验证用户是否提交了正确的主题,我使用自定义验证器并使用 luis 验证用户是否输入了正确的主题。
在对话的瀑布步骤中,我使用用户输入的主题向他展示各自的主题。但在这里我也必须再次点击 luis 服务以从用户消息中提取主题,然后使用主题列表中的实体过滤器。
我的问题是:是否可以将值从 promptValidatorContext 传递到当前步骤上下文或瀑布对话框集中的下一个对话框。
正如您在下面的示例代码中看到的那样,我使用相同的用户消息两次访问 luis 应用程序,如果可以在 promptValidatorContext 和 dialogContext 之间共享值,这将帮助我避免两次访问 luis 服务并且可以做同样的工作,打一次。
示例代码:
class MainDialog(ComponentDialog):
def __init__(self, dialog_id, luis_app):
self.dialog_id = dialog_id
self.luis_app = luis_app
self.add_dialog(TextPrompt('topic', self.TopicValidator))
self.add_dialog(WaterFallDialog('wf_dialog', [self.Welcome, self.Topic, self.FinalStep])
async def Welcome(self, step_context):
return await step_context.prompt(
'topic',
options = PromptOptions(
prompt = MessageFactory.text('Welcome to the bot, I can show you documents of topic Math, English, Science'),
retry_prompt = MessageFactory.text("I am sorry I didn't understand please try again with different wording")
)
)
async def TopicValidator(self, prompt_context: PromptValidatorContext):
for_luis = prompt_context.recognized.value
#hit the luis app to get the topic name
topic_name = self.luis_app(for_luis)
if topic_name in ['Math', 'Science', 'English']:
return True
else:
return False
async def Topic(self, step_context):
topic_name = self.luis_app(step_context.context.activity.text) #using the same user message as used in Validator function
#filter documents based on topics with custom function filter_doc
docs = filter_doc(topic_name)
return await step_context.prompt('docs', options = PromptOptions(prompt = docs))
async def FinalStep(self, step_context):
#code for final step
我真的想重申我认为你应该使用选择提示。选择提示比您想象的要灵活得多。选择识别确实非常先进,它能够识别短语中间的选择,您甚至可以像在 LUIS 列表实体中一样提供同义词。对话框库中有一个 entire folder 专用于选择识别。你认为你通过使用 LUIS 为用户提供了更好的体验,但实际上你给了他们更糟糕的体验,因为他们无法输入像 1 或 2 这样的序数作为他们的选择。根据你告诉我的情况,我确信选择提示是最适合你的选择。
话虽这么说,这是您要的信息。
通常的做法是每轮只调用一次任何给定的 LUIS 端点。如果您的 LUIS 模型对于您的机器人来说是全局的,那么在该对话框之外调用它会更有意义,因此我假设此 LUIS 模型特定于此对话框。
最明显的解决方案是将 LUIS 结果存储在转弯状态中。你可以这样存储它:
prompt_context.context.turn_state[MY_KEY] = self.luis_app(for_luis);
您可以像这样检索值:
topic_name = step_context.context.turn_state[MY_KEY];
另一个想法是使 luis_app
成为 memoized function(缓存其自身结果的函数)。由于其缓存的最佳位置是转向状态,因此这与第一个想法并没有太大不同。主要区别在于您将更改 luis_app
代码并保持对话代码不变。
另一个想法是将您的 LUIS 结果放入提示结果中。您可以随意修改验证器中的识别值。
prompt_context.recognized.value = self.luis_app(prompt_context.recognized.value);
在瀑布的下一步中使用 step_context.result
访问该值。我应该提一下,您还可以修改传入 activity 的文本 属性,但这可能被认为是不好的做法。
最后,您可以创建自己的提示 class,它会自动使用 LUIS 实体作为其识别值。也许你可以称它为 EntityPrompt
或其他名称。