コンテンツにスキップ

AI WF2Des — 概要

WF2Des は、プロジェクトのデザインルールの下で 直接組み立て(direct assembly) によって、Figma の ワイヤーフレーム をハイファイな ネイティブ Figma デザイン に変換します。ワイヤーフレームの各セクションについて、LLM が登録済みのコンポーネント(およびその variant、text、image アセット)を選択し、決定的な validator がルールを強制し、Figma plugin が結果をキャンバス上にマテリアライズします。retrieval も、埋め込みも、ベクトル検索も、学習コーパスもありません — エンジンはプロジェクト自身のコンポーネントレジストリとルールセットを直接読み込み、それらから組み立てます。これがインデックス化されたベクトルから候補プールをリランキングする des2code との決定的な違いです。

1 つの Lambda worker が generation(2-phase parse → assemble)と 6 種の discriminated wf2des-events message (frame_registration、rule_upload、resync、component_upload、component_capture、render_review)を処理します。 generation は product row で追跡し、event_run_id を持つ internal event は wf2des_event_status に queued/processing/done/failed progress を記録します。

バックエンドが製品契約を所有 します — wf2des PostgreSQL 行、および実行を作成・読み込み・confirm・cancel・place・feedback するエンドポイント — 一方で AI 側が実行を所有 します。ワーカーは PostgreSQL に絶対に書き込まず、PG 認証情報を保持しません。generation の完了は generation 専用の ai-status Webhook を通じて戻され、バックエンドがそれを 1 つのトランザクション内で行に適用します。internal event は Webhook に触れず、wf2des 行も反転しません。

  • キュー: バックエンド所有の generation SQS キュー(parse / assemble)。AI 所有の wf2des-events 取り込みキュー(rule / plugin イベント)。AI 所有の EventBridge スケジュール(component resync のみ)
  • ソース: guinness-ai-v2 — apps/wf2des
  • 主要な出力: plugin がマテリアライズするネイティブ Figma デザイン。generation は加えて S3 結果アーティファクト + マニフェストを書き込み、ai-status Webhook を POST します
  • ストア: 1 つの PostgreSQL テーブル wf2des(バックエンド所有)+ 6 つの DocumentDB コレクション + S3 アーティファクト
  • ステータス報告: generation のみ ai-status Webhook。internal event は Webhook を持たず、tracked の場合は wf2des_event_status を使います

技術スタック

レイヤ 採用技術
ランタイム Python 3.12 on AWS Lambda(コンテナイメージ。ReportBatchItemFailures による部分バッチ SQS)
AI フレームワーク PydanticAI(エージェントオーケストレーション、プロバイダー非依存)— ステップが明示的に LLM を呼ぶ箇所のみで使用
LLM ティア Fast tier(parse / wf_parse の role + intent)、strong tier(assemble のセクション選択)。モデル id はデプロイごとに設定
データベース Amazon DocumentDB(guinness_v2、DocumentDB 5.0)— 6 つの wf2des コレクション
オブジェクトストレージ Amazon S3 — snapshot、結果アーティファクト + マニフェスト、config
キュー AWS SQS: バックエンド所有の generation キュー + AI 所有の wf2des-events 取り込みキュー。component resync 用の AWS EventBridge スケジュール
Figma アクセス サービスアカウント PAT 経由の Figma REST(component sweep、rule_process のボードレンダリング、snapshot / memo フォールバック)
ステータス通知 Webhook POST /v1/webhooks/ai-status(X-API-Key 付き)— generation のみ
データプレーン API internal-api アプリにホストされた wf2des-api ルートグループ(DocDB + S3 のみ)
ロギング 共有 observability パッケージ経由の構造化ログ
RDB アクセスなし — ワーカーは PostgreSQL / MySQL に決して書き込まず、PG 認証情報を保持しない
Retrieval なし — 埋め込みなし、ベクトルインデックスなし、類似度検索なし、学習コーパスなし

生成エンジン — 直接組み立て

Generation は看板となる能力です。これは 決定的ファースト(deterministic-first)なパイプライン であり、LLM は限定され、エビデンスに pin された判断のみを行い、それ以外はすべて再現可能な変換です。どこにも類似度機構はありません: 埋め込みなし、ベクトル検索なし、インデックスに対する候補リランキングなし、学習コーパスなし。ワーカーはプロジェクト自身のコンポーネントレジストリとルールセットを読み込み、それらから直接組み立てます。

パイプライン、順に:

  1. 決定的な WFNode 抽出 — ワイヤーフレーム snapshot を WFNode ツリーに走査します(可視の FRAME / GROUP / INSTANCE / TEXT の各子孫 + 画像塗りの矩形。vector の葉は親に折りたたむ。隠しレイヤーはスキップ)。ツリー形状は決定的 です — LLM がそれを発明したり再形成したりすることは決してありません。
  2. LLM は role + intent のみを割り当てる(fast tier)— 各ノードは共有の要素タイプ語彙から role を、OPEN memo と variant ラベルから導出した intent を得ます。これは parse における唯一の LLM ステップであり、ツリー形状には決して触れません。
  3. 決定的な候補セット — プロジェクトの registry を dedup / hygiene 折りたたみした後、本番 default の role→kind gate が各 section に構造上不適切な component kind を除外します。vector scoring や similarity retrieval はなく、ストレートでテナントスコープのセットです。size は gate ではなく selection signal のままです。
  4. LLM のセクション並列選択(strong tier)— セクションは独立して並列に判断されます。各 section の admissible candidate から、閉じた case(下記)、component key、variant props、text-slot fill を選びます。各候補はその完全な構造で判断され、選択は K サンプルの自己整合性(self-consistency)投票 によって行われます(K 個のサンプルにわたる多数決の解決が勝ちます)。memo intent は request prompt より優先され、rules digest は advisory input です — validator が常に上書きします。選択の前に、実行は design_resolution 決定レジャー(自律品質ラチェット)を参照し、選択後に選ばれた解決を書き戻します — 人手による修正ループが存在しないため、品質はマシン側で収束します。
  5. 決定的な縫合 — セクションごとの判断が自己完結型の DesignSpec(spec ツリー + spec_nodes_flat + style_bindings マップ)に縫合されます。spec は同じ判断から再現可能です。
  6. 決定的な rules validator — 違反は安全な範囲で自動修正され、そうでなければフラグ付けされます。ルール未登録の場合、validator は no-op となり、全ノードに rules_unvalidated フラグが付きます。
  7. 計算された confidence — confidence は validator 違反、unmatched/composed カウント、slot の曖昧さ、component-fit(role の一致)から 計算 されます。モデルの自己申告は決して使われません。
  8. plugin が spec をマテリアライズ し、キャンバス上のネイティブ Figma にします。bounded actual-render review は元 output を保持するか、隣に 1 回だけ correction candidate を構築します。検証済み correction のみが元 output を置換します。

spec はちょうど 5 つのノードケース を持ちます:

Spec ノード 意味
layout_frame 子ノードを保持する auto-layout コンテナ(direction、gap、padding、sizing)
instance 登録済みコンポーネントのインスタンス — component key、variant props、text-slot および asset 塗り
compose 合成されたサブツリー(単一のコンポーネントが適合しない)— 最も根拠が弱いとして 常にフラグ付け
text style token にバインドされたコンテンツを持つ text ノード
unmatched 確信できるマッチのないノードのプレースホルダ — フラグ付け され、静かに削除されることは決してない

明確な線引き: compose セクションは常にフラグ付けされ、unmatched ノードは常に可視のプレースホルダになり、confidence は決してモデルの自己申告ではありません。これらが揃うことで、低 confidence な判断はすべて隠されるのではなく、デザイナーのレビュー用に表面化され続けます。


実行ファミリー

1 つの worker が generation と 5 つの internal event path を処理します。Generation はインタラクティブでジョブ追跡されるフローです。internal event は generation の ai-status webhook ではなく wf2des_event_status を使い、wf_parse と rule_process は PG フリーでもあります。component_sweep のみ backend-side registry effect(sweep マニフェストからの design type=component upsert)も生成しますが、wf2des 行の反転は決して生じません。render_review は plugin render evidence を評価して correction 1 回 + verification 1 回だけを許可します。メッセージとフィールドの詳細は I/O 定義 を参照してください。

実行 トリガー 何をするか 主要な出力
Generation(parse + assemble) バックエンド所有の generation SQS キュー ワイヤーフレームフレームを parse し、confirm のために待機(または auto-confirm)した後、コンポーネントを選択し、spec を縫合 + 検証し、confidence を計算 ネイティブ Figma デザイン(plugin)+ S3 結果アーティファクト + マニフェスト + ai-status Webhook
wf_parse wf2des-events — plugin frame-registration イベント generation-parse と同じ parse パイプラインだが、wireframe キャッシュドキュメントのみを書き込む — 結果ドキュメント、プレビュー、Webhook はなし wireframe キャッシュドキュメント
rule_process wf2des-events — rule-upload イベント 選択されたガイドラインボードをレンダリングし(Figma REST、PAT)、各ボードを vision 抽出し、フラグメントを決定的にマージして 1 つのイミュータブルな design_rule リビジョンにする(ボード + ルールを 1 つのドキュメントに) design_rule ドキュメント
component_sweep EventBridge スケジュール、または wf2des-events plugin resync イベント 決定的な Figma REST フルファイル巡回。コンポーネント instancing コンテキストをリフレッシュし、レジストリ用の発見コンポーネントマニフェストを発行(LLM なし) design_component ドキュメント + コンポーネント snapshot + sweep マニフェスト
component_capture wf2des-events — plugin capture event plugin からしか取得できない publish key、axis、variant evidence を sweep-derived field を劣化させず merge enriched design_component docs + event status
render_review wf2des-events — plugin render evidence actual PNG + node geometry + diagnostics を review。grounded correction を 1 回だけ提案でき、その後は verification のみ review result/candidate artifacts + event status

バックエンド ↔ AI の分担

所有権はクリーンなコントロールプレーン / データプレーンの線に沿って分割されます。

バックエンド — 製品コントロールプレーン。 バックエンドは wf2des PostgreSQL 行(status / phase / attempt)と、あらゆる製品向けエンドポイント(create、get、confirm、cancel、placement、feedback)を所有します。また ai-status Webhook ハンドラ をホストし、これが 完了時の唯一の PG 書き込み者 です — generation 実行の行がターミナル状態に進められる唯一の場所です。バックエンドは(generation ジョブをエンキューする前に)行を まず 書き込み、完了 Webhook を attempt ガード付きで 1 つのトランザクション内に適用します。

AI 側 — ワーカーとその実行。 AI 側は apps/wf2des ワーカーと実行の配管を所有します: バックエンド所有の generation キューが generation(parse / assemble)を駆動し、AI 所有の wf2des-events 取り込みキューが内部実行を駆動し(バックエンドは 送信権限のみ を保持)、AI 所有の EventBridge スケジュール が component resync を駆動します。AI 側は wf2des-api データプレーン も所有します — internal-api アプリ内のルートグループで、DocumentDB + S3 のみ を読み書きし、プレビュー、placement、ファイル登録のために plugin が使用します。

厳格ルール。 ワーカーは PostgreSQL に絶対に書き込まず、PG 認証情報を保持しません。ワーカーは自身の DocumentDB コミットを (wf2des_id, attempt) でフェンシングし、両方を Webhook 経由で報告します。バックエンドが attempt ガード付きで行を進めます。システム内のあらゆる PG 効果はバックエンド側で — ai-status ハンドラまたは confirm / placement / feedback エンドポイントによって — 適用され、ワーカーによっては決して適用されません。


処理フロー

Generation のハッピーパス(インタラクティブ confirm を表示。auto-confirm のショートカット付き):

flowchart TD
    A["Backend: INSERT wf2des row<br/>status '0' phase parse (row FIRST)<br/>+ capture WF snapshot"] --> B["SendMessage → generation queue<br/>(parse: wf2des_id, attempt, nonce, URLs, hash)"]
    B --> C["Worker: parse<br/>deterministic WFNode extraction<br/>+ LLM roles/intent + parse.json"]
    C --> D["Webhook: parse_done"]
    D --> E["ai-status handler:<br/>wf2des.phase → '1' awaiting_confirm"]
    E --> F{"auto_confirm?"}
    F -->|no| G["Plugin previews via wf2des-api<br/>→ designer confirms"]
    G --> H["Backend confirm endpoint<br/>CAS on awaiting_confirm + attempt<br/>→ phase '2' assemble → enqueue assemble"]
    F -->|yes| I["assemble chained in the<br/>same parse invocation<br/>(no awaiting_confirm park)"]
    H --> J["Worker: assemble<br/>rehydrate pins → role/kind candidate gate<br/>→ LLM section selection → stitch spec<br/>→ rules validator → computed confidence"]
    I --> J
    J --> K["S3: result artifact + manifest"]
    K --> L["Webhook: succeeded + manifest key"]
    L --> M["ai-status handler:<br/>wf2des status → '1' completed<br/>+ result refs + flag_count (one PG txn)"]
    M --> N["Plugin materializes native Figma<br/>on the canvas"]
フェーズ 処理 出力
行 + snapshot バックエンドが wf2des 行(status '0'、phase parse)を挿入し、トリガー時点のワイヤーフレーム snapshot をキャプチャした後、エンキュー ジョブより前に行が存在。generation キュー上の parse メッセージ
Parse 決定的な WFNode 抽出 + memo ステータス。LLM が role + intent を割り当て。wireframe キャッシュドキュメント + イミュータブルな parse.json + 結果ドキュメントの parse ブロックを書き込む parse.json アーティファクト + parse_done Webhook
Awaiting confirm ハンドラが行を phase awaiting_confirm で待機させる。plugin が wf2des-api 経由でプレビューし、デザイナーが confirm(auto-confirm ではスキップ) phase '1' awaiting_confirm。confirm で assemble メッセージ
Assemble pin を再水和。role/kind-admissible candidate set を構築。LLM の section-parallel selection(K サンプル投票、design_resolution レジャーを参照後に書き戻し)。spec を縫合。rules validator を実行。confidence を計算 結果ドキュメントの spec / validator / confidence ブロック
Complete S3 結果アーティファクト + マニフェストを書き込む。succeeded Webhook を POST。ハンドラが 1 つの PG トランザクションで行を completed に反転 status '1' completed + 結果参照 + flag_count
Materialize plugin が spec を読み込み、キャンバス上にネイティブ Figma デザインを構築。placement フィールドは wf2des-api 経由で書き戻される ネイティブ Figma デザイン

auto_confirm 経路は awaiting_confirm の待機を完全にスキップします — assemble が同じ parse 呼び出し内で背中合わせに実行され、succeeded Webhook のみが発火します。


ストア

WF2Des は 1 つの PostgreSQL テーブル(バックエンド所有)と 6 つの DocumentDB コレクション(AI 所有)に触れ、加えてアーティファクトと snapshot 用に S3 を使用します。完全なドキュメント形状とフェンシングは I/O 定義 を参照してください。

ストア 用途
PostgreSQL wf2des(バックエンド所有) generation 実行の行 — status / phase / attempt + 結果参照 + flag_count。バックエンドのみが書き込み。内部実行は行を持たない
DocumentDB wireframe parse 済みワイヤーフレームのキャッシュドキュメント(WFNode ツリー + memo + summary)。generation-parse と wf_parse が書き込む
DocumentDB design_rule イミュータブルなルールリビジョンドキュメント — (design_rule_id, content_hash) ごとに 1 つ。各リビジョンはマージ済みの抽出ルールセット と ソースとなるガイドラインボード画像(選択 LLM の vision リファレンス)を保持。コレクションがルールのリビジョン履歴
DocumentDB design_component コンポーネントの instancing コンテキスト のみ(variant props、text/image slot、default size)— レジストリのライフサイクルはプラットフォーム design 行に存在
DocumentDB project_figma_file ファイルごとの style capture + sweep ウォーターマーク / マーカー。component sweep をスコープ
DocumentDB design_generation_result generation 実行自身のドキュメント — pin 済みの inputs、parse、spec、selection、validator_report、confidence、placement
DocumentDB design_resolution 決定レジャー — 構造的なセクションシグネチャ → コンポーネント解決。mined/voted の provenance + 決定的スコア(選択の前に参照され、選択後に書き戻される自律品質ラチェット)。完全な形状は I/O 定義 を参照

コンポーネントレジストリは共有プラットフォームの design テーブル(type=component)です — des2code が消費するのと同じカタログ — であって、wf2des 専用のテーブルではありません。component_sweep はマニフェストを発行し、バックエンドがそれを design 行の upsert として適用します。design_component コレクションはそれらの行にキー付けされた assembly/instancing コンテキストのみを保持します。


モジュール構成

プラットフォームワーカーレシピ(design-import / des2code と同じ handler / service / schemas / repo 分割)に従い、決定的エンジンとルール取り込みパイプラインをそれぞれ独立したパッケージに分離しています。

apps/wf2des/src/wf2des/
  handler.py      # Lambda エントリ — SQS / イベント解析、batchItemFailures、ウォームスタートクライアント
  service/        # 実行ファミリーごとに 1 モジュール(ドメインはコールグラフ到達性で決定)
    dispatch.py   #   process_record() — 1 レコード入力、1 実行ファミリー出力
    generation.py #   parse + ボード理解 + assemble
    rules.py      #   rule_process
    sweep.py      #   component_sweep
    registration.py #  wf_parse
    render_review.py #   render_review
    shared.py     #   複数ファミリーから到達されるヘルパー
  engine/         # 決定的: I/O なし、ネットワークなし
    candidates.py #   選択に提示する候補集合
    stitch.py     #   決定を入力に DesignSpec を出力
    validate.py   #   ルールバリデータ + 算出 confidence
  ingest/         # NODE ルールパイプライン: comprehend → ロール別 extract → 決定的マージ
  schemas/        # Pydantic モデル(ドメインごとに 1 モジュール)。パッケージ自体が契約サーフェス
  llm.py          # LLM フェンス — ワーカー内で Agent を構築する唯一の場所
  nodes.py        # engine と実行フェーズが共有するワイヤーフレームノードのヘルパー
  repo.py         # DocumentDB + S3 + Figma REST + ai-status webhook の I/O
  figma.py        # スナップショット解析 / WFNode 抽出 / component-sweep のファイル全走査
  prompts.py      # 全プロンプトと PROMPT_VERSION pin
  constants.py    # ドメイン定数(閾値、語彙、式の pin)
  usage.py        # ステージ別 LLM 使用量の集計
  config.py       # Config(pydantic-settings)
モジュール 責務
handler.py 全トリガー(SQS + EventBridge)の Lambda ハンドラ、batchItemFailures
service/ 実行ファミリーごとに 1 モジュール。dispatch.process_record() が generation と各 discriminated internal event をルーティング
engine/ 決定的な候補選択・stitch・検証。純粋関数で I/O を持たない
ingest/ NODE ルールパイプライン(現行): comprehend、ロール別 extract、権威ゲート付きマージ
schemas/ Pydantic メッセージ + ドキュメントモデル = 契約サーフェス(形状変更時に index_schema_version をバンプ)
llm.py Agent 構築の全体。モデル ID・プロンプト pin・設定を 1 か所に集約
repo.py DocumentDB upsert、S3 get/put、Figma REST 読み取り、webhook POST
figma.py スナップショット解析、WFNode 抽出、component-sweep 走査
usage.py ステージ別 LLM 使用量。design_rule / design_generation_result に永続化
config.py 環境変数(pydantic-settings)

環境と設定

wf2des に関連する環境と設定です。具体的なモデル id、キュー URL、スケジュールレート、シークレット ARN は デプロイごとに設定 されます。

変数 / 設定 説明 例 / デフォルト
DOCUMENTDB_CONNECTION_STRING DocumentDB 接続文字列 mongodb://user:pass@host:27017/?tls=true
DOCUMENTDB_NAME DocumentDB データベース名 guinness_v2
DOCUMENTDB_CA_PATH TLS CA バンドルパス /var/task/global-bundle.pem
コレクションごとの名前 6 つのコレクションの環境変数で上書き可能なコレクション名 wireframe、design_rule、design_component、project_figma_file、design_generation_result、design_resolution
Generation キュー parse / assemble を駆動するバックエンド所有の SQS キュー キュー URL はデプロイごと
wf2des-events キュー AI 所有の取り込みキュー(rule / plugin イベント。バックエンドは send-only) キュー URL はデプロイごと
EventBridge スケジュール component_sweep の resync sweep を呼び出す AI 所有のスケジュール cron / rate はデプロイごと
WEBHOOK_BASE_URL バックエンド ai-status Webhook エンドポイント(プライベート VPC) https://api.internal/v1/webhooks/ai-status
WEBHOOK_API_KEY X-API-Key として送る共有サービスキー Secrets Manager 値
S3 結果バケット 結果アーティファクト + マニフェスト用のバックエンド所有 AI バケット バケット名はデプロイごと
S3 結果キープレフィックス クライアント向けアーティファクトプレフィックス {org}/{proj}/wf2des/
Figma サービスアカウント PAT wf2design 自身の シークレットストア — component_sweep、rule_process のボードレンダリング、snapshot / memo フォールバックが使用 シークレット ARN はデプロイごと(プラットフォームの figma_token では決してない)
DEFAULT_ORGANIZATION_ID シングルテナントのデフォルト。全ドキュメントの organization_id 1
FAST_MODEL parse role/intent openai:gpt-4o-mini
STRONG_MODEL section matching と rule consolidation。matching model は実行ごとに inputs.llm に pin openai:gpt-5.4
VISION_MODEL rule-board comprehension/extraction openai:gpt-5.4-mini
SCREEN_REVIEW_MODEL / SCREEN_REVIEW_REASONING_EFFORT whole-screen planning と actual-render review。run ごとに pin openai:gpt-5.4 / high。非 GPT は none
CANDIDATE_KIND_GATE / SCREEN_PLANNING_ENABLED production selection/review switch true / true
PROMPT_VERSION プラットフォームワーカーレシピに従う pin されたプロンプトバージョン pin

すべての環境変数は AI インフラストラクチャ — 環境変数 に記載されています。


公式のフィールドレベル契約: I/O 定義。