前阵子在捣鼓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都分开触发 不会提前触发 让你的程序响应时间更快。
当然也许还会有更快更好的运行方式,我这只是自己尝试出来的方法 有这类需求而且找不到好方法的时候可以使用我这个方法 有好方法的同志也可以分享出来。大家互相学习一起努力