コンテンツにスキップ

guinness-ai-v2 テックスタック

guinness-ai-v2 モノレポ全体で使用する技術スタックの概要です。


サマリー

カテゴリ 技術
言語 Python 3.12
実行環境 AWS Lambda
AI フレームワーク PydanticAI
LLM OpenAI(provider:model 形式で設定)
埋め込み OpenAI Embeddings API(SDK 直呼び出し)
スキーマ / バリデーション Pydantic v2
環境変数管理 pydantic-settings
データベース Amazon DocumentDB(MongoDB 互換)
ストレージ Amazon S3
キュー AWS SQS
HTTP クライアント httpx
AWS SDK boto3
ロギング loguru
テスト pytest
パッケージ管理 uv workspace

ランタイム

Python 3.12 on AWS Lambda

各ワーカー(design-import・code-import・des2code)は AWS Lambda 上の Python 3.12 で動作します。SQS トリガーで起動し、処理完了後は Webhook でバックエンドに通知します。

計画中の Page Import validator と Code2WF converter も同じ SQS-triggered Lambda pattern に従います。ページキャプチャ自体は Lambda の外にある信頼された local/CI CLI で Playwright を使用します。

Lambda ウォームスタート最適化: DocumentDB クライアント・S3 クライアント・PydanticAI エージェントはモジュールトップレベルで初期化し、コールドスタート時にのみ生成します。


AI フレームワーク

PydanticAI

エージェントオーケストレーションに使用します。V1 で使用していた LangChain / LangGraph を置き換えます。

特徴 内容
プロバイダー非依存 モデルは provider:model 形式で指定(例: openai:gpt-5.4-nano)
構造化出力 Pydantic モデルを output_type に指定して型安全な出力を取得
同期実行 Lambda 上では run_sync を使用
ストリーミング des2code のコード生成はストリーミングで実行
テスト pydantic_ai.models.test.TestModel でエージェントをモック
from pydantic_ai import Agent
from pydantic import BaseModel

class DesignDescription(BaseModel):
    layout: str
    semantic_words: list[str]

agent = Agent(
    "openai:gpt-5.4-nano",    # provider:model 形式
    output_type=DesignDescription,
    system_prompt="...",
)
result = agent.run_sync(user_prompt)
description: DesignDescription = result.output

V1 からの変更: langchain-openai・langgraph は削除。


埋め込み生成

OpenAI Embeddings API(SDK 直呼び出し)

PydanticAI は埋め込みを扱わないため、openai SDK を直接呼び出します。

項目 値
モデル EMBEDDING_MODEL 環境変数で設定(例: text-embedding-3-small)
次元数 512(DocumentDB HNSW インデックスと一致)
呼び出し方式 複数の埋め込みを 1 回のバッチで生成(ドリフト防止)
response = openai_client.embeddings.create(
    model=config.embedding_model,
    input=[visual_text, semantic_text],  # 1 回のバッチ
    dimensions=512,
)
visual_vector = response.data[0].embedding
semantic_vector = response.data[1].embedding

スキーマ / バリデーション

Pydantic v2

SQS 入力・DocumentDB ドキュメント・Webhook ペイロードのすべてを Pydantic モデルで定義します。

from pydantic import BaseModel, Field, model_validator

class CodeImportMessage(BaseModel):
    code_id: str
    organization_id: int
    project_id: int
    source_code: str = Field(..., min_length=1)
    css_code: str | None = None
    img_url: str | None = None

    @model_validator(mode="after")
    def validate_uuid(self) -> "CodeImportMessage":
        uuid.UUID(self.code_id)
        return self

pydantic-settings

環境変数を BaseSettings でバリデーションします。必須変数はデフォルト値なしで定義し、起動時にエラーを即座に検出します。

from pydantic_settings import BaseSettings

class Config(BaseSettings):
    desc_model: str
    embedding_model: str
    openai_api_key: str
    documentdb_connection_string: str
    webhook_base_url: str

データベース

Amazon DocumentDB(MongoDB 互換)

AI ワーカー専用のベクトルデータベースです。4D 管理の PostgreSQL データベースとは完全に分離しており、AI ワーカーは RDS へ直接アクセスしません。

計画中の Page Import と Code2WF worker は S3 artifact を使用し、DocumentDB にはアクセスしません。

コレクション 書き込みワーカー 読み取りワーカー
design design-import des2code
code code-import des2code

HNSW ベクトルインデックス

各コレクションは生成する signal に応じて visual、semantics、structural、context のベクトルインデックスを持ちます。

インデックス パス 次元 類似度 パラメータ
visualVectorIndex visual.vector_embedding 512 cosine m=16, efConstruction=64
semanticVectorIndex semantics.vector_embedding 512 cosine m=16, efConstruction=64
structuralVectorIndex structural.vector_embedding 512 cosine m=16, efConstruction=64
contextVectorIndex context.vector_embedding 512 cosine m=16, efConstruction=64

structuralVectorIndex は design、contextVectorIndex は code に適用します。

design コレクションはさらに structuralVectorIndex(Figma 構造埋め込み)を持ちます。

ドライバー

pymongo を使用します。接続文字列は DOCUMENTDB_CONNECTION_STRING で設定し、TLS CA は /var/task/global-bundle.pem(Lambda)を使用します。


AWS サービス

サービス 用途
SQS ジョブキュー(design-import・code-import・des2code の各キュー)
S3 デザイン画像・コンポーネントスクリーンショットの取得
Lambda ワーカー実行環境(SQS トリガー)
DocumentDB ベクトルデータベース

Page Import と Code2WF は専用の SQS queue と DLQ を使用します。Page Import は captured/normalized page artifact を S3 に保存し、Code2WF は既存 DesignSpecModel を含むWF2Des-shaped result artifactをS3に保存します。

SQS の部分的失敗は batchItemFailures で報告し、失敗したレコードのみ SQS にリトライさせます。

return {"batchItemFailures": [{"itemIdentifier": record["messageId"]}]}

HTTP クライアント

httpx

Webhook POST(POST /v1/webhooks/ai-status)に使用します。

import httpx

httpx.post(
    config.webhook_base_url,
    json=payload,
    headers={"X-API-Key": config.webhook_api_key},
    timeout=10,
)

ロギング

loguru

構造化ログに使用します。print() は禁止です。

from loguru import logger

logger.info("process_record started", code_id=message.code_id, project_id=message.project_id)
logger.error("webhook failed", code_id=message.code_id, status_code=resp.status_code)

テスト

pytest

テストランナーです。

PydanticAI TestModel

PydanticAI エージェントのモックに使用します。

from pydantic_ai.models.test import TestModel

agent = build_vision_agent.__wrapped__(TestModel())

パッケージ管理

uv workspace

モノレポ全体のパッケージ管理に使用します。各アプリは pyproject.toml で独立したプロジェクトとして定義され、共有パッケージは packages/ に配置します。


共有パッケージ

パッケージ 内容
packages/agentic PydanticAI エージェント定義(vision・code_semantics・code_visual・code_gen)
packages/models DocumentDB コレクション定義・HNSW インデックス作成
packages/helpers S3 ダウンロード・Webhook POST・埋め込み生成の共通ユーティリティ
packages/utils pydantic-settings 基底・DocumentDB 接続シングルトン

V1 からの主な変更

V1 V2
LangChain + LangGraph PydanticAI
単一埋め込み 複数 signal 埋め込み(visual + semantic + structural/context)
MySQL 直接書き込み Webhook のみ(RDS 非アクセス)
PyMySQL 削除
langchain-openai / langgraph 削除
loguru なし(print / loguru 混在) loguru に統一