RASA3获取用户输入,从数据库查询数据,返回给用户前台(踩坑记录)

前阵子在捣鼓rasa人工智能 看上了他的可编程性。于是乎开始捣鼓

安装和初始化的教程我就跳过了,直接进入正题:

nlu.yml:

nlu:

- regex: user_input_name
  examples: |
    - (?<=查)[a-zA-Z0-9\u4e00-\u9fa5]{2,5}(?=的)
    
- intent: info_input_name
  examples: |
    - 请帮我查[张三](user_input_name)的性别
    - 帮我查[张三](user_input_name)的性别
    - 查[张三](user_input_name)的性别
    - 我想查[张三](user_input_name)的性别
#这里使用中文的话要去config中配置语种

regex是正则表达式 表达user_input这个字段(暂且叫做字段 本名是词槽)的范围 我这里就不多解释了。

config.yml:

# The config recipe.
# https://rasa.com/docs/rasa/model-configuration/
recipe: default.v1

# The assistant project unique identifier
# This default value must be replaced with a unique assistant name within your deployment
assistant_id: 20230529-100826-amicable-gain

# Configuration for Rasa NLU.
# https://rasa.com/docs/rasa/nlu/components/
language: zh

pipeline:
# # No configuration for the NLU pipeline was provided. The following default pipeline was used to train your model.
# # If you'd like to customize it, uncomment and adjust the pipeline.
# # See https://rasa.com/docs/rasa/tuning-your-model for more information.
#   - name: WhitespaceTokenizer
   - name: JiebaTokenizer #支持中文
   - name: RegexFeaturizer
   - name: LexicalSyntacticFeaturizer
   - name: CountVectorsFeaturizer
     analyzer: char_wb
     min_ngram: 1
     max_ngram: 4
   - name: DIETClassifier
     epochs: 200
     constrain_similarities: true
     entity_recognition: false
   - name: EntitySynonymMapper
   - name: ResponseSelector
     epochs: 200
     constrain_similarities: true
   - name: FallbackClassifier
     threshold: 0.3
     ambiguity_threshold: 0.1
   - name: RegexFeaturizer
   - name: RegexEntityExtractor
     case_sensitive: False
     use_lookup_tables: False
     use_regexes: True
     use_word_boundaries: True
 
# Configuration for Rasa Core.
# https://rasa.com/docs/rasa/core/policies/
policies:
# # No configuration for policies was provided. The following default policies were used to train your model.
# # If you'd like to customize them, uncomment and adjust the policies.
# # See https://rasa.com/docs/rasa/policies for more information.
   - name: MemoizationPolicy
   - name: TEDPolicy
     max_history: 5
     epochs: 200
     constrain_similarities: true
   - name: RulePolicy
   

这是配置文件。不多解释了 官方文档上都有详解。

domain.yml: 这是比较重要的地方

version: '3.1'

intents:
#添加前面的意图名和form表单名
  - info_input_name
  - name_form
  
actions:
#行为名
  - validate_name_form
responses:
#响应 utter_output_name是响应名 {}内的是插槽名
  utter_output_name:
  - text: '{user_input_name}的性别是{db_get_sex}'



entities:
#实体名
- user_input_name、


forms:
#form表单名 name_form
  name_form:
    required_slots: #填写表单需要的插槽
    - user_input_name



slots:  #插槽
#插槽名
  user_input_name:
    type: text   #插槽类型
    influence_conversation: false   #是否影响程序
    mappings:   #插槽来源
    - type: from_entity   #来源的类型
      entity: user_input_name  #来源的实体名 这几个最好写成同一个

  db_get_sex:    
    type: text
    mappings:
    - type: custom    #来源于用户 待会会使用行为方法进行操作


session_config:
  session_expiration_time: 60
  carry_over_slots_to_new_session: true

rule.yml:

rules:
#形式1
- rule: avtivate get_uname form  #名称 随便取 唯一
  steps:  
  - intent: get_user_msg     #你的意图
  - action: uname_form       #触发的form表单
  - active_loop: uname_form  #开始获取表单所需的值

- rule: stop get_uname form   #名称 随便取 唯一
  condition:      
  # 条件是:表单处于活跃状态
  - active_loop: uname_form
  steps:
  # 表单停用
  - action: uname_form
  - active_loop: null
  - slot_was_set:
    - requested_slot: null
  # 一旦槽填满后,提交表单时要运行的动作
  - action: utter_output_user    #这边直接触发回复字段 因为在form表单获取的过程中就自动触发了form验证的Action

Action.py:

from typing import Text,  Any, Dict
from rasa_sdk import Action
from rasa_sdk import Tracker, FormValidationAction
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.types import DomainDict
from rasa_sdk.events import SlotSet


import pymysql   #mysql  需要pip安装


conn = pymysql.connect(host='localhost',
                       port=3306,
                       user='你的mysql用户名',
                       passwd='mysql密码',
                       db='rasa',
                       charset = 'utf8'
                       )



#继承两个
class SexMsgForm(FormValidationAction,Action):

    #必须写 return的是Action的名字
    def name(self) -> Text:
        return "validate_name_form"   #前面action设置的值
    
    # 返回一下输入的字段就行了,方法名称是extract_+插槽名 他会自动检测
    async def extract_user_input_name(
        self,
        dispatcher: "CollectingDispatcher",
        tracker: "Tracker",
        domain: "DomainDict",
    ) -> Dict[Text, Any]:
        #从tracker获取到用户输入的slot的值
        return {"user_input_name":tracker.get_slot('user_input_name')}
    
    #使用了Action的run方法 因为extract不能返回slot
    def run(self, dispatcher, tracker, domain):

        print("你进入了自定义form")
        vall = tracker.get_slot("user_input_name")
        # print("slot:")
        # print(vall)

        sql = "select usex from tuser where uname = %s"   #这里使用的%s是占位符 防止SQL

        cursor = conn.cursor()

        try:
            cursor.execute(sql,vall)  #在这里将占位符填充
            resul = cursor.fetchall() #获取所有值使用fetchall()时结果是二维数组,获取第一条时使用fetchone()时是一维数组 
            usex=resul[0][0]        #

        except Exception as e:
            print("Exception:",e)
            conn.rollback
            cursor.close()
            return [SlotSet("db_get_sex",usex)]
        finally:
            cursor.close()

        return [SlotSet("db_get_sex",usex)]  #将Slot设置值并返回给程序

这里不要在action.py中直接使用Action,也不要在slot的底下加Action名 我设置的所有Action无一例外全部都会自己触发 并且使用官方文档的使用方式导致我每次触发意图都会触发三次所有Action 2s的响应时间直接变成了10秒多 这个方法可以使你的每个form都分开触发 不会提前触发 让你的程序响应时间更快。

当然也许还会有更快更好的运行方式,我这只是自己尝试出来的方法 有这类需求而且找不到好方法的时候可以使用我这个方法 有好方法的同志也可以分享出来。大家互相学习一起努力

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值