AI Engineering Academy · レッスン

Agent用Toolの定義

@toolデコレーターを使ってカスタムToolを作成し、各Toolを呼び出すタイミングをLLMが判断するための明確な説明を記述して、Pydanticによる入力検証を追加します。

レッスン 2/413 ステップ

「Agent用Toolの定義」はCoddyKit上の無料AI Engineering Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAI Engineering Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AI Engineering Academyコースには全4レッスンが含まれています。

ツールでエージェントに強力な能力を与える

ツールを持たないエージェントは、既に知っていることについて推論することしかできず、ウェブを検索したり、データベースに問い合わせたり、メールを送信したりすることはできません。ツールは、エージェントが現実世界のアクションを実行し、最新情報を取得できるようにして、その能力を拡張するPython関数です。信頼性の高いエージェントを構築するうえで、ツールを明確に定義することは最も重要な手順の1つです。

LangChainの@toolデコレーター

LangChainの@toolデコレーターは、任意のPython関数をエージェントが呼び出せるツールに変換します。関数のdocstringは、LLMが呼び出しタイミングを判断する際に使用するツールの説明になります。明確で具体的な説明にすると、エージェントがツールを選択する精度が大幅に向上します。

from langchain_core.tools import tool

@tool
def get_weather(city: str) -> str:
    '''Get the current weather conditions for a given city.
    Use this tool when the user asks about weather in a specific location.
    Input should be just the city name, e.g. 'London' or 'New York'.
    '''
    # Real implementation would call a weather API
    return f'The weather in {city} is 18 degrees Celsius and partly cloudy.'

print(get_weather.name)         # 'get_weather'
print(get_weather.description)  # The docstring above

型アノテーションとスキーマ生成

LangChainは、Pythonの型アノテーションから各ツールのJSON Schemaを自動的に生成します。エージェントはこのスキーマをシステムプロンプトで受け取るため、必要な引数、その型、制約を把握できます。ツール関数には必ず正確な型をアノテーションしてください。

from langchain_core.tools import tool

@tool
def calculate_compound_interest(
    principal: float,
    annual_rate: float,
    years: int
) -> float:
    '''Calculate compound interest earned over a number of years.
    Args:
        principal: Initial investment amount in dollars.
        annual_rate: Annual interest rate as a decimal (e.g. 0.05 for 5%).
        years: Number of years to compound.
    Returns:
        Final amount after compounding.
    '''
    return principal * (1 + annual_rate) ** years

# Inspect the auto-generated schema
print(calculate_compound_interest.args_schema.schema())

Pydanticによる入力検証

複雑な入力を受け取るツールでは、args_schemaとしてPydanticモデルを定義します。これにより、自動検証、型の強制変換、フィールド単位の詳しいドキュメントが利用でき、LLMはツールの呼び出し方法を判断する際にそれらを参照できます。

from langchain_core.tools import tool
from pydantic import BaseModel, Field

class SearchInput(BaseModel):
    query: str = Field(description='The search query to look up.')
    num_results: int = Field(default=5, ge=1, le=20, description='Number of results to return (1-20).')

@tool(args_schema=SearchInput)
def web_search(query: str, num_results: int = 5) -> str:
    '''Search the web for current information on any topic.
    Use this for facts that may have changed after the model training cutoff.
    '''
    return f'Searching for "{query}", returning {num_results} results...'

効果的なツール説明を書く

ツールの説明は、ツール定義で最も重要な部分です。LLMはその説明を読んで、ツールをいつ、どのように呼び出すかを判断します。よい説明では、次の点に答えます。このツールは何をするのか?いつ使うべきか?入力はどのような形式か?出力は何になるのか?

  • 悪い例:「検索ツール」
  • よい例:「最新のニュース、事実、データをウェブで検索します。最近の出来事や、学習データに含まれていない事実についてユーザーが尋ねた場合に使用します。入力:簡潔な検索クエリ」

ツールの戻り値の型

ツールは文字列、辞書、構造化されたPydanticオブジェクトを返せます。ただし、エージェントは最終的に、結果を会話に含めるためテキストとして扱う必要があります。辞書を返した場合、LangChainはそれを文字列にシリアライズします。複雑なネストデータは、生のJSONではなく読みやすい概要に整形すると、モデルが推論しやすくなります。

from langchain_core.tools import tool
import json

@tool
def get_stock_price(ticker: str) -> str:
    '''Look up the current stock price for a given ticker symbol.
    Input should be the stock ticker symbol in uppercase, e.g. AAPL or MSFT.
    '''
    # Stub — real implementation calls a financial API
    data = {'ticker': ticker, 'price': 182.50, 'currency': 'USD', 'change': '+1.2%'}
    return f'{ticker}: ${data["price"]} ({data["change"]})'

ツールエラーを適切に処理する

ツールは失敗することがあります。APIが停止したり、ネットワークタイムアウトが発生したり、ユーザーが無効な入力を提供したりします。例外によってエージェントのループ全体がクラッシュするのを防ぐため、ツールの処理をtry/exceptで囲み、説明的なエラー文字列を返します。そうすれば、エージェントは失敗について推論し、再試行するか別の方法を使うか判断できます。

from langchain_core.tools import tool
import requests

@tool
def fetch_url(url: str) -> str:
    '''Fetch the text content of a web page given its URL.
    Use for accessing specific documents or web pages the user references.
    '''
    try:
        resp = requests.get(url, timeout=10)
        resp.raise_for_status()
        return resp.text[:2000]  # Return first 2000 chars
    except requests.Timeout:
        return 'Error: Request timed out after 10 seconds.'
    except requests.HTTPError as e:
        return f'Error: HTTP {e.response.status_code}'
    except Exception as e:
        return f'Error fetching URL: {str(e)}'

非同期ツール

エージェントが多数のツール呼び出しを実行する場合や、ツールがI/O待ちのネットワークリクエストを行う場合は、イベントループをブロックしないように非同期ツール関数を定義します。LangChainのエージェントエグゼキューターは非同期ツールをネイティブにサポートしているため、ツール関数でasync defを使用するだけで済みます。

from langchain_core.tools import tool
import httpx

@tool
async def async_fetch(url: str) -> str:
    '''Asynchronously fetch content from a URL.
    Preferred over fetch_url when making multiple concurrent requests.
    '''
    async with httpx.AsyncClient(timeout=10) as client:
        try:
            resp = await client.get(url)
            resp.raise_for_status()
            return resp.text[:2000]
        except Exception as e:
            return f'Error: {str(e)}'

ツールをツールキットに整理する

関連するツールが多数ある場合は、ツールをツールキットにまとめます。ツールキットはツールのリストを返すクラスです。LangChainのツールキットは、コンストラクターでAPIキーなどの設定を受け取り、get_tools()メソッドを公開するという共通パターンに従います。これにより、ツールをすっきりと管理でき、さまざまなエージェントで再利用できます。

from langchain_core.tools import BaseTool
from typing import List

class WeatherToolkit:
    def __init__(self, api_key: str):
        self.api_key = api_key

    def get_tools(self) -> List[BaseTool]:
        return [
            get_weather,          # defined earlier with @tool
            get_weather_forecast,  # another tool
            get_weather_alert      # another tool
        ]

# Usage
toolkit = WeatherToolkit(api_key='your_weather_api_key')
tools = toolkit.get_tools()
print(f'Loaded {len(tools)} weather tools')

ユーザーロールでツールへのアクセスを制限する

すべてのユーザーがすべてのツールにアクセスできる必要はありません。読み取り専用ユーザーが send_email や delete_record ツールを実行できてはいけません。認証されたユーザーの権限に基づいてエージェントに渡すツールを選択し、ロールベースのツールアクセスを実装してください。

def get_tools_for_user(user_role: str) -> list:
    read_tools = [web_search, get_weather, calculate_compound_interest]
    write_tools = [send_email, create_calendar_event, update_record]

    if user_role == 'admin':
        return read_tools + write_tools
    elif user_role == 'member':
        return read_tools
    else:
        return [web_search]  # Guest: only public search

ツールドキュメントのベストプラクティス

適切にドキュメント化されたツールは、エージェントのエラーを大幅に減らします。次のベストプラクティスに従ってください。明確な動詞から始まる名前(websearchではなくsearch_web)を使用し、想定される入力形式を明示し、誤検出を避けるためにツールを使用してはいけない場合を記載します。また、モデルが正しく解析できるよう、出力の形式も説明してください。

クイックチェック

LangChainエージェント向けのツール定義についての理解度を確認しましょう。

レッスンのまとめ

このレッスンでは、@toolデコレーターによって、docstringを説明として使用するPython関数をエージェントから呼び出せるツールに変換できること、Pydanticスキーマによって型付き入力を検証できること、そしてツールはエラーを適切に処理し、説明的なエラー文字列を返すべきであることを学びました。次は、LangChainで完全なReActエージェントを組み立て、その推論ステップを追跡します。

無料で開始

AI チューターと学ぶ Python — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
30
レッスン
120

よくある質問

「Agent用Toolの定義」レッスンは無料ですか?

はい。「Agent用Toolの定義」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AI Engineering Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AI Engineering Academyコースには全4レッスンが含まれています。

「Agent用Toolの定義」で何を学びますか?

@toolデコレーターを使ってカスタムToolを作成し、各Toolを呼び出すタイミングをLLMが判断するための明確な説明を記述して、Pydanticによる入力検証を追加します。 ブラウザで直接実行するハンズオンコードでAI Engineering Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

AI Engineering Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのAI Engineering Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「Agent用Toolの定義」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このAI Engineering Academyレッスンでコードを書いて実行できますか?

はい。すべてのAI Engineering Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. ReActフレームワーク:Think、Act、Observe
  2. Agent用Toolの定義
  3. LangChainでReAct Agentを構築する
  4. エージェントの失敗とループへの対処
← AI Engineering Academyに戻る