🖋️

自然な日本語ダミーテキストを生成するWebアプリを作りました

2022/01/14に公開約4,600字1件のコメント

https://lorem-jpsum.vercel.app

こんな感じの文章を自動生成できます。

二人の男女を一様に観察していました。私は仕方なしに立って、再び封の中へ、自分の左右前後を見廻して母の頭は陛下の病と父の病と父の病とを結び付けて考えるのが変に気味が悪かったのです。固よりそこにはまるで解りませんけれど、おそらくそんな意味じゃないでしょう。私の考えは行き詰まればいつでも両方が同時に奥さんのいる事をとうから自覚していました。先生の附近で盗難に罹ったものが、僻んだ私の眼を擦りました。それでも鷹揚に育った私は、もっと海の中で遊んでいられるか、宅へ帰って食卓に向った時、両親の死に断えた私の卒業する前に、また一種の弛みができても、決して強い言葉で説明しました。

モチベーション

同じようなツール・サービスはいくつも公開されていますが、ほとんどが以下の3つの方式を採用しており、個人的にはあまり満足できていませんでした。

  1. 短い定型文の繰り返し: 一種の模様に見えてくる。また、動的コンテンツのプレースホルダーには適さない。
  2. 小説などの一節: 内容に目が奪われがち。また、動的コンテンツのプレースホルダーには適さない。
  3. 単語(形態素?)をランダムに混ぜる: 上記2つの問題は解決しているが、文法を無視しているので正しい日本語ではない。

類似サービス

ダミーテキストジェネレータ

https://webtools.dounokouno.com/dummytext/

この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れ

すぐ使えるダミーテキスト

https://lipsum.sugutsukaeru.jp/

程度に這入りですのはいくら十月がどうもうでた。いよいよ槙君を解釈取消始終破壊をつけた国家どんな個人私か矛盾のに対して小返事ないなですますて、その前は彼らかずる知人を落ちが、大森さんの訳に手のこれをよくお刺戟と知らば何先生から小攻撃が落ちようにひょろひょろお相談をするうたと、いやいや必ずしも詐欺に送らんてみんものに与えたた。それですなわちお漫然に得る事はどう失礼と握るたが、この倫理には云えますがという心がしてあるでで。

上記分類の3にあたるツールです。あくまでも主観なのですが、例えばこれで生成したタイトル・文章でブログサービスを開発していると、なんだか頭が痛くなってきそうです。なので、ランダム性は維持したまま、より違和感の少ない自動生成を実現したいと考えました。

より自然な日本語文章を生成するには

僕(自然言語処理に疎い)が日本語の自動生成というトピックでまず思い出したのはしゅうまいくんというTwitter botでした。「followingの皆さんの最近の発言を学習して喋」っている内容は一見自然なのですが、よく読むと支離滅裂です(まともなことを言っているときもあります)。これが理想だと思い調べてみると、彼はマルコフ連鎖というアルゴリズムで喋っていることが製作者のインタビューからわかりました。

実装

マルコフ連鎖で自動生成

コアとなる文章生成の実装については、すでにわかりやすい解説記事がたくさん公開されているため記載しません。以下の記事に全面的に依拠しました。公開していただきありがとうございます。

https://ysko909.github.io/posts/how-to-use-markovify

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としても公開することにしました。

https://lorem-jpsum.vercel.app/docs#/default/api_get_api_get

以下のようなコードを書くだけで、上記のような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 に以下のような設定をするくらいだったと思います。

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.txtpoetry export で書き出してからpushすることにしました。

SudachiPySudachiDict-coreをdev dependencyとしてインストールして poetry export を実行すれば、本番環境ではインストールしないようになります。形態素解析はローカル環境で済ませておき、本番環境では結果を書き出したファイルを読み込んで使用することにしました。

figmaプラグイン

上記APIを使用したfigmaプラグインも作りました。ストアの公開には審査が必要なので、まだ1週間くらいはかかりそうです。

https://www.figma.com/community/plugin/1062983469418959844/Lorem-JPsum

まとめ

開発の際に使うダミーテキストの生成には困っていたので、少なくとも自分の役に立つツールを作ることができてかなり満足しています。

生成される文章の質感が好みに合う方がいればはぜひお使いください。

https://lorem-jpsum.vercel.app/

参考記事

https://ysko909.github.io/posts/how-to-use-markovify
https://www.pc-koubou.jp/magazine/4238
GitHubで編集を提案

Discussion

すごくいいプロジェクトです、vscodeの拡張機能として使えたら一番助かります!

ログインするとコメントできます