Agents SDKを使った判例検索 (3)

Agents SDKを使った判例検索コード( database_query.py )解析の2回目。今回はこのコードの「 検索ツール 」部分について、1行ずつその働きを見ていく。

class CaseSearch(BaseModel):

PythonのPydanticライブラリを使用して、データの構造(スキーマ)を定義している。具体的には、CaseSearch(判例検索)という名前のデータモデルを作成しようとしている。

1. 各要素の意味

  • class CaseSearch:CaseSearch という名前の新しいクラス(データのひな形)を作る。
  • (BaseModel):Pydanticが提供する BaseModel というクラスを継承している。これにより、このクラスは単なるデータの集まりではなく、型チェックやバリデーション(妥当性確認)の機能を備えるようになる。

2. なぜPydanticを使うのか?

Pydanticの BaseModel を使うと、以下のようなことが自動でできるようになるから。

  1. データ型の強制:指定した型と違うデータが入ってきたときにエラーを出してくれる。
  2. 構造の定義:「判例検索にはキーワード(string)と年代(int)が必要」といったルールを明確に定義できる。
  3. 変換が容易:JSONデータをPythonのオブジェクトに変換したり、その逆を行ったりするのが簡単になる。
    keywords: str = Field(..., description="検索語(スペース区切り)")

Pydanticのモデル内で以下のようなフィールド(属性)の詳細なルールを定義している。

パーツ意味
keywords: str変数名が keywords で、型は文字列(string)であることを示す。
Field(...)Pydanticの Field 関数。バリデーション(検証)ルールやメタデータを設定するために使う。
... (Ellipsis)フィールドが必須項目であることを意味する。データを作る際にこれを省略するとエラーになる。
description="検索語(スペース区切り)"項目の説明文。AIは description を読んで「ここにはスペース区切りの検索語を入れればいいんだな」と理解する。これにより、AIが正しい形式でデータを生成してくれるようになる。
    court: Optional[str] = Field(None, description="裁判所名(部分一致)")

courtという変数について、 keywords とは対照的に、あってもなくても良い(任意項目)というルールを定義している。特に裁判所の名前のようにユーザーが指定する場合もあれば、指定しない場合もあるデータを扱うのに適した書き方である。

パーツ意味
Optional[str]str(文字列)または None(空)のどちらでも良いことを示している
Field(None, ...)最初の引数が None になっているため、デフォルト値は None(空)となる。これにより、データ作成時にこの項目を省略してもエラーにならない。
description="裁判所名(部分一致)"AIに対して、この項目が裁判所名であり、部分一致での検索が可能であることを伝えている。
    limit: int = Field(5, ge=1, le=20, description="最大件数")

検索結果の件数を制御するための変数(limit)に関する設定。単なる数値指定ではなく、入力される値に制限(バリデーション)をかけているのが特徴。これにより、システムが想定外の負荷を受けたり、エラーになったりするのを防いでいる。

パーツ意味
limit: int変数名が limit で、整数過多(integer) であることを示している。
5 (第1引数)デフォルト値が5であることを示す。ユーザーが件数を指定しなかった場合、自動的に 5 が設定される。
ge=1Greater than or equal to の略。limitが1以上である必要があることを示している。
le=20Less than or equal to の略。limitが20以下である必要があることを示している。
description="最大件数"AIに対し、limit=取得するデータの最大件数であることを伝えている。
@function_tool
def search_cases(q: CaseSearch) -> str:

上で作成した Pydantic モデル(CaseSearch)を、AIエージェントが実際に道具(ツール)として使えるように登録している。各要素の意味は以下のとおり。

@function_tool(デコレータ)

この関数が単なる関数ではなく、AIエージェントが呼び出せるツールであることを宣言している。デコレータを付けることで、SDKは関数の名前、引数の型、説明文を自動的に解析し、AIに「こんなツールが使えますよ」と伝えてくれる。

q: CaseSearch(引数の型指定)

引数 q に対して、先ほど定義した CaseSearch クラスを型として指定している。これにより、AIは CaseSearch で定義した keywords, court, limit という項目を正しい形式(JSON)で生成しなければならないというルールを理解する。Pydantic で書いた descriptionge=1 といった制約も、この時に AI への指示書として一緒に送られる。

-> str(戻り値の型)

この関数を実行した結果、最終的に文字列(string)が返されることを示している。通常は、データベースから検索した判例の一覧などが文字列として AI に戻される。

◼︎処理の流れ(イメージ図)

AIが「東京地裁の不法行為の判例を探して」とユーザーに言われた時の動きは以下のようになる。

  1. AIの判断:「判例を探す必要があるな。search_cases というツールを使おう」
  2. データの作成CaseSearch モデルに従い、{"keywords": "不法行為", "court": "東京地裁", "limit": 5} というデータを作成。
  3. バリデーション:作成されたデータが Pydantic モデル(ge=1 など)に違反していないかチェック。
  4. 実行:search_cases(q) が呼び出され、実際の検索処理(DBへのアクセス)が行われる。
  5. 回答:検索結果の文字列が AI に戻り、AIがそれを元にユーザーへ回答を作成。
    """
    cases テーブルを全文 LIKE 検索し、ヒットした裁判例の一覧を返す。
    """

上のトリプルクォートで囲まれた部分は、Pythonのドキュメント文字列(docstring)と呼ばれる。通常のプログラムで docstring は「開発者向けのメモ」に過ぎないが、@function_tool と組み合わされた場合、AIエージェントがそのツールを「いつ、何のために使うべきか」を判断するための説明書として機能する。

1. 文言の具体的な意味

  • cases テーブル:データベースの中に「cases(事件/裁判例)」という名前の表があり、そこにデータが格納されていることを示唆している。
  • 全文 LIKE 検索:SQLという言語で使われる LIKE 演算子(パターンマッチング)を用いて、キーワードが含まれているかどうかを検索する仕組みのこと。
  • ヒットした裁判例の一覧を返す:検索の結果、条件に合うデータをリスト形式(文字列)で出力することを明示している。

2. AIエージェントにおけるdocstringの役割

@function_tool を使っている場合、この説明文はプログラムの実行には直接関係しないものの、AIの挙動を決定づける。たとえば、ユーザーが「過去の判決を教えて」と言ったとき、AIはこのドキュメントを見て「search_cases 関数に『裁判例の一覧を返す』と書いてあるから、これを使おう!」と判断する。プロンプトの一部として送信されるこの説明文は、内部的にAIへの命令文(システムプロンプト)に組み込まれるため、ここを詳しく書けば書くほど、AIはツールの使い時を間違えなくなる。