RASA动态表单配置问题:表单卡在contact_prefer槽位无法推进
Rasa动态表单卡顿问题排查与解决方案
问题描述
需要为basic_info_form实现动态问询逻辑,满足以下要求:
- 当
contact_prefer取值为phone_call或text时,询问confirm_phone槽位;否则跳过该槽位,直接询问street_address。 - 当
confirm_phone取值为other时,询问other_phone槽位,之后继续询问street_address。 - 当
confirm_address取值为no时,询问full_address槽位,之后继续询问home_members;否则直接询问home_members。
实际运行时表单始终卡在contact_prefer槽位,重复询问该问题。
卡顿原因排查
contact_prefer槽位映射错误
domain中contact_prefer的映射类型设为custom,指定了validate_basic_info_form但未实现对应的提取逻辑,导致用户输入后槽位无法被正确填充,表单一直认为该槽位未收集完成,重复询问。required_slots方法逻辑错误
代码中additional_slots初始化为[""],会将空字符串添加到必填槽列表中,破坏表单的槽位收集顺序和逻辑,导致表单流程异常。部分槽位映射条件错误
confirm_phone和confirm_address的映射条件中,requested_slot被错误设置为phone_type,这会导致只有当请求的槽位是phone_type时才会填充这两个槽位,完全不符合业务逻辑。extract_confirm_phone方法无返回值
该方法仅创建了SlotSet对象但未返回,导致提取到的confirm_phone值无法被设置到槽位中,后续逻辑无法触发。
解决方案
1. 修正domain.yml配置
主要修正槽位映射和必填槽的基础配置:
version: "3.1" config: store_entities_as_slots: true intents: - greet - goodbye - affirm - deny - mood_great - mood_unhappy - bot_challenge slots: options: type: text influence_conversation: false mappings: - type: from_text conditions: - active_loop: basic_info_form requested_slot: options language: type: text influence_conversation: false mappings: - type: from_text conditions: - active_loop: basic_info_form requested_slot: language phone: type: text influence_conversation: false mappings: - type: from_text conditions: - active_loop: basic_info_form requested_slot: phone phone_type: type: text influence_conversation: false mappings: - type: from_text conditions: - active_loop: basic_info_form requested_slot: phone_type contact_prefer: type: text influence_conversation: true mappings: - type: from_text conditions: - active_loop: basic_info_form requested_slot: contact_prefer confirm_phone: type: text influence_conversation: false mappings: - type: from_text conditions: - active_loop: basic_info_form requested_slot: confirm_phone other_phone: type: text influence_conversation: false mappings: - type: from_text conditions: - active_loop: basic_info_form requested_slot: other_phone street_address: type: text influence_conversation: false mappings: - type: from_text conditions: - active_loop: basic_info_form requested_slot: street_address city: type: text influence_conversation: false mappings: - type: from_text conditions: - active_loop: basic_info_form requested_slot: city zipcode: type: text influence_conversation: false mappings: - type: from_text conditions: - active_loop: basic_info_form requested_slot: zipcode confirm_address: type: text influence_conversation: false mappings: - type: from_text conditions: - active_loop: basic_info_form requested_slot: confirm_address full_address: type: text influence_conversation: false mappings: - type: from_text conditions: - active_loop: basic_info_form requested_slot: full_address home_members: type: text influence_conversation: false mappings: - type: from_text conditions: - active_loop: basic_info_form requested_slot: home_members race: type: text influence_conversation: false mappings: - type: from_text conditions: - active_loop: basic_info_form requested_slot: race hispanic: type: text influence_conversation: false mappings: - type: from_text conditions: - active_loop: basic_info_form requested_slot: hispanic gender: type: text influence_conversation: false mappings: - type: from_text conditions: - active_loop: basic_info_form requested_slot: gender responses: utter_greet: - text: "Hello!\nI'm Lucky. Do you need any help?" utter_ask_options: - text: "What do you need help with?\n1) Financial Advice\n2) Housing Questions" utter_ask_language: - text: "All right, I hope to help you with that.\nFirst, let's get to know each other. My primary language is English, but I am learning how to speak more languages. \nWhat is you primary language?\n -English\n -Spanish\n -Other" utter_ask_phone: - text: "That's awesome! My phone number is 214-739-6151. What yours?" utter_ask_phone_type: - text: "Please tell me which type of phone is this? \n Cell Phone \n Home Phone" utter_ask_contact_prefer: - text: "Wow so many ways to talk to you. How do you prefer I get in touch with you in the future? \n Email \n Phone Call \n Text(SMS)" utter_ask_confirm_phone: - text: "Which number should I use to reach out to you later? \n{phone} \nOther" utter_ask_other_phone: - text: "What is the new number you want me to reach you through?" utter_ask_street_address: - text: "Great! Did you know my home address is this website. What's your address?" utter_ask_city: - text: "What city do you live in?" utter_ask_zipcode: - text: "Oh nice! What is your Zip code?" utter_ask_confirm_address: - text: "Perfect. Can you verify that this is your full address?\n {street_address},{city} - {zipcode} \n- Yes\n- No" utter_ask_full_address: - text: "Oh no! Please help me correct it." utter_ask_home_members: - text: "I'm the only chatbot that lives on this webpage. How many people live at your household including you?" utter_fascinated: - text: "Oooh ok. You know, I have always been fascinated by humans. There is so much diversity in mankind.\nI am interested to know what type of human you are but please feel free to choose \"prefer not to say\" if you do not want to answer my next few questions." utter_ask_race: - text: "What ethnicity/race are you? \n-Black / African American\n-Native Hawaiian or other Pacific Islander\n-White\n-American Indian or Alaskan Native\n-Asian\n-More than one race / Other\n-Prefer Not To Say" utter_ask_hispanic: - text: "Are you Hispanic/Latino?\n-Yes\n-No\n-Prefer Not To Say" utter_ask_gender: - text: "Fun fact: I have no gender. What gender are you?\n-Female\n-Male\n-Gender Non-Conforming\n-Prefer Not To Say" utter_goodbye: - text: "Bye" utter_thank_you: - text: "Thank you for bearing with me! I learned a lot about you which will help me help you. \nI just have a few more questions to ask you..." utter_iamabot: - text: "I am Lucky, your online assitant." actions: - action_submit_form - validate_basic_info_form forms: basic_info_form: required_slots: - options - language - phone - phone_type - contact_prefer - street_address - city - zipcode - confirm_address - home_members - race - hispanic - gender
2. 修正actions.py代码
实现完整的动态必填槽逻辑和槽位验证:
from typing import Any, Text, Dict, List, Union from rasa_sdk import Action, Tracker from rasa_sdk.executor import CollectingDispatcher from rasa_sdk.forms import FormValidationAction from rasa.nlu.utils import write_json_to_file from rasa_sdk.events import SlotSet class ActionSubmitForm(Action): def name(self) -> Text: return "action_submit_form" def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text,Any])->List[Dict[Text,Any]]: write_json_to_file('output/slots_values.json', tracker.slots) return [] class ValidateBasicInfoForm(FormValidationAction): def name(self) -> Text: return "validate_basic_info_form" async def required_slots( self, domain_slots: List[Text], dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text,Any], ) -> List[Text]: # 初始化额外槽位列表 additional_slots = [] # 条件1:根据contact_prefer决定是否添加confirm_phone contact_prefer = tracker.slots.get("contact_prefer") if contact_prefer in ['phone_call','Text(SMS)']: additional_slots.append("confirm_phone") # 条件2:如果confirm_phone是other,添加other_phone confirm_phone = tracker.slots.get("confirm_phone") if confirm_phone == 'other': additional_slots.append("other_phone") # 条件3:根据confirm_address决定是否添加full_address confirm_address = tracker.slots.get("confirm_address") if confirm_address == 'no': additional_slots.append("full_address") # 保持原有槽位顺序,插入额外槽位到对应位置 # 找到contact_prefer的索引,插入后续动态槽位 try: contact_prefer_idx = domain_slots.index("contact_prefer") + 1 for slot in reversed(additional_slots): if slot not in domain_slots: domain_slots.insert(contact_prefer_idx, slot) except ValueError: pass # 处理confirm_address后的full_address插入 try: confirm_address_idx = domain_slots.index("confirm_address") + 1 if 'full_address' in additional_slots and 'full_address' not in domain_slots: domain_slots.insert(confirm_address_idx, "full_address") except ValueError: pass return domain_slots async def extract_confirm_phone( self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict ) -> Dict[Text, Any]: confirm_phone = tracker.latest_message.get("text") # 返回槽位设置字典 return {"confirm_phone": confirm_phone}
关键逻辑说明
- 动态槽位添加:在
required_slots方法中,根据已收集的槽位值动态添加或移除必填槽位,确保流程符合业务规则。 - 槽位顺序控制:通过索引插入的方式,将动态槽位插入到正确的流程位置,保证问询顺序符合预期。
- 槽位提取修正:修正
extract_confirm_phone方法的返回值,确保槽位能被正确填充。
内容的提问来源于stack exchange,提问作者Rishi
相关产品推荐
相关产品推荐

