Jevの既知の弱点とは|jev-1.13の9つの苦手と回避策、日本語の精度、データの扱い
TypeSafe AIが公開するjev-1.13の9つの弱点(文字どおりの読み取り、計算、日付、間接参照、敵対的入力など)と公式の回避策、日本語の注意点、学習不使用とZDRの方針をまとめます。

Jev(ジェヴ)を業務システムに組み込むとき、LLM エージェントのように「AI に流れごと任せる」設計でよいのでしょうか。
結論から言うと、公式ドキュメントは、制御の流れはコードが持ち、System One モデルには狭く構造化された判断だけを任せる「AI を組み込んだソフトウェア」の形を勧めています。
実務では、通常のワークフローを先に組み、AI が必要な箇所にだけ質問を差し込む順番になります。
How to build with TypeSafe のページでは、ソフトウェアの作り方を3つに分けて比べています。
System One はエージェント用ではなく、AI を組み込んだソフトウェアを作るためのモデルだ、という位置づけです。
従来のソフトウェアは、信頼できる単純な部品を組み合わせた決定木で、部品が確実だから高い抽象化を積めます。
LLM エージェントは指示を読んで自分で次の一手を選ぶため、人が見守っている間はよくても、ループのたびに脱線の機会が増えるとされています。
AI を組み込んだソフトウェアでは、決定的な処理と制御の流れをコードが持ち、モデルは常識的な判断や非構造データの解釈にだけ現れ、各 AI タスクは原子的で制約付きです。
公式は、判断と確率が型や JSON スキーマに合う形で返る「構造化」、質問が互いの隠れた文脈にならない「並列」、しきい値や if 文にそのまま使える「比較可能」の3つを挙げています。
さらに、多くの問い合わせが約 100 ミリ秒で終わる「高速」、RLCD による「校正された信頼度」、繰り返しても答えが安定する「自己一貫性」が続きます。
公式は、知能と速度・コストの比で 100 倍超を目標にしていると述べています。
決定的な処理は信頼でき安価なので、コードに置きます。
公式の例は、請求書の期限超過日数を計算して 30 日を超えたら回収に回す、という素朴な条件分岐です。
days_overdue = (today - invoice.due_date).days
if days_overdue > 30:
route_to_collections(invoice)state には、いま聞く質問に関係する文脈だけを入れます。
公式の例では「フライトが欠航した、返金できるか」という問い合わせ文と返金ポリシーの2項目だけを渡し、ポリシーが返金を支持するかを Noul(ヌール、はい/いいえ)で聞いています。
state は入れ子の JSON にし、質問文からは `support.tickets[0].message` のようにバッククォートで囲んだパスで特定の値を指すと曖昧さが減るとされています。
公式がこのガイドで最も重要だと述べているのが、質問の分解です。
広い質問は複数の判断を1つの答えの裏に隠しますが、原子的な質問はそれを表に出すので、コードで点検・調整・合成ができます。
迷惑メール判定の例では、is_spam という1問の代わりに、認証情報を求めているか、予期しない報酬を告げているか、時間の圧力をかけているか、送信者名とドメインが食い違うか、リンク先のドメインが食い違うか、リンク文言が行き先を隠しているか、という6つの Noul に分けています。
Choice(選択肢)の criteria(基準)は what / not_for / examples のように同じ項目名を全選択肢で揃えると、モデルが選択肢同士を直接比べられるとされています。
同じ state への質問は1回のリクエストにまとめて並列に走るため、分解しても往復は増えません。
独立した答えは、決定的なルールか重み付き和で合成します。
answers = response.answers
# Combine independent signals into one application-specific score.
quality = (
0.4 * answers["answers_request"].noul
+ 0.4 * answers["citations_are_supported"].noul
+ 0.2 * (1 - answers["contradicts_context"].noul)
)最後に confidence(信頼度)で分岐し、自信のない答えは人か高価な推論モデルに回します。
公式の例は 0.8 未満を人のレビューへ送る2行で、しきい値は自分のデータで信頼度と正解率をプロットして検証するよう勧められています。
公式ページ末尾のサポート窓口の例は、以上を1つの関数にまとめたものです。
前半では、閉じた案件をモデルを呼ばずに返し、未配達の注文だけを抜き出して state を組み立てます。
if ticket["status"] == "closed":
return "no_action"
open_orders = [
order for order in customer["orders"] if order["status"] != "delivered"
]
state = {
"ticket": {
"message": ticket["message"],
"sender": ticket["sender"],
"links": ticket["links"],
},
"customer": {
"plan": customer["plan"],
"open_orders": open_orders,
},
"policy": {
"sensitive_credentials": ["password", "security code", "API key"],
},
}この state に、担当チームを選ぶ Choice、迷惑メールの3つの兆候と返金要求・注文言及を聞く Noul、怒りの度合いを測る Score(段階採点)の計 7 問を1回で投げます。
後半は合成と分岐です。
answers = response.answers
spam_risk = (
0.45 * answers["requests_credentials"].noul
+ 0.30 * answers["sender_identity_mismatch"].noul
+ 0.25 * answers["unexpected_reward"].noul
)
spam_is_uncertain = 0.4 < spam_risk < 0.6
if spam_is_uncertain or answers["topic"].confidence < 0.75:
return route_to_human_review(ticket)
if spam_risk >= 0.6:
return quarantine_as_spam(ticket)
if answers["topic"].choice == "billing":
return route_to_billing(
ticket,
refund_requested=answers["refund_requested"].noul >= 0.7,
)迷惑メールの重みはコードが持ち、合成値が 0.4 と 0.6 の間なら迷いとして人に回します。
担当チームの confidence が 0.75 未満でも同じです。
返金要求のような投機的に聞いておいた答えは、該当する経路に入ったときだけ使われます。
カスタマーサポート: 担当チーム分けと迷惑メール判定を、上の例のように1回の呼び出しで済ませられます。
閉じた案件の除外のような決定的な処理(入力が同じなら必ず同じ結果になる処理)はコードに残すのが前提です。
経理・請求: 期限超過はコードで判定し、支払い遅延の理由が正当かどうかのような文章の解釈だけを Noul に渡す分担が考えられます。
ポリシー文を state に同梱すれば、自社の規定に基づいた判断になります。
情報システム・セキュリティ: 迷惑メールの6つの兆候のように、判定を原子的な質問に分けて重み付けする方法は、フィッシング(偽の送信者を装って認証情報を盗む手口)対策にそのまま使えると考えられます。
どの兆候が効いたかが数字で残るため、誤検知の調整がしやすくなります。
| 向いている | 向いていない |
|---|---|
| 流れが事前に決まっていて、要所の判断だけが曖昧な業務 | 次の一手そのものを毎回 AI に決めさせたい探索的な作業 |
| 非構造データを型付きの答えに変えてコードで扱いたい | 文章そのものを生成したい |
公式の設計原則は、決定的な処理と制御の流れをコードに置き、System One には狭く構造化された質問だけを渡す、という一点に集約されます。
核心は、広い判断を原子的な質問に分解して1回で並列に聞き、答えの合成と信頼度による分岐をコードが握ることです。
次の一手は、あなたの業務で「AI に判断させたい」と思っている1つの問いを、上の迷惑メールの例にならって4つから6つの Noul に分けてみることです。