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-statusWebhook を POST します - ストア: 1 つの PostgreSQL テーブル
wf2des(バックエンド所有)+ 6 つの DocumentDB コレクション + S3 アーティファクト - ステータス報告: generation のみ
ai-statusWebhook。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 された判断のみを行い、それ以外はすべて再現可能な変換です。どこにも類似度機構はありません: 埋め込みなし、ベクトル検索なし、インデックスに対する候補リランキングなし、学習コーパスなし。ワーカーはプロジェクト自身のコンポーネントレジストリとルールセットを読み込み、それらから直接組み立てます。
パイプライン、順に:
- 決定的な WFNode 抽出 — ワイヤーフレーム snapshot を WFNode ツリーに走査します(可視の FRAME / GROUP / INSTANCE / TEXT の各子孫 + 画像塗りの矩形。vector の葉は親に折りたたむ。隠しレイヤーはスキップ)。ツリー形状は決定的 です — LLM がそれを発明したり再形成したりすることは決してありません。
- LLM は role + intent のみを割り当てる(fast tier)— 各ノードは共有の要素タイプ語彙から
roleを、OPEN memo と variant ラベルから導出したintentを得ます。これは parse における唯一の LLM ステップであり、ツリー形状には決して触れません。 - 決定的な候補セット — プロジェクトの registry を dedup / hygiene 折りたたみした後、本番 default の role→kind gate が各 section に構造上不適切な component kind を除外します。vector scoring や similarity retrieval はなく、ストレートでテナントスコープのセットです。size は gate ではなく selection signal のままです。
- 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決定レジャー(自律品質ラチェット)を参照し、選択後に選ばれた解決を書き戻します — 人手による修正ループが存在しないため、品質はマシン側で収束します。 - 決定的な縫合 — セクションごとの判断が自己完結型の
DesignSpec(spec ツリー +spec_nodes_flat+style_bindingsマップ)に縫合されます。spec は同じ判断から再現可能です。 - 決定的な rules validator — 違反は安全な範囲で自動修正され、そうでなければフラグ付けされます。ルール未登録の場合、validator は no-op となり、全ノードに
rules_unvalidatedフラグが付きます。 - 計算された confidence — confidence は validator 違反、unmatched/composed カウント、slot の曖昧さ、component-fit(role の一致)から 計算 されます。モデルの自己申告は決して使われません。
- 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 定義。