Skip to content

Instantly share code, notes, and snippets.

@kadowaki
Created February 26, 2026 00:37
Show Gist options
  • Select an option

  • Save kadowaki/9e7becc3244827d8e79c536aea434009 to your computer and use it in GitHub Desktop.

Select an option

Save kadowaki/9e7becc3244827d8e79c536aea434009 to your computer and use it in GitHub Desktop.
ツール定義のサンプルコード完全版 - example_5.py
from datetime import date
from pathlib import Path
from typing import Literal
from pydantic import BaseModel, Field
from pydantic_ai import Agent
# 解析対象のHTMLをファイルから読み込む
html_path = Path(__file__).with_name("pytopics.html")
with open(html_path, encoding="utf-8") as f:
SAMPLE_HTML = f.read()
ARTICLE_BODIES: dict[str, str] = {
"/article/2026/01/monthly-python-2601": "CrewAIは複数のAIエージェントを協調させるフレームワークです...",
"/article/2025/12/monthly-python-2512": "PyreflyはMeta社が開発したRust製のPython型チェッカーです...",
"/article/2025/11/monthly-python-2511": "t-stringはPython 3.14で導入されたテンプレート文字列リテラルです...",
"/article/2025/10/monthly-python-2510": "Pydanticはデータバリデーションと設定管理のためのライブラリです...",
"/article/2025/09/monthly-python-2509": "Python 3.14ではasyncioにタスク可視化機能が追加されました...",
"/article/2025/08/monthly-python-2508": "PrefectはPythonベースのワークフロー管理フレームワークです...",
}
class ArticleInfo(BaseModel):
"""記事のメタデータ(カテゴリ・タグ付き)"""
title: str = Field(min_length=1, description="記事のタイトル")
author: str = Field(min_length=1, description="著者名")
published_date: date = Field(description="公開日")
url: str = Field(description="記事のURL(相対パス)")
# カテゴリは以下の選択肢のいずれかとする
category: Literal[
"Web開発",
"型・ツール",
"AI・機械学習",
"パッケージ管理",
"Python新機能",
"その他",
] = Field(description="記事のカテゴリ")
# タグは1~5個のリストとする
tags: list[str] = Field(
min_length=1,
max_length=5,
description="技術タグのリスト",
)
class ArticleList(BaseModel):
"""記事一覧"""
articles: list[ArticleInfo]
# Agentのinstructionsで、ツールを使って記事本文を参照するように指示
agent = Agent(
"openai:gpt-5.2",
output_type=ArticleList,
instructions=(
"与えられたHTMLから記事の一覧情報を抽出してください。"
"各記事のカテゴリとタグを判定するために、"
"fetch_article_bodyツールで記事本文を参照してください。"
),
retries=3,
)
# fetch_article_bodyツールを定義
@agent.tool_plain
def fetch_article_body(url: str) -> str:
"""記事のURLを受け取り、記事本文の冒頭部分を返す。
Args:
url: 記事の相対パス(例: /article/2026/01/monthly-python-2601)
"""
body = ARTICLE_BODIES.get(url)
if body:
return body
return f"{url}: 本文が見つかりません"
res = agent.run_sync(SAMPLE_HTML)
for article in res.output.articles:
print(f"{article}\n")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment