digital base
プロダクトドキュメントお知らせ会社概要

お問い合わせ

ご質問やご相談など、お気軽にお問い合わせください。

デジタルベース株式会社

〒106-0047
東京都港区南麻布3-20-1 5階

サイトメニュー

  • トップページ
  • プロダクト
  • ドキュメント
  • 最新ニュース
  • 記事一覧
  • 会社情報

お問い合わせ

  • info@digital-base.co.jp

NVIDIA Inception Program / Intel Partner ISV /
NTTPC Innovation LAB

© デジタルベース株式会社. All rights reserved.
記事一覧に戻る
2026.04.30技術情報

データ連携基盤におけるPythonの型設計|pydanticとdictの使い分けと渡し方

社内データをAIに連携する基盤の保守性を支える、Pythonの型設計を解説します。入出力境界でのpydanticによる検証と内部処理でのdictの使い分け、認証情報の管理、日付・タイムゾーンの正規化を整理します。

デジタルベース株式会社

データ連携基盤におけるPythonの型設計|pydanticとdictの使い分けと渡し方

概要

複数のデータソース(DB、API、ファイル、SaaS)をLLMやRAG基盤に連携する際、Pythonでのデータ定義と受け渡しの設計は、保守性に関わります。型が統一されていないと、変換・検証・エラーハンドリングの責務が分散し、上流の仕様変更への対応が難しくなります。

DigitalBaseが社内AI基盤・データ連携の実装で標準としている設計指針は、入出力境界(API、DB、外部SaaS)にはpydanticモデルを置き、内部処理はdictで流す構成です。境界で型を確定させ、内部は柔軟に保つことで、データソースの増減や仕様変更に強い基盤を構築できます。


なぜ型定義が必要か

データ連携の運用では、次のような変更やデータの差異への対応が必要です。

  • 上流のSaaSがフィールドをサイレントに変更する(status → state)
  • DBのカラムが追加されるが、Python側は古い前提のまま動作する
  • 文字列で来るはずの数値が、特定条件下でNullになる
  • 日付フォーマットが拠点ごとに異なる

型定義の役割は、境界で必ず形を確定させ、内部では信頼してよい状態を作ることにあります。境界でバリデーションを一度通せば、下流の処理は値の妥当性を都度チェックする必要がなくなり、処理ロジックに集中できます。


型定義の3つの選択肢

データの取り回しには、用途に応じて3つの選択肢を使い分けます。

選択肢バリデーションパフォーマンス主な用途
dictなし最速内部の中間データ、動的キー
dataclassなし(静的型のみ)速い内部のドメインモデル
pydantic.BaseModelあり(実行時)やや重いAPI/DB/外部I/Oの境界

実行時バリデーションは外部I/Oの境界で行い、内部の高頻度処理には持ち込まないことが基本方針です。

pydanticモデルの基本形

from datetime import datetime from pydantic import BaseModel, Field, field_validator class CustomerRecord(BaseModel): id: str name: str email: str company: str | None = None created_at: datetime revenue: float = Field(default=0.0, ge=0) @field_validator("email") @classmethod def normalize_email(cls, v: str) -> str: return v.strip().lower()
  • 必須/任意を型で表現:str | None = None で任意フィールドを明示する
  • Field でバリデーション:ge=0、max_length=100 などを宣言的に記述する
  • field_validator で正規化:trim・lowercase などの整形は型側で済ませる

正規化やバリデーションを型に寄せることで、レコードを受け取った下流のコードは整形済みであることを前提にできます。


dictでの取り回し

パイプライン内部でレコードを流す際は、dictが最も柔軟です。理由は次の3点です。

  1. オペレーターを汎用化できる:filter・sort・aggregate は中身のスキーマを知らずに動作する
  2. シリアライズコストが少ない:JSON/DBとの行き来がそのまま行える
  3. 動的フィールド追加が容易:上流で増えたカラムをそのまま下流に流せる
# 入口でpydantic検証 → 内部はdictで流す records: list[dict] = [ CustomerRecord.model_validate(raw).model_dump() for raw in raw_records ] # transform_filter filtered = [r for r in records if r["revenue"] >= 1_000_000] # transform_set for r in filtered: r["tier"] = "enterprise" if r["revenue"] >= 10_000_000 else "standard"

境界で一度 model_validate を通したあとは model_dump() でdict化し、以降のパイプラインは型に縛られず汎用的に処理します。


認証情報の扱い

外部APIの認証情報は、コードや設定JSONに直接記述しない設計が必要です。専用のVaultテーブル(またはシークレットマネージャー)を用意し、オペレーター側はキーのIDだけを参照する設計とします。

class HttpSourceConfig(BaseModel): url: str credential_id: str # vault のID参照のみ async def run_http_source(cfg: HttpSourceConfig) -> AsyncGenerator[dict, None]: cred = await vault.get(cfg.credential_id) # 復号して取得 headers = {"Authorization": f"Bearer {cred.token}"} ...

設定をそのままログやエラーメッセージに出力しても秘匿情報が漏れない構造になり、設定ファイルのバージョン管理やレビューも安全に行えます。


日付・タイムゾーンの正規化

拠点や外部システムごとに異なる日付表現は、境界で吸収します。原則は次の3点です。

  • 境界では必ずタイムゾーン付きdatetimeへ変換し、UTCに揃える
  • 内部はUTCで保持し、表示の直前にローカルタイムゾーンへ変換する
  • DBもタイムゾーン付き型を用いる:PostgreSQLなら TIMESTAMPTZ
from datetime import datetime, UTC def normalize_datetime(s: str) -> datetime: s = s.replace("/", "-") dt = datetime.fromisoformat(s) if dt.tzinfo is None: dt = dt.replace(tzinfo=UTC) return dt.astimezone(UTC)

タイムゾーンの扱いを境界に閉じ込めることで、内部ロジックは常にUTC前提で記述でき、拠点をまたぐ集計や比較のバグを防げます。


まとめ

社内AI基盤のデータ連携では、型検証と環境差への対応を入出力境界に集約します。設計の要点は次の2点です。

  1. 境界で型確定、内部はdict:pydanticは入口・出口に置き、内部はdictで柔軟に流す
  2. 認証・日付は型側で吸収:オペレーター本体に環境差や秘匿情報を持ち込まない

各オペレーターの責務を限定し、上流の変化を境界で吸収する構造にしておくことで、SaaSのAPI仕様変更や新フィールド追加に強い基盤を構築できます。

下記のお悩みなら、ご相談ください

PoC から商用化に進むには、次の 3 点が必要になります。統合型 AI エージェント基盤「DigitalBase」は、 これらを 1 つの製品で提供しています。お気軽にご相談ください。