微信公號DIY:訓練微信聊天機器人&公號變身圖片上傳工具

上一篇 一小時搭建微信聊天機器人 介紹瞭如何搭建一個可用的聊天機器人,可是和機器人聊完你會發現,聊天機器人實在是太傻了,來回就那麼幾句。這是由於咱們給聊天機器人的數據太少,他只能在咱們給的訓練集中找它認爲最合適的。那麼,如何導入更多的訓練數據呢?
我能想到最簡單的方法是找對話的數據,而後把這些數據做爲訓練數據訓練機器人。python

感謝 candlewill 已經收集好了大量的訓練數據,dialog_corpus https://github.com/candlewill/Dialog_Corpusgit

這個庫中包含電影臺詞、中英文短信息、天然語言處理相關的數據集、小黃雞語料等。這裏我選擇電影臺詞語料。github

語料地址爲:dgk_lost_conv:https://github.com/rustch3n/dgk_lost_conv數據庫

chatterbot 訓練邏輯處理模塊

這個模塊提供訓練機器人的方法,chatterbot自帶了經過輸入list來訓練(["你好", "你好啊"] 後者是前者的回答)以及經過導入Corpus格式文件來訓練的方式。json

這裏咱們選擇使用第一種,經過輸入list來訓練機器人。api

處理訓練數據

首先下載數據集:服務器

wget https://codeload.github.com/rustch3n/dgk_lost_conv/zip/master
# 解壓
$ unzip dgk_lost_conv-master.zip複製代碼

咱們先打開一個文件看下數據結構:微信

E
M 你得想一想辦法 我弟弟是無辜的
M 他但是美國公民啊
M 對此我也無能爲力
M 你固然能
M 再去犯罪現場看看 定能證明清白
M 你看 我不過是個夜間辦事員而已
M 你若真想解決問題
M 最好等領事來
M 他早上才上班
M 我很抱歉
E
M 那我本身來搞定
M 你兄弟
M 關在哪一個監獄?
M 索納監獄
E
M 怎麼了?
M 那裏關的都是最窮兇極惡的罪犯
M 別的監獄都不收複製代碼

.conv 語料文件中:E 是分隔符 M 表示會話。由於我是使用輸入list 的方式訓練數據,這時我能夠以分隔符E爲分隔,將一段對話放入一個list中,那麼上述例子中的訓練數據應該被格式化爲:markdown

convs = [
    [
       '你得想一想辦法 我弟弟是無辜的',
       '他但是美國公民啊',
       '對此我也無能爲力',
       '你固然能',
       '再去犯罪現場看看 定能證明清白',
       '你看 我不過是個夜間辦事員而已',
       '你若真想解決問題',
       '最好等領事來',
       '他早上才上班',
       '我很抱歉'
    ],
    [
       '那我本身來搞定',
       '你兄弟',
       '關在哪一個監獄?',
       '索納監獄',
    ],
    [
       '怎麼了?',
       '那裏關的都是最窮兇極惡的罪犯',
       '別的監獄都不收',
    ]
]複製代碼

導入訓練數據的腳本以下:數據結構

from chatterbot import ChatBot
from chatterbot.trainers import ListTrainer

# 初始化聊天機器人
momo = ChatBot(
    'Momo',
    storage_adapter='chatterbot.storage.MongoDatabaseAdapter', # 使用mongo存儲數據
    logic_adapters=[ # 指定邏輯處理模塊
            "chatterbot.logic.BestMatch",
            "chatterbot.logic.MathematicalEvaluation",
            "chatterbot.logic.TimeLogicAdapter",
        ],
    input_adapter='chatterbot.input.VariableInputTypeAdapter',
    output_adapter='chatterbot.output.OutputAdapter',
    database='chatterbot', # 指定數據庫
    read_only=True
)

# 讀取.conv 數據文件,由於我服務器配置較低,因此選擇了一個內容較少的文件
# 這個函數是一個生成器
def read_conv(filename='prisonb.conv'):
    with open(filename, 'rt') as f:
        conv = []
        # 逐行讀取
        for line in f:
            _line = line.replace('\n', '').strip()  # 預處理字符串 去掉首位空格
            if _line == 'E':  # 若是是分隔符 表示對話結束 返回對話列表
                yield conv
                conv = []  # 重置對話列表
            else:  # 不是分隔符則將內容加入對話列表
                c = _line.split()[-1]  # 其實這裏若是對話中包含空格 對話數據會不完整,應該只去掉M和開頭的空格
                conv.append(c)


def traine_momo():
    for conv in read_conv():
        print(conv)
        momo.set_trainer(ListTrainer) # 指定訓練方式
        momo.train(conv) # 訓練數據


def main():
    traine_momo()


if __name__ == '__main__':
    main()複製代碼

這個腳本比較簡單,只是簡單的將數據從對話文件中讀取出來,而後拼接爲對話列表輸入聊天機器人。

因爲這裏對話大部分都是多行數據,聊天機器人匹配結果時運算量會大幅提高,我單核cpu的服務器在導入一個700k 的語料文件後每次聊天都會讓cpu飈到100%!🤦‍ 無奈之下只能刪掉大半數據。

對話示例如圖:

使用電影臺詞訓練後的聊天截圖
使用電影臺詞訓練後的聊天截圖

導入電影臺詞後,雖然訓練數據大幅提高,可是你會發現聊天機器人開始答非所問了,這是由於聊天數據噪音太大,對白也有點問題。

使用圖靈機器人訓練

以前在對比聊天機器人實現方案的時候,我試用過 圖靈機器人,他們號稱中文語境下智能渡最高的機器人大腦。他們的對話比我本身的搭建的靠譜不少,那麼咱們是否是能夠利用一下他的數據呢?

個人方案是這樣的,在圖靈機器人新建兩個機器人教練A 和 教練B,讓兩個機器人互相對話,而後把訓練數據導入chatterbot。

  1. 打開 www.tuling123.com,註冊帳號
  2. 新建兩個機器人(免費用戶最多能夠建立5個,每一個機器人天天最多請求5000次)
  3. 調用對話API,讓兩個機器人互相聊天

建好機器人後的界面:

機器人示例🤖
機器人示例🤖

訓練示例代碼以下:

# tuling_trainer.py
import sys
from time import sleep

from chatterbot import ChatBot
from chatterbot.trainers import ListTrainer

import requests

API_URL = "http://www.tuling123.com/openapi/api"
API_KEY0 = ""  # 機器人1 的key
API_KEY1 = ""  # 機器人2 的key

# 初始化chatterbot
momo = ChatBot(
    'Momo',
    storage_adapter='chatterbot.storage.MongoDatabaseAdapter',
    logic_adapters=[
            "chatterbot.logic.BestMatch",
            "chatterbot.logic.MathematicalEvaluation",
            "chatterbot.logic.TimeLogicAdapter",
        ],
    input_adapter='chatterbot.input.VariableInputTypeAdapter',
    output_adapter='chatterbot.output.OutputAdapter',
    database='chatterbot',
    read_only=True
)

# 請求圖靈機器人接口
def ask(question, key, name):
    params = {
        "key": key,
        "userid": name,
        "info": question,
    }
    res = requests.post(API_URL, json=params)
    result = res.json()
    answer = result.get('text')
    return answer


def A(bsay):
    # 打印 A 和 B 的對話內容
    print('B:', bsay)
    answer = ask(bsay, API_KEY0, 'momo123')
    print('A:', answer)
    return answer


def B(asay):
    print('A:', asay)
    answer = ask(asay, API_KEY1, 'momo456')
    print('B', answer)
    return answer


def tariner(asay):
    momo.set_trainer(ListTrainer)  # 設置處理方式
    while True:  # 兩個機器人訓練的主循環
        conv = []
        conv.append(asay) # 先把 A 說的第一句加入到對話列表
        bsay = B(asay)  # A 先問 B
        conv.append(bsay) # 將B 的回答加入到對話列表
        momo.train(conv) # 將對話用於訓練
        print(conv)
        conv = []
        conv.append(bsay) # 用B的對話 去問 A 步驟和上述方式一致
        asay = A(bsay)
        conv.append(asay)
        momo.train(conv)
        print(conv)
        sleep(5)  # 控制頻率


def main(asay):
    tariner(asay)


if __name__ == '__main__':
    main(*sys.argv[1:])  # 接收參數做爲開始的第一句話

# 執行腳本
# python tuling_trainer.py 你好?複製代碼

使用圖靈聊天機器人訓練的時候是須要監測的,由於若是兩個機器人說的內容同樣的時候,機器人可能會一直重複同一句話,直到調用次數耗盡,你須要看一下兩個機器人的對話是否陷入了僵局。

固然也能夠在程序中加入判斷,先多設定幾個開始打招呼的句子,若是一句話連續出現屢次的時候,換下一個句子糾正他們。

如下是我訓練了兩天以後的結果:

對話示例
對話示例

雖然仍是答非所問,可是已經比以前像樣了。

圖靈聊天機器人免費版天天可調用5000 次,若是以爲次數太少能夠多新建幾個輪流使用

聊天機器人的配置及訓練方式就到這裏了,接下來介紹個更實用的功能,如何讓微信公號變成圖牀。

如何讓微信公號化身圖片上傳助手

在使用 markdown 格式來寫文章的過程當中,發現圖片地址是一個比較麻煩的事情,每次貼圖獲取圖片URL都是一個比較麻煩的過程。
以我使用的七牛爲例,獲取圖片地址的步驟以下:

  1. 登陸七牛網站,打開存儲空間>內容管理
  2. 上傳文件
  3. 返回內容管理找到剛纔上傳的文件,獲取外鏈

按照這個步驟上傳一張圖片至少耗時半分鐘。

那能不能簡化這個步驟呢?

答案是能夠!

微信公號是能夠發送圖片消息的,個人作法是

  1. 將圖片發送到公號
  2. 服務器獲取觸發圖片消息的處理邏輯> 將圖片使用七牛提供的第三方資源抓取API另存到,七牛存儲空間
  3. 將設定好的圖片地址返回給微信,發送到公號消息對話中

示例以下圖所示:

上傳圖片到七牛
上傳圖片到七牛

實現步驟

  • 註冊個七牛帳號
  • 新建存儲空間
  • 在我的中心祕鑰管理獲取 AccessKey 和 SecreKey
  • pip install qiniu

代碼實現以下:

# media.py
# 圖片抓取邏輯處理
from qiniu import Auth, BucketManager

from momo.settings import Config

def qiniu_auth():
    access_key = str(Config.QINIU_ACCESS_TOKEN)
    secret_key = str(Config.QINIU_SECRET_TOKEN)
    auth = Auth(access_key, secret_key)
    return auth

def media_fetch(media_url, media_id):
    '''抓取url的資源存儲在庫'''
    auth = qiniu_auth()
    bucket = BucketManager(auth)
    bucket_name = Config.QINIU_BUCKET  # 存儲空間名稱
    ret, info = bucket.fetch(media_url, bucket_name, media_id) # 參數依次是第三方圖片地址,空間名稱,目標文件名
    if info.status_code == 200:
        return True, media_id # 若是上傳成功,返回文件名
    return False, None複製代碼

抓取第三方圖片文檔地址爲:第三方資源抓取 https://developer.qiniu.com/kodo/api/1263/fetch

微信圖片消息處理邏輯代碼:

class WXResponse(_WXResponse):

    def _image_msg_handler(self):
        media_id = self.data['MediaId']
        picurl = None
        if not picurl:
            picurl = self.data['PicUrl']  # 從消息中獲取圖片地址
        is_succeed, media_key = media_fetch(picurl, media_id) # 使用圖片抓取接口將圖片存儲到七牛並獲取圖片文件名
        if is_succeed:
            qiniu_url = '{host}/{key}'.format(host=Config.QINIU_HOST, key=media_key) # 拼接圖片地址
        else:
            qiniu_url = '圖片上傳失敗,請從新上傳'
        self.reply_params['content'] = qiniu_url # 返回圖片地址
        self.reply = TextReply(**self.reply_params).render()複製代碼

代碼已開源道github,詳細代碼邏輯參考 gusibi/momo: https://github.com/gusibi/momo/tree/chatterbot

歡迎試用體驗:

  • 請不要上傳高清圖片,微信會壓縮損壞圖片質量
  • 也不要上傳太我的的圖片,畢竟內容我能看到

總結

這一篇主要提供了兩個訓練 chatterbot 的思路,以及使用公號做爲圖片上傳客戶端提升上傳圖片的效率的解決方法。
接下來公號仍是繼續開發,準備給公號加一個記帳功能,促使本身養成記帳的習慣。

預告

下一篇的公號DIY 將介紹 記帳的功能設計以及實現思路


最後,感謝女友支持。

歡迎關注(April_Louisa) 請我喝芬達
歡迎關注
歡迎關注
請我喝芬達
請我喝芬達
相關文章
相關標籤/搜索