スレート・アンバー・レッドに色分けされた大量の投稿カードが、1本の水平な光線で一斉に判定されている概念図

学生時代のChrome拡張をJevで作り直した ── System Oneモデルで8投稿を244msで判定する

はじめに こんにちは。and factory でサーバーサイドエンジニアをしている松ヶ浦です。 Jevが話題ですね。 僕も公開されたその日のうちにウェイトリストへ登録して、翌日アクセスキーを付与されると、休憩時間を使って遊びました。 驚いたのは速さでした。AIを使ったというより、ローカルの関数を呼んだときの感触に近く、一周回ってAIを使っていない普通のアプリを触っているような感覚になりました。 ひとしきり遊んでから、学生時代にチームで作ったものを思い出しました。Xのタイムラインから誹謗中傷を検知して隠すChrome拡張です。判定はGPT-3.5のAPIに投げていました。 あれ、Jevを使えば同じことがずっと速くできるのでは。 そう思って作り直したので、その記録です。結論から書くと、1リクエストに8投稿を詰めて質問を絞るpackモードでは、8投稿の判定が244msで返りました。1投稿ずつ全6問を聞くsoloモードでは2263msです。拡張の既定はpackモードで、各ユーザーが自分のAPIキーで直接Jevを呼ぶ形にしたため、バックエンドも要らなくなりました。 Jevは何を返すモデルなのか JevはTypeSafeが公開したSystem Oneモデルです(TypeSafeの発表記事)。System Oneは、人間の速い直感的な判断(システム1)になぞらえた呼び名で、じっくり考えて文章を組み立てるのではなく、即座に答えを返すことに振り切ったモデルを指します。 いちばん大きな特徴は、文字列を生成しないことです。返るのは型の付いた構造化された値だけで、公式は「モデルは型エラーを起こさない」と書いています。 レスポンスの形式には3種類あります。 Noul: yesである確率を返す。 Choice: 選択肢から1つ選び、分布とconfidenceを返す。 Score: 順序付きのレベルに対する確率加重値とconfidenceを返す。 公称のレイテンシは70〜500ms、価格は入力が100万トークンあたり0.042ドルで、出力は無料とされています。 そして設計上いちばん重要なのが、stateは1度しか読まれず、すべての質問が並列に評価されるという性質です。これは後半でそのまま速度の話につながります。 もう1つ、ChoiceとScoreの答えにはcalibrated confidenceという確信度が付きます(Noulには付きません)。較正されているという意味で、confidenceが高いほど実際の正答率も高くなります。これも後で使います。 コラム: OpenAIのModeration APIとは何が違うのか この手のモデルの話を聞いて、昔からあるOpenAIのModeration APIを思い出しました。文章を生成せず、テキストを投げると分類結果が返り、しかも速いモデルです。 違うのは、誰が判断基準を決めるかです。 Moderation APIは、カテゴリがサービス側で固定されています。ヘイト、ハラスメント、自傷、性的、暴力といった区分ごとのスコアと、有害である可能性があるかどうかのフラグ(flagged)が返ります。用途が有害コンテンツの検知に寄せてあるぶん、そのままで強い一方、区分そのものは動かせません。「この投稿は内輪のノリか」といった、自分のアプリにしか意味のない問いは立てられません。 Jevは逆で、質問を自分で設計します。stateに文脈を置いて、そこに対して聞きたいことを自分の言葉で並べます。返ってくるのは、その質問に対する確率やスコアです。汎用の分類・スコアリング・抽出のための道具で、モデレーション専用ではありません。 今回のアプリは、まさに「軸そのものを自分で決めたい」側でした。判定の肝は「強い言葉が入っているか」ではなく「悪意があるか」の見極めで、これは既成のカテゴリでは表現できません。 学生時代にチームで作った「へいたん」 へいたんは、学生時代にチームで作ったChrome拡張です。Xのタイムラインを読み取り、誹謗中傷と判定した投稿を隠します。構成は、拡張からAWS Lambda(FastAPI)を叩き、その先でGPT-3.5を呼んで、結果をRedisに7日キャッシュするというものでした。 タイムラインの判定は、GPT-3.5に「この投稿の安全性レベルをJSONで返せ」と頼む方式です。判定用のプロンプトは13行ほどで、例文は入っていません。 へいたんには、投稿前に強い言葉を穏やかな表現へ書き換える提案機能もありました。こちらのプロンプトは85行あり、「変換する例」と「変換しない例」を列挙しています。「返答には変換結果のみを含んでください」「諭すのではなく変換してください」といった、出力の形式を守らせるための念押しも何度か出てきます。モデルに言うことを聞かせるための記述が、判断基準そのものと同じ場所に同居していました。文章を生成するモデルを相手にする以上、当時はこう書くしかなかった部分です。 作り直す 作り直した版はre:へいたんと名付けました。WXT 0.21とReact 19で書いています。対象はタイムラインの検閲だけです。書き換え提案の機能は、Jevが文字列を生成しないので移植していません。 構成はこうなりました。 1 2 3 Chrome拡張 (WXT + React) ↓ Jev 以上です。へいたんではAPIキーをサーバー側に持つ必要があり、そのためにLambdaを置いていました。re:へいたんでは、各ユーザーが自分で発行したAPIキーを拡張の設定に入れ、拡張から直接Jevを呼びます。キャッシュも拡張の中に持たせたので、バックエンドが要らなくなりました。 判定の軸 へいたんの書き換え用プロンプトに並んでいた例文と、re:へいたんの判定は、同じ方向を向いています。どちらも「強い言葉が入っているか」ではなく「悪意があるか」で見分けようとしています。変わったのは、その基準をどこに置くかです。 Jevには文章を渡せますが、レスポンスは文章ではなく構造化されたデータです。そのため「こういう投稿は変換しないでください」と書いても、その指示に従った文章は返ってきません。判断基準は、質問の形に割る必要があります。 ...

2026年9月18日 · 読了時間: 2分 · 松ヶ浦健