1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

語源英単語アプリ開発で、Claude Code のコスト削減のため、検証を TYPESAFE AI の Jev に任せてみた

1
Posted at

語源で英単語を覚える Web アプリ「Etymo!」と、医学用語版の「Metymo!」のデータを、Claude Code で直す作業をしました。データ量が多いため、Claude Code のトークン消費が問題になります。Claude Code を API の従量課金で使っていると、1 件ずつ Claude に読ませて判断させた分が、そのまま費用になります。

そこで、件数の多い判定は Jev (TYPESAFE AI の判断に特化したモデル) に任せ、Claude には確率の低い境界の語だけを見せる分担にしました。辞書の 5,538 語のうち、既存のまとまり 1,727 件の検証では、Claude が目を通したのは 60 件 (約 3.5%) で、Jev の費用は見積もりで約 $0.06 でした。まとまりの追加でも同じ分担を使い、候補 644 語から 576 語にまとまりを付けました。この記事では、その分担のしかたと、試してみて分かった注意点を書きます。

この記事の要点

  • やったこと: 英単語アプリの辞書データの検証で、件数の多い判定を TYPESAFE AI の Jev に任せ、Claude Code には確率の低い境界の語だけを見せた
  • 結果: 既存のまとまり 1,727 件のうち、Claude が見たのは 60 件 (約 3.5%)。誤り 42 件を直した。新しいまとまりも 576 語に追加した
  • Jev の費用: 約 2,760 回の判定で約 $0.1 (見積もり)
  • 前提: 使う前に、正解の分かっている 150 組で Jev の精度を測った (AUC 0.973)
  • 注意点: 綴りの偶然の一致は Jev も見逃す。データを変えたあとの再実行で、判定済みでない組を送ってしまった

直したかったデータ

アプリは、英単語を語根に分けて表示します。たとえば conservable は con + serv + able です。さらに、語の中に別の見出し語が含まれている場合は、その部分を「まとまり」(データ上は chunks という項目) として囲んで見せます。conservable なら con + serv が conserve (保存する) に当たるので、(con + serv) = conserve + able と表示します。

conservable の表示。con と serv が conserve (保存する) のまとまりとして灰色の枠で囲まれ、その右に able が並ぶ

このまとまりに、2 種類の問題がありました。

  • 付いているべき語に付いていない。considerable には consider のまとまりがあるのに、conservable には conserve のまとまりがありませんでした。
  • 間違った語を指している。admission が ad + (miss + ion) = mission になっていました。接頭辞を除いた残りが偶然 mission の綴りになっていただけで、本来の親語は admit です。

直す前の表示は次のとおりです。左の conservable にはまとまりが無く、右の admission では miss と ion が mission (使命) のまとまりになっています。

直す前の conservable の表示。con、serv、able が並ぶだけで、conserve のまとまりが無い 直す前の admission の表示。miss と ion が mission (使命) のまとまりとして囲まれている

どちらも、1 件ずつ「この語はこの親語から派生したと言えるか」を判断する作業です。候補は数百から千件以上あり、Claude にすべて読ませるとトークンを大きく使います。

分担のしかた

Claude Code と Jev の役割を、次のように分けました。

担当 やること
Claude Code 候補を洗い出すスクリプトを書く、Jev を呼ぶスクリプトを書く、集計する、境界の語を判断する、データに適用して検証する
Jev 候補 1 件ごとに「このまとまりは正しい」という命題の確率を返す

Claude Code の仕事は、ほとんどがスクリプトを書くことになります。判定の結果を全件読む必要はありません。

Jev について

判定には TYPESAFE AI の Jev を使いました。Jev は判断に特化したモデルで、文章を生成する代わりに、命題が正しい確率を 0〜1 で返します。API には、判断の材料になるテキスト (state) と、判定してほしい命題 (questions) を渡します。1 回の呼び出しに命題を複数入れることもできます。

payload = {
    "model": "jev-latest",
    "state": "見出し語: conservable\n語根分解 (parts): ...\n提案するまとまり: parts[0..1] = 見出し語「conserve」...",
    "questions": {
        "chunk_ok": {
            "type": "noul",
            "instructions": "命題: この語は親語から派生した語であり、提案した parts の範囲がちょうど親語に当たる。...",
        }
    },
}
# 応答の例: {"answers": {"chunk_ok": {"type": "noul", "noul": 0.72}}, "usage": {"input_tokens": 776, "output_tokens": 21}}

確率の根拠となる理由は返しません。辞書や Web を参照することもないので、判断の材料は state に書いたものだけです。今回は、子の語と親語それぞれの語根分解と、Wiktionary の語源記述を state に入れました。1 回あたりの入力は約 770 トークン、出力は約 20 トークンでした。

使ってみて、費用のほかに次の点が作業を楽にしました。

  • 今回の呼び出しは、あとで書く誤送信の分も含めて約 2,860 回でした。エラーで判定できなかった組は 1 件もありませんでした。内部で再試行した回数は記録していません。
  • 応答は確率の数値が決まった形で返るので、応答の解釈で失敗することがありません。同じ日に使った汎用の LLM (後述) では、応答の文章から JSON を取り出す処理を書く必要がありました。
  • 正しいか誤りかの二択でなく確率が返るので、確率の帯で Claude が見る範囲を決められます。この記事の分担は、この性質に依っています。

先に試走で精度を測る

Jev を信用してよいかは、使う前に確かめました。正解が分かっている組を用意して、Jev がどれだけ見分けられるかを測ります。

  • 正しい組 100 件: 既存のまとまりから無作為に選んだもの
  • 誤りの組 50 件: 以前の監査で誤りとして削除したもの (comparable←parable、opportunity←unity など) と、今回の候補のうち明らかに誤りのもの (ancestor←story など)

結果は AUC 0.973 でした。AUC は、正しい組の確率が誤りの組より高く出る割合で、1 に近いほどよく見分けられています。本番で使った区切り (0.8 と 0.5) で分けると、次のようになります。

確率 正しい組 (100 件) 誤りの組 (50 件)
0.8 以上 68 件 (68%) 0 件 (0%)
0.5〜0.8 26 件 (26%) 9 件 (18%)
0.5 未満 6 件 (6%) 41 件 (82%)

0.8 以上には誤りの組が 1 件も入らず、0.5 未満には正しい組が 6 件しか入りませんでした。中間の 0.5〜0.8 には両方が混ざるので、ここを Claude が見ることにしました。

この試走は 150 回の呼び出しで済みます。費用は 1 セントに届きません。

確率で 3 つに分け、Claude には境界だけを見せる

本番の判定では、確率で候補を 3 つに分けました。

  • 0.8 以上: 採用の候補。Claude は一覧を流し見して、偶然の一致だけを外す
  • 0.5〜0.8: Claude が 1 件ずつ判断する
  • 0.5 未満: 不採用の候補。ただし、他の帯で採用した型と同じ正しい派生がないかを Claude が見る

Claude に見せる一覧は、1 件 1 行の短い形式にしました。たとえば admission<mission[1-2]0.26 は、「admission を分けた要素のうち、0 から数えて 1〜2 番目 (miss + ion) が mission を指していて、確率は 0.26」という意味です。スクリプトの出力も、件数と要確認の行だけにしています。全件の表を出力すると、それだけで Claude のトークンを使うためです。

まとまりの追加: 候補 644 語

まとまりを持たない約 3,800 語から、別の見出し語に当たりそうな候補を機械的に 644 語抜き出しました。語の中の連続した要素について、次の 3 通りで別の見出し語と照合しています。

  • 語源キーの並びが一致する
  • 語義のラベルを外し、同じ語根の別の綴り (fic と fact など) を 1 つにまとめると一致する
  • キーは違うが、綴りが当たる (語末の e が落ちる conserve→conserv、y が i になる、-ate が落ちる negotiate→negoti)

キーの照合だけでは足りませんでした。既存のまとまりの多くは、子の語と親語で語源キーの付け方が揃っていません (biological←biology など)。

この 644 語を Jev で判定した結果は次のとおりです。

確率 語数 Claude の扱い
0.8 以上 218 一覧を流し見しただけ
0.5〜0.8 341 1 語 1 行で判断
0.5 未満 82 1 語 1 行で判断

確率をそのまま採否にはせず、Claude が次の判断を加えました。

  • 確率が 0.5 以上でも、誤りの 10 語は外した。incoming←coming のような綴りの偶然の一致や、commune を指していた communism・community など
  • 0.5 未満でも、他の帯で採用した型と同じ正しい派生の 27 語は採用した。accuracy←accurate、illustration←illustrate など
  • より近い親語がある語は、そちらを採った。activation は active でなく activate に、unsuccessful は success でなく successful にした
  • 親語の最初の語義が合わない 52 語は、まとまりに添える意味を選び直した。semiconductor←conductor は「指揮者」でなく「導体」にした

最終的に 576 語にまとまりを追加しました。-able・-ible で終わる 3 要素以上の語は、54 語中 53 語にまとまりが付きました。

こちらは、Claude が 1 語ずつ見た語が約 420 語あり、見た割合は次の見直しより大きくなっています。それでも、0.8 以上の 218 語は流し見で済み、残りも 1 語 1 行の短い形式で判断できました。

既存のまとまりの見直し: 1,727 件

既存のまとまり 1,727 件を、同じ質問で判定し直しました。0.5 未満は 60 件で、Claude が見たのはこの 60 件だけです。

60 件の内訳は、付け替え 28 件、削除 14 件、そのまま残すもの 18 件でした。付け替えたのは、admission←mission を admit に、conversion←version を convert に、informal←inform を formal に直したような例です。直したあとの admission は、ad と miss が admit (認める) のまとまりになります。

修正後の admission の表示。ad と miss が admit (認める) のまとまりとして囲まれ、その右に ion が並ぶ

削除したのは、satisfactory←factory や conscience←science のように、意味の離れた語を指していたものです。

費用

Jev の費用は、以前に全件判定したときの実績 (約 1,300 万トークンで約 $0.6) の単価から見積もった値です。

作業 呼び出し回数 費用 (見積もり)
試走 150 1 セント未満
まとまりの追加 883 約 $0.04
既存のまとまりの見直し 1,727 約 $0.06

既存のまとまりの見直しで Jev に送った入力は、計 132 万トークンでした。

同じ分担は Jev 以外でも使えます。同じ日に、全 1.1 万語の品詞と日本語の意味の食い違い、例文の誤りを、OpenRouter 経由の gemini-3.5-flash-lite で 100 語ずつ照合しました。費用は 2 つの照合を合わせて $0.18 で、Claude は指摘された約 120 件だけを見ました。

注意点

Jev の確率は、正しい語でも低めに出ることがある

試走では、正しい組の確率の中央値が 0.83 でした。ところが本番の候補では、正しい派生でも 0.5〜0.8 に入るものが多く出ました。negotiable←negotiate や conservable←conserve は、どちらも 0.7 台です。試走のしきい値をそのまま当てはめず、中間帯は人が見る前提にしておくと安全です。

綴りの偶然の一致は、Jev も見逃す

incoming←coming は、in + coming と綴りは一致しますが、income の派生でも coming の派生でもありません。この組には Jev も 0.79 という高い確率を付けました。確率の高い帯も、流し見はしたほうがよいと思います。

再実行で、判定済みのものを送り直さない

判定のスクリプトは、結果を JSONL に追記し、判定済みの組は送らない作りにしました。ところが試走の組は「その時点のデータから無作為に選ぶ」作りだったため、データにまとまりを追加したあとで再実行すると、選ばれる組が変わりました。結果として、判定済みでない 103 件を Jev に送ってしまいました。

判定の対象を無作為に選ぶときは、抽出元を git のコミットで固定しておく必要があります。

使用量を記録しておく

最初のスクリプトは、Jev の応答に含まれる使用量 (入力・出力のトークン数) を保存していませんでした。あとから費用を聞かれても、見積もりしか出せません。判定のたびに使用量を JSONL に書いておけば、集計時に合計を出せます。

まとめ

件数の多い判定は Jev に任せ、Claude Code には確率の低い境界の語だけを見せると、トークンの消費を大きく抑えられます。既存のまとまり 1,727 件の検証で Claude が見たのは 60 件、Jev の費用は見積もりで約 $0.06 でした。Jev を使う前に、正解の分かっている組で試走して精度を確かめておくことが前提になります。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?