AnthropicのFunction Calling機能マスターガイド:AIと外部システムの連携📒ノートブック付

AI API

はじめに

こんにちは!この記事では、AnthropicのAIモデルを使用したFunction Calling(関数呼び出し)機能について、詳しく解説します。Function Callingは、AIモデルと外部システムやAPIを連携させる強力な機能です。この機能を使いこなすことで、AIの能力を大幅に拡張し、より高度で実用的なアプリケーションを開発することができます。

Function Callingとは

Function Callingは、AIモデルに特定の関数やAPIを呼び出す能力を与える機能です。これにより、AIは自然言語での対話を通じて、外部システムと連携し、より複雑なタスクを実行できるようになります。

例えば、ユーザーが「東京の明日の天気は?」と質問した場合、AIは適切な天気API関数を呼び出し、その結果を解釈して回答することができます。

環境設定

まずは、必要なライブラリをインストールし、APIキーを設定しましょう。

# 必要なライブラリをインストール
!pip install litellm

# 必要なモジュールをインポート
import os
from litellm import completion

from google.colab import userdata
userdata.get('ANTHROPIC_API_KEY')

# Anthropic APIキーを環境変数に設定
os.environ["ANTHROPIC_API_KEY"] = userdata.get('ANTHROPIC_API_KEY')

your-api-keyの部分を、あなたの実際のAnthropic APIキーに置き換えてください。APIキーは厳重に管理し、公開しないよう注意しましょう。

基本的な使い方

Function Callingの基本的な使い方を見ていきましょう。まずは、単一の関数を定義し、AIにそれを使用させる例を示します。

from openai import OpenAI
import json
from pprint import pprint

def get_current_temperature(location, unit="fahrenheit"):
    """指定された都市の現在の気温を取得する"""
    if "tokyo" in location.lower():
        return json.dumps({"location": "Tokyo", "temperature": "10", "unit": unit})
    elif "san francisco" in location.lower():
        return json.dumps({"location": "San Francisco", "temperature": "72", "unit": unit})
    elif "paris" in location.lower():
        return json.dumps({"location": "Paris", "temperature": "22", "unit": unit})
    else:
        return json.dumps({"location": location, "temperature": "unknown"})

def get_current_weather(location):
    """指定された都市の現在の天気を取得する"""
    if "tokyo" in location.lower():
        return json.dumps({"location": "Tokyo", "weather": "sunny"})
    elif "san francisco" in location.lower():
        return json.dumps({"location": "San Francisco", "weather": "rain"})
    elif "paris" in location.lower():
        return json.dumps({"location": "Paris", "weather": "cloudy"})
    else:
        return json.dumps({"location": location, "weather": "unknown"})
import json

def unescape_unicode(s):
    return json.loads(f'"{s}"')

def display_model_response(response):
    print("ModelResponse:")
    print(f"  id: {response.id}")
    print(f"  created: {response.created}")
    print(f"  model: {response.model}")
    print(f"  object: {response.object}")
    print(f"  system_fingerprint: {response.system_fingerprint}")

    print("  choices:")
    for choice in response.choices:
        print(f"    index: {choice.index}")
        print(f"    finish_reason: {choice.finish_reason}")
        print("    message:")
        print(f"      content: {choice.message.content}")
        print(f"      role: {choice.message.role}")

        if choice.message.tool_calls:
            print("      tool_calls:")
            for tool_call in choice.message.tool_calls:
                print(f"        id: {tool_call.id}")
                print(f"        type: {tool_call.type}")
                print("        function:")
                print(f"          name: {tool_call.function.name}")

                # Unicodeエスケープシーケンスをデコード
                args = json.loads(tool_call.function.arguments)
                decoded_args = {k: unescape_unicode(v) for k, v in args.items()}
                print(f"          arguments: {decoded_args}")

    print("  usage:")
    print(f"    prompt_tokens: {response.usage.prompt_tokens}")
    print(f"    completion_tokens: {response.usage.completion_tokens}")
    print(f"    total_tokens: {response.usage.total_tokens}")

# 使用例
# display_model_response(response)
# 関数の定義
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "指定された場所の現在の天気を取得します",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "都市名、例:東京",
                    },
                    "unit": {"type": "string", "enum": ["摂氏", "華氏"]},
                },
                "required": ["location"],
            },
        },
    }
]

# AIに関数呼び出しを要求
messages = [{"role": "user", "content": "東京の今日の天気は?"}]

response = completion(
    model="anthropic/claude-3-5-sonnet-20240620",
    messages=messages,
    tools=tools,
    tool_choice="auto",
)

print(response)
    ModelResponse(id='chatcmpl-91bae9bb-82c4-483a-9ef9-0586f7357217', choices=[Choices(finish_reason='tool_calls', index=0, message=Message(content='はい、東京の今日の天気をお調べしますね。天気情報を取得するために、get_current_weather関数を使用します。', role='assistant', tool_calls=[ChatCompletionMessageToolCall(function=Function(arguments='{"location": "\\u6771\\u4eac"}', name='get_current_weather'), id='toolu_01NZHUe4H8FFBdLEsp6rxjJt', type='function')]))], created=1720074621, model='claude-3-5-sonnet-20240620', object='chat.completion', system_fingerprint=None, usage=Usage(prompt_tokens=519, completion_tokens=98, total_tokens=617))
display_model_response(response)
    ModelResponse:
      id: chatcmpl-91bae9bb-82c4-483a-9ef9-0586f7357217
      created: 1720074621
      model: claude-3-5-sonnet-20240620
      object: chat.completion
      system_fingerprint: None
      choices:
        index: 0
        finish_reason: tool_calls
        message:
          content: はい、東京の今日の天気をお調べしますね。天気情報を取得するために、get_current_weather関数を使用します。
          role: assistant
          tool_calls:
            id: toolu_01NZHUe4H8FFBdLEsp6rxjJt
            type: function
            function:
              name: get_current_weather
              arguments: {'location': '東京'}
      usage:
        prompt_tokens: 519
        completion_tokens: 98
        total_tokens: 617

このコードでは:

  1. toolsリストで、get_current_weather関数を定義しています。この関数は場所と温度単位を受け取り、天気情報を返すことを想定しています。
  2. ユーザーからの質問をメッセージリストに格納しています。
  3. completion関数を呼び出し、AIに関数の使用を指示しています。tool_choice="auto"は、AIが適切な関数を自動で選択することを意味します。

実行すると、AIは関数の呼び出しを提案するレスポンスを返します。

複数の関数の定義と使用

実際のアプリケーションでは、複数の関数を定義し、状況に応じて適切な関数を選択することが多いでしょう。以下は、天気情報と交通情報を取得する2つの関数を定義する例です。

import random
from datetime import datetime

def get_traffic_info(location):
    """
    指定された場所の現在の交通情報を取得します。

    :param location: 都市名または地域名(例:渋谷)
    :return: 交通情報を含む辞書
    """
    # 実際のAPIを使用する代わりに、ランダムなデータを生成
    congestion_levels = ["低", "中", "高", "非常に高い"]
    incidents = ["事故", "工事", "イベント", "なし"]

    traffic_info = {
        "location": location,
        "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        "congestion_level": random.choice(congestion_levels),
        "incident": random.choice(incidents),
        "average_speed": random.randint(10, 60),  # km/h
        "travel_time_increase": random.randint(0, 30)  # minutes
    }

    return traffic_info

# 使用例
if __name__ == "__main__":
    location = "渋谷"
    info = get_traffic_info(location)
    print(f"{location}の交通情報:")
    for key, value in info.items():
        print(f"  {key}: {value}")
渋谷の交通情報:
  location: 渋谷
  timestamp: 2024-07-04 06:30:21
  congestion_level: 非常に高い
  incident: 事故
  average_speed: 36
  travel_time_increase: 2
# 複数の関数を定義
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "指定された場所の現在の天気を取得します",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "都市名、例:東京",
                    },
                    "unit": {"type": "string", "enum": ["摂氏", "華氏"]},
                },
                "required": ["location"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_traffic_info",
            "description": "指定された場所の現在の交通情報を取得します",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "都市名または地域名、例:渋谷",
                    },
                },
                "required": ["location"],
            },
        },
    }
]

# AIに関数呼び出しを要求
messages = [{"role": "user", "content": "渋谷の交通状況を教えて"}]

response = completion(
    model="anthropic/claude-3-5-sonnet-20240620",
    messages=messages,
    tools=tools,
    tool_choice="auto",
)

print(response)
    ModelResponse(id='chatcmpl-a424fce1-9cfd-4ad7-88cf-69cf2fc8489d', choices=[Choices(finish_reason='tool_calls', index=0, message=Message(content='はい、渋谷の交通状況について調べてみましょう。そのために、交通情報を取得する機能を使用します。', role='assistant', tool_calls=[ChatCompletionMessageToolCall(function=Function(arguments='{"location": "\\u6e0b\\u8c37"}', name='get_traffic_info'), id='toolu_011cq8Z9PrjF1EECt7hqQoQm', type='function')]))], created=1720074623, model='claude-3-5-sonnet-20240620', object='chat.completion', system_fingerprint=None, usage=Usage(prompt_tokens=728, completion_tokens=99, total_tokens=827))
display_model_response(response)
    ModelResponse:
      id: chatcmpl-a424fce1-9cfd-4ad7-88cf-69cf2fc8489d
      created: 1720074623
      model: claude-3-5-sonnet-20240620
      object: chat.completion
      system_fingerprint: None
      choices:
        index: 0
        finish_reason: tool_calls
        message:
          content: はい、渋谷の交通状況について調べてみましょう。そのために、交通情報を取得する機能を使用します。
          role: assistant
          tool_calls:
            id: toolu_011cq8Z9PrjF1EECt7hqQoQm
            type: function
            function:
              name: get_traffic_info
              arguments: {'location': '渋谷'}
      usage:
        prompt_tokens: 728
        completion_tokens: 99
        total_tokens: 827

このコードでは:

  1. 天気情報を取得するget_current_weather関数と交通情報を取得するget_traffic_info関数の2つを定義しています。
  2. ユーザーの質問に基づいて、AIが適切な関数(この場合は両方)を選択し、呼び出しを提案します。

AIは、ユーザーの質問に応じて、適切な関数(または複数の関数)の呼び出しを提案します。

関数の結果をAIに解釈させる

関数呼び出しの結果を受け取った後、その結果をAIに解釈させ、ユーザーに分かりやすく説明させることができます。以下は、その方法を示す例です。

# AIに関数呼び出しを要求
messages = [{"role": "user", "content": "東京の今日の天気は?"}]

response = completion(
    model="claude-3-5-sonnet-20240620",
    messages=messages,
    tools=tools,
    tool_choice="auto",
)

# AIの関数呼び出し提案をメッセージリストに追加
messages.append(response.choices[0].message.model_dump())

# 関数の実行結果(ここではダミーデータ)
tool_result = '{"location": "東京", "temperature": "25", "unit": "摂氏", "condition": "晴れ"}'

# 関数の実行結果をメッセージリストに追加
messages.append(
    {
        "tool_call_id": response.choices[0].message.tool_calls[0].id,
        "role": "tool",
        "name": response.choices[0].message.tool_calls[0].function.name,
        "content": tool_result,
    }
)

# AIに結果を解釈させる
second_response = completion(
    model="claude-3-5-sonnet-20240620",
    messages=messages,
    tools=tools,
    tool_choice="auto",
)

print(second_response)
    ModelResponse(id='chatcmpl-f242db11-e405-41c8-8425-61547046c70b', choices=[Choices(finish_reason='stop', index=0, message=Message(content='東京の今日の天気情報をお伝えします:\n\n現在の東京の天気は晴れです。気温は25度(摂氏)となっています。\n\n晴れの天気なので、外出には良い条件かもしれません。ただし、季節や時間帯によっては暑さ対策が必要かもしれませんので、外出の際は適切な服装や日よけ、水分補給などにご注意ください。\n\n他に知りたい情報や、別の地域の天気について聞きたいことはありますか?', role='assistant', tool_calls=[]))], created=1720074629, model='claude-3-5-sonnet-20240620', object='chat.completion', system_fingerprint=None, usage=Usage(prompt_tokens=863, completion_tokens=163, total_tokens=1026))
display_model_response(second_response)
    ModelResponse:
      id: chatcmpl-f242db11-e405-41c8-8425-61547046c70b
      created: 1720074629
      model: claude-3-5-sonnet-20240620
      object: chat.completion
      system_fingerprint: None
      choices:
        index: 0
        finish_reason: stop
        message:
          content: 東京の今日の天気情報をお伝えします:

    現在の東京の天気は晴れです。気温は25度(摂氏)となっています。

    晴れの天気なので、外出には良い条件かもしれません。ただし、季節や時間帯によっては暑さ対策が必要かもしれませんので、外出の際は適切な服装や日よけ、水分補給などにご注意ください。

    他に知りたい情報や、別の地域の天気について聞きたいことはありますか?
          role: assistant
      usage:
        prompt_tokens: 863
        completion_tokens: 163
        total_tokens: 1026

このコードでは:

  1. 最初のAIレスポンス(関数呼び出しの提案)をメッセージリストに追加しています。
  2. 関数の実行結果(ここではダミーデータ)をメッセージリストに追加しています。
  3. 更新されたメッセージリストを使って、AIに結果を解釈させています。

AIは関数の実行結果を解釈し、ユーザーに分かりやすい形で説明します。

エラー処理と例外

実際のアプリケーションでは、関数呼び出しが失敗したり、予期せぬ結果が返ってくる可能性があります。そのような場合のエラー処理も重要です。

# エラー処理を含む関数呼び出し
try:
    response = completion(
        model="anthropic/claude-3-5-sonnet-20240620",
        messages=messages,
        tools=tools,
        tool_choice="auto",
    )

    # 関数呼び出しの提案がある場合
    if response.choices[0].message.tool_calls:
        # ここで実際の関数を呼び出し、結果を取得する
        # (この例ではダミーデータを使用)
        tool_result = '{"error": "天気情報の取得に失敗しました"}'

        messages.append(response.choices[0].message.model_dump())
        messages.append(
            {
                "tool_call_id": response.choices[0].message.tool_calls[0].id,
                "role": "tool",
                "name": response.choices[0].message.tool_calls[0].function.name,
                "content": tool_result,
            }
        )

        # エラー結果をAIに解釈させる
        error_response = completion(
            model="anthropic/claude-3-5-sonnet-20240620",
            messages=messages,
            tools=tools,
            tool_choice="auto",
        )

        print(error_response)
    else:
        print(response)

except Exception as e:
    print(f"エラーが発生しました: {str(e)}")
    ModelResponse(id='chatcmpl-4abcf23f-179d-4183-af8a-4b0f7ac198c1', choices=[Choices(finish_reason='stop', index=0, message=Message(content='東京の今日の天気情報が取得できました。以下が現在の天気状況です:\n\n- 場所: 東京\n- 気温: 25度(摂氏)\n- 天候: 晴れ\n\n今日の東京は晴れで、気温は25度と快適な気候のようです。外出するには良い天気ですね。日中は暖かいかもしれませんが、急な天候の変化に備えて軽い上着を持ち歩くのもいいかもしれません。\n\n何か他に知りたいことはありますか?例えば、明日の天気予報や、特定の地域の交通情報なども調べることができます。', role='assistant', tool_calls=[]))], created=1720074634, model='claude-3-5-sonnet-20240620', object='chat.completion', system_fingerprint=None, usage=Usage(prompt_tokens=863, completion_tokens=200, total_tokens=1063))

このコードでは:

  1. try-exceptブロックを使用して、エラーをキャッチしています。
  2. 関数呼び出しの結果にエラーが含まれている場合(ここではダミーデータを使用)、そのエラー情報をAIに解釈させています。
  3. 予期せぬ例外が発生した場合も適切に処理しています。

エラー処理を適切に行うことで、アプリケーションの堅牢性が向上します。

実践的な例:天気予報ボット

これまでの知識を組み合わせて、簡単な天気予報ボットを作成してみましょう。このボットは、ユーザーが指定した場所の天気を調べ、適切なアドバイスを提供します。

import random
from datetime import datetime, timedelta

def get_weather_forecast(location, days):
    """
    指定された場所の天気予報を取得します。

    :param location: 都市名(例:大阪)
    :param days: 予報を取得する日数(1-7)
    :return: 天気予報のリスト
    """
    if not 1 <= days <= 7:
        raise ValueError("days must be between 1 and 7")

    weather_conditions = ["晴れ", "曇り", "雨", "雪", "霧"]
    wind_directions = ["北", "北東", "東", "南東", "南", "南西", "西", "北西"]

    forecast = []
    for i in range(days):
        date = (datetime.now() + timedelta(days=i)).strftime("%Y-%m-%d")
        forecast.append({
            "date": date,
            "location": location,
            "condition": random.choice(weather_conditions),
            "temperature": {
                "max": random.randint(0, 35),
                "min": random.randint(-5, 30)
            },
            "precipitation": random.randint(0, 100),
            "humidity": random.randint(30, 90),
            "wind": {
                "speed": random.randint(0, 30),
                "direction": random.choice(wind_directions)
            }
        })

    return forecast

# 使用例
if __name__ == "__main__":
    try:
        location = "大阪"
        days = 5
        weather_info = get_weather_forecast(location, days)
        print(f"{location}の{days}日間の天気予報:")
        for day in weather_info:
            print(f"日付: {day['date']}")
            print(f"  天候: {day['condition']}")
            print(f"  気温: 最高 {day['temperature']['max']}°C, 最低 {day['temperature']['min']}°C")
            print(f"  降水確率: {day['precipitation']}%")
            print(f"  湿度: {day['humidity']}%")
            print(f"  風: {day['wind']['speed']}m/s, {day['wind']['direction']}風")
            print()
    except ValueError as e:
        print(f"エラー: {e}")
    大阪の5日間の天気予報:
    日付: 2024-07-04
      天候: 雨
      気温: 最高 17°C, 最低 27°C
      降水確率: 69%
      湿度: 72%
      風: 9m/s, 北風

    日付: 2024-07-05
      天候: 雨
      気温: 最高 22°C, 最低 15°C
      降水確率: 23%
      湿度: 44%
      風: 3m/s, 南西風

    日付: 2024-07-06
      天候: 雨
      気温: 最高 8°C, 最低 14°C
      降水確率: 14%
      湿度: 52%
      風: 11m/s, 北西風

    日付: 2024-07-07
      天候: 雨
      気温: 最高 32°C, 最低 12°C
      降水確率: 11%
      湿度: 59%
      風: 9m/s, 西風

    日付: 2024-07-08
      天候: 晴れ
      気温: 最高 7°C, 最低 5°C
      降水確率: 64%
      湿度: 31%
      風: 7m/s, 南西風
# 天気予報ボットの実装
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather_forecast",
            "description": "指定された場所の天気予報を取得します",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "都市名、例:大阪",
                    },
                    "days": {
                        "type": "integer",
                        "description": "予報を取得する日数(1-7)",
                    },
                },
                "required": ["location", "days"],
            },
        },
    }
]

def weather_bot(user_input: str) -> str:
    messages: List[Dict[str, Any]] = [{"role": "user", "content": user_input}]

    try:
        # AIに関数呼び出しを要求
        response = completion(
            model="anthropic/claude-3-5-sonnet-20240620",
            messages=messages,
            tools=tools,
            tool_choice="auto",
        )
        print("-------------")
        display_model_response(response)
        print("-------------")

        if response.choices[0].message.tool_calls:
            tool_call = response.choices[0].message.tool_calls[0]

            # 関数呼び出しのパラメータを解析
            function_args = json.loads(tool_call.function.arguments)
            location = function_args["location"]
            days = function_args["days"]

            # 実際の天気予報データを取得
            weather_data = get_weather_forecast(location, days)
            tool_result = json.dumps(weather_data)

            messages.append(response.choices[0].message.model_dump())
            messages.append(
                {
                    "tool_call_id": tool_call.id,
                    "role": "tool",
                    "name": tool_call.function.name,
                    "content": tool_result,
                }
            )

            # 結果をAIに解釈させる
            final_response = completion(
                model="anthropic/claude-3-5-sonnet-20240620",
                messages=messages,
                tools=tools,
                tool_choice="auto",
            )

            print("-------------")
            display_model_response(final_response)
            print("-------------")
            return final_response.choices[0].message.content
        else:
            return response.choices[0].message.content

    except Exception as e:
        return f"申し訳ありません。エラーが発生しました: {str(e)}"

# ボットの使用例
user_query = "大阪の明日と明後日の天気を教えて。外出する際のアドバイスもお願い。"
result = weather_bot(user_query)
print(result)
    -------------
    ModelResponse:
      id: chatcmpl-2c75cc44-bb78-4542-ad99-bd43654380fd
      created: 1720074636
      model: claude-3-5-sonnet-20240620
      object: chat.completion
      system_fingerprint: None
      choices:
        index: 0
        finish_reason: tool_calls
        message:
          content: はい、大阪の明日と明後日の天気予報を確認し、外出する際のアドバイスをお伝えいたします。天気予報を取得するために、get_weather_forecast 関数を使用します。
          role: assistant
          tool_calls:
            id: toolu_01WdS9bHCGjx2VANRG9soEZM
            type: function
            function:
              name: get_weather_forecast
              arguments: {'location': '大阪', 'days': '2'}
      usage:
        prompt_tokens: 569
        completion_tokens: 140
        total_tokens: 709
    -------------
    -------------
    ModelResponse:
      id: chatcmpl-4db22858-62cd-4e8d-a2e3-99bbec04e92e
      created: 1720074649
      model: claude-3-5-sonnet-20240620
      object: chat.completion
      system_fingerprint: None
      choices:
        index: 0
        finish_reason: stop
        message:
          content: 大阪の明日と明後日の天気予報が取得できました。それぞれの日の天気と外出時のアドバイスをお伝えします。

    1. 明日(2024年7月4日)の天気:
       - 天候:曇り
       - 最高気温:31°C
       - 最低気温:-3°C(※この値は異常に低いため、データエラーの可能性があります)
       - 降水確率:41%
       - 湿度:76%
       - 風:北西の風、風速19m/s

    外出時のアドバイス:
    - 曇り空ですが、気温の変動が大きいようです。最低気温のデータに誤りがある可能性がありますが、朝晩は冷え込む可能性があるので、羽織るものを持参しましょう。
    - 日中は暑くなるので、熱中症対策として水分補給を忘れずに。
    - 降水確率が41%あるので、折りたたみ傘を持参すると安心です。
    - 風が強めなので、帽子や髪の長い方は髪をまとめるなどの対策をしてください。

    2. 明後日(2024年7月5日)の天気:
       - 天候:雨
       - 最高気温:13°C
       - 最低気温:14°C
       - 降水確率:98%
       - 湿度:31%
       - 風:北の風、風速28m/s

    外出時のアドバイス:
    - 雨天確定の天気なので、雨具(傘、レインコート)は必須です。
    - 気温が低めで、最高気温と最低気温の差が小さいです。寒暖の差は少ないですが、涼しい一日になりそうです。
    - 風が非常に強いので、折りたたみ傘よりもレインコートの方が安全かもしれません。
    - 湿度が低めなので、意外と蒸し暑くはならないかもしれませんが、雨と強風で体感温度は下がる可能性があります。暖かい服装を心がけましょう。
    - 強風と雨で視界が悪くなる可能性があるので、外出時は十分注意してください。可能であれば、重要な用事以外は延期することをおすすめします。

    両日とも天候が不安定で、特に明後日は悪天候が予想されます。外出の際は天気の変化に注意し、安全に気をつけてお過ごしください。
          role: assistant
      usage:
        prompt_tokens: 883
        completion_tokens: 757
        total_tokens: 1640
    -------------
    大阪の明日と明後日の天気予報が取得できました。それぞれの日の天気と外出時のアドバイスをお伝えします。

    1. 明日(2024年7月4日)の天気:
       - 天候:曇り
       - 最高気温:31°C
       - 最低気温:-3°C(※この値は異常に低いため、データエラーの可能性があります)
       - 降水確率:41%
       - 湿度:76%
       - 風:北西の風、風速19m/s

    外出時のアドバイス:
    - 曇り空ですが、気温の変動が大きいようです。最低気温のデータに誤りがある可能性がありますが、朝晩は冷え込む可能性があるので、羽織るものを持参しましょう。
    - 日中は暑くなるので、熱中症対策として水分補給を忘れずに。
    - 降水確率が41%あるので、折りたたみ傘を持参すると安心です。
    - 風が強めなので、帽子や髪の長い方は髪をまとめるなどの対策をしてください。

    2. 明後日(2024年7月5日)の天気:
       - 天候:雨
       - 最高気温:13°C
       - 最低気温:14°C
       - 降水確率:98%
       - 湿度:31%
       - 風:北の風、風速28m/s

    外出時のアドバイス:
    - 雨天確定の天気なので、雨具(傘、レインコート)は必須です。
    - 気温が低めで、最高気温と最低気温の差が小さいです。寒暖の差は少ないですが、涼しい一日になりそうです。
    - 風が非常に強いので、折りたたみ傘よりもレインコートの方が安全かもしれません。
    - 湿度が低めなので、意外と蒸し暑くはならないかもしれませんが、雨と強風で体感温度は下がる可能性があります。暖かい服装を心がけましょう。
    - 強風と雨で視界が悪くなる可能性があるので、外出時は十分注意してください。可能であれば、重要な用事以外は延期することをおすすめします。

    両日とも天候が不安定で、特に明後日は悪天候が予想されます。外出の際は天気の変化に注意し、安全に気をつけてお過ごしください。

このコードでは:

  1. get_weather_forecast関数を定義し、場所と日数を指定して天気予報を取得できるようにしています。
  2. weather_bot関数を作成し、ユーザーの入力を処理します。
  3. AIに関数呼び出しを要求し、その結果(ここではダミーデータ)をAIに解釈させています。
  4. エラー処理を適切に行い、問題が発生した場合にも適切なメッセージを返すようにしています。

この天気予報ボットは、ユーザーの質問に応じて天気情報を取得し、その情報を基に適切なアドバイスを提供します。実際の使用では、ダミーデータの代わりに実際の天気APIを使用することで、リアルタイムの天気情報を提供できます。

まとめと発展的な使い方

Function Callingを使うことで、AIの能力を大幅に拡張し、より実用的なアプリケーションを開発することができます。以下に、Function Callingの発展的な使い方をいくつか紹介します。

  1. 複数のAPIの連携:
    天気情報だけでなく、交通情報や観光スポット情報など、複数のAPIを組み合わせることで、より総合的な情報を提供するボットを作成できます。
# 複数のAPIを連携させる例
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather_forecast",
            "description": "指定された場所の天気予報を取得します",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "都市名"},
                    "days": {"type": "integer", "description": "予報を取得する日数(1-7)"},
                },
                "required": ["location", "days"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_tourist_spots",
            "description": "指定された場所の観光スポットを取得します",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "都市名"},
                    "count": {"type": "integer", "description": "取得するスポットの数"},
                },
                "required": ["location"],
            },
        },
    },
]

# 使用例
user_query = "京都の明日の天気と、おすすめの観光スポットを3つ教えて"
# ここで実際の処理を行います
  1. 逐次的な関数呼び出し:
    一つの関数の結果を基に、次の関数を呼び出すような複雑な処理も可能です。
# 逐次的な関数呼び出しの例
def sequential_function_calling(user_query):
    messages = [{"role": "user", "content": user_query}]

    while True:
        response = completion(
            model="anthropic/claude-3-5-sonnet-20240620",
            messages=messages,
            tools=tools,
            tool_choice="auto",
        )

        if not response.choices[0].message.tool_calls:
            return response.choices[0].message.content

        messages.append(response.choices[0].message.model_dump())

        # ここで実際の関数を呼び出し、結果を取得します
        # この例ではダミーデータを使用
        tool_result = '{"result": "ダミーデータ"}'

        messages.append(
            {
                "tool_call_id": response.choices[0].message.tool_calls[0].id,
                "role": "tool",
                "name": response.choices[0].message.tool_calls[0].function.name,
                "content": tool_result,
            }
        )

# 使用例
result = sequential_function_calling("複雑なタスクの実行をお願いします")
print(result)
    申し訳ありませんが、具体的にどのようなタスクを実行したいのか、もう少し詳しく教えていただけますでしょうか?現在利用可能なツールは、天気予報の取得と観光スポットの情報取得に関するものです。これらのツールを使って何か特定の情報を得たいことはありますか?例えば、ある都市の天気予報を知りたい、または特定の場所の観光スポットについて調べたいなど、具体的なリクエストをいただければ、それに応じてツールを使用してお手伝いさせていただきます。
  1. ユーザー入力の検証:
    Function Callingを使って、ユーザーの入力を検証し、必要に応じて追加情報を要求することもできます。
# ユーザー入力の検証例
def validate_user_input(user_input):
    tools = [
        {
            "type": "function",
            "function": {
                "name": "request_additional_info",
                "description": "ユーザーに追加情報を要求します",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "field": {"type": "string", "description": "必要な追加情報のフィールド名"},
                        "reason": {"type": "string", "description": "追加情報が必要な理由"},
                    },
                    "required": ["field", "reason"],
                },
            },
        },
    ]

    messages = [{"role": "user", "content": f"この入力は有効ですか?必要な情報が足りない場合は追加で質問してください:{user_input}"}]

    response = completion(
        model="anthropic/claude-3-5-sonnet-20240620",
        messages=messages,
        tools=tools,
        tool_choice="auto",
    )

    return response

# 使用例
validation_result = validate_user_input("明日の予定を教えて")
print(validation_result)
    ModelResponse(id='chatcmpl-4161ef5a-72b5-427e-b555-34100352c8c8', choices=[Choices(finish_reason='tool_calls', index=0, message=Message(content='この質問に直接答えるためのツールは提供されていないようです。しかし、ユーザーの予定を確認するには、おそらく追加の情報が必要だと考えられます。ユーザーの特定の日付や個人情報などが必要かもしれません。そこで、追加情報を要求するツールを使用して、必要な情報を取得しましょう。', role='assistant', tool_calls=[ChatCompletionMessageToolCall(function=Function(arguments='{"field": "\\u65e5\\u4ed8", "reason": "\\u4e88\\u5b9a\\u3092\\u78ba\\u8a8d\\u3059\\u308b\\u305f\\u3081\\u306b\\u5177\\u4f53\\u7684\\u306a\\u65e5\\u4ed8\\u304c\\u5fc5\\u8981\\u3067\\u3059\\u3002\\u300c\\u660e\\u65e5\\u300d\\u3068\\u6307\\u5b9a\\u3055\\u308c\\u3066\\u3044\\u307e\\u3059\\u304c\\u3001\\u30b7\\u30b9\\u30c6\\u30e0\\u304c\\u6b63\\u78ba\\u306a\\u65e5\\u4ed8\\u3092\\u628a\\u63e1\\u3059\\u308b\\u305f\\u3081\\u306b\\u306f\\u3001\\u4eca\\u65e5\\u306e\\u65e5\\u4ed8\\u3082\\u77e5\\u308b\\u5fc5\\u8981\\u304c\\u3042\\u308a\\u307e\\u3059\\u3002"}', name='request_additional_info'), id='toolu_01BQVKXP9X1wChNUhV5HvUxz', type='function')]))], created=1720074657, model='claude-3-5-sonnet-20240620', object='chat.completion', system_fingerprint=None, usage=Usage(prompt_tokens=583, completion_tokens=248, total_tokens=831))
display_model_response(validation_result)
    ModelResponse:
      id: chatcmpl-4161ef5a-72b5-427e-b555-34100352c8c8
      created: 1720074657
      model: claude-3-5-sonnet-20240620
      object: chat.completion
      system_fingerprint: None
      choices:
        index: 0
        finish_reason: tool_calls
        message:
          content: この質問に直接答えるためのツールは提供されていないようです。しかし、ユーザーの予定を確認するには、おそらく追加の情報が必要だと考えられます。ユーザーの特定の日付や個人情報などが必要かもしれません。そこで、追加情報を要求するツールを使用して、必要な情報を取得しましょう。
          role: assistant
          tool_calls:
            id: toolu_01BQVKXP9X1wChNUhV5HvUxz
            type: function
            function:
              name: request_additional_info
              arguments: {'field': '日付', 'reason': '予定を確認するために具体的な日付が必要です。「明日」と指定されていますが、システムが正確な日付を把握するためには、今日の日付も知る必要があります。'}
      usage:
        prompt_tokens: 583
        completion_tokens: 248
        total_tokens: 831

これらの発展的な使い方を組み合わせることで、より高度で柔軟なAIアプリケーションを開発することができます。

結論

Function Callingは、AIと外部システムを連携させる強力なツールです。この機能を使いこなすことで、単なる質問応答システムから、実際のタスクを遂行できる実用的なAIアシスタントへと進化させることができます。

ただし、実際のアプリケーション開発では、セキュリティやプライバシー、エラー処理、パフォーマンスなど、様々な要素を考慮する必要があります。また、AIの判断が常に正しいとは限らないため、重要な決定や危険を伴う操作については、人間による最終確認を設けることが重要です。

Function Callingの可能性は無限大です。この機能を活用して、革新的なAIアプリケーションを開発してください。皆さんの創造力が、AIの未来を切り開いていくことでしょう。

📒ノートブック

Google Colab

コメント

タイトルとURLをコピーしました