Rasa 2自定义动作返回SlotSet时规则后续动作未触发、槽值不更新问题
核心问题排查与修复方案
1. 规则执行中断、utter_ask_deal未触发原因
- 自定义动作
ActionGetOffer的run方法仅在user_asked_percentage > current_bargain分支内有返回语句,其余分支无显式返回,Rasa要求自定义动作的run方法必须返回事件列表(无事件需返回空列表[]),无返回会被判定为动作执行异常,直接中断后续规则步骤。 - 当你返回
SlotSet事件时,如果current_bargain槽配置了influence_conversation: true,Rasa会判定会话状态发生变更,需要重新预测后续动作,不会继续执行原规则中预设的utter_ask_deal步骤,这是返回SlotSet后后续动作不执行的核心原因。 - 你提到的「不返回SlotSet后续动作可以正常执行」是正常现象:没有槽更新事件时会话状态未发生变更,Rasa会按规则定义的顺序继续执行后续步骤。
2. current_bargain槽值未更新原因
- 单独调用
SlotSet不会生效:SlotSet是Rasa的事件对象,必须放在run方法的返回列表中,Rasa才会处理该事件完成槽值更新,单独调用不会触发任何槽变更逻辑。 - 槽配置错误:如果
current_bargain槽未在domain中声明、类型不匹配(比如返回float但槽类型设为text)、未设置初始值导致tracker.get_slot('current_bargain')取到None,执行+2时报错动作执行失败,槽值自然不会更新。 - 动作执行异常:代码未做非空判断,当
current_bargain初始为None时,current_bargain = tracker.get_slot('current_bargain') + 2会抛出类型错误,导致动作执行失败,返回的SlotSet不会被处理。
3. 修复步骤
步骤1:调整domain中槽的配置
关闭current_bargain等业务槽的会话影响属性,保证槽更新不会打断规则执行,同时设置初始值避免空值报错:
slots: current_bargain: type: float initial_value: 0.0 influence_conversation: false current_bargain_price: type: float initial_value: 0.0 influence_conversation: false price: type: float influence_conversation: false
步骤2:补全自定义动作的逻辑
统一所有分支的返回逻辑,增加非空判断:
from typing import List, Dict, Text, Any from rasa_sdk import Action, Tracker from rasa_sdk.executor import CollectingDispatcher from rasa_sdk.types import DomainDict from rasa_sdk.events import SlotSet class ActionGetOffer(Action): def name(self) -> Text: return "action_get_offer" def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: DomainDict) -> List[Dict[Text, Any]]: dispatcher.utter_message(text = "Ok! Let me see what I can do!") product_price = 500 platform_bargain_percentage = 5 vendor_bargain_percentage = 5 max_bargain = platform_bargain_percentage + vendor_bargain_percentage offer_price = int(tracker.get_slot("price") or 0) user_asked_percentage = (offer_price / product_price) * 100 # 处理槽空值场景 current_bargain = (tracker.get_slot('current_bargain') or 0) + 2 events = [] if user_asked_percentage > current_bargain: dispatcher.utter_message(text = "Okay so I just checked and sorry but we can't give away for that price!") current_bargain_price = tracker.get_slot('current_bargain_price') or 0 if current_bargain_price == 0: current_bargain_price = (product_price - ((current_bargain/100) * product_price)) if current_bargain <= max_bargain: dispatcher.utter_message(text = f"How about {product_price - ((current_bargain/100) * product_price)}?") else: dispatcher.utter_message(text = "Hmm...wanna make a fresh offer then?") # 把槽更新事件加入返回列表 events.append(SlotSet("current_bargain", value = float(current_bargain))) # 所有场景统一返回事件列表 return events
可选优化
如果调整槽配置后仍有规则执行中断问题,可以直接把utter_ask_deal的调用放到自定义动作中,无需依赖规则后续步骤:
在run方法末尾加一行dispatcher.utter_message(response="utter_ask_deal")即可。
内容的提问来源于stack exchange,提问作者Praneeth Vasarla
相关产品推荐
相关产品推荐

