RASA2.0搭建中文聊天机器人
环境搭建
# 优先安装这几个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
-
页面测试
- 我的源码地址:
https://gitee.com/menfeng/rasa-weather-edition
希望点赞关注支持哦!!!!
后期还有大波福利发送