python制作聊天机器人原理_用 Python 来做一个聊天机器人吧!(一)
在我的一個回答里,我提到了用 Python 搭建聊天機器人。從今天開始,我就帶著大家從0開始搭建一個聊天機器人。
(順便說一句,我喜歡把鏈接像上面這樣加在文字里,如果找不到文中所說的資源,可以看看周圍有沒有鏈接。)
準備工作
首先,你要有一臺安裝了 Python 的電腦,推薦 Python3.6+。另外,系統最好使用 Windows 系統,因為把機器人和 QQ 對接的軟件 CoolQ 只有 Windows 版,雖然使用 Docker 和 wine 可以在其它系統上運行,但不能保證穩定性。
然后,你需要在系統中安裝并運行 MongoDB 數據庫服務。安裝方法可以看這里。記得安裝完成之后運行 MongoDB 服務,也就是把 MongoDB 作為服務安裝到系統中,以保持后臺運行。
其次,你可能會需要一個好看的控制臺,最好像 Conemu 一樣既方便又美觀的。畢竟寫累了還可以舔舔老婆(劃去
Chatterbot
Chatterbot 是一個 Python 庫,我們的聊天機器人就是主要基于這一個庫。
安裝和其他的 Python 庫一樣簡單:
pip3 install chatterbot chatterbot_corpus
其中 chatterbot_corpus 是 Chatterbot 自帶的語料庫。
現在簡單說一下 Chatterbot 的原理。Chatterbot 是比較簡單的聊天機器人,它需要大量對話語料來支撐它的運行。當用戶給它一個輸入時,它會在所有的語料庫中尋找和這句話最相似的一句話,然后返回語料庫中的下一句。
所以,在使用 Chatterbot 前,我們需要先進行訓練。
from chatterbot import ChatBot
from chatterbot.trainers import ChatterBotCorpusTrainer
bot = ChatBot(
'Sakura',
storage_adapter='chatterbot.storage.MongoDatabaseAdapter'
)
trainer = ChatterBotCorpusTrainer(bot)
trainer.train("chatterbot.corpus.chinese")
trainer.train("chatterbot.corpus.english")
我們分析一下這幾行代碼。
bot = ChatBot(
'Sakura',
storage_adapter='chatterbot.storage.MongoDatabaseAdapter'
)
這是創建一個聊天機器人,名字叫 Sakura(你也可以改成自己起的名字),使用 MongoDB 中的數據。(其實 Chatterbot 還支持 SQL,但是速度太慢了。)
這句代碼里面有一個單詞 adapter,官方翻譯為“適配器”。其實它更準確的含義是“組件”。創建 Chatbot 時還有很多 xxx_adapter 這樣的參數,可以為機器人開啟各種各樣的功能。不過有一點要注意,有些功能可能只對于英語進行了適配,對其他語言支持并不好。
trainer = ChatterBotCorpusTrainer(bot)
trainer.train("chatterbot.corpus.chinese")
trainer.train("chatterbot.corpus.english")
這幾行就是具體的訓練代碼了。注意,這是最新版(2019/8/18)的寫法,之前版本有所不同,使用的是bot.set_trainer(ChatterBotCorpusTrainer)和bot.train,具體寫法可以參看網上其他文章。
chatterbot.corpus.chinese是 Chatterbot 自帶的語料庫之一。 Chatterbot 的英文語料庫是非常不錯的,只是數據量有點少。但是 Chatterbot 的中文語料庫是由英文語料庫完全機器翻譯來的,而且不太符合中文語境。我自己爬取網絡言情小說,提取其中的對話,整理了一個語料庫,可以替換 chatterbot 自帶的語料庫。
上面所說的訓練代碼單獨保存再一個文件里,因為在每次改動語料庫之前它只需要運行一次。
現在,把訓練的代碼運行一下,不出意外的話,你會看到一系列進度條,大概這樣:Conemu 支持控制臺背景圖片,欸嘿嘿~(可以猜一下背景是誰,雖然猜對了也沒有獎)
如果你在上面的[nltk_data]那里卡住了,屬于網絡環境的問題,我也沒有辦法,只能放棄 Chatterbot 框架了(之后的系列文章中會有涉及)。
(2020/2/14補充)注意!如果在 Chatterbot 啟動的時候,出現以[nltk_data]開頭的網絡錯誤,請看下面的補充內容! 即使前幾次啟動成功,在之后的某一次啟動失敗,也是管用的!(2020/2/3補充)破案了!出現這個問題的原因是 chatterbot 把判斷 nltk 數據是否存在的代碼寫錯了,導致每次啟動都需要下載數據,再加上特殊的網絡環境,就會出現這個問題。解決方法如下:首先手動下載 nltk 數據(方法自行百度),然后找到 chatterbot 目錄(一般在python目錄/Lib/site-packages/chatterbot)中的 utils.py,將最后面幾個函數中的nltk_download_corpus('stopwords'),nltk_download_corpus('averaged_perceptron_tagger'),nltk_download_corpus('vader_lexicon')分別改為 nltk_download_corpus('corpora/stopwords'),nltk_download_corpus('taggers/averaged_perceptron_tagger'),nltk_download_corpus('sentiment/vader_lexicon')。
訓練完成之后,機器人就能支持基本的對話了。
那么,怎么在自己的代碼里插入這個機器人呢?
首先,要創建機器人實例,代碼和上面訓練時一樣:
from chatterbot import ChatBot
bot = ChatBot(
'Sakura',
storage_adapter='chatterbot.storage.MongoDatabaseAdapter'
)
bot 對象有一個get_response方法,顧名思義,就是獲取一句回答。
現在可以試一下:
print(bot.get_response('你好嗎?'))
在經過短暫的等待之后,就能看到機器人的回答啦~
print(bot.get_response('你好嗎?'))
# 輸出:你好!
get_response返回的是一個Statement對象,它有兩個常用的屬性text和confindence,分別代表返回的語句的內容和可信度(0到1)。
r = bot.get_response('你好嗎?')
print('{},confidence={}'.format(r.text, r.confidence))
# 輸出:你好! ,confidence=1.0
這就是基本操作了。雖然也沒有進階操作就對了(劃去
然后是一只無限對話的小程序:
from chatterbot import ChatBot
bot = ChatBot(
'Sakura',
storage_adapter='chatterbot.storage.MongoDatabaseAdapter'
)
def r(s):return bot.get_response(s).text
while True:
i = input('>>> ').strip()
if i != 'exit':
print(r(i))
else:
break
享受和機器人沙雕對話的樂趣吧!
CoolQ
現在我們已經有了能用的機器人了,但是只有我們一個人和機器人對話沒有意思,接下來我們要把它部署到QQ上。
首先你要有一個QQ小號,當然不怕嚇到朋友的同學也可以用自己的大號當機器人。
我們使用的軟件是酷Q,一個專門用于架設QQ機器人的軟件。酷Q Air 版可以免費使用,支持基本的接收發送文字消息等功能。
運行酷Q并登錄之后,我們會在屏幕上看到一個懸浮窗:當然頭像是你的賬號的頭像咯
右鍵懸浮窗,選擇「應用-應用管理」菜單,可以看到一個這樣的界面:
這里需要解釋一下酷Q運行的原理了。酷Q是依賴于安裝的各種「應用」運行的,每個應用其實是一個動態鏈接庫,酷Q通過調用動態鏈接庫的對應接口,執行應用的功能。但是問題來了,Python 并不能編譯成動態鏈接庫,該怎么辦呢?
大家注意到我的應用列表中最后一個「HTTP API」了嗎?這就是解決方法。CoolQ HTTP API是一個將酷Q的接口封裝為HTTP接口或Socket接口的應用,理論上,它可以解決一切編程語言連接酷Q的問題。
在 CoolQ HTTP API 的 gtihub 倉庫的 release 頁面可以找到最新版本的下載鏈接,下載完成之后,將 cpk 文件放入酷Q 目錄下的 app 文件夾中。
然后我們需要 Python 端的對應接口。Aiocqhttp 就是 Python 上的 CoolQ HTTP API 接口。同樣,它可以用 pip 安裝:
pip3 install aiocqhttp
在連接 CoolQ HTTP API 時,我推薦使用反向 WebSocket 方式,雖然配置起來有點麻煩,但是能保證穩定運行。
首先配置 CoolQ HTTP API。在酷Q目錄\app\io.github.richardchien.coolqhttpapi\config下,找到一個文件名為QQ號的 json 文件,按照如下步驟進行:增加如下兩行
"ws_reverse_url": "ws://127.0.0.1:7700/ws/",
"use_ws_reverse": true,
(如果端口號沖突,可以把這里的7700改為其他端口。)找到access_token行,設置為當前賬號的QQ號,或者其他能唯一標識這個賬號的信息。(如果不需要同時運行多個機器人, 也可以隨便寫。)
看看這個 json 里有沒有use_http 和use_ws這兩項,如果沒有,添加這兩項,并且把值改為false。這是為了on為了禁用用不到的功能。
如果有ws_reverse_event_url和`ws_reverse_api_url 這兩項,把他們刪除。這兩項分別表示 WebSocket 的事件接口和方法接口,其值可以由ws_reverse_url自動配置,所以不需要填寫。
新版 CoolQ HTTP API 會在啟動時彈出它自己的控制臺,如果嫌它太難看,方法是將show_log_console一項改為false。
如果在 Python 端需要執行初始化代碼,請將 CoolQ HTTP API 升級到最新版本(v4.14及以上),然后在配置文件中加入這樣一行:"ws_reverse_use_universal_client": true。
每次修改配置文件之后,都需要重啟酷Q。
接下來就可以擼 Python 端的代碼了。
先上一個模板代碼:
from aiocqhttp import CQHttp
bot = CQHttp(access_token='你剛才設置的 access_token', enable_http_post=False)
@bot.on_message('private')
async def handle_msg(context):
await bot.send(context, '現在為您復讀:')
return {'reply': context['message']}
if __name__ == '__main__':
bot.run(host = '127.0.0.1', port = 7700)
不要忘了把access_token改成剛才設置的內容。
現在我們分析一下這段代碼:
bot = CQHttp(access_token='你剛才設置的 access_token', enable_http_post=False)
創建一個機器人實例,因為設置了enable_http_post=False,所以啟用的是反向 WebSocket 模式,這個模式下,只需要傳入 access_token 即可。
if __name__ == '__main__':
bot.run(host = '127.0.0.1', port = 7700)
在本地的 7700 端口開啟反向 WebSocket 服務。如果機器人的主程序有公網IP,那么還可以實現把任意一個酷Q連接到機器人(雖然我買不起公網IP,也沒試過)。
@bot.on_message('private')
async def handle_msg(context):
await bot.send(context, '現在為您復讀:')
return {'reply': context['message']}
這就是機器人的邏輯代碼了。Aiocqhttp 把酷Q的各種事件封裝為裝飾器,最常用的就是@bot.on_message(),這個裝飾器可以帶一個字符串參數, private、group和discuss分別代表私聊消息、群消息、討論組消息;也可以不帶參數 ,表示處理全部消息。除此之外,還有on_notice、on_request、on_meta_event裝飾器分別對應其他三種事件。這三種裝飾器也可以帶參數,參數內容為要處理的事件類型(notice_type、request_type或meta_event_type,具體取值見事件列表)。
處理消息的內容寫在函數里。由于消息的收發是異步的,所以要使用async def xxx(context):的語法。函數名可以任意取,也可以創建多個不同函數名的函數來處理同一個消息(但是我并不確定按什么順序執行)。
函數參數只有一個:context,類型為字典,代表 CoolQ HTTP API 傳來的事件參數。具體內容的格式參看這里,比如對于接收消息的事件,context['message']就代表了消息內容。
在函數里,可以通過await bot.xxx(...)的語法來調用 CoolQ HTTP API 提供的 API,在API列表中的API全部可以直接通過bot.API名字()調用,API參數通過命名參數提供,也就是類似于bot.send_private_msg(user_id=123456, message='hello')的形式。另外,Aiocqhttp 提供了一個發送消息的簡單操作,調用形式為await bot.send(context, '消息內容')。
處理事件的函數可以有一個返回值,也是一個字典,代表事件的響應數據,就是事件列表中每 個事件下面的響應數據列表,用于快速處理事件。最簡單地,return {'reply':'消息內容'}就會回復發來消息的人。在群聊中,如果不指定'at_sender':false,還會自動@發消息的人。當然,也可以沒有返回值。
上面的這一段代碼,就是一個復讀機機器人,會自動復讀所有的私聊消息。
所以,人類的本質是——人類的本質是——
CoolQ x Chatterbot
現在,終于可以為我們的機器人注入靈魂了。把 Chatterbot 嵌入 CoolQ 機器人實際上并不是一件難事。
廢話不多說,直接上代碼:
from aiocqhttp import CQHttp
from chatterbot import ChatBot
bot = CQHttp(access_token='你剛才設置的 access_token', enable_http_post=False)
chatterbot = ChatBot(
'Sakura',
storage_adapter='chatterbot.storage.MongoDatabaseAdapter'
)
def r(s):
return chatterbot.get_response(s)
@bot.on_message('private')
async def handle_msg(context):
rep = r(context['message'].strip())
if rep.confidence > 0.65:
return {'reply':rep.text}
if __name__ == '__main__':
bot.run(host = '127.0.0.1', port = 7700)
邏輯很簡單,判斷回答的可信度是否大于0.65,如果是,作出回答。
當然,可以在這段代碼的基礎上,進一步拓展,實現更加復雜的處理邏輯。
在下一篇文章里,我會介紹我在編寫自己的機器人時用到的一些處理邏輯和小技巧。(雖然也不知道下一篇文章會鴿幾個月)
下一篇文章:忘憂北萱草:用 Python 來做一個聊天機器人吧!(二)?zhuanlan.zhihu.com
(封面PID:72774437)
現已加入知乎專欄:用 Python 來做一個聊天機器人吧!?zhuanlan.zhihu.com
總結
以上是生活随笔為你收集整理的python制作聊天机器人原理_用 Python 来做一个聊天机器人吧!(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python3之字典生成器结合lambd
- 下一篇: python公式计算器_Python-计