rasa是我去年的時候學習使用的,但是後面沒怎麼用了。如今已經過去一年了,rasa代碼的變化已經很大了,比如原來使用flask作爲網絡框架,現在已經換成性能更高的sanic了(https://www.jianshu.com/p/636833c71c2a),具體性能表如下圖所示;rasa core和rasa nlu合併成了rasa。
我看到最近一年以來,網上有很多關於rasa的相關技術文檔,但是很多都是入門級別的,或者翻譯一下rasa的官方的doc,缺乏對rasa內部組件的定製化開發和關鍵代碼的走讀。我這裏打算通過兩篇文章寫一下相關內容。
如果你是一個還沒有接觸過的rasa的萌新,你可以先看一下別人寫的技術博客先學習一下。
下面推薦幾個我覺得不錯的。
1. 來自 colin_gao 的 《rasa對話系統踩坑記》:https://www.jianshu.com/p/5d9aa2a444a3
代碼地址: https://github.com/GaoQ1/rasa_chatbot_cn
2. 來自 邱震宇(https://www.zhihu.com/people/qiu-zhen-yu-87/activities) 的 《基於RASA的task-orient對話系統解析》:https://zhuanlan.zhihu.com/p/75517803
3. rasa翻譯系列:https://zhuanlan.zhihu.com/p/88112269
4. 最後還有我自己的 《rasa安裝和測試》:https://blog.csdn.net/hero00e/article/details/85122797,不過版本已經過時了,只能看看,使用就不推薦了。
其中,第一個有10篇內容,第二個有3篇內容。
一、環境部署
先說一下我的環境:
centos7
python 3.6
rasa 1.2.0 (用的版本比較舊,不過不影響後面的開發)
rasa-sdk 1.2.0
我對應的github地址:https://github.com/tedljw/rasa_instructions
首先你需要下載rasa-1.2.0(下載地址: https://github.com/RasaHQ/rasa/tree/1.2.0)和rasa-sdk-1.2.0(下載地址: https://github.com/RasaHQ/rasa-sdk/tree/1.2.0)的代碼。分別取出rasa-1.2.0中的rasa目錄,和rasa-sdk-1.2.0中的rasa_sdk目錄放到我的代碼的根目錄下就可以了,具體如下圖所示。當然,你也可以通過pip install rasa==1.2.0 rasa-sdk==1.2.0來處理,不過我因爲會改動源碼就不這麼操作了。
下面介紹一下我的目錄結構
.
├── config.yml pipeline的component和policy的配置
├── credentials.yml 開放的端口類型,這裏我用rest
├── data 訓練需要的數據
│ ├── nlu.md
│ └── stories.md
├── domain.yml 配置你的意圖和對應的action執行的地方
├── endpoints.yml 輸出地址和端口配置
├── __init__.py
├── models
├── reference 參考代碼
├── mychat
│ ├── actions
│ │ └── actions.py action文件
│ ├── components
│ │ └── preprocessing.py components文件
│ ├── policies
│ │ └── fqa.py policy文件
│ └── web 這個是我的web端測試api
│ ├── __init__.py
│ ├── server.py
│ ├── static
│ └── templates
├── rasa rasa-1.2.0的代碼
└── rasa_sdk rasa_sdk-1.2.0的代碼
二、自定義component組件
component就是根目錄下config.yaml裏的pipeline,它屬於rasa_nlu,你可以理解爲rasa的文本預處理過程。關於如何自定義自己的component文件,官方有一個文檔說明:
component文件有以下結構構成:
name = "my_preproces" #組件名字
provides = [] #當前組件能夠計算出什麼上下文
requires = [] #當前組件需要提供什麼上下文
defaults = {} #組件的默認參數,可以被pipeline中參數覆寫
language_list = ["en"] #組件支持的語言
__init__ #組件的初始化
create #在訓練之前初始化組件
train #訓練組件,如果不需要訓練就不需要實現
persist #保存組件模型到本地以備將來使用,如果沒有需要保存的東西,可以不實現
load #定義如何加載persist(持久化)後的模型,或者說從本地加載保存的東西,若沒有保存東西到本地,也不需要實現
process #使用組件進行處理,從message中取想要的數據,計算完成後更新到message中
具體實現可以參看我的代碼中的preprocessing.py文件,你的工作主要是在process中對你收到的文本進行處理,然後通過message類的set來把你的處理結果以json的形式放進message中,然後往下游傳遞。
完成以上步驟後,你還需要去 rasa/nlu/registry.py 文件下添加你寫的component函數。
具體參考我reference目錄下的registry.py文件的 34,73,126行。
三、自定義policy組件
policy用來決定對話中的每一步將執行的action,它的配置在config.yaml中。它屬於rasa_core模塊。具體內容可以查看官方文檔:https://rasa.com/docs/rasa/core/policies/。
priority: int = 4, #policy的優先級
nlu_threshold: float = 0.3, #觸發本policy所需的最低閾值
core_threshold: float = 0.3, #觸發action的所需的最低閾值
fallback_action_name: Text = "fqa", #如果意圖或操作的置信度低於各自的閾值,則調用後備操作的名稱
train #訓練組件,如果不需要訓練就不需要實現
predict_action_probabilities #預測下一步需要執行的action,這也是我們可以自定義處理的地方
persist #保存pilicy組件模型到本地
load #加載保存好的policy組件模型
具體實現可以參考我的代碼中的fqa.py文件,你的工作主要是在predict_action_probabilities函數中對你接收到的 tracker進行操作(https://rasa.com/docs/rasa/api/tracker/),配合你能操作的action(domain類),具體的使用,你可以參考rasa的源碼或者我寫的fqa.py文件的predict_action_probabilities部分。
完成以上步驟後,你還需要去 rasa\core\policies\__init__.py 文件下添加你寫的policy類。
from mychat.policies.fqa import FqaPolicy
四、自定義action組件
如官方說述,action有4種類別,Utterance actions,Retrieval actions,Custom actions,Default actions。我們這裏討論Custom actions(https://rasa.com/docs/rasa/core/actions/#custom-actions),通過自定義的action,我們可以完成一些複雜的操作。action的使用需要rasa_sdk的支持。
一般來說,action代碼包括2個函數
name #用以返回action的名字
run #執行action的具體操作,通過傳入的tracker類來獲取對話的狀態,比如:message,slot,state等
一句話,action內,你可以編寫你的任何想法,不論是sql的調用,還是訓練好的model,網絡爬蟲。
五、編譯和運行
改了config,domain,data等需要執行一下rasa train。或者你第一運行,也需要執行以下rasa train。這個指令的目的是爲了生成多輪對話模型,當然這裏面還有你設定好的配置信息。
python -m rasa train
結果生成在在models文件中
啓動action
python -m rasa_sdk --actions mychat.actions.actions
啓動程序,其中 -m 指定train那一步生成的多輪模型的文件夾地址,--enable-api 開放web server api, --log-file log輸出文件, --endpoints 指定連接action端口
python -m rasa run -m models --enable-api --log-file out.log --endpoints endpoints.yml
最後,你可以選擇使用
curl -XPOST http://localhost:5005/webhooks/rest/webhook -d '{"sender": "user1", "message": "你好"}' -H "Content-type: application/json"
發送消息
收到回覆:
[{"recipient_id":"user1","text":"Hello World!"}]
也可以選擇我的代碼中的web前端。
只需要在根目錄下執行 python mychat/web/server.py