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

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槽位,重复询问该问题。

卡顿原因排查

  1. contact_prefer槽位映射错误
    domain中contact_prefer的映射类型设为custom,指定了validate_basic_info_form但未实现对应的提取逻辑,导致用户输入后槽位无法被正确填充,表单一直认为该槽位未收集完成,重复询问。

  2. required_slots方法逻辑错误
    代码中additional_slots初始化为[""],会将空字符串添加到必填槽列表中,破坏表单的槽位收集顺序和逻辑,导致表单流程异常。

  3. 部分槽位映射条件错误
    confirm_phone和confirm_address的映射条件中,requested_slot被错误设置为phone_type,这会导致只有当请求的槽位是phone_type时才会填充这两个槽位,完全不符合业务逻辑。

  4. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 17:37:02