上一篇 一小時搭建微信聊天機器人 介紹瞭如何搭建一個可用的聊天機器人,但是和機器人聊完你會發現,聊天機器人實在是太傻了,來回就那麼幾句。這是因為我們給聊天機器人的資料太少,他只能在我們給的訓練集中找它認為最合適的。那麼,如何匯入更多的訓練資料呢?
我能想到最簡單的方法是找對話的資料,然後把這些資料作為訓練資料訓練機器人。
感謝 candlewill 已經收集好了大量的訓練資料,dialog_corpus https://github.com/candlewill/Dialog_Corpus 。
這個庫中包含電影臺詞、中英文簡訊息、自然語言處理相關的資料集、小黃雞語料等。這裡我選擇電影臺詞語料。
語料地址為:dgk_lost_conv:https://github.com/rustch3n/dgk_lost_conv
chatterbot 訓練邏輯處理模組
這個模組提供訓練機器人的方法,chatterbot自帶了通過輸入list來訓練(["你好", "你好啊"] 後者是前者的回答)以及通過匯入Corpus格式檔案來訓練的方式。
這裡我們選擇使用第一種,通過輸入list來訓練機器人。
處理訓練資料
首先下載資料集:
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中,那麼上述例子中的訓練資料應該被格式化為:
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。
- 開啟 www.tuling123.com,註冊賬號
- 新建兩個機器人(免費使用者最多可以建立5個,每個機器人每天最多請求5000次)
- 呼叫對話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都是一個比較麻煩的過程。
以我使用的七牛為例,獲取圖片地址的步驟如下:
- 登入七牛網站,開啟儲存空間>內容管理
- 上傳檔案
- 返回內容管理找到剛才上傳的檔案,獲取外鏈
按照這個步驟上傳一張圖片至少耗時半分鐘。
那能不能簡化這個步驟呢?
答案是可以!
微信公號是可以傳送圖片訊息的,我的做法是
- 將圖片傳送到公號
- 伺服器獲取觸發圖片訊息的處理邏輯> 將圖片使用七牛提供的
第三方資源抓取
API另存到
,七牛儲存空間 - 將設定好的圖片地址返回給微信,傳送到公號訊息對話中
示例如下圖所示:
實現步驟
- 註冊個七牛賬號
- 新建儲存空間
- 在個人中心祕鑰管理獲取 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) | 請我喝芬達 |
---|---|