コネヒト開発者ブログ

コネヒト開発者ブログ

LLMを使って分かち書きフィルタを書かずにテキスト処理をする

こんにちは。CTOの永井(shnagai)です。

この記事はコネヒト & コネヒト生成AI Advent Calendar 2024 の8日目の記事です。

adventar.org

今日は、LLMを使って形態素解析処理をいかに楽に出来るかを実験したので、その内容について書いていきたいと思います。

やりたいこと・モチベーション

  • 社内の盛り上げツールとして、ワードクラウドを作りたい
  • ワードクラウドは文章の特長を捉えているとよりうれしい
  • 一般的なワードは省きたい
  • Pythonを使う
  • フリーテキストなので形態素解析が必要だが、テンポラリな処理なので辞書等はない
  • できるだけ楽して作りたい(一番大事なモチベーション)

形態素解析する時につらい処理

形態素解析をする時に一番気を遣う部分が不要な単語をいかに削り意味のある文字を残せるかという部分です。 例えば、これまでだとPythonで形態素解析をするときは、 下記のように不要な単語を消すフィルタを書いていました。

秘伝のタレと化したreplace処理が使うごとに拡張されていきます。

def japanese_wakati(text):
    tokens = tokenizer.tokenize(text)
    words = " ".join(
        token.base_form
        for token in tokens
        if token.part_of_speech.split(",")[0] in ["名詞"]
    )
    return words

wakati_text = japanese_wakati(text)

wakati_text = (
    wakati_text.replace("https", "")
    .replace("今", "")
)

for char in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ":
    wakati_text = wakati_text.replace(char, "")

# ワードクラウドを生成する処理
...

LLMを使った関数を追加してみる

延々とフィルタを追加しているときに、ふとLLMを使ったらもっとうまくいくのではと思いつき試してみました。 is_not_significant という特長的でない単語をOpenAI APIを利用して削除する関数を用意します。 この関数内でのプロンプト内容を変えることで、最終的な出力がどう変わるかを実験しました。

def is_not_significant(text):
    response = openai.chat.completions.create(
        messages=[
            {
                "role": "user",
                "content": f"以下のテキストから特徴的ではない単語を削除してください:\n{text}\n",

            }
        ],
        model="gpt-4o",
    )
    return response.choices[0].message.content

# 日本語のテキストを分かち書き
wakati_text = japanese_wakati(text)

# 特徴的ではない文字列を削除
wakati_text = is_not_significant(wakati_text)

# ワードクラウドを生成する処理
...

最終的なアウトプットにどんな変化が起きたか

ここからは、上で説明した関数のプロンプトを変えることで最終的なアウトプットであるワードクラウドがどのように変わったかを示していきます。

0. まずは、LLMを使っていない元々のワードクラウド

1. [プロンプト]以下のテキストから最終的にワードクラウドを生成します。特徴的なワードクラウドを作りたいので不要な単語を削除してください

指示文に対する回答が返ってきていてワードクラウドに反映されています。それはそう。 また、この指示では特徴的な文章だけを残してしまいイメージと違うものが出来上がっています。

2. [プロンプト]以下のテキストから最終的にワードクラウドを生成します。不要な単語を削除してください。尚、出力はテキストの羅列のみで受け答えはしないでください

いい感じで元のワードクラウドに近いものが出てきました。いくつか不要なワードが削られていますが元のワードクラウドとの差分はいまいちわかりません。

3. 手動フィルタを外す+[プロンプト]以下のテキストから最終的にワードクラウドを生成します。不要な単語を削除してください。尚、出力はテキストの羅列のみで受け答えはしないでください

最後に手動フィルタを外して実行してみました。そうです、OpenAI APIでよしなに手動で除去していたようなノイズは削除されていました。 しかも泣く泣く諦めていた英単語も表示されるようになっています。 優秀すぎて、これまで自分が頑張って溜めてきたフィルタは一瞬にして用無しとなりました。 これが正解だなと個人的には納得して、フィルタをすべてコメントアウトしました。

まとめ

便利の一言です。 これまでフィルタや正規表現で頑張っていたテキスト処理の前処理において、LLMを活用して精度向上と開発効率向上を実現出来る可能性を感じました。 今回の例は一例で、社内ツールなので特に制約なく使えたという面が強いですが、遊び心をもって普段から知見を溜めていくことでプロダクトにも活用出来る武器を日常から増やしていけるといいなと思っております。