PythonのPydanticとC#を比較してみた + C++ DCOMの思い出 #pydantic - Qiita
OpenAI Structured OutputsのPydantic連携を実装してみました | 株式会社divx(ディブエックス)
勉強になりました。
これから、Pydanticを使用してC#クラスを変換して行きたいと思います。
同じShiftAggregateというC#内部クラスをコパイと、Google AIモードの両方で生成させてみました。
コパイ生成モデル
from pydantic import BaseModel, Field
from typing import List
class ShiftAggregate(BaseModel):
use: bool = Field(
description="A flag to indicate whether it is valid or invalid. 有効(true)か無効かを示すフラグ。"
)
name: str = Field(
default="ShiftAggregateDef",
description="Object Name オブジェクト名"
)
def_name: str = Field(
description="Definition name 定義名。シフトオブジェクトのORまたはNOTの集合体。必須。"
)
color: str = Field(
default="Grey",
description="Background color ラベル背景色"
)
operator: str = Field(
default="OR",
description="Operator 演算子。OR または NOT のみ。必須。"
)
members: List[str] = Field(
default_factory=list,
description="List of shift object names shift_objectの名前集合。必須。"
)
label: str = Field(
description="Label name as displayed name ラベル名(GUI表示名)。必須。"
)
下は、GOOGLE AIモード生成です。
from typing import List, Literal, Optional from pydantic import BaseModel, Field from mcp.server.fastmcp import FastMCP # 1. C# のクラスを Pydantic モデルとして定義 class ShiftAggregate(BaseModel): use: bool = Field( default=False, description="有効(true)か無効か。無効ならソルバは参照しない" ) name: str = Field( default="ShiftAggregateDef", description="オブジェクト名" ) def_name: str = Field( ..., description="定義名。シフトオブジェクトのORまたはNOTの集合体" ) color: str = Field( default="Grey", description="ラベル背景色" ) # Operator は OR または NOT のみ operator: Literal["OR", "NOT"] = Field( default="OR", description="演算子。OR または NOT のみ" ) members: List[str] = Field( default_factory=list, description="シフトオブジェクトの名前集合" ) label: str = Field( ..., description="表示用ラベル名" ) # 2. MCP サーバーの作成 mcp = FastMCP("ShiftManager") # 3. ツールとして登録 @mcp.tool() async def register_shift_aggregate(data: ShiftAggregate) -> str: """ シフトの集合体定義(ShiftAggregate)を登録します。 """ # ここに WinForms API (call_winforms_api) への送信処理などを記述 # 例: payload = data.model_dump() return f"定義 '{data.label}' (Operator: {data.operator}) を受け付けました。" if __name__ == "__main__": mcp.run()
さらに、C#クラスを少し修正して再度AIモードにお願いしました。修正した部分が分かって生成していることが分かります。こうした基本クラスならば、手で書くよりもAIにお願いした方が圧倒的に速いです。C#クラスのコメント部をdescriptionに解釈して書いてくれるので、その点でも楽です。model_dump()もBaseModelを継承して自動生成してくれます。AIモードは、MCPをどのように実装したらよいかを、解説しながら実装例を示してくれます。私のようなMCP初心者には、有難いです。基本的クラスは、こうした手法により、Python側のコードは、ほぼコピペで完結できます。C#側は、かなり手を加える必要があります。
コパイでは、C#コメントは、そのままPythonコメントになりましたが、Google AIモードでは、徒手選択追加されています。必ずしもC#コメントと同じになる訳ではありません。概して分かり易い方向に作用しますが、余計なお世話だ、という場合もあります。
驚くべきは、定義していないクラスまで生成したことです。それが、正確にPythonに変換生成されていました。以前GUIのC#コードを公開していたことがありましたが、それを参照したとしか考えられない、と思っています。驚きました。
from typing import List, Literal
from pydantic import BaseModel, Field
from mcp.server.fastmcp import FastMCP
# 1. C#のクラス構造をPydanticモデルで定義
class ShiftAggregate(BaseModel):
use: bool = Field(
default=False,
description="有効(true)か無効かを示すフラグ。無効ならソルバは参照しない"
)
# const扱いの名前。LLMが変更しないようdefault固定にする
name: str = Field(
default="ShiftAggregateDef",
frozen=True,
description="オブジェクト名(固定値: ShiftAggregateDef)"
)
def_name: str = Field(
default="",
description="定義名。シフトオブジェクトのORまたはNOTの集合体を表す一意識別子"
)
color: str = Field(
default="Grey",
description="ラベル背景色(例: Blue, #FF0000)"
)
# Operatorをリテラルで制限
Operator: Literal["OR", "NOT"] = Field(
default="OR",
description="演算子。OR(いずれか)またはNOT(以外)のみ選択可能"
)
members: List[str] = Field(
default_factory=list,
description="シフトオブジェクト名のリスト(例: ['日勤', '夜勤'])"
)
label: str = Field(
default="",
description="GUI(予定入力・解上)での表示名"
)
# 2. MCPサーバの初期化
mcp = FastMCP("ShiftProjectManager")
# 3. ツールとしての登録
@mcp.tool()
async def add_shift_aggregate(aggregate_data: ShiftAggregate) -> str:
"""
WinFormsアプリに新しいシフト集計定義(ShiftAggregate)を追加または更新します。
"""
# 実際にはここで call_winforms_api("update_settings", payload, ...) 等を呼び出す
payload = aggregate_data.model_dump()
# デバッグ出力
print(f"Sending to WinForms: {payload}")
return f"シフト定義 '{aggregate_data.label}' を {aggregate_data.Operator} 条件で登録しました。"
if __name__ == "__main__":
# サーバの起動
mcp.run()
0 件のコメント:
コメントを投稿