5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Jev + Generative UI で Web 制作の LLM トークンを 72% 削減できた話(3ページの企業サイトで実測)

5
Last updated at Posted at 2026-09-24

要点

  • 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

生成したページの比較

トップページの初回生成比較。左がLLM直接生成、右がJev + json-render

左右とも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を使います。撮影スクリプトはcurllsofを利用し、ポート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.mdresults/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の構築を生成ではなく選択に寄せる設計が、トークンと費用の両方を圧縮することを実測で確認できました。ページ数やモデルが変われば数値は変わります。

参考リンク

5
6
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
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?