You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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 []
完善方案

核心优化点

  1. 精准场景判断:回退动作需先确认当前处于菜单场景(即上一个动作是action_AB),避免在其他对话流程中误触发菜单重显。
  2. 意图置信度校验:即使意图被识别为A/B,若置信度过低也应触发回退,防止错误跳转。
  3. 优化文本匹配逻辑:原代码的文本包含判断过于宽泛(比如输入"apple"会误触发A),改用精准的关键词/完全匹配。
  4. 统一多语言支持:回退提示语与菜单提示语保持风格一致,同时支持多语言翻译。
  5. 修复按钮格式: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 []

额外配置要求

  1. Domain文件配置:在domain.yml中注册动作与意图:
actions:
  - action_AB
  - action_fallback
intents:
  - A
  - B
  - nlu_fallback
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 17:45:39