Anthropicとは?使い方やClaudeのAIエージェントの作り方を解説

Anthropic 使い方 Claude AIエージェント

2024年5月31日、Anthropic社が生成AI「Claude 3」が外部ツールやAPIと連携できるようにする「Tool use」機能を一般公開しました。

Messages API・Amazon Bedrock・Google CloudのVertex AI上のClaude 3モデルファミリー全てにおいて利用できます。

これはOpenAIでいうところのFunction Calling機能のようなもので、ユーザーからの入力メッセージに対して、特定のツールを使用して回答を生成します。

このツールは、250以上設定でき、ユーザーからの入力に応じて90%以上の精度で適切なツールを選択して、応答を生成できるそうです。

ただ、ツールについては、使用方法についての詳細に記述することが重要で、ツールの目的やパラメータ、使用時の注意点などを明確にする必要があります。

今回は、Tool機能の概要を紹介し、実際に使ってみようと思います。

是非最後までご覧ください!

目次

Anthropicとは

Anthropicとは、OpenAIに所属していた複数人のメンバーが立ち上げた、生成AIを取り扱うスタートアップ企業です。現在ではOpenAIの競合企業としても知られており、ChatGPTよりも安価なLLM「Claude 3」を提供していることから、すでにさまざまな大手企業と提携しています。

とくに、Amazon(AWS)が最大で40億ドル、Googleが追加で20億ドルもの巨額出資をしているのも特徴。API連携で外部ツールに生成AI機能を導入したいと考えているなら、注目しておきたい企業の1つです。

Tool機能の概要

Anthropic社がClaude 3シリーズ向けに一般開放したTool use機能は、OpenAIでいうところのFunction Calling機能にあたるものです。

この機能の開放により、ユーザーは事前に定義された特定のツール(例えば、株価を取得するツールや天気情報を提供するツールなど)を利用して応答を生成できるようになりました。

ツールは、ユーザーが定義することができ、実際のツール定義の例を以下に示します。

{
  "name": "get_weather",
  "description": "Get the current weather in a given location",
  "input_schema": {
    "type": "object", 
    "properties": {
      "location": {
        "type": "string",
        "description": "The city and state, e.g. San Francisco, CA"
      },
      "unit": {
        "type": "string",
        "enum": ["celsius", "fahrenheit"],
        "description": "The unit of temperature, either 'celsius' or 'fahrenheit'"
      }
    },
    "required": ["location"]
  }
}

こちらは、特定の場所の最近の天気を取得するツールです。

ツール定義の主要部分の説明です。

  • name: ツールの名前で、次の正規表現に従うする必要があります。 ^[a-zA-Z0-9_-]{1,64}$
  • description: ツールの機能、使用時期、動作方法についての詳細なプレーンテキストの説明を記載します。
  • input_schema:予期されるパラメータを定義するオブジェクトです。

このツール定義について、Anthropicからベストプラクティスがアナウンスされているので紹介します。

  • ツールに関する以下の情報を詳細に説明する必要がある
    • ツールの機能
    • いつ使用すべきか(いつ使用すべきでないか)
    • 各パラメータの意味とそれがツールの動作にどのように影響するか
    • ツール名が不明な場合にツールが返さない情報など、重要な注意事項や制限事項
  • 少なくとも3~4文を目標に説明を記述する
    • もしツールが複雑な場合は、それ以上の量の説明を記述することを目標にします。
  • 例よりも説明を優先
    • ツールの使用方法の例をプロンプトに含めることはできますが、最も重要なのは目的とパラメータについての具体的な説明で、例は説明が完全に具体化された場合のみ記載します。

これらのベストプラクティスをもとに作成されたツール定義がこちらです。

{
  "name": "get_stock_price",
  "description": "Retrieves the current stock price for a given ticker symbol. The ticker symbol must be a valid symbol for a publicly traded company on a major US stock exchange like NYSE or NASDAQ. The tool will return the latest trade price in USD. It should be used when the user asks about the current or most recent price of a specific stock. It will not provide any other information about the stock or company.",
  "input_schema": {
    "type": "object",
    "properties": {
      "ticker": {
        "type": "string",
        "description": "The stock ticker symbol, e.g. AAPL for Apple Inc."
      }
    },
    "required": ["ticker"]
  }
}

こちらは、特定の銘柄の現在または直近の株価を取得するツールです。

descriptionはとても詳細に書かれています。

Retrieves the current stock price for a given ticker symbol. The ticker symbol must be a valid symbol for a publicly traded company on a major US stock exchange like NYSE or NASDAQ. The tool will return the latest trade price in USD. It should be used when the user asks about the current or most recent price of a specific stock. It will not provide any other information about the stock or company.

指定したティッカーシンボルの現在の株価を取得します。ティッカーシンボルは、NYSEやNASDAQのような米国の主要な証券取引所で公開されている企業の有効なシンボルでなければなりません。このツールは、最新の取引価格を米ドルで返します。このツールは、ユーザーが特定の銘柄の現在または直近の価格について尋ねる場合に使用します。その銘柄や企業に関するその他の情報は提供されません。

次に、Claudeによるツールの使用について解説します。

Claudeは、以下のような流れでツールを使用して、応答を生成します。

  • ツールの指定と入力の提供: ユーザーまたはシステムからのメッセージに基づいて、Claudeは利用すべきツールを判断し、そのツールに渡すべき具体的な入力情報を生成します。この入力情報は、ツールのinput_schemaに基づいて構成されます。
  • tool_useレスポンスブロックの生成: Claudeがツールの使用を決定した場合、stop_reasonがtool_useとされ、ツールの名前、一意の識別子(id)、およびツールへの入力情報が含まれたtool_useコンテンツブロックがAPIレスポンスに含まれます。このブロックは、ユーザーが実際にツールを実行するために必要な情報を提供します。
  • ツールの実行: ユーザーはtool_useブロックから情報を取得し、対応するツールを自身のコードベースで実行します。このとき、Claudeから提供された入力パラメータをツールに渡します。
  • ツール結果のフィードバック: ツールの実行結果(成功またはエラー)を、tool_resultタイプのコンテンツブロックを含む新しいメッセージとしてClaudeに送り返します。このメッセージには、対応するtool_useリクエストのidと結果の内容が含まれます。
  • 応答の生成: ツールの実行結果を受け取ったClaudeは、その情報を基にユーザーへの最終的な応答を生成します。この応答は、ユーザーの元の質問に対する具体的な答えや、ツールの実行に関連する追加情報を含むことができます。

また、ツールの使用の際のベストプラクティスも共有されています。

  • モデル選択:複雑なツールの使用をナビゲートするには Claude 3 Opusを使用し、単純なツールを扱う場合は Haikuを使用することをお勧めします。
  • ツール選択:250以上のツールから、ユーザーの入力に応じて90%以上の精度で適切なツールを選択できます。
  • 最適なツール定義:よりシンプルなインターフェイスとよりシンプルなツールを使用することが推奨され、複雑で深くネストされたツールの使用は避けてください。
  • 順次ツール使用:Claude は通常、一度に1つのツールを使用し、そのツールの出力を使用して次のアクションを通知することを好みます。プロンプトとツールを慎重に設計することで、Claude に複数のツールを並行して使用するように指示できますが、これにより、Claude が以前のツール使用の結果に依存するパラメーターにダミー値を入力する可能性があります。
  • 再試行:Claudeはツール使用リクエストが無効であるか、必要なパラメータが欠落している場合、エラー応答を返して再試行できますが、2 ~ 3 回試行が失敗すると、諦めてさらに再試行する代わりにユーザーに謝罪するようになります。
  • デバッグ:予期しないツール使用動作をデバッグするときは、Claude の思考の連鎖出力 (ある場合) に注意して、なぜその選択が行われているかを理解してください。
  • タグ:検索ツールを使用すると、 <検索品質_反射> XML タグとその応答内の検索品質スコアが返ってくることがあります。その際は、「応答で返された検索結果の品質を反映しないでください」という文プロンプトの最後に追加することで対処できます。

ここからは、実際にTool機能を使ってみようと思います。

なお、Claude 3 Haikuについて知りたい方はこちらの記事をご覧ください。

Tool機能のトークン数

Tool機能のトークン数は、モデルに送信された入力トークンの総数と生成された出力トークンの数の合計であり、これが課金対象になります。

また、モデルごとにシステムプロンプトが異なり、それらのトークン数は各モデル固定で追加されます。

  • Claude 3 Opus: 395トークン
  • Claude 3 Sonnet: 159トークン
  • Claude 3 Haiku: 264トークン

各モデルの料金については、以下のリンクから確認してください。

models-overview

Tool機能の使い方

ここでは、Messaging APIを使ってTool use機能を利用する方法を紹介していきます。

Messaging APIを使用するので、まずはANTHROPIC APIキーの取得と環境変数の設定、anthropicのインストールを行います。

APIキーは、以下のリンクから取得できます。

Anthropic console

取得したAPIキーを環境変数に追加します。

export ANTHROPIC_API_KEY=your_api_key

次に、anthropicパッケージのインストールを行います。

pip install anthropic

これでMessaging APIは利用できるので、試しに先ほどの例にあった天気を取得するツール定義を使ってみましょう。

import anthropic
client = anthropic.Anthropic()

response = client.beta.tools.messages.create(
    model="claude-3-opus-20240229",
    max_tokens=1024,
    tools=[
        {
            "name": "get_weather",
            "description": "Get the current weather in a given location",
            "input_schema": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city and state, e.g. San Francisco, CA"
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "The unit of temperature, either \"celsius\" or \"fahrenheit\""
                    }
                },
                "required": ["location"]
            }
        }
    ],
    messages=[{"role": "user", "content": "What is the weather like in San Francisco?"}]
)

print(response)

すると、このような応答が出力されました。(出力されたものを綺麗に整えています)

{
  "id": "msg_01LitcYPe64A1BG1na6Udja5",
  "model": "claude-3-opus-20240229",
  "role": "assistant",
  "stop_reason": "tool_use",
  "stop_sequence": null,
  "type": "message",
  "usage": {
    "input_tokens": 527,
    "output_tokens": 159
  },
  "content": [
    {
      "text": "<thinking>\nThe user has asked for the current weather in San Francisco. The relevant tool is get_weather, which requires a location parameter. The user provided the location \"San Francisco\", but did not specify a state. However, given San Francisco is a major, well-known city, we can reasonably infer they mean San Francisco, CA without needing to ask for clarification. The unit parameter is optional, so we do not need to ask the user to provide that.\n</thinking>",
      "type": "text"
    },
    {
      "id": "toolu_01FgoznQmsmMkaKtss5jAGVb",
      "input": {
        "location": "San Francisco, CA"
      },
      "name": "get_weather",
      "type": "tool_use"
    }
  ]
}

テキストの部分にはこう書かれています。

ユーザーはサンフランシスコの現在の天気を尋ねている。該当するツールは get_weather で、location パラメータが必要です。ユーザは location 〚San Francisco〛を指定したが、州は指定しなかった。しかし、San Franciscoが有名な大都市であることから、説明を求めるまでもなく、カリフォルニア州サンフランシスコを意味していると合理的に推測できます。unitパラメータはオプションなので、ユーザーにその入力を求める必要はありません。

このまま続けて以下のコードを実行します。

import anthropic
client = anthropic.Anthropic()

response = client.beta.tools.messages.create(
    model="claude-3-opus-20240229",
    max_tokens=1024,
    tools=[
        {
            "name": "get_weather",
            "description": "Get the current weather in a given location",
            "input_schema": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city and state, e.g. San Francisco, CA"
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "The unit of temperature, either 'celsius' or 'fahrenheit'"
                    }
                },
                "required": ["location"]
            }
        }
    ],
    messages=[
        {
            "role": "user",
            "content": "What's the weather like in San Francisco?"
        },
        {
            "role": "assistant",
            "content": [
                {
                    "type": "text",
                    "text": "<thinking>\nThe user has asked for the current weather in San Francisco. The relevant tool is get_weather, which requires a location parameter. The user provided the location \"San Francisco\", but did not specify a state. However, given San Francisco is a major, well-known city, we can reasonably infer they mean San Francisco, CA without needing to ask for clarification. The unit parameter is optional, so we do not need to ask the user to provide that.\n</thinking>",
                },
                {
                    "type": "tool_use",
                    "id": "toolu_01FgoznQmsmMkaKtss5jAGVb",
                    "name": "get_weather",
                    "input": {"location": "San Francisco, CA"}
                }
            ]
        },
        {
            "role": "user",
            "content": [
                {
                    "type": "tool_result",
                    "tool_use_id": "toolu_01FgoznQmsmMkaKtss5jAGVb", # from the API response
                }
            ]
        }
    ]
)

print(response)

結果はこのようになりました。

{
  "id": "msg_01FeeQLgTHox74PfEJjCxmDj",
  "model": "claude-3-opus-20240229",
  "role": "assistant",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "type": "message",
  "usage": {
    "input_tokens": 712,
    "output_tokens": 32
  },
  "content": [
    {
      "text": "According to the weather information, it is currently 65°F (18°C) and partly cloudy in San Francisco, CA.",
      "type": "text"
    }
  ]
}

出力された応答を日本語訳したものです。

気象情報によると、サンフランシスコ(カリフォルニア州)の現在の気温は65°F(18℃)、一部曇り。

このように、気温と天気の情報を教えてくれました。

ただ、実行時のサンフランシスコは気温12℃で晴れだったので、全然違う情報を出力しています。

その点は気になりますが、これで実際に使えることが分かりました。

ここからは、指定した銘柄の株価を取得するツールを作って、株価検索エージェントを作ってみようと思います!

Tool機能を使って株価検索エージェントを作ってみた!

早速、株価検索エージェントを作成していきましょう!

今回は、公式ドキュメントなどを参考に作成していきます。

まず現在の株価を取得する方法ですが、ここではYahoo! Financeから情報を取得するためのAPIであるyfinanceを使用します。

yfinanceは、オープンソースなのでpip installで簡単にインストールできます。

pip install yfinance

最初は先ほどと同じように、必要なモジュールをインポートして、ツールを定義します。

import anthropic
import yfinance as yf

client = anthropic.Anthropic()

tools = [
    {
        "name": "get_stock_price",
        "description": "Get the current stock price for a given ticker symbol",
        "input_schema": {
            "type": "object",
            "properties": {
                "ticker_symbol": {
                    "type": "string",
                    "description": "The stock ticker symbol, e.g., AAPL for Apple Inc."
                }
            },
            "required": ["ticker_symbol"]
        }
    }
]

ツール定義は、claudeのドキュメントにあったものをそのまま使っています。

次に、株価を取得するための関数を定義します。

# 株価を取得するための関数
def get_stock_price(ticker_symbol):
    stock = yf.Ticker(ticker_symbol)
    hist = stock.history(period="1d")
    current_price = hist['Close'].iloc[0]
    return current_price

ここでは、ticker_symbolから株価を取得したい銘柄のティッカーシンボルを受け取り、yfinanceライブラリを使用して現在の株価を取得する関数を定義しています。

histで株価履歴の取得をし、current_priceで現在の株価の抽出しています。

次に、ユーザーからの質問をAnthropic APIに送信します。

#ユーザーからの質問をAnthropic APIに送信
def ask_claude(question):
    initial_response = client.beta.tools.messages.create(
        model="claude-3-sonnet-20240229",
        max_tokens=1024,
        tools=tools,
        messages=[{"role": "user", "content": question}]
    )

ここで、初期応答にツールの使用が必要とされる場合(tool_use)、定義されたツール(get_stock_price)を呼び出し、その入力(ティッカーシンボル)に基づいて株価を取得します。

    if initial_response.stop_reason == "tool_use":
        tool_use = next(block for block in initial_response.content if block.type == "tool_use")
        tool_name = tool_use.name
        tool_input = tool_use.input

        #ここで株価取得ツールを呼び出す
        #株価取得ツールを呼び出して結果を取得
        tool_result = get_stock_price(tool_input["ticker_symbol"])

        #ツール結果を文字列に変換
        tool_result_str = str(tool_result) 

ここで結果を文字列に変換しないと、エラーになってしまうのでご注意ください。

最後に、ツールの結果をClaudeに送り返し、最終的な応答を得ます。

        #ツールの結果をClaudeに送り返し、最終的な応答を得る
        response = client.beta.tools.messages.create(
            model="claude-3-sonnet-20240229",
            max_tokens=4096,
            messages=[
                {"role": "user", "content": question},
                {"role": "assistant", "content": initial_response.content},
                {
                    "role": "user",
                    "content": [
                        {
                            "type": "tool_result",
                            "tool_use_id": tool_use.id,
                            "content": tool_result_str,
                        }
                    ],
                },
            ],
            tools=tools,
        )   

        final_response = next(
            (block.text for block in response.content if hasattr(block, "text")),
            None,
        )
        
        return final_response
    else:
        #ツールが使用されなかった場合の処理
        return next(
            (block.text for block in initial_response.content if hasattr(block, "text")),
            "Unable to process the request."
        )

question = "What is the stock price of AAPL?"
print(ask_claude(question))

これらのパートをすべてまとめたコードがこちらです。

import anthropic
import yfinance as yf

client = anthropic.Anthropic()

tools = [
    {
        "name": "get_stock_price",
        "description": "Get the current stock price for a given ticker symbol",
        "input_schema": {
            "type": "object",
            "properties": {
                "ticker_symbol": {
                    "type": "string",
                    "description": "The stock ticker symbol, e.g., AAPL for Apple Inc."
                }
            },
            "required": ["ticker_symbol"]
        }
    }
]

#株価を取得するための関数
def get_stock_price(ticker_symbol):
    stock = yf.Ticker(ticker_symbol)
    hist = stock.history(period="1d")
    current_price = hist['Close'].iloc[0]
    return current_price

#ユーザーからの質問をAnthropic APIに送信
def ask_claude(question):
    initial_response = client.beta.tools.messages.create(
        model="claude-3-sonnet-20240229",
        max_tokens=1024,
        tools=tools,
        messages=[{"role": "user", "content": question}]
    )

    if initial_response.stop_reason == "tool_use":
        tool_use = next(block for block in initial_response.content if block.type == "tool_use")
        tool_name = tool_use.name
        tool_input = tool_use.input

        #ここで株価取得ツールを呼び出す
        #株価取得ツールを呼び出して結果を取得
        tool_result = get_stock_price(tool_input["ticker_symbol"])

        #ツール結果を文字列に変換
        tool_result_str = str(tool_result) 

        #ツールの結果をClaudeに送り返し、最終的な応答を得る
        response = client.beta.tools.messages.create(
            model="claude-3-sonnet-20240229",
            max_tokens=4096,
            messages=[
                {"role": "user", "content": question},
                {"role": "assistant", "content": initial_response.content},
                {
                    "role": "user",
                    "content": [
                        {
                            "type": "tool_result",
                            "tool_use_id": tool_use.id,
                            "content": tool_result_str,
                        }
                    ],
                },
            ],
            tools=tools,
        )   

        final_response = next(
            (block.text for block in response.content if hasattr(block, "text")),
            None,
        )
        
        return final_response
    else:
        #ツールが使用されなかった場合の処理
        return next(
            (block.text for block in initial_response.content if hasattr(block, "text")),
            "Unable to process the request."
        )

question = "What is the stock price of AAPL?"
print(ask_claude(question))

これを実行すれば、question = “What is the stock price of AAPL?”に対する回答が得られるはずです。

結果は、この通りAppleの現在の株価を出力してくれました。

Googleで調べても、同じ株価なので正しい情報だということが分かりますね!

ちなみに、ティッカーシンボルではなく企業名で質問しても、問題なく答えてくれます。

question = "What is the stock price of Apple?"

今回紹介したツール機能は、比較的簡単に自分がやらせたいことをAIにやらせることができる便利機能ですので、みなさんも是非使ってみてください!

なお、Claude 3がプロンプトエンジニアリングをしてくれるclaude-prompt-engineerについて知りたい方はこちらの記事をご覧ください。

Tool機能を使って自分だけの最強エージェントを作ろう!

AnthropicのTool機能は、OpenAIでいうところのFunction Calling機能のようなもので、ユーザーからの入力メッセージに対して、特定のツールを使用して回答を生成します。

ツールは、ユーザー自身で定義できますが、使用方法についての詳細に記述することが重要で、ツールの目的やパラメータ、使用時の注意点などを明確にする必要があります。

また、ツールを実際に使用する際も、タスクに応じてモデルを変更したり、できるだけ並列処理はさせず、一つ一つタスクを実行することで、より良い応答が得られます。

ツール使用時もトークン数に応じて料金がかかり、システムプロンプト分のトークンは、固定で入力トークンに追加されるので、その点は注意が必要です。

この機能を活用すれば、自分の目的に合わせたこれまでにない高度なAIエージェントの作成が可能になります。

もしこの記事を読んで気になった方は是非試してみてください!

サービス紹介資料

生成系AIの業務活用なら!

・生成系AIを活用したPoC開発

・生成系AIのコンサルティング

・システム間API連携

最後に

いかがだったでしょうか?

AnthropicのTool use機能は、外部ツール連携を手軽に実現し、精度の高い応答を生成します。ツール選定や使用方法における柔軟性を活かし、業務の自動化や効率化を促進させましょう。

株式会社WEELは、自社・業務特化の効果が出るAIプロダクト開発が強みです!

開発実績として、

・新規事業室での「リサーチ」「分析」「事業計画検討」を70%自動化するAIエージェント
・社内お問い合わせの1次回答を自動化するRAG型のチャットボット
・過去事例や最新情報を加味して、10秒で記事のたたき台を作成できるAIプロダクト
・お客様からのメール対応の工数を80%削減したAIメール
・サーバーやAI PCを活用したオンプレでの生成AI活用
・生徒の感情や学習状況を踏まえ、勉強をアシストするAIアシスタント

などの開発実績がございます。

まずは、無料相談にてご相談を承っておりますので、ご興味がある方はぜひご連絡ください。

➡︎生成AIを使った業務効率化、生成AIツールの開発について相談をしてみる。

生成AIを社内で活用していきたい方へ
無料相談

「生成AIを社内で活用したい」「生成AIの事業をやっていきたい」という方に向けて、生成AI社内セミナー・勉強会をさせていただいております。

セミナー内容や料金については、ご相談ください。

また、サービス紹介資料もご用意しておりますので、併せてご確認ください。

投稿者

  • ゆうや

    ロボット工学専攻。 大学時代は、対話ロボットのための画像キャプションの自動生成について研究。 趣味は、サウナとドライブ。

  • URLをコピーしました!
  • URLをコピーしました!
目次