GoogleがOSSとして発表したlangextract。非構造化なテキストから構造化情報を得ることができます。structured outputとかでうまく収得することもできるので、敢えて必要なのかな・・・と思いつつ試してみました。Colabで試してみます。LLMは「Qwen3-4B-Instruct-2507-gguf」を利用します。4Bモデルだとエラー続発・・・なんてことになるのでしょうか。
少し悩ませたのが、ollamaで利用すると、長文を処理させるとtimeout起因エラーが起きます。調べると、今時点の実装では現状ソースコード弄るしかありませんでした。そこで、max_char_bufferを小さく取るとエラーが回避できました。timeoutは、設定できるようにしてほしい。
Qwen3-4B-Instruct-2507-ggufやgemma3:4bを使って試してみましたが、エラーがでず、それなりに成功しているようです。正確さは詳細には確認していませんが、こういう処理を場合、jsonのフォーマットエラーが0.1%でも出るととかなりメンドくさいです。そのあたりも実験した範囲では回避してくれているようでした。
手間もかからず、最低限のコードで抜き取ることできて、また主要なLLMモデルで処理できます。また、長い文章をチャンクして処理できる点も便利でした。
ローカルLLMも利用しやすくなっています。こういうものをゴリゴリ回して構造化にしていくのも現実的ですよね。
モデル: mmnga/Qwen3-4B-Instruct-2507-gguf
例:
解析テキスト(青空文庫ぼっちゃんから)
「無法でたくさんだ」とまたぽかりと撲なぐる。「貴様のような奸物はなぐらなくっちゃ、答えないんだ」とぽかぽかなぐる。おれも同時に野だを散々に擲き据えた。しまいには二人とも杉の根方にうずくまって動けないのか、眼がちらちらするのか逃げようともしない。
結果(例示はgithubの例)
Class: character
Text: ぽかり
Attributes: {'emotional_state': 'frustration', 'action': 'punches'}
Class: emotion
Text: 「無法でたくさんだ」
Attributes: {'feeling': 'anger', 'intensity': 'high'}
Class: character
Text: 貴様
Attributes: {'emotional_state': 'hostility', 'role': 'opponent'}
Class: emotion
Text: 「貴様のような奸物はなぐらなくっちゃ、答えないんだ」
Attributes: {'feeling': 'determination', 'intent': 'to retaliate'}
Class: character
Text: おれ
Attributes: {'emotional_state': 'rage', 'action': 'threw someone violently'}
Class: relationship
Text: 二人とも杉の根方にうずくまって動けないのか、眼がちらちらするのか逃げようともしない
Attributes: {'type': 'mutual confrontation', 'state': 'immobile', 'emotional_undercurrent': 'fear and exhaustion'
Colab: