日萌社
人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度學習實戰(不定時更新)
在線聊天的總體架構與工具介紹:Flask web、Redis、Gunicorn服務組件、Supervisor服務監控器、Neo4j圖數據庫
linux 安裝 neo4j、linux 安裝 Redis、supervisor 安裝
在線部分:werobot服務、主要邏輯服務、句子相關模型服務、BERT中文預訓練模型+微調模型(目的:比較兩句話text1和text2之間是否有關聯)、模型在Flask部署
離線部分+在線部分:命名實體審覈任務RNN模型、命名實體識別任務BiLSTM+CRF模型、BERT中文預訓練+微調模型、werobot服務+flask
9.1 系統聯調與測試
- 學習目標:
- 掌握如何啓動系統在線部分的服務.
- 掌握對運行服務分別進行測試的過程.
- 系統架構圖:
- 系統在線部分的主要服務:
- werobot服務
- 主要邏輯服務
- 句子相關模型服務
- redis服務(會話管理)
- neo4j服務(圖數據查詢)
- 說明: 系統聯調與測試是對系統在線部分服務的聯調與測試, 不包含離線部分的內容.
- 啓動系統在線部分的服務:
- 以掛起的方式啓動werobot服務
- 使用supervisor啓動主要邏輯服務及其redis服務
- 以掛起的方式啓動子相關模型服務
- 啓動和查看neo4j服務(默認已啓動)
- 以掛起的方式啓動werobot服務:
nohup python /data/wr.py &
- 運行位置: /dara/目錄下.
- 通過端口查看掛起的服務進程:
# 通過yum安裝lsof命令
sudo yum install lsof -y
# 查看80端口的進程
lsof -i:80
- 使用supervisor啓動主要邏輯服務及其redis服務
- supervisor配置文件簡要分析:
...
; 使用gunicorn啓動基於Flask框架的主要邏輯服務
[program:main_server]
command=gunicorn -w 1 -b 0.0.0.0:5000 app:app ; the program (relative uses PATH, can take args)
stopsignal=QUIT ; signal used to kill process (default TERM)
stopasgroup=false ; send stop signal to the UNIX process group (default false)
killasgroup=false ; SIGKILL the UNIX process group (def false)
stdout_logfile=./log/main_server_out ; stdout log path, NONE for none; default AUTO
stdout_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
stderr_logfile=./log/main_server_error ; stderr log path, NONE for none; default AUTO
stderr_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
; 啓動redis服務,作爲會話管理數據庫
[program:redis]
command=redis-server
- 啓動服務:
# 使用supervisord命令, 讀取指定目錄下的文件
supervisord -c /data/doctor_online/main_serve/supervisor.conf
- 查看啓動的服務狀態
supervisorctl status all
- 輸出效果:
main_server RUNNING pid 31609, uptime 0:32:20
redis RUNNING pid 31613, uptime 0:32:18
- 以掛起的方式啓動句子相關模型服務:
- 編寫啓動腳本start.sh
# 腳本中是使用gunicorn啓動服務的命令
gunicorn -w 1 -b 0.0.0.0:5001 app:app
- 以掛起的方式啓動服務
nohup sh /data/doctor_online/bert_serve/start.sh &
- 通過端口查看掛起的服務進程
# 通過yum安裝lsof命令
sudo yum install lsof -y
# 查看5001端口的進程
lsof -i:5001
- 啓動和查看neo4j服務(圖數據查詢):
# neo4j服務在之前應該一直處在啓動狀態
neo4j start
# 查看服務啓動狀態:
neo4j status
- 進行測試:
- 第一步: 明確測試說明.
- 第二步: 添加打印測試內容.
- 第三步: 重新啓動主要邏輯服務.
- 第四步: 進行數據流測試並查看打印日誌.
- 第一步: 測試說明
- 因爲主要邏輯服務是所有在線服務的中心服務(該服務將接收或發送請求給其他服務), 因此我們的測試打印信息都在主要邏輯服務中進行.
- 第二步: 添加打印測試內容
class Handler(object):
"""主要邏輯服務的處理類"""
def __init__(self, uid, text, r, reply):
"""
:param uid: 用戶唯一標示uid
:param text: 該用戶本次輸入的文本
:param r: redis數據庫的連接對象
:param reply: 規則對話模版加載到內存的對象(字典)
"""
self.uid = uid
self.text = text
self.r = r
self.reply = reply
def non_first_sentence(self, previous):
"""
description: 非首句處理函數
:param previous: 該用戶當前句(輸入文本)的上一句文本
:return: 根據邏輯圖返回非首句情況下的輸出語句
"""
# 嘗試請求模型服務, 若失敗則打印錯誤結果
###################################################
# 能夠打印該信息, 說明已經進入非首句處理函數.
print("準備請求句子相關模型服務!")
###################################################
try:
data = {"text1": previous, "text2": self.text}
result = requests.post(model_serve_url, data=data)
if not result.text: return unit_chat(self.text)
###################################################
# 能夠打印該信息, 說明句子相關模型服務請求成功.
print("句子相關模型服務請求成功, 返回結果爲:", result.text)
###################################################
except Exception as e:
print("模型服務異常:", e)
return unit_chat(self.text)
###################################################
# 能夠打印該信息, 說明開始準備請求neo4j查詢服務.
print("請求模型服務後, 準備請求neo4j查詢服務!")
###################################################
# 繼續查詢圖數據庫, 並獲得結果
s = query_neo4j(self.text)
###################################################
# 能夠打印該信息, 說明neo4j查詢成功.
print("neo4j查詢服務請求成功, 返回結果:", s)
###################################################
# 判斷結果爲空列表, 則直接使用UnitAPI返回
if not s: return unit_chat(self.text)
# 若結果不爲空, 獲取上一次已回覆的疾病old_disease
old_disease = self.r.hget(str(self.uid), "previous_d")
if old_disease:
# new_disease是本次需要存儲的疾病, 是已經存儲的疾病與本次查詢到疾病的並集
new_disease = list(set(s) | set(eval(old_disease)))
# res是需要返回的疾病, 是本次查詢到的疾病與已經存儲的疾病的差集
res = list(set(s) - set(eval(old_disease)))
else:
# 如果old_disease爲空, 則它們相同都是本次查詢結果s
res = new_disease = list(set(s))
# 存儲new_disease覆蓋之前的old_disease
self.r.hset(str(self.uid), "previous_d", str(new_disease))
# 設置過期時間
self.r.expire(str(self.uid), ex_time)
# 將列表轉化爲字符串, 添加到規則對話模版中返回
res = ",".join(s)
###################################################
# 能夠打印該信息, 說明neo4j查詢後有結果並將使用規則對話模版.
print("使用規則對話模版進行返回對話的生成!")
###################################################
print("###################################################")
return self.reply["2"] %res
def first_sentence(self):
"""首句處理函數"""
# 直接查詢圖數據庫, 並獲得結果
###################################################
# 能夠打印該信息, 說明進入了首句處理函數並馬上進行neo4j查詢
print("該用戶近期首次發言, 不必請求模型服務, 準備請求neo4j查詢服務!")
###################################################
s = query_neo4j(self.text)
###################################################
# 能夠打印該信息, 說明已經完成neo4j查詢.
print("neo4j查詢服務請求成功, 返回結果爲:", s)
###################################################
# 判斷結果爲空列表, 則直接使用UnitAPI返回
if not s: return unit_chat(self.text)
# 將s存儲爲"上一次返回的疾病"
self.r.hset(str(self.uid), "previous_d", str(s))
# 設置過期時間
self.r.expire(str(self.uid), ex_time)
# 將列表轉化爲字符串, 添加到規則對話模版中返回
res = ",".join(s)
###################################################
# 能夠打印該信息, 說明neo4j查詢後有結果並將使用規則對話模版.
print("使用規則對話生成模版進行返回對話的生成!")
###################################################
print("###################################################")
return self.reply["2"] %res
# 設定主要邏輯服務的路由和請求方法
@app.route('/v1/main_serve/', methods=["POST"])
def main_serve():
###################################################
# 能夠打印該信息, 說明werobot服務發送請求成功.
print("已經進入主要邏輯服務, werobot服務運行正常!")
###################################################
# 接收來自werobot服務的字段
uid = request.form['uid']
text = request.form['text']
# 從redis連接池中獲得一個活躍連接
r = redis.StrictRedis(connection_pool=pool)
# 根據該uid獲取他的上一句話(可能不存在)
previous = r.hget(str(uid), "previous")
# 將當前輸入的文本設置成上一句
r.hset(str(uid), "previous", text)
###################################################
# 能夠打印該信息, 說明redis能夠正常讀取和寫入數據.
print("已經完成初次會話管理, redis運行正常!")
###################################################
# 讀取規則對話模版內容到內存
reply = json.load(open(reply_path, "r"))
# 實例化主要邏輯處理對象
handler = Handler(uid, text, r, reply)
# 如果previous存在, 說明不是第一句話
if previous:
# 調用non_first_sentence方法
return handler.non_first_sentence(previous)
else:
# 否則調用first_sentence()方法
return handler.first_sentence()
- 第三步: 重新啓動主要邏輯服務
supervisorctl restart all
- 第四步: 進行數據流測試並查看打印日誌
- 測試請求1: 用戶關注公衆號後首次發送一些症狀描述.
- 測試請求2: 首次發送後用戶繼續發送一些症狀描述.
- 測試請求1:
- 用戶關注公衆號後首次發送一些症狀描述.
- 對應數據流:
- werobot服務-->請求主要邏輯服務-->主要邏輯服務中請求redis服務-->請求neo4j查詢服務-->使用規則對話模版/UnitAPI.
- 對應操作:
- 關注公衆號(使用新用戶), 發送"我最近有些腹痛".
- 查看主要邏輯服務日誌:
cat /data/doctor_online/main_serve/log/main_server_out
- 日誌打印結果:
## 打印如下結果說明測試成功!
已經進入主要邏輯服務, werobot服務運行正常!
已經完成初次會話管理, redis運行正常!
該用戶近期首次發言, 不必請求模型服務, 準備請求neo4j查詢服務!
neo4j查詢服務請求成功, 返回結果爲: ['癲癇', '小兒糖尿病', '腎上腺危象', '異位急性闌尾炎', '急性膽囊炎']
使用規則對話模版進行返回生成的對話!
- 測試請求2:
- 首次發送後用戶繼續發送一些症狀描述.
- 對應數據流:
- werobot服務-->請求主要邏輯服務-->主要邏輯服務中請求redis服務-->請求句子相關模型服務-->請求neo4j查詢服務-->使用規則對話模版/UnitAPI.
- 對應操作:
- 發送"我最近有些腹痛"後, 繼續發送"並且左腹部有一些紅點".
- 日誌打印結果:
## 打印如下結果說明測試成功!(使用UnitAPI返回結果)
已經進入主要邏輯服務, werobot服務運行正常!
已經完成初次會話管理, redis運行正常!
準備請求句子相關模型服務!
句子相關模型服務請求成功, 返回結果爲: 1
請求模型服務後, 準備請求neo4j查詢服務!
neo4j查詢服務請求成功, 返回結果: []
- 注意: 打印日誌若不能即時出現, 重新啓動主要邏輯服務即可.
-
本章總結:
- 學習了掌握如何啓動系統在線部分的服務:
- 以掛起的方式啓動werobot服務
- 使用supervisor啓動主要邏輯服務及其redis服務
- 以掛起的方式啓動子相關模型服務
- 啓動和查看neo4j服務(默認已啓動)
- 學習瞭如何進行測試:
- 第一步: 明確測試說明.
- 第二步: 添加打印測試內容.
- 第三步: 重新啓動主要邏輯服務.
- 第四步: 進行數據流測試並查看打印日誌.
- 第一步: 測試說明
- 因爲主要邏輯服務是所有在線服務的中心服務(該服務將接收或發送請求給其他服務), 因此我們的測試打印信息都在主要邏輯服務中進行.
- 第二步: 添加打印測試內容
- 第三步: 重新啓動主要邏輯服務
- 第四步: 進行數據流測試並查看打印日誌
- 測試請求1: 用戶關注公衆號後首次發送一些症狀描述.
- 測試請求2: 首次發送後用戶繼續發送一些症狀描述.
- 學習了掌握如何啓動系統在線部分的服務:
- 注意事項:
- 這個安裝手冊只適用於操作系統: centos7.
- 安裝部署步驟:
- 1: 拷貝必備文件.
- 2: 安裝Anaconda科學計算環境, 包括python2, pip, pandas, numpy, matplotplib等科學計算包.
# 將環境包安裝在/root/目錄下
cd /root
curl -O https://repo.anaconda.com/archive/Anaconda3-5.2.0-Linux-x86_64.sh
sh Anaconda3-2019.07-Linux-x86_64.sh
# 配置~/.bashrc, 添加一行: export PATH=/root/anaconda/bin/:$PATH
- 3: 安裝項目需要的若干獨立工具.
# 安裝Flask
pip install Flask==1.1.1
# 安裝Redis數據庫
yum install redis -y
# 安裝python中的redis驅動
pip install redis
# 安裝gunicorn
pip install gunicorn==20.0.4
# 安裝supervisor
yum install supervisor -y
# 安裝lsof
yum install lsof -y
- 4: 安裝項目需要的重要工具Pytorch.
# 安裝pytorch
pip install pytorch
- 5: 安裝圖數據庫neo4j.
# 第一步: 將neo4j安裝信息載入到yum檢索列表
cd /tmp
wget http://debian.neo4j.org/neotechnology.gpg.key
rpm --import neotechnology.gpg.key
cat <<EOF> /etc/yum.repos.d/neo4j.repo
# 寫入下面內容
[neo4j]
name=Neo4j RPM Repository
baseurl=http://yum.neo4j.org/stable
enabled=1
gpgcheck=1
# 第二步: 使用yum install命令安裝
yum install neo4j-3.3.5
# 第三步: 使用自己的配置文件
cp /data/neo4j.conf /etc/neo4j/neo4j.conf
- 6: 啓動neo4j圖數據庫並查看狀態.
# 啓動neo4j命令
neo4j start
# 查看狀態命令
neo4j status
- 7: 使用腳本生成圖譜.
# 執行已經寫好的腳本代碼, 將數據寫入到neo4j數據庫中
python /data/doctor_offline/neo4j_write.py
- 8: 使用腳本訓練模型.
# 在線部分只有一個模型bert-chinese
cd /data/doctor_online/bert_server/
python train.py
- 9: 以掛起的方式啓動werobot服務.
# 啓動werobot服務, 使得用戶可以通過微信接口和AI醫生完成對話.
nohup python /data/wr.py &
- 10: 使用supervisor啓動主要邏輯服務及其redis服務.
# supervisor配置文件簡要分析
# 文件路徑位置/data/doctor_online/main_serve/supervisor.conf
; 使用gunicorn啓動基於Flask框架的主要邏輯服務
[program:main_server]
command=gunicorn -w 1 -b 0.0.0.0:5000 app:app ; the program (relative uses PATH, can take args)
stopsignal=QUIT ; signal used to kill process (default TERM)
stopasgroup=false ; send stop signal to the UNIX process group (default false)
killasgroup=false ; SIGKILL the UNIX process group (def false)
stdout_logfile=./log/main_server_out ; stdout log path, NONE for none; default AUTO
stdout_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
stderr_logfile=./log/main_server_error ; stderr log path, NONE for none; default AUTO
stderr_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
; 啓動redis服務,作爲會話管理數據庫
[program:redis]
command=redis-server
# 使用supervisord命令, 讀取指定目錄下的文件
supervisord -c /data/doctor_online/main_serve/supervisor.conf
# 查看啓動的服務狀態
supervisorctl status
- 11: 以掛起的方式啓動句子相關模型服務.
# 以掛起的方式啓動服務, 代碼已經預先編寫好
# 腳本start.sh中的內容是 gunicorn -w 1 -b 0.0.0.0:5001 app:app
nohup sh /data/doctor_online/bert_serve/start.sh &
- 12: 啓動和查看neo4j服務(圖數據查詢):
# neo4j服務在之前應該一直處在啓動狀態
neo4j start
# 查看服務啓動狀態:
neo4j status
- 13: 進行測試.
測試1: 關注公衆號(新用戶), 發送"我最近有些腹痛".
測試2: (老用戶)發送"我最近有些腹痛"後, 繼續發送"並且左腹部有一些紅點".