如何为Rasa聊天机器人创建指定场景的回退动作?
问题描述
我已经创建了一个带两个按钮的ActionPayrollandattMenu(对应动作action_AB),当用户不点击按钮而是输入内容,且输入内容既不匹配按钮对应的意图(A、B)也不属于其他动作时,希望重新展示这个带按钮的菜单动作。以下是我编写的代码,请问该如何完善对应的回退动作?
from typing import Text, Dict, Any, List from rasa_sdk import Action, Tracker from rasa_sdk.executor import CollectingDispatcher from rasa_sdk.events import FollowupAction from datetime import datetime, timedelta import pytz from googletrans import Translator class ActionPayrollandattMenu(Action): def name(self) -> Text: return "action_AB" def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> List[Dict[Text, Any]]: message = "Please select your preferred option:" buttons = [ {"title": "AAA", "id": "A"}, {"title": "BBB", "id": "B"}, ] #print("Tracker.Event",tracker.events," ") language = tracker.slots.get("language") intent_name = tracker.latest_message.get("intent").get("name") print("A intent name: ",intent_name) latest_action = tracker.latest_action_name print("A latest action: ",latest_action) #print(f"language: {language}") if language and language != "en": translator = Translator() message = translator.translate("Please select your preferred option:", dest=language).text else: message = "Please select your preferred option:" buttons = [ {"title": "AAA", "id": "A"}, {"title": "BBB", "id": "B"} ] for button in buttons: if language and language != "en": button["title"] = translator.translate(button["title"], dest=language).text dispatcher.utter_message(text=message, buttons=buttons) IST = pytz.timezone('Asia/Kolkata') date = (datetime.datetime.now(IST) + datetime.timedelta(minutes=2)).strftime("%Y-%m-%d %H:%M:%S") entities = tracker.latest_message.get("entities") date = datetime.datetime.strptime(date,"%Y-%m-%d %H:%M:%S") reminder=remind(date,entities) return [reminder] class ActionFallback(Action): def name(self) -> Text: return "action_fallback" def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> List[Dict[Text, Any]]: intent_name = tracker.latest_message.get("intent").get("name") if intent_name not in ["A", "B"]: if "A" in tracker.latest_message.get("text").lower(): return [FollowupAction("action_A")] elif "B" in tracker.latest_message.get("text").lower(): return [FollowupAction("action_B")] else: dispatcher.utter_message("Sorry, I didn't understand. Please select your preferred option:") return [FollowupAction("action_AB")] return []
完善方案
核心优化点
- 精准场景判断:回退动作需先确认当前处于菜单场景(即上一个动作是
action_AB),避免在其他对话流程中误触发菜单重显。 - 意图置信度校验:即使意图被识别为A/B,若置信度过低也应触发回退,防止错误跳转。
- 优化文本匹配逻辑:原代码的文本包含判断过于宽泛(比如输入"apple"会误触发A),改用精准的关键词/完全匹配。
- 统一多语言支持:回退提示语与菜单提示语保持风格一致,同时支持多语言翻译。
- 修复按钮格式:Rasa按钮标准格式需用
payload字段绑定意图,而非id。
修正后的完整代码
优化后的ActionPayrollandattMenu
from typing import Text, Dict, Any, List from rasa_sdk import Action, Tracker from rasa_sdk.executor import CollectingDispatcher from rasa_sdk.events import ReminderScheduled from datetime import datetime, timedelta import pytz from googletrans import Translator class ActionPayrollandattMenu(Action): def name(self) -> Text: return "action_AB" def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> List[Dict[Text, Any]]: # 初始化基础文本与按钮(使用Rasa标准payload格式) base_message = "Please select your preferred option:" buttons = [ {"title": "AAA", "payload": "/A"}, {"title": "BBB", "payload": "/B"} ] language = tracker.slots.get("language", "en") # 多语言翻译处理 if language != "en": translator = Translator() message = translator.translate(base_message, dest=language).text for button in buttons: button["title"] = translator.translate(button["title"], dest=language).text else: message = base_message dispatcher.utter_message(text=message, buttons=buttons) # 定时提醒(修复原代码的datetime调用错误) IST = pytz.timezone('Asia/Kolkata') reminder_time = datetime.now(IST) + timedelta(minutes=2) reminder = ReminderScheduled( intent_name="EXTERNAL_reminder", trigger_date_time=reminder_time, entities=tracker.latest_message.get("entities"), name="menu_reminder", kill_on_user_message=True ) return [reminder]
完善后的ActionFallback
class ActionFallback(Action): def name(self) -> Text: return "action_fallback" def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> List[Dict[Text, Any]]: latest_intent = tracker.latest_message.get("intent") intent_name = latest_intent.get("name") intent_confidence = latest_intent.get("confidence") language = tracker.slots.get("language", "en") # 检查最近两个动作是否包含菜单动作,确认当前处于菜单场景 previous_actions = [event.get("name") for event in tracker.events if event.get("event") == "action"] is_menu_context = "action_AB" in previous_actions[-2:] # 置信度过低的A/B意图视为未理解 if intent_name in ["A", "B"] and intent_confidence < 0.7: intent_name = "nlu_fallback" if is_menu_context and intent_name not in ["A", "B"]: user_text = tracker.latest_message.get("text").lower().strip() # 精准匹配用户输入的关键词 if user_text in ["a", "aaa"]: return [FollowupAction("action_A")] elif user_text in ["b", "bbb"]: return [FollowupAction("action_B")] else: # 多语言回退提示语 fallback_msg = "Sorry, I didn't understand. Please select your preferred option:" if language != "en": translator = Translator() fallback_msg = translator.translate(fallback_msg, dest=language).text dispatcher.utter_message(text=fallback_msg) return [FollowupAction("action_AB")] # 非菜单场景的通用回退提示 default_fallback_msg = "Sorry, I didn't get that. Could you rephrase?" if language != "en": translator = Translator() default_fallback_msg = translator.translate(default_fallback_msg, dest=language).text dispatcher.utter_message(text=default_fallback_msg) return []
额外配置要求
- Domain文件配置:在
domain.yml中注册动作与意图:
actions: - action_AB - action_fallback intents: - A - B - nlu_fallback
- Rasa回退策略:在
config.yml中配置触发阈值:
policies: - name: RulePolicy core_fallback_threshold: 0.3 core_fallback_action_name: "action_fallback" enable_fallback_prediction: True
内容的提问来源于stack exchange,提问作者hazeeb hashim siddique
相关产品推荐
相关产品推荐

