AIを活用した入力判定やテキスト分類に興味があるエンジニアの方や、APIの従量課金コスト・セキュリティリスクを抑えたい開発を行えるように考えました。外部APIを叩かずに、ブラウザ内のローカルLLMを使って完全無料・高速で選択肢判定を実装する方法をまとめました。
最近、選択肢の判断を素早く行ってくれる「Jev」というサービスが話題になっていました。
LLMを活用して選択肢を素早く判定するという仕組みを見て、私は率直にこう思いました。
「これって、別に特別な技術を使っているわけではないのでは?」
「あらかじめ選択肢を用意して判定させるなら、生成AIの初期からあるアプローチじゃないかな?」
確かに判定速度の速さは魅力的です。
1回あたりの利用料がいくら安価だとしても、高速だからこそ大量に呼び出されれば、トータルのAPI費用は跳ね上がってしまいます。
そこで「外部通信を挟まず、完全無料でブラウザだけで手軽に判定できないか?」と考え、ライブラリを作ってみました。
無料で簡単に判定させることはできるか?
解決策として着目したのが、Chromeに新しく追加された「Prompt API」です。
参照:Prompt API(Google Chrome Developer)
Prompt APIを使うと、端末ローカルで動作する「Gemini Nano」をJavaScriptから直接呼び出せます。
ローカルLLMには、Web開発において非常に大きな強みがあります。
・外部APIを呼ばないため、何回実行しても費用は0円です。
・データが端末外に送信されないため、個人情報や機密データも安全に扱えます。
・計算リソースはユーザーの端末側を使うため、サーバー負荷を気にする必要がありません。
これを利用すれば、コストを気にすることなく何度でも実行できる判定システムが実現できると考えました。
作成した内容(nano-judgement.js)
この仕組みを誰でもHTMLの属性だけで手軽に使えるよう、nano-judgement.js というライブラリにまとめました。
詳細な仕様やドキュメントは、以下の公開ページにまとめています。
HTMLのカスタムデータ属性(data-*)をタグに付与するだけで、手軽にAI判定を組み込めます。
1. タグ内に選択肢をJSONで持たせる方法
入力エリアに選択肢を直接埋め込む最小限の実装例です。
<textarea
data-nano-judgement
data-judge-reason="true"
data-judge-target="#auto-result-2"
data-judge-choices='[
{"id":"X","name":"大手クラウドのマネージドDB","description":"高可用性で運用コスト最小だが月額費用が高め"},
{"id":"Y","name":"社内自前サーバー構築","description":"初期費用のみで機密保持が高いが保守運用負荷が甚大"},
{"id":"Z","name":"無料ホスティングサービス","description":"手軽だが障害時のSLA保証やバックアップ体制がない"}
]'
rows="2"
>医療系データを扱う基幹システムで、データの消失や情報漏洩は絶対に許されず、24時間365日の連続稼働が必須。</textarea>
<div id="auto-result-2" class="result-target-area">
<div style="font-size:0.85rem; color:var(--text-muted); font-style:italic;">判定中、または結果がここに表示されます...</div>
</div>
data-nano-judgement・・・判定のための入力枠であると判定する属性
data-judge-reason・・・判定理由も合わせて返却するかどうかの属性(trueにすると理由も返されますが、出力のために応答速度が遅くなる可能性があります)
data-judge-target・・・判定結果を更新する先のセレクターの指定(これは設置する側の実装のため)
data-judge-choices・・・判定する選択肢のためのjson id=選択肢にふる値、name=名称、description=簡単な判定基準
2. 既存のセレクトボックスと連動させる方法
フォーム内の要素をそのまま選択肢として流用することもできます。
<textarea data-nano-judgement="" data-judge-select="#supportPriority" data-judge-target="#auto-result-3" rows="2" placeholder="問い合わせ内容を入力してください..." data-judge-status="completed">本番データベースへの接続が突如遮断され、決済処理が全てエラーになっています。顧客からの問い合わせが殺到しています。</textarea>
data-judge-select・・・select要素のセレクターを指定することで、selectの要素を選択肢として利用する
他にも画像や音声ファイルを渡して分類することもできるように作っています。
詳しい実装はこちらをご確認ください。
https://pawn-4-git.github.io/nano-judgement.js/#implementation-guide
体感速度を引き上げる3つの工夫
ブラウザ内完結とはいえ、ユーザー体験を損なわないためには「速さ」が欠かせません。そこで以下の3つの工夫を組み込みました。
1. 入力中のバックグラウンド判定
送信ボタンを押すのを待つのではなく、ユーザーが文字を入力している段階で裏側で判定処理を開始します。書き終えて送信を押す頃には結果が出ている状態を目指しました。途中で大きく文章が追記された場合は、前の判定を破棄して自動で再判定を走らせます。
2. セッションストレージによるキャッシュ
一度判定した結果はSessionStorageに一時保存します。入力テキストの前方一致などをチェックし、同じ文脈の入力であれば過去の判定を即座に再利用して返します。
3. トークン削減のための英語プロンプト変換
Gemini Nanoへ渡すトークン数を極力減らすため、入力テキストや選択肢をTranslate API等で一度英語に変換してからモデルに渡しています。処理するトークンが減ることで、判定速度の底上げに繋がると考えています。
まとめ
外部の生成AIサービスを使えば手軽に高精度な機能を作れますが、大量の判定処理を回す場合はコストとインフラ負荷が大きな課題になります。
ChromeのPrompt APIとGemini Nanoを組み合わせれば、「完全無料」「データが外に出ない安心感」「サーバー負荷なし」という大きなメリットを享受できます。さすがにJevの速度には敵いませんが、簡単な判定なら事前判定がされて数秒で回答を表示させることができました。(GeminiNanoの性能によるので、思ったより判定までの時間差があります)
注意点としてはpromptAPIが使える環境である必要があるので、PCのChromeで一定程度の性能が必要になる点です。全ての環境で使えるわけではないので、社内の業務サービスのWebサービスであったり、問い合わせページなど機能が動かなくてもサービスとして成り立つ場所などで使えるかと思いました。
