# 优先安装这几个python包,后面缺什么补充什么
rasa==2.0.0
rasa-sdk==2.4.1
tensorflow==2.3.2
Flask==1.1.2
初始化项目
# 命令创建rasa项目所需的所有文件,并根据一些示例数据训练一个简单的机器人
rasa init
初始化后会创建以下文件,介绍几个重要的文件,当然这些文件结构你也可以自己调整
文件名 | 作用 |
---|---|
config.yml | 配置NLU和Core的文件 |
/data/nlu.yml | NLU的训练语句,意图加包含意图的话术 |
/data/stories.yml | 对话的故事,可以理解为剧本 |
domain.yml | 作用域,里面注册你定义的意图,对话模板,自定义action,槽位等 |
endpoints.yml | action的端口,action对外暴露的接口配置文件 |
/models/xxxx.tar,gz | 训练的模型 |
我项目的目录结构是这样的,可以作为参考
.
├── actions
│ ├── action_kn_test.py
│ ├── action_trademark_analy.py
│ ├── action_trademark_explain.py
│ ├── action_trademark_keyword.py
│ ├── action_weather_query.py
│ ├── __init__.py
│ └── __pycache__
│ ├── action_kn_test.cpython-36.pyc
│ ├── action_trademark_analy.cpython-36.pyc
│ ├── action_trademark_explain.cpython-36.pyc
│ ├── action_trademark_keyword.cpython-36.pyc
│ ├── action_weather_query.cpython-36.pyc
│ └── __init__.cpython-36.pyc
├── App
│ ├── def_func.py
│ ├── def_settings.py
│ ├── ext.py
│ ├── __init__.py
│ ├── models.py
│ ├── __pycache__
│ │ ├── ext.cpython-36.pyc
│ │ ├── __init__.cpython-36.pyc
│ │ └── views.cpython-36.pyc
│ ├── settings.py
│ ├── static
│ │ ├── css
│ │ │ └── style2.css
│ │ ├── images
│ │ │ ├── ai.png
│ │ └── js
│ │ ├── chat.js
│ │ └── jquery-3.3.1.min.js
│ ├── templates
│ │ └── chat.html
│ └── views.py
├── configs
│ ├── config.yml
│ ├── credentials.yml
│ ├── domain.yml
│ ├── endpoints.yml
│ ├── zh_jieba_mitie_embeddings_config.yml
│ └── zh_jieba_supervised_embeddings_config.yml
├── data
│ ├── dict
│ │ ├── cityname.txt
│ │ └── userdict.txt
│ ├── nlu
│ │ └── nlu.yml
│ ├── rules.yml
│ ├── stories
│ │ ├── stories.yml
│ │ └── story1.md
│ └── total_word_feature_extractor_zh.dat
├── models
│ └── 20210420-153935.tar.gz
├── __pycache__
├── server.py
├── shell_diectory
│ ├── run_shell
│ └── train_shell
定义你的NLU
- intent: query_weather
examples: |
- 我想查询天气
- 我想查询[广州]{"entity":"address"}的天气
- [明天]{"entity":"datetime"}天气怎么样?
- 我想查询[明天]{"entity":"datetime"}[深圳]{"entity":"address"}的天气
准备地名词库
定义你stories剧本
## query_weather(天气查询)
* query_weather
- weather_form
- active_loop{"name":"weather_form"}
在domain.yml 注册,注册你定义的意图,实体,槽位,问话模板,表单,自定义的action等
version: "2.0"
intents:
- greet
- goodbye
- affirm
- deny
- mood_great
- mood_unhappy
- bot_challenge
- query_weather # 意图查天气
entities:
- kn_question_num
- datetime # 实体时间
- address # 实体地址
actions:
- action_test
slots:
kn_question_num:
type: text
datetime:
type: text # 你需要填入的槽位时间
address:
type: text # 你需要填入的槽位地址
requested_slot:
type: unfeaturized
responses:
utter_greet:
- text: "Hey! How are you?"
utter_cheer_up:
- text: "Here is something to cheer you up:"
image: "https://i.imgur.com/nGF1K8f.jpg"
utter_did_that_help:
- text: "Did that help you?"
utter_happy:
- text: "Great, carry on!"
utter_goodbye:
- text: "Bye"
utter_iamabot:
- text: "I am a bot, powered by Rasa."
utter_ask_datetime:
- text: "请问你要查询什么时候的天气?" # 自动询问模板
utter_ask_address:
- text: "请问你要查询哪里的天气?" #自动询问模板
forms:
weather_form: {} #多轮问话表单
session_config:
session_expiration_time: 60
carry_over_slots_to_new_session: true
自定义action.py
‘’‘
@author: 小帆芽芽
date: 2021/04/25
‘’‘
from rasa_sdk.types import DomainDict
from typing import Dict, Text, Any, List, Union
from flask import jsonify
from rasa_sdk import Tracker, Action
from rasa_sdk.events import UserUtteranceReverted, Restarted, SlotSet, EventType
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.forms import FormAction
# from actions import ChatApis
# from actions.WeatherApis import get_weather_by_day
from requests import (
ConnectionError,
HTTPError,
TooManyRedirects,
Timeout
)
# from test.qachat import get_qa
from rasa_sdk import ActionExecutionRejection
from rasa_sdk.events import SlotSet, AllSlotsReset
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.forms import FormAction, REQUESTED_SLOT
import requests, random, math
import re
import json
# import jieba
import logging
logger = logging.getLogger(__name__)
# 查询天气
class QueryWeather(FormAction):
'''
心知天气API
'''
def __init__(self):
super().__init__()
# 天气查询私钥
self.KEY = '你的私钥'
self.LOCATION = 'beijing' # 所查询的位置,可以使用城市拼音、v3 ID、经纬度等
self.url = 'https://api.seniverse.com/v3/weather/daily.json' # API URL,可替换为其他 URL
self.UNIT = 'c' # 单位
self.LANGUAGE = 'zh-Hans' # 查询结果的返回语言
self.data={
'key': self.KEY,
'location': self.LOCATION,
'language': self.LANGUAGE,
'unit': self.UNIT,
'start': 0,
'days': 10
}
# 0 代表今天,1 代表明天,2代表后天
self.num = 0
def name(self) -> Text:
return "weather_form"
@staticmethod
def required_slots(tracker):
return ['address','datetime']
# 槽值映射,不管用户说什么都将填入槽中
def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict[Text, Any]]]]:
return {'address':[self.from_text()],'datetime':[self.from_text()]}
# 槽值验证
def validate_address(self,slot_value, dispatcher, tracker, domain):
# list=['北京','上海','深圳','广州']
path = './data/dict/cityname.txt'
d_ = [i.strip() for i in open(path, 'r').readlines()]
# if slot_value in list:
if slot_value in d_:
return {"address":slot_value}
else:
dispatcher.utter_message('您输入的不是地名哟')
return {"address":None}
# 槽值验证
def validate_datetime(self,slot_value, dispatcher, tracker, domain):
d_list = ['今天','明天','后天']
if slot_value in d_list:
# if slot_value in d_:
return {"datetime":slot_value}
else:
dispatcher.utter_message('暂不支持查询 {} 的天气'.format(slot_value))
return {"datetime":None}
def submit(self,dispatcher, tracker, domain):
date = tracker.get_slot('datetime')
address = tracker.get_slot('address')
self.judge_time(date)
text_day, text_night, high, low, wind_direction, humidity, wind_speed, wind_scale,date_ = self.get_weather(address)
s='{}{}({})的天气情况是:白天{},晚上{}.当天最高温度是{}摄氏度,最低温度是{}摄氏度.风向{},风速{},风力等级为{},空气湿度为{}%'.format(
address,date,date_, text_day,text_night,high,low,wind_direction,wind_speed,wind_scale,humidity
)
dispatcher.utter_message('小娜为您查询到:')
dispatcher.utter_message(s)
# return [AllSlotsReset()]
return [Restarted()]
def judge_time(self,date):
if date == '今天':
self.num = 0
elif date == '明天':
self.num = 1
elif date == '后天':
self.num = 2
def get_weather(self,address):
self.LOCATION = address
str_ = requests.get(url=self.url,params=self.data,timeout=2).text
dic = json.loads(str_)
print(dic)
# 白天天气
text_day = dic['results'][0]['daily'][self.num]['text_day']
# 夜晚天气
text_night = dic['results'][0]['daily'][self.num]['text_night']
# 最高温度
high = dic['results'][0]['daily'][self.num]['high']
# 最低温度
low = dic['results'][0]['daily'][self.num]['low']
# 风向
wind_direction = dic['results'][0]['daily'][self.num]['wind_direction']
# 湿度(百分比)
humidity = dic['results'][0]['daily'][self.num]['humidity']
# 风速
wind_speed = dic['results'][0]['daily'][self.num]['wind_speed']
# 风力等级
wind_scale = dic['results'][0]['daily'][self.num]['wind_scale']
# 日期
date_ = dic['results'][0]['daily'][self.num]['date']
return text_day,text_night,high,low,wind_direction,humidity,wind_speed,wind_scale,date_
采用flask外部调用接口
'''
@author:小帆芽芽
@date:2021/04/25
'''
import json
import re
import requests
from flask import Blueprint, render_template, request
blue = Blueprint('rasa', __name__)
REQUEST_URL = "http://localhost:5005/webhooks/rest/webhook"
HEADERS = {'Content-Type': 'application/json; charset=utf-8'}
def init_route(app):
app.register_blueprint(blue)
@blue.route('/', methods=['GET', 'POST'])
def test():
# return 'this a test page', 200
return render_template('chat.html')
@blue.route('/chat',methods=['GET'])
def chat():
data=request.args.to_dict()
message=data['message']
if message:
answer = rasaresponse('xiaofangyaya',message)
return answer
def rasaresponse(user,msg):
requestDict={'sender':user,'message':msg}
rsp=requests.post(REQUEST_URL, data=json.dumps(requestDict),headers=HEADERS)
# content=rsp.text.encode('utf-8').decode("unicode-escape")
if rsp.status_code == 200:
rsp_json=json.loads(rsp.text.encode())
content_text = ''
if len(rsp_json):
# print(rsp_json)
for i in range(len(rsp_json)):
# txt_=rsp_json[i]['text']
txt_=rsp_json[i].get('text')
print('rasa返回内容是---------->{}'.format(txt_))
if txt_:
content_text=content_text+txt_
else:
content_text=content_text + '\n' + rsp_json[i]['image']
return content_text
else:
return '哎呀,这个小娜也不懂呢~~~'
else:
return '返回错误,请重新输入问话。'
运行rasa,依次执行以下命令
# 启动服务
# 1. 启动rasa server
python -m rasa run --port 5005 -m models/20210420-153935.tar.gz --endpoints configs/endpoints.yml --credentials configs/credentials.yml --debug
# 2. 启动action server
python -m rasa run actions --port 5055 --actions actions --debug
# 3. 启动server.py
python server.py
页面测试