gpt2 slack bot 我開個頭,你編下去?

穀粒先生發表於2019-03-26

記得在校的時候,某巖做過一個app,講接龍故事的。類似於我寫一段,另一個人寫接下來的一段,最後湊成一個完整的故事。當時,可產生了不少有意思的段子。最近,GPT2 模型的釋出,讓人不禁想到,有沒有可能讓機器來完成這個任務呢?機器寫十四行詩、機器寫莎士比亞風格的文章,機器寫對聯,這些都已經成為了現實。人工智慧雖然沒有帶來突飛猛進的質變,但著實催生了很多有意思的小玩意兒。對於GPT2,一個字概括來說就是:壕——資料量大,算力能夠 cover 住。這套演算法模型網羅了幾乎現有的所有文字資料,成功“過擬合“地屠榜,重新整理多個 NLP 任務榜單排行。作者為了預防濫用模型、同時讓別的研究者能夠有個初步地認識,開源了一個小一些地模型。該模型的能力之一,就是我們今天的主題:接著別人地話寫故事。今天我們要通過演算法來實現。

雖然作者有在盡力簡化復現難度,但對於很多不是這行的人,讓他去敲命令列來走完整個流程,還是困難重重。能夠將深奧的原理講給普通人聽,並且簡單易懂,是一項科學傳播的必備能力。做為技術向的工程師,在產品處於雛形階段時,能夠通過一個 MVP 最小价值產品,實現核心功能,也是一項大大的加分項。對於今天的任務,我們選取容易上手,介面豐富的 slack 作為我們的前端互動視窗。

如何構建一個 MVP 產品;或者具體的來講,在我們的這個任務中,如何將資料探勘工程師的模型成果,轉化為可落地、可感知的產品或服務呢。操起斧子直接開幹,依葫蘆畫瓢擼個前後端出來嗎?這,其實是很多技術人員的一個誤區——認為什麼都可以從技術層面解決,”少廢話別bb,bb is cheap,show me the code“。但從一個商業產品或服務商的角度來看,客戶與渠道是前臺,我們的客戶是誰、如何觸達客戶以及選用何種渠道維繫客戶,是一個一開始就要考慮的事情。

以這個 GPT2 bot 為例,我希望的客戶是對 GPT感興趣,但又沒基礎去折騰的學生或是其他領域的人士,抑或是沒時間去跑 demo 的專業同行。如何觸達客戶:你看的這篇文章的平臺,就是我的觸達媒介。我最後選擇用 slack 交付我的服務,而不是 qq 或 微信,是因為他成本更低,雖然阻擋了部分潛在客戶,但權衡後是可以接受的。最後的工作才是依葫蘆畫瓢,照擼一個出來。本文參照了EdwardHuCS,並在其基礎上做了部分改動。

雖然這波 AI 熱潮,讓很多像我這樣的非科班得以上車。但在實際生產環境中,我們還是暴露了諸多問題。其中之一,便是工程能力薄弱。會寫 SQL 、會手推演算法、會調包,但是就是不會寫能跑的整個小系統。在業務變化快的公司中,這可能不是一個好事情。你的模型也許還在細調引數,但突然整個業務就沒了。如果你能拿出一個能跑的馬兒,興許能影響這個業務。這就是前面提到的加分項。

言歸正傳,我們回到在slack上面。我們的核心就以下程式碼:

核心程式碼解讀

匯入一些基礎配置

import os
import time
import re
from slackclient import SlackClient
import sys
from gpt2.src import generate_unconditional_samples
# instantiate Slackk client
slack_client = SlackClient('') # 認證口令
# starterbot's user ID in Slack: value is ssigned after the bot starts up
starterbot_id = None

複製程式碼

延遲配置以及樣例和匹配模式

# constants
RTM_READ_DELAY = 1 # 1 second delay between reading from RTM
EXAMPLE_COMMAND = "God, to me, is like a "
MENTION_REGEX = "^<@(|[WU].+?)>(.*)" 
複製程式碼
通過 slack 的事件,解析出我們的訊息和對應的頻道
def parse_bot_commands(slack_events):
    """
        Parses a list of events coming from the Slack RTM API to find bot commands.
        If a bot command is found, this function returns a tuple of command and channel.
        If its not found, then this function returns None, None.
    """
    for event in slack_events:
        if event["type"] == "message" and not "subtype" in event:
            user_id, message = parse_direct_mention(event["text"])
            if user_id == starterbot_id:
                return message, event["channel"]
    return None, None
複製程式碼

訊息解析

def parse_direct_mention(message_text):
    """
        Finds a direct mention (a mention that is at the beginning) in message text
        and returns the user ID which was mentioned. If there is no direct mention, returns None
    """
    matches = re.search(MENTION_REGEX, message_text)
    # the first group contains the username, the second group contains the remaining message
    return (matches.group(1), matches.group(2).strip()) if matches else (None, None)
複製程式碼

核心的模型匯入

def handle_command(command, channel):
    """
        Executes bot command if the command is known
    """
    # Default response is help text for the user
    response = "Not sure what you mean. Try *{}*.".format(EXAMPLE_COMMAND)

    # This is where you start to implement more commands!
    if len(command) < 2:
        response = "Sure...write some more text then I can do that!"
    else:
        # 這裡可以替換成任何你想要的模型
        response = '"'+command+generate_unconditional_samples.sample_model(nsamples=1, length=6*len(command), top_k=len(command), command=command)[0]


    # Sends the response back to the channel
    slack_client.api_call(
        "chat.postMessage",
        channel=channel,
        text=response)
複製程式碼

主函式入口

if __name__ == "__main__":
    if slack_client.rtm_connect(with_team_state=False):
        print("Starter Bot connected and running!")
        # Read bot's user ID by calling Web API method `auth.test`
        starterbot_id = slack_client.api_call("auth.test")["user_id"]
        while True:
            command, channel = parse_bot_commands(slack_client.rtm_read())
            if command:
                handle_command(command, channel)
            time.sleep(RTM_READ_DELAY)
    else:
        print("Connection failed. Exception traceback printed above.")
複製程式碼

開始安裝並執行

git clone git@github.com:kuhung/slack-gpt2.git
cd slack-gpt2
獲取 slack app 的 token,並填充進上面的 slack_client
複製程式碼
conda create -n slackbot python=3.6
source activate slackbot
pip install -r requirements.txt
cd gpt2
pip install -r requirements.txt
python download_model.py 117M
cd ..
python starterbot.py
複製程式碼

如果你不熟悉或從來沒用過slack,也沒關係,還記得開頭說的交付嗎?直接加入我的 workspace,一起測評 GPT2 bot。連結:加入我的 slack workspace

總結

如同大多數應用場景一樣,資料探勘的演算法需要落地,最好的辦法就是封裝成一個介面,給到前後端去呼叫。這其中還有很多效能優化的東西,但作為一個 sideproject,以上操作足夠讓你給別人眼前一亮的感覺。

原文連結:kuhungio.me/2019/slack-…

相關文章