自然な日本語ダミーテキストを生成するWebアプリを作りました
こんな感じの文章を自動生成できます。
二人の男女を一様に観察していました。私は仕方なしに立って、再び封の中へ、自分の左右前後を見廻して母の頭は陛下の病と父の病と父の病とを結び付けて考えるのが変に気味が悪かったのです。固よりそこにはまるで解りませんけれど、おそらくそんな意味じゃないでしょう。私の考えは行き詰まればいつでも両方が同時に奥さんのいる事をとうから自覚していました。先生の附近で盗難に罹ったものが、僻んだ私の眼を擦りました。それでも鷹揚に育った私は、もっと海の中で遊んでいられるか、宅へ帰って食卓に向った時、両親の死に断えた私の卒業する前に、また一種の弛みができても、決して強い言葉で説明しました。
モチベーション
同じようなツール・サービスはいくつも公開されていますが、ほとんどが以下の 3 つの方式を採用しており、個人的にはあまり満足できていませんでした。
- 短い定型文の繰り返し: 一種の模様に見えてくる。また、動的コンテンツのプレースホルダーには適さない。
- 小説などの一節: 内容に目が奪われがち。また、動的コンテンツのプレースホルダーには適さない。
- 単語(形態素?)をランダムに混ぜる: 上記 2 つの問題は解決しているが、文法を無視しているので正しい日本語ではない。
類似サービス
ダミーテキストジェネレータ
この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れ
すぐ使えるダミーテキスト
程度に這入りですのはいくら十月がどうもうでた。いよいよ槙君を解釈取消始終破壊をつけた国家どんな個人私か矛盾のに対して小返事ないなですますて、その前は彼らかずる知人を落ちが、大森さんの訳に手のこれをよくお刺戟と知らば何先生から小攻撃が落ちようにひょろひょろお相談をするうたと、いやいや必ずしも詐欺に送らんてみんものに与えたた。それですなわちお漫然に得る事はどう失礼と握るたが、この倫理には云えますがという心がしてあるでで。
上記分類の 3 にあたるツールです。あくまでも主観なのですが、例えばこれで生成したタイトル・文章でブログサービスを開発していると、なんだか頭が痛くなってきそうです。なので、ランダム性は維持したまま、より違和感の少ない自動生成を実現したいと考えました。
より自然な日本語文章を生成するには
僕(自然言語処理に疎い)が日本語の自動生成というトピックでまず思い出したのはしゅうまいくんという Twitter bot でした。「following の皆さんの最近の発言を学習して喋」っている内容は一見自然なのですが、よく読むと支離滅裂です(まともなことを言っているときもあります)。これが理想だと思い調べてみると、彼はマルコフ連鎖というアルゴリズムで喋っていることが製作者のインタビューからわかりました。
実装
マルコフ連鎖で自動生成
コアとなる文章生成の実装については、すでにわかりやすい解説記事がたくさん公開されているため記載しません。以下の記事に全面的に依拠しました。公開していただきありがとうございます。
1 つ躓いた点は、mecab-python3が Apple Silicon 搭載の Mac では上手くインストールできなかったことです。issue を参照しながら 2 時間ほど格闘しましたが、僕の環境では成功しませんでした。SudachiPyは何も問題なくインストールできたのでこちらを使用させていただきました。
Web アプリ化
言語
形態素解析やマルコフ連鎖のライブラリは Python 製のものが多かったため、Web サービスも Python で書くことにしました。
(Web なら JavaScript で書けると便利ですが、形態素解析はkuromoji.jsがあるものの、マルコフ連鎖はスター数 50 くらいのライブラリしか見つかりませんでした。)
技術スタック
- FastAPI
- Jinja2
- Tailwind
- Vercel
FastAPI
SPA にする理由もないため、FastAPI からシンプルに html を返す方式にしました。スタイリングは Tailwind です。Ajax は使っておらず、form からクエリ文字列と共に GET しています。
また、せっかく FastAPI を使っているので API としても公開することにしました。
以下のようなコードを書くだけで、上記のような API ドキュメンテーションを自動で作成してくれます。
@app.get(
"/api",
response_model=ApiResponse,
)
@limiter.limit("300/minute")
@limiter.limit("30/second")
def api_get(
request: Request,
sentence_count: int = 8,
source: Literal["ginga-tetsudo", "kokoro"] = "ginga-tetsudo",
):
paragraph = services.prod.make_paragraph(source, sentence_count)
return ApiResponse(paragraphs=[paragraph])
from typing import List
from pydantic import BaseModel
class ApiResponse(BaseModel):
paragraphs: List[str]
一応レートリミットもかけてあります。SlowAPIという気の利いた名前の便利なライブラリを使わせていただきました。
Vercel にデプロイするのは、Next.js などと比べれば若干面倒です。といっても vercel.json
に以下のような設定をするくらいだったと思います。
{
"version": 2,
"builds": [{ "src": "server.py", "use": "@vercel/python" }],
"routes": [{ "src": "/(.*)", "dest": "server.py" }]
}
依存管理
Vercel にはサーバーレス関数の 50MB 制限があるので、形態素解析機能(と辞書)はデプロイしないことにしました。
Python の依存ライブラリ管理ツールとして Poetry を使用したため、できればその機能の範囲内で上手く処理したかったです。また、デプロイ先が Vercel のため、Vercel がどのように Python の依存をインストールするかも考慮する必要があります。どうも Vercel はデフォルトでは pyproject.toml
は認識してくれないようだったので、requirements.txt
を poetry export
で書き出してから push することにしました。
SudachiPy
と SudachiDict-core
を dev dependency としてインストールして poetry export
を実行すれば、本番環境ではインストールしないようになります。形態素解析はローカル環境で済ませておき、本番環境では結果を書き出したファイルを読み込んで使用することにしました。
figma プラグイン
上記 API を使用した figma プラグインも作りました。ストアの公開には審査が必要なので、まだ 1 週間くらいはかかりそうです。
まとめ
開発の際に使うダミーテキストの生成には困っていたので、少なくとも自分の役に立つツールを作ることができてかなり満足しています。
生成される文章の質感が好みに合う方がいればはぜひお使いください。
参考記事
Discussion
すごくいいプロジェクトです、vscodeの拡張機能として使えたら一番助かります!