kk366-code

SKILL.md - Implementation Patterns

- **Memory Efficiency**: 大容量ファイルを扱う際、メモリ(RAM)を消費しすぎないようにストリームベースのコピーを徹底する。

kk366-code 0 Updated 3w ago

Resources

20
GitHub

Install

npx skillscat add kk366-code/vertex-ai-starter

Install via the SkillsCat registry.

SKILL.md

SKILL.md - Implementation Patterns

🐍 Modern Python Best Practices (2026)

AIがコードを生成・修正する際は、以下の2026年3月時点の最新プラクティスを遵守してください。

  • Python Version: Python 3.14+ の機能を優先的に使用します。
  • Type Annotations: OptionalUnion は使用せず、常に | (Pipe syntax) を使用してください(例: str | None, int | float)。
  • Native Types: list[], dict[], tuple[] などの組み込みジェネリクスを直接使用します。
  • Strict Linting: 常に ruff の最新ルール(特に UP カテゴリ)に従い、レガシーな構文(例: .format())を排除し、f-strings を使用してください。
  • Dependency Management: パッケージ管理には uv を使用し、実行時は uv run を前提とします。

🤖 Vertex AI (google-genai) Implementation

Geminiを使用して構造化データを取得する場合は、以下の定石に従ってください。

  1. Define Schema: Pydanticの BaseModel を定義し、各フィールドに詳細な Field(description=...) を記述します。
  2. Config Settings: response_mime_type="application/json"response_schema を設定します。
  3. Validation: レスポンスは model_validate_json() を使用してパースし、型安全なオブジェクトとして返します。
# Implementation Pattern
async def analyze(prompt: str, schema: type[T]) -> T:
    config = genai.types.GenerateContentConfig(
        response_mime_type="application/json",
        response_schema=schema,
        temperature=0.1
    )
    response = await client.aio.models.generate_content(
        model="gemini-2.5-flash", 
        contents=[prompt], 
        config=config
    )
    return schema.model_validate_json(response.text)

☁️ Google Cloud Storage (GCS) Operations

  • Upload First: AI解析の前に CloudStorageManager を使用してファイルをアップロードします。
  • URI Passing: Geminiにはローカルパスではなく、必ず gs:// 形式のURIを渡してください。
  • Mime-types: デフォルトは image/png ですが、image/jpeg も適切にサポートしてください。

🧪 Testing Strategy (Async Mocking)

Gemini APIのテストには、pytest-mock を使用した以下のパターンを採用します。

  • Mock Target: core.client.aio.modelsgenerate_content をモックします。
  • Async Setup: new_callable=mocker.AsyncMock を指定して、非同期呼び出しを正しくシミュレートします。
mock_method = mocker.patch.object(
    core.client.aio.models,
    "generate_content",
    new_callable=mocker.AsyncMock,
    return_value=mock_response
)

⚠️ Known Pitfalls & Safety

  • Project ID Validation: 実行前に必ず .env から GOOGLE_CLOUD_PROJECT が正しく読み込まれているかチェックしてください。
  • Error Handling: 解析不能な場合(画像が壊れている等)は、例外を投げるのではなく、スキーマの success=False フィールドを使用して正常に応答を返してください。
  • Text Encoding: 特にWindows環境での実行を考慮し、ファイル操作やログ出力時は常に UTF-8 を明示してください。

Google SDK の None チェックパターン

google-genai レスポンスフィールド: embed_content() など多くのメソッドがフィールドを | None 付きで型定義している。インデックスアクセスや .values などの取得前に必ずガードを入れる。

# NG: mypy エラーになる
return list(response.embeddings[0].values)

# OK: None チェック後にアクセス
if not response.embeddings:
    raise ValueError("埋め込み生成に失敗しました。")
values = response.embeddings[0].values
if values is None:
    raise ValueError("埋め込み値がNoneでした。")
return list(values)

Firestore to_dict() の直接インデックスアクセス: snapshot.to_dict() の戻り型は dict[str, Any] | Nonemodel_validate() に渡すだけなら mypy はパスするが、data["key"] のように直接アクセスする場合は None チェックが必要。

# snapshot.exists チェック後でも to_dict() は型上 None を返しうる
data = snapshot.to_dict()
if data is None:
    return None
data["embedding"] = list(data["embedding"])  # None チェック後なら安全

Firestore Vector Search の型スタブ問題: AsyncCollectionReference.find_nearest() は型スタブ上で sync VectorQuery を返すと誤解釈されるため、stream()async for で使う際に mypy エラーが出る。# type: ignore[attr-defined] で抑制する(ランタイムは正常動作)。

async for doc in vector_query.stream():  # type: ignore[attr-defined]
    ...

🐍 Python / FastAPI

Safe Temporary File Handling

  • Automatic Cleanup with tempfile:
    tempfile モジュールを活用することで、ディスク容量の圧迫や予期せぬファイルの残留を防ぎます。

    # 推奨されるパターン
    with tempfile.TemporaryDirectory(dir=Path("upload")) as tmp_dir:
        local_path = Path(tmp_dir) / file.filename
        # 処理を実行...
    # スコープを抜けると tmp_dir とその中身は自動で物理削除される
    

FastAPI Modern Patterns (2026)

  • Annotated Type Hints:
    FastAPI の各コンポーネント定義には Annotated を標準採用します。これにより、メタデータと型定義を分離し、可読性を高めます。
  • prompt: Annotated[str, Form()]
  • file: Annotated[UploadFile, File()]
  • api_key: Annotated[str, Security(verify_api_key)]

Annotated over Default Arguments

  • Ruff B008 Avoidance: デフォルト引数での関数呼び出しを避け、Annotated を活用することで # noqa: B008 を排除し、静的解析をクリーンに保つ。
  • Explicit Dependency: 認証(Security)や依存(Depends)の結果を変数として受け取ることで、将来的な拡張性(ユーザー情報の利用など)を確保する。

Efficient File Handling with shutil

  • shutil.copyfileobj: アップロードされた UploadFile ストリームをローカルファイルに効率的に書き出すために使用。

  • Memory Efficiency: 大容量ファイルを扱う際、メモリ(RAM)を消費しすぎないようにストリームベースのコピーを徹底する。