(テッテケテッテーテーテテー)ミニドラ語翻訳機~

9 min読了の目安(約5500字TECH技術記事

日本語を入力するだけで、ミニドラ語に翻訳してくれるひみつ道具を開発しました!

はじめに

ミニドラが話すミニドラ語、という言葉をご存知ですか?
アニメでは「ドラドラ」とか「ドララ~」など、正規表現で表すと^(ドー*ラ+ー*)+$くらいのレパートリーです
しかし、漫画のほうでは
10644063_761250850582759_516278085_n.jpg
と、^(ドー*ラ+ー*)+$に当てはまらない「スースーシーシーワーワーナーナー」と喋っているではありませんか!
ドラミちゃんのセリフから日本語に訳すると「すっかり調べて、悪いところを直しました」を言ってそうです

この「すっかり調べて、悪いところを直したよ」から「スースーシーシーワーワーナーナー」を開発しました

使用技術及び環境

翻訳機の仕様

ドラえもん公式にミニドラ語のルール的なものは見つからなかったので、さっきの1コマからひねり出します
もし、ミニドラ語のルールがあったら教えて下さい

1コマからわかること

「スースーシーシーワーワーナーナー」 = 「すっかり調べて、悪いところを直したよ」
であるのはほぼ確定っぽそうです(「直したよ」は「直しました」や「直した」など、表記ゆれの可能性はあります)

否定も会話の流れからして、考えにくいです
「直しませんでした(直せませんでした)」と言っている人に「直してくれたの?」と聞き返すのは不自然かなと

ミニドラ語と日本語を紐付け

次に、ミニドラ語と日本語が紐付けてみました
法則性として、単体で意味のある単語(自立語)の頭文字を繰り返すルールがありそうです
表にまとめると以下のようになります

ミニドラ語 日本語 発声する音の頭文字
スースー すっかり
シーシー 調べて
ワーワー 悪いところを
ナーナー 直したよ

日本語を解析

自立語の頭文字を繰り返すルールが分かったとなれば、あとはどれが自立語なのかがわかれば翻訳機の完成です
ここで、「すっかり調べて、悪いところを直したよ」をCOTOHA APIを使って解析してもらいました
COTOHA APIが提供するAPI一覧はこちらになりますが、今回は構文解析を使いました
解析した結果をすべて載せたいところですが、冗長なので重要な部分だけをまとめました

表記 品詞
すっかり 連用詞
調べ 動詞語幹
形容詞語幹
動詞語幹

どうやら、上の3品詞はミニドラ語の対象になりそうです
最初に言ってた自立語にも含まれてそうです(高校時代で勉強した内容の覚えている範囲で)
他にも自立後になりそうな品詞は以下くらいなので、それも対象にしています

  • 名詞
  • 連体詞
  • 独立詞

名詞の精度を上げる

これで完成・・・かと思いきや、今回たまたま「すっかり調べて、悪いところを直したよ」の解析で見つけたので、対処できたのですが、「ところ」が名詞として判定されました
つまり、このまま実装すると「スースーシーシーワーワートートーナーナー」と、余計なものが出てきてしまいます
なので、この「トートー」を除外します
「ところ」の解析結果を見ると、以下のようになります

{
    "id": 6,
    "form": "ところ",
    "kana": "トコロ",
    "lemma": "所",
    "pos": "名詞",
    "features": [],
    "dependency_labels": [
        {
            "token_id": 4,
            "label": "amod"
        },
        {
            "token_id": 7,
            "label": "case"
        }
    ],
    "attributes": {}
}

除外の判定に使えそうな部分がdependency_labels、依存関係ラベルのみなので、こちらを利用します
リファレンスを見ると、「ところ」はtoken_idが4の形態素に修飾されているとのこと
token_idが4、つまりidが4となっているのはここには載せていませんが「悪」です
どうやら、修飾対象になるものはミニドラ語からは発音されないルールになっていそうなので、amodは除外します

最終的なコード

以上を踏まえて実装したコードは以下になります

import requests
import json
import sys
import configparser

config_ini = configparser.ConfigParser()
config_ini.read('config.ini', encoding = 'utf-8')
BASE_URL = "https://api.ce-cotoha.com/api/dev/nlp/"
# 払い出されたCLIENT_IDとCLIENT_SECRETを直書きしてもOKです(コピペで誤って晒すのを防ぐためにconfigparser使いました)
CLIENT_ID = config_ini['CONOHA_CLIENT']['ID']
CLIENT_SECRET = config_ini['CONOHA_CLIENT']['SECRET']

def auth(client_id, client_secret):
    token_url = "https://api.ce-cotoha.com/v1/oauth/accesstokens"
    headers = {
        "Content-Type": "application/json",
        "charset": "UTF-8"
    }

    data = {
        "grantType": "client_credentials",
        "clientId": client_id,
        "clientSecret": client_secret
    }
    r = requests.post(token_url,
                      headers=headers,
                      data=json.dumps(data))
    return r.json()["access_token"]

def parse(sentence, access_token):
    base_url = BASE_URL
    headers = {
        "Content-Type": "application/json",
        "charset": "UTF-8",
        "Authorization": "Bearer {}".format(access_token)
    }
    data = {
        "sentence": sentence,
        "type": "default"
    }
    r = requests.post(base_url + "v1/parse",
                      headers=headers,
                      data=json.dumps(data))
    return r.json()

def exist_dependency_labels(labels, tag):
    for label in labels:
        if label["label"] == tag:
            return True
    return False

if __name__ == "__main__":
    # ミニドラ語に翻訳する文章
    sentence = "すっかり調べて、悪いところを直したよ"
    # 実行時に引数で翻訳する文章が与えられていたら、そっちを翻訳します
    args = sys.argv
    if len(args) >= 2:
        sentence = str(args[1])

    access_token = auth(CLIENT_ID, CLIENT_SECRET)
    parse_sentence = parse(sentence, access_token)
    result_list = list()
    # 翻訳対象の品詞を設定
    targets_pos = list()
    targets_pos.append("名詞")
    targets_pos.append("動詞語幹")
    targets_pos.append("形容詞語幹")
    targets_pos.append("連体詞")
    targets_pos.append("連用詞")
    targets_pos.append("独立詞")
    for chunks in parse_sentence['result']:
        for token in chunks["tokens"]:
            if token["pos"] in targets_pos:
                if not exist_dependency_labels(token["dependency_labels"], "amod"):
                    result_list.append(token["kana"][0] + 'ー')
                    result_list.append(token["kana"][0] + 'ー')

    # 翻訳結果を出力
    print(sentence)
    print('↓')
    print(''.join(result_list))

オレ プログラム ウゴカス オマエ ゲンシジン ナルにあるコードをベースに作成しています

実演

いろんな文章をミニドラ語にしてみました

$ python minidorago.py なんだ、いつものパターンか
なんだ、いつものパターンか
↓
ナーナーイーイーパーパー

$ python minidorago.py みんなのハート打ち抜くぞー
みんなのハート打ち抜くぞー
↓
ミーミーハーハーウーウー

$ python minidorago.py 俺の隣がインスタ映え
俺の隣がインスタ映え
↓
オーオートートーイーイーハーハー

ものによってはうなされているような・・・w

終わりに

これを使えばみんなもミニドラ語を話せるので、ミニドラのような可愛さで会話ができるように(?)なりました

$ python minidorago.py 最後までありがとうございました
最後までありがとうございました
↓
サーサーアーアー

伝わるかどうかは保証できません

参考