コンテンツにスキップ

AI Des2Code - I/O 定義

このページは apps/des2code/ の公式 I/O contract である。field、shape、status、failure mode を変更する場合は、実装 merge 前にこのページと テストケース設計 を更新する。


概要

flowchart LR
  api[guinness-backend] -->|INSERT/UPDATE des2code status pending| RDB[(PostgreSQL)]
  api -->|SendMessage| Q[(SQS des2code)]
  Q --> L[AI Des2Code worker]
  L -->|find_one _id=design_id| D[(DocumentDB design)]
  L -->|hybrid retrieval + rerank| C[(DocumentDB code)]
  L -->|PutObject result/failed artifact| S3[(S3 backend AI bucket)]
  L -->|POST /v1/webhooks/ai-status| api
  api -->|persist latest des2code result + artifact ref| RDB
  L -->|structured logs| Logs[(CloudWatch / logs)]
項目 値
トリガー des2code queue 上の SQS record
読み取り DocumentDB design、DocumentDB code
書き込み S3 result artifact + guinness-backend への Webhook POST
RDB 書き込み worker はなし。backend が Webhook 受信後に PostgreSQL へ書く
Webhook POST /v1/webhooks/ai-status への success/failure 通知が必須
LLM 呼び出し 任意の top-candidate rerank のみ。デフォルト無効
空の matchedCodes 空の matchedCodes array を持つ success
結果保持 timestamp 付き S3 artifact は 30 日 lifecycle。backend PostgreSQL は latest status/result と artifact reference を保持

入力

SQS メッセージ

Lambda は標準 AWS SQS event を受け取る。Records[*].body には次の field を持つ JSON string が入る。

{
  "Records": [
    {
      "messageId": "0192a3b4-c5d6-7e8f-9a0b-1c2d3e4f5a6b",
      "body": "{\"design_id\":\"42_hDDA9BNori9OTXSClduXqR_40002029:37033\",\"project_id\":42,\"organization_id\":1}"
    }
  ]
}
フィールド 型 必須 検証 備考
design_id string Yes min_length=1 既存の design._id と一致する必要がある
project_id integer Yes gt=0 vector search と backend status の scope
organization_id integer Yes gt=0 design validation、vector search、backend status の tenant scope
Body unwrap は他 worker と同じ utility に従う。raw payload、SQS-in-SQS、API Gateway proxy shape を、flat object になるまで受け付ける。

DocumentDB design 読み取り

項目 値
コレクション DESIGN_TABLE_NAME、default design
操作 find_one({"_id": design_id})
document 未存在 failure path。ID が分かる場合は failed webhook を送り、再送出
scope 不一致 design.project_id または design.organization_id が SQS message と不一致なら failure path

読み取る field:

フィールド 型 用途
_id string design identity
project_id integer consistency / search scope
organization_id integer consistency / tenant scope
visual.vector_embedding float[512] visual vector-search query
semantics.vector_embedding float[512] semantic vector-search query
structural.vector_embedding float[512] structural/context retrieval query
query_terms string[] 決定的 term-overlap reranking
figma_node object reranking 用 Figma node evidence
localized_regions object|null 任意の localized visual/layout evidence

DocumentDB code 取得

worker は CODE_TABLE_NAME(default code)に対して hybrid retrieval を実行する。

項目 値
検索回数 index がある場合、record ごとに visual + semantic + context の 3 回
検索スコープ organization_id + project_id
候補プール CANDIDATE_POOL_SIZE、default 50
最終上限 MAX_MATCHES、default 10
numCandidates max(80, CANDIDATE_POOL_SIZE)
類似度 Cosine
検索結果が空 empty matchedCodes の success

matched code document から project する field:

フィールド 型 用途
_id string match identity。codeId として返却
name string | null name として返却
source_code string | null sourceCode として返却
css_code string | null cssCode として返却
semantics.metadata.words string[] semanticValue として返却
visual.metadata.image_url string | null 将来の UI/API 用に保持可能
code_context object|null 決定的 reranking evidence
context.vector_embedding float[512]|null context retrieval vector
$meta score float visual、semantic、context similarity の元 score

実行時設定

環境変数 型 デフォルト 検証 用途
MAX_MATCHES integer 10 gt=0 最終出力 cap
CANDIDATE_POOL_SIZE integer 50 gte=MAX_MATCHES reranking 前の retrieval pool
VISUAL_SIMILARITY_WEIGHT float 0.15 ge=0 visual evidence の retrieval score weight
SEMANTIC_SIMILARITY_WEIGHT float 0.35 ge=0 semantic evidence の retrieval score weight
STRUCTURAL_SIMILARITY_WEIGHT float 0.20 ge=0 structural/context evidence の retrieval score weight
RERANK_SIGNAL_WEIGHT float 0.30 ge=0 決定的 rerank evidence weight
DES2CODE_LLM_RERANK_ENABLED boolean false boolean 任意の top-candidate LLM rerank を有効化
DES2CODE_LLM_RERANK_TOP_N integer 10 gt=0 LLM 有効時に送る候補数
RESULT_BUCKET string dev-guinness-backend min_length=1 result artifact の S3 bucket
DES2CODE_RESULT_TTL_DAYS integer 30 gt=0 expiresAt metadata と lifecycle expectation
WEBHOOK_BASE_URL string required URL backend webhook URL。通常 /v1/webhooks/ai-status で終わる
WEBHOOK_API_KEY string required non-empty service-to-service auth として X-API-Key で送る

少なくとも 1 つの retrieval または rerank weight は 0 より大きい必要がある。

最終 score:

similarity =
  retrieval_score
  + deterministic_rerank_score
  + optional_llm_rerank_adjustment

最終 similarity は純粋な vector similarity ではなく rank score である。欠けている signal は boost せず、side-specific field は null のままにする。


処理コントラクト

  1. SQS body を unwrap / validate する。
  2. design_id で design document を取得する。
  3. design document の scope が SQS organization_id / project_id と一致することを検証する。
  4. vector と index が存在する場合、visual、semantic、structural/context retrieval を実行する。
  5. code._id で candidate pool に merge する。
  6. design.query_terms、Figma node evidence、semantic words、code_context、import relation、family diversity、component-level compatibility、localized visual/layout evidence から決定的 rerank signal を計算する。
  7. retrieval と決定的 signal から final rank score を計算する。
  8. DES2CODE_LLM_RERANK_ENABLED=true の場合、上位 DES2CODE_LLM_RERANK_TOP_N 候補と圧縮 evidence のみ LLM に渡す。strict structured output を必須にする。
  9. final rank score で sort し、score/evidence field を付与して MAX_MATCHES で cap する。
  10. success payload を build する。
  11. timestamp 付き S3 result artifact を 1 件書き込む。
  12. result と artifact metadata を含む success webhook を backend へ POST する。
  13. des2code.completed を log する。

ソースコード生成はしない。生成用 image download はしない。DocumentDB des2code document は書かない。


出力

内部成功 payload

process_record() はテストとローカルスクリプト向けにこの shape を返す。Lambda handler は通常の SQS partial-batch-failure response を返す。

{
  "type": "des2code",
  "recordId": "42_hDDA9BNori9OTXSClduXqR_40002029:37033",
  "projectId": 42,
  "organizationId": 1,
  "status": "success",
  "result": {
    "matchedCodeCount": 2,
    "matchedCodes": [
      {
        "codeId": "0192a3b4-c5d6-4e8f-9a0b-1c2d3e4f5a6b",
        "name": "Button Primary",
        "semanticValue": ["button", "primary", "cta"],
        "similarity": 0.92,
        "visualSimilarity": 0.95,
        "semanticSimilarity": 0.89,
        "structuralSimilarity": 0.77,
        "scoreBreakdown": {
          "retrieval": 0.61,
          "termOverlap": 0.12,
          "rarityBoost": 0.05,
          "familyDiversity": 0.04,
          "relationBoost": 0.03,
          "visualLayout": 0.07
        },
        "matchedTerms": ["button_primary", "submit", "login"],
        "matchedDesignNodes": ["40002029:37101"],
        "matchedCodeContext": {
          "family": "button",
          "variant": "primary",
          "exports": ["Button"],
          "referencedComponents": ["button"]
        },
        "llmEvidence": null,
        "sourceCode": "export function Button() { ... }",
        "cssCode": null
      },
      {
        "codeId": "1192a3b4-c5d6-4e8f-9a0b-1c2d3e4f5a6c",
        "name": "Input Field",
        "semanticValue": ["input", "form"],
        "similarity": 0.87,
        "visualSimilarity": null,
        "semanticSimilarity": 0.87,
        "structuralSimilarity": 0.62,
        "scoreBreakdown": {
          "retrieval": 0.54,
          "termOverlap": 0.14,
          "rarityBoost": 0.03,
          "familyDiversity": 0.03,
          "relationBoost": 0.02,
          "visualLayout": 0.04
        },
        "matchedTerms": ["input", "form"],
        "matchedDesignNodes": ["40002029:37080"],
        "matchedCodeContext": {
          "family": "input",
          "variant": null,
          "exports": ["TextInput"],
          "referencedComponents": ["input"]
        },
        "llmEvidence": null,
        "sourceCode": "export function TextInput() { ... }",
        "cssCode": ".input { ... }"
      }
    ]
  }
}
フィールド 型 備考
type string 常に "des2code"
recordId string SQS design_id の echo
projectId integer SQS project_id の echo
organizationId integer SQS organization_id の echo
status string "success"
result.matchedCodeCount integer final cap 後の件数
result.matchedCodes object[] ranked matches
result.matchedCodes[].codeId string code._id
result.matchedCodes[].name string | null code.name
result.matchedCodes[].semanticValue string[] code.semantics.metadata.words
result.matchedCodes[].similarity float final rank score。range は weight 設定に依存
result.matchedCodes[].visualSimilarity float | null raw visual score、0.0 から 1.0
result.matchedCodes[].semanticSimilarity float | null raw semantic score、0.0 から 1.0
result.matchedCodes[].structuralSimilarity float | null raw structural/context score、0.0 から 1.0
result.matchedCodes[].scoreBreakdown object retrieval と決定的 rerank score component
result.matchedCodes[].matchedTerms string[] code evidence と一致した design query term
result.matchedCodes[].matchedDesignNodes string[] match を裏付ける Figma node id または region id
result.matchedCodes[].matchedCodeContext object|null match を裏付ける code context evidence
result.matchedCodes[].llmEvidence object|null LLM rerank 有効時の任意 reason/confidence
result.matchedCodes[].sourceCode string | null code.source_code
result.matchedCodes[].cssCode string | null code.css_code

Score は rank score。percent ではなく、worker 側で丸めない。

S3 result artifact の保存

Des2Code は immutable result artifact を S3 に書き込む。backend は Webhook 経由で artifact metadata を受け取り、latest artifact reference を PostgreSQL に保存する。

項目 値
バケット RESULT_BUCKET、default dev-guinness-backend
キー {organization_id}/{project_id}/des2code/{url_encoded_design_id}-{YYYYMMDDTHHMMSSffffffZ}-result.json
failure キー {organization_id}/{project_id}/des2code/{url_encoded_design_id}-{YYYYMMDDTHHMMSSffffffZ}-failed.json
Content-Type application/json
object tag des2code_result=true
暗号化 bucket default SSE-S3
保持期間 des2code_result=true tag に scoped した 30 日 lifecycle

success artifact の shape:

{
  "type": "des2code",
  "recordId": "42_hDDA9BNori9OTXSClduXqR_40002029:37033",
  "projectId": 42,
  "organizationId": 1,
  "status": "success",
  "generatedAt": "2026-06-28T00:00:00Z",
  "expiresAt": "2026-07-28T00:00:00Z",
  "result": {
    "matchedCodeCount": 2,
    "matchedCodes": []
  }
}

Webhook - 成功

POST {WEBHOOK_BASE_URL}
Content-Type: application/json
X-API-Key: {WEBHOOK_API_KEY}
{
  "type": "des2code",
  "recordId": "42_hDDA9BNori9OTXSClduXqR_40002029:37033",
  "projectId": 42,
  "organizationId": 1,
  "status": "success",
  "artifact": {
    "bucket": "dev-guinness-backend",
    "key": "1/42/des2code/42_hDDA9BNori9OTXSClduXqR_40002029%3A37033-20260628T000000000000Z-result.json",
    "contentType": "application/json",
    "expiresAt": "2026-07-28T00:00:00Z"
  },
  "result": {
    "matchedCodeCount": 2,
    "matchedCodes": []
  }
}

backend は PostgreSQL に最新 status/result と artifact reference を保存し、backend REST API と MCP v2 から公開する。

Webhook - 失敗

design_id、project_id、organization_id が判明した後に処理が失敗した場合、worker は original exception を再送出する前に failed webhook を送る。

{
  "type": "des2code",
  "recordId": "42_hDDA9BNori9OTXSClduXqR_40002029:37033",
  "projectId": 42,
  "organizationId": 1,
  "status": "failed",
  "artifact": {
    "bucket": "dev-guinness-backend",
    "key": "1/42/des2code/42_hDDA9BNori9OTXSClduXqR_40002029%3A37033-20260628T000000000000Z-failed.json",
    "contentType": "application/json",
    "expiresAt": "2026-07-28T00:00:00Z"
  },
  "error": {
    "message": "Design not found"
  }
}

Webhook delivery failure は processing failure として扱い、SQS retry で status/result を後続配送できるように再送出する。


エラーハンドリング

シナリオ 挙動
SQS event envelope が不正 raise。ID 不明なら webhook なし
Body を unwrap / parse できない raise。ID 不明なら webhook なし
Pydantic validation 失敗 raise。ID を安全に復元できる場合のみ failed webhook
design document 未存在 failed webhook、log、再送出
design scope 不一致 failed webhook、log、再送出
vector search が match を返さない empty matchedCodes の success webhook、log、ack
S3 write error log して SQS retry のため再送出
Webhook POST failure log して再送出し SQS retry
DocumentDB read error 可能なら failed webhook、log、再送出
batch 内に複数 record 各 record を試行し、失敗は SQS batch item failures で返す

冪等性

SQS delivery は at least once。成功した各 attempt は timestamp 付き S3 artifact を新規に書く。backend webhook handler は (type, recordId) に対して idempotent であり、design の最新 result と artifact reference を保存する。同じ SQS message の再処理は、その design_id に対する backend の最新 Des2Code result を置き換える。


フィールドリファレンス

ソース Worker での用途 Webhook / 返却名
SQS design_id design lookup key recordId
SQS project_id search scope / design-scope validation / S3 prefix projectId
SQS organization_id tenant scope / design-scope validation / S3 prefix organizationId
design.visual.vector_embedding visual search query emit しない
design.semantics.vector_embedding semantic search query emit しない
design.structural.vector_embedding structural/context retrieval query emit しない
design.query_terms 決定的 rerank input 一致時は matchedTerms
design.figma_node, design.localized_regions node/layout evidence 一致時は matchedDesignNodes
code._id match key codeId
code.name match label name
code.semantics.metadata.words semantic descriptor semanticValue
code.context.vector_embedding context retrieval target emit しない
code.code_context rerank evidence matchedCodeContext
code.source_code code implementation sourceCode
code.css_code code styling cssCode
retrieval / rerank score ranking similarity, visualSimilarity, semanticSimilarity, structuralSimilarity, scoreBreakdown