要点
- Jev(TypeSafeの判断専用モデル)+ json-renderを使うGenerative UI方式は、LLMに直接コードを生成させる方式に比べ、架空の企業サイト3ページで合計LLMトークン(キャッシュ分を除く)を72%削減できました。
- 初回生成+修正3回の合計で、LLMトークンは13,954から3,968へ71.6%減り、費用は$0.7830から$0.2988へ61.8%減りました(Jevの参考費用込み)。
- 削減量の約6割は修正フェーズで生まれ、修正3回では、Jev + json-render側のLLM呼び出しをゼロにできました。
- できあがったページは、見た目・構成ともに両方式でほぼ同等です。
はじめに
この記事は、生成AIを使ったWeb開発やAI駆動開発の導入を検討しているエンジニアを対象にしています。比較するのは「LLMに直接コードを生成させる方式」と「Jev + json-renderを組み合わせる方式」の2つです。架空のB2B SaaS企業サイト3ページを両方式で実際に生成し、初回生成と修正3回にかかったLLMトークン・費用を実測しました。この記事を読むと、両方式でできあがるページの見た目の違いと、トークン・費用の削減幅が分かります。
記事内の数値は1回の実行・1つのモデル(claude-sonnet-5)での実測値です。モデルやページ数、修正内容が変われば数値は変わります。
Jev と Generative UI の概要
この記事では、Jev と Generative UI(json-render)の仕組みは動かすのに必要な範囲の概要にとどめます。詳しい解説は別の記事に譲ります。
Jev とは
Jevは、TypeSafeが提供するSystem Oneモデル(判断専用のAIモデル)です。自然文とアプリの状態を受け取り、選択肢から1つ選ぶ(Choice)・段階で評価する(Score)・条件の真偽を確率で返す(Noul)といった型付きの判断と確率を返します。文章やコードは生成しません。応答が速く(今回の計測では1回の呼び出しが1秒未満でした)、単価はTypeSafeの公式発表による入力100万トークンあたり$0.042、出力は無料です。本記事では、候補の中からどのUI部品を採用し、どう並べるかを判断させる役割に使っています。
Generative UI とは
Generative UIは、AIが実行時に画面の構成を決める仕組みの総称です。本記事で使うjson-render(Vercel Labs)は、アプリ側があらかじめ許可した部品とpropsの型をカタログとして定義しておき、AIは「どの部品を、どのpropsで、どの順に置くか」をJSONのSpecとして出力し、json-renderがそれを検証してReactに描画する、という宣言的なタイプです。AIが直接HTMLやReactのコードを書くのではなく、決められた部品の組み合わせだけを選ぶため、壊れたUIや未知の部品が出ません。json-renderには、Jevで候補から構成を選ばせる実験的なAPI(experimental_composeSpec)があり、本記事はそれを使っています。
いずれも詳しい仕組みやAPIの使い方は別の記事で扱います。
2つの方式
LLM直接生成
LLMに、共通の部品ライブラリを使ったReact/TSXコードをそのまま書かせる方式です。ページごとに1回LLMを呼び出し、見出し・本文・使う部品の組み合わせを、事前に指定した必須要素・順序の制約の範囲でLLMが決めます。
Jev + json-render
Jevが、文言のない候補からページ構成を選びます。採用が決まったセクションだけをLLMが文言化し、その結果をJSON Spec(ページ構造を表すJSON)に反映します。json-renderがそのSpecを検証し、Reactコンポーネントとして描画します。
実験の条件
架空のB2B SaaS企業サイトを想定し、トップ・サービス・お問い合わせの3ページを両方式で生成しました。両方式とも同じ部品ライブラリ(Page / Hero / Features / Testimonials / Pricing / FAQ / News / Team / ContactForm / CTAの10種類)、同じCSS、同じLLM(Claude Sonnet 5)を使い、文言の分量規定(箇条書きの件数など)も同一です。各ページの本文セクションは5〜7個としました(Hero と CTA を含み、Header と Footer は除きます)。
初回生成後、次の3回の修正を順番に適用しています。
- 修正①: トップページのHeroをsplit(製品画像つき)からcentered(中央寄せ)に変更
- 修正②: トップページのPricingセクションを削除し、FAQをFeaturesの直後に移動
- 修正③: 全ページのCTA文言を変更し、ボタンのintentをprimaryに統一
本記事のLLMトークンは、Claude Codeが報告する入力+出力トークンです。キャッシュの読み書き分は含みません。計測したのは、ページ生成に使ったLLMの入力+出力トークンと費用です。費用は実請求額ではなく、Claude Codeが報告する定価換算とJevの公式単価による換算です。Jevの単価はTypeSafeの公式発表による入力100万トークンあたり$0.042、出力は無料です。
直接生成側は修正のたびにTSX全文を再生成します(差分編集ではありません)。両方式とも新規部品・任意CSS・フックの生成は禁止し、トップページの初期セクション順は指定しています。差分編集や候補外の変更、候補設計の工数は比較に含めていません。
結果
| LLM直接生成 | Jev + json-render | |
|---|---|---|
| 初回生成(3ページ)LLMトークン | 7,804 | 3,968 |
| 修正3回LLMトークン | 6,150 | 0 |
| 合計LLMトークン | 13,954 | 3,968 |
| Jevトークン(入力+出力) | 0 | 48,490 |
| LLM呼び出し回数 | 8 | 3 |
| 費用(LLM定価+Jev参考単価) | $0.7830 | $0.2988 |
| 検証合格 | 3/3ページ | 3/3ページ |
削減率は、合計LLMトークンが71.6%、費用(Jev参考値込み)が61.8%でした。LLM呼び出し回数の内訳は、初回3件+修正5件(トップ2回+全3ページ1回)です。検証合格は、セクション数・項目数・順序・指定文言の機械検証によるもので、文章品質やUXの同等性の評価ではありません。
ページ別(初回生成)の内訳です。
| ページ | LLM直接生成トークン | Jev + json-renderトークン | 判定 |
|---|---|---|---|
| お問い合わせ | 2,185 | 1,040 | 両方PASS |
| サービス | 4,247 | 1,464 | 両方PASS |
| トップ | 1,372 | 1,464 | 両方PASS |
生成したページの比較
左右ともHero→Features→Testimonials→Pricing→FAQ→CTAの並びで、文言だけが別々に生成されています。
構成はほぼ同じで、TestimonialsとFAQの順序だけが入れ替わっています。
Heroの構成とセクション数は異なりますが、いずれもお問い合わせフォームを中心に据えた構成です。
両方式とも指示どおりPricingが消え、FAQがFeaturesの直後に移動しています。
両方式ともCTAの見出しとボタン文言が「まずは無料相談から」「無料相談を予約する」に統一されています。
差が生まれる理由
初回生成では、Jev + json-render側はLLMに文言だけを書かせるため出力が短くなります。修正①②では、直前のSpecと保存済みの候補を使い、Jevが候補の中から置換・削除・移動を選ぶだけで完結します。修正③では、指示に含まれる新しい文言をコードでCTA候補に設定して候補一覧に追加し、Jevがその候補への置換を選びます。そのため今回の修正ではLLMによる文言生成が不要でした。
// arms/b-jev/run.ts(runEdit、抜粋)
for await (const event of experimental_composeSpec({
catalog,
candidates,
initialSpec, // 直前フェーズのSpecをそのまま渡す
prompt, // 修正指示文
evaluate,
maxSteps: 8,
})) {
// ...
}
初回生成でJevに構成を選ばせる呼び出しは、次のように統一しています(promptの条件は一部省略しています)。
// arms/b-jev/compose.ts(抜粋)
for await (const event of experimental_composeSpec({
catalog,
candidates,
prompt: `法人向けAIエージェント基盤の${slug}ページ。${page.purpose}`,
evaluate,
maxElements: 12,
maxSteps: 8,
instructions: {
root: "Page が root。",
next: nextInstruction, // 「Hero先頭・CTA末尾・本文5〜7個」等の指示
},
})) {
// ...
}
Jevに渡す候補は、文言のないプレースホルダです。実際に生成されたトップページの候補(2件抜粋。propsは一部省略)はこうなっています。
[
{
"id": "hero-split",
"description": "Split-layout hero with a product screenshot beside the copy, for concrete/trustworthy framing.",
"element": { "type": "Hero", "props": { "variant": "split" } },
"resource": "hero"
},
{
"id": "hero-centered",
"description": "Centered hero focusing the message on a single call to action, no product screenshot.",
"element": { "type": "Hero", "props": { "variant": "centered" } },
"resource": "hero"
}
]
候補の生のpropsは自動では送られず、Jevはdescription・prompt・構築指示・明示したcontextを判断材料にします。修正①でHeroをcenteredへ変えるときは、この2件のうちhero-centeredを選び直すだけで、LLMを呼ばずに完了します。
自分の環境で試す
この記事の実験に使ったコード一式は、公開リポジトリnogataka/jev-json-render-benchmark(MIT)で公開しています。
動作には次の環境が必要です。
- Node.js 24 と pnpm
- Claude Codeをサブスクリプション認証で使います。
ANTHROPIC_API_KEYを設定しているとAPI課金になるため、未設定の状態にしておく必要があります - TypeSafeのAPIキー(console.typesafe.aiで発行し、
TYPESAFE_API_KEYに設定します。従量課金です) - 画面ショットを撮る場合(任意)は
playwright-cliとChromium、Python 3 + Pillowを使います。撮影スクリプトはcurl・lsofを利用し、ポート8899を使います。
再現手順は次のとおりです。
git clone https://github.com/nogataka/jev-json-render-benchmark.git && cd jev-json-render-benchmark
pnpm install
pnpm typecheck && pnpm smoke && pnpm poc:mock # 無課金の動作確認
export TYPESAFE_API_KEY=...
pnpm experiment --run 1 --pages top,services,contact
pnpm aggregate-simple --run 1
bash scripts/screenshot.sh 1 && python3 scripts/compose-shots.py 1
結果はresults/run-1/summary-simple.mdとresults/run-1/shots/に出力されます。リポジトリのresults/example/には、この記事で使った集計結果と比較画像を同梱しています。
注意点
- Jevは文言やデータを生成しません。文言は別途LLMで用意する必要があります。
- 候補(部品の種類と用途の説明)をあらかじめ設計しておく必要があります。候補が不足していると、Jevはそもそも選べません。
- Jevのトークンは別モデルのため、LLMトークンとは合算せず、費用でのみ合算しています(Jevは参考単価)。
- 本実験は、既成コンポーネントを使うページ生成と、候補の置換・削除・移動で対応できる修正を対象にしています。直接生成側は毎回TSX全文を再生成するため、差分編集との比較ではありません。新規部品の実装、候補外の変更、候補設計の工数は比較対象に含めていません。
- 今回は1回の実行・3ページでの計測です。モデルやページ数が変われば数値は変わります。
まとめ
3ページの企業サイトという小さな規模でも、Jev + json-renderは初回生成と修正を合わせた合計LLMトークン(キャッシュ分を除く)を71.6%、費用を61.8%削減しました。削減量の約6割は修正フェーズで生まれ、修正3回ではJev + json-render側のLLM呼び出しをゼロにできました。生成されたページの見た目・構成は両方式でほぼ同等でした。今回の条件(既成コンポーネントを使うページ生成と、候補の置換・削除・移動で対応できる修正)では、UIの構築を生成ではなく選択に寄せる設計が、トークンと費用の両方を圧縮することを実測で確認できました。ページ数やモデルが変われば数値は変わります。




