系統聯調測試與部署

日萌社

人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度學習實戰(不定時更新)


智能對話系統:Unit對話API

在線聊天的總體架構與工具介紹:Flask web、Redis、Gunicorn服務組件、Supervisor服務監控器、Neo4j圖數據庫

linux 安裝 neo4jlinux 安裝 Redissupervisor 安裝

neo4j圖數據庫:Cypher

neo4j圖數據庫:結構化數據流水線、非結構化數據流水線

命名實體審覈任務:BERT中文預訓練模型

命名實體審覈任務:構建RNN模型

命名實體審覈任務:模型訓練

命名實體識別任務:BiLSTM+CRF part1

命名實體識別任務:BiLSTM+CRF part2

命名實體識別任務:BiLSTM+CRF part3

在線部分: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: (老用戶)發送"我最近有些腹痛"後, 繼續發送"並且左腹部有一些紅點".

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章