2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Discordで対話可能なマルコフ連鎖BOTを作った(Python)

Last updated at Posted at 2024-06-25

あらまし

住み着いているDiscordサーバで対話のできるBOTが動かせたら面白いなと思って、とりあえず簡単に動きそうなマルコフ連鎖を使ったBOTを作ってみた。
入力されたテキストを含むマルコフ連鎖のモデルを作って、それを元に返信する単純な学習機能を入れてます。

image.png

環境

私はUbuntuServerでscreenの中にvenvを建てて動かしてます。
こいつらを入れて動かします。

ライブラリのインストール
python3 -m pip install -U discord.py 
py -3 -m pip install -U discord.py #Windowsの場合はこっち
pip install mecab-python3
pip install unidic-lite 
pip install markovify

中身

BOTを動かしたいサーバのチャンネルIDとBOTのトークンは適宜書き換えてください。
discordbot.pyと同ディレクトリにm.txtを置いて動かします。m.txtにはある程度文章を入れておきます。
マルコフ連鎖に使うデータが無いと返信が帰ってこないのでモデル生成の部分は state_size=1 としています。会話を進めてある程度m.txtに文章量が集まったら1ずつ増やすといいです。

discordbot.py
import discord
import MeCab
import unidic_lite
import markovify
import random


CHANNELID = XXXXXXXXXXXXXXXXXXX #チャンネルID

TOKEN = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' #BOTのトークン

intents = discord.Intents.default()
intents.message_content = True
intents.messages = True

client = discord.Client(intents=discord.Intents.all())



@client.event
async def on_ready():
    print('---------------------------------------------------')
    print('                  起動しました                      ')
    print('---------------------------------------------------')



@client.event
async def on_message(message):
    if message.channel.id != CHANNELID:
        return
    if not message.author.bot:
        channel = client.get_channel(CHANNELID)


        m1 = (message.content) 
  
        # 末尾を"。"に定める
        matubi = (m1[-1])
        if matubi == "。":
            m2 = m1
        else:
            m2 = m1 + "。"

        # 学習データに書き込み
        f = open('m.txt', 'a')
        f.write(m2)
        f.write("\n")
        f.close()

        # 学習データを読み込み
        with open('m.txt', 'r') as f:
            kotoba = f.read().split("\n")

        print(m2)

        # 話題になりそうなワードを抽出
        mecab = MeCab.Tagger() 
        result = mecab.parse(m2)

        l1 = [line.split()[0] for line in mecab.parse(m2).splitlines()
        if '0' in line.split()[-1]]

        l2 = [line.split()[0] for line in mecab.parse(m2).splitlines()
        if '1' in line.split()[-1]]

        l3 = l1 + l2

        #リストを作成できなかった場合冒頭の単語を取る
        kazu = len(l3)
        if kazu < 1:
            words = mecab.parse(m2).split()
            #print(words)
            wadai = words[0]
        else:
            wadai = random.choice(l3)

        # 文章の処理
        breaking_chars = ['(', ')', '[', ']', '"', "'"]
        splitted_kotoba = ''

        for line in kotoba:

            parsed_nodes = mecab.parseToNode(line)

            while parsed_nodes:
                try:
                    if parsed_nodes.surface not in breaking_chars:
                        splitted_kotoba += parsed_nodes.surface

                    if parsed_nodes.surface != '。' and parsed_nodes.surface != '、':
                        splitted_kotoba += ' '

                    if parsed_nodes.surface == '。':
                        splitted_kotoba += '\n'

                except UnicodeDecodeError as error:
                    print('Error : ', line)
                finally:
                    parsed_nodes = parsed_nodes.next

        # モデル作成
        model = markovify.NewlineText(splitted_kotoba,well_formed=False,state_size=1)

        # wadaiから続く文章を生成
        sentence = model.make_sentence_with_start(beginning=wadai,strict=False)
        if sentence is not None:
            #。を除く
            out = (''.join(sentence.split()))
            out = out[:-1]
            print(out)
        else:
            print('None')
            out = 'None'

        # discordに送信
        await message.channel.send(out)


client.run(TOKEN)

雑にコピペしたりして書いたので蛇足な部分があるかも。

おわりに

偶に偶然人間らしく振る舞ったりしてなかなか面白いです。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?