LiteLLMでAnthropicのParallel Function Callingを試す

## はじめに

こんにちは！今回は、LiteLLMライブラリを使って、Anthropicの最新モデルであるClaude 3.5 sonnetのパラレル関数呼び出し（Parallel Function Calling）機能を試してみます。この記事は、AIと自然言語処理に興味がある初心者から中級者のプログラマーを対象としています。

パラレル関数呼び出しとは、AIモデルが複数の外部関数を同時に呼び出し、その結果を統合して回答を生成する機能です。この機能を使うことで、より正確で詳細な情報をAIに提供することができます。

では、早速始めましょう！

## 環境設定

まず、必要なライブラリをインストールし、環境を設定します。Google Colabで新しいノートブックを開き、以下のセルを実行してください。

```python
!pip install litellm rich
```

次に、必要なモジュールをインポートします。

```python
import os
from litellm import completion
from rich.console import Console
from rich.tree import Tree
from rich.table import Table
from rich.panel import Panel
from rich.syntax import Syntax
from typing import Dict, Any

console = Console()
```

## APIキーの設定

Anthropic APIを使用するには、APIキーが必要です。以下のコードでAPIキーを環境変数として設定します。

```python
from google.colab import userdata


# AnthropicのAPIキーを設定
# 注意: 実際のAPIキーに置き換えてください
os.environ["ANTHROPIC_API_KEY"] = userdata.get('ANTHROPIC_API_KEY')
```


## 便利関数の定義

```python
from rich.console import Console
from rich.syntax import Syntax
from rich.panel import Panel
from rich.tree import Tree
from rich.table import Table
from typing import Dict, Any

def display_rich_function_call_response(response: Dict[str, Any]) -> None:
    # モデル情報を表示するためのツリーを作成
    model_info = Tree("Function Call Response")
    model_info.add(f"ID: [cyan]{response['id']}[/cyan]")
    model_info.add(f"Created: [cyan]{response['created']}[/cyan]")
    model_info.add(f"Model: [cyan]{response['model']}[/cyan]")
    model_info.add(f"Object: [cyan]{response['object']}[/cyan]")
    model_info.add(f"System Fingerprint: [cyan]{response['system_fingerprint']}[/cyan]")

    # 使用量情報を表示するためのテーブルを作成
    usage_table = Table(title="Usage", show_header=True, header_style="bold magenta")
    usage_table.add_column("Metric", style="dim")
    usage_table.add_column("Value", justify="right")
    usage = response['usage']
    usage_table.add_row("Prompt Tokens", str(usage['prompt_tokens']))
    usage_table.add_row("Completion Tokens", str(usage['completion_tokens']))
    usage_table.add_row("Total Tokens", str(usage['total_tokens']))

    # 選択肢（Choices）情報を表示するためのツリーを作成
    choices_tree = Tree("Choices")
    for idx, choice in enumerate(response['choices']):
        choice_tree = choices_tree.add(f"Choice {idx}")
        choice_tree.add(f"Finish Reason: [green]{choice['finish_reason']}[/green]")
        choice_tree.add(f"Index: [green]{choice['index']}[/green]")

        message = choice['message']
        message_tree = choice_tree.add("Message")
        message_tree.add(f"Role: [blue]{message['role']}[/blue]")

        # Content を Syntax オブジェクトとして作成
        content_syntax = Syntax(message['content'], "markdown", theme="monokai", line_numbers=True, word_wrap=True)
        # Panel でラップして message_tree に追加
        message_tree.add(Panel(content_syntax, title="Content", border_style="blue"))

        if message['tool_calls']:
            tool_calls_tree = choice_tree.add("Tool Calls")
            for tool_call in message['tool_calls']:
                tool_call_tree = tool_calls_tree.add(f"Tool Call {tool_call['index']}")
                tool_call_tree.add(f"ID: [yellow]{tool_call['id']}[/yellow]")
                tool_call_tree.add(f"Type: [yellow]{tool_call['type']}[/yellow]")
                function_tree = tool_call_tree.add("Function")
                function_tree.add(f"Name: [red]{tool_call['function']['name']}[/red]")

                # Arguments を Syntax オブジェクトとして作成
                args_syntax = Syntax(tool_call['function']['arguments'], "json", theme="monokai", word_wrap=True)
                # Panel でラップして function_tree に追加
                function_tree.add(Panel(args_syntax, title="Arguments", border_style="red"))

    # 作成したツリーとテーブルを表示
    console = Console(width=120)  # コンソールの幅を広げる
    console.print(Panel(model_info, title="Function Call Response", border_style="bold"))
    console.print(usage_table)
    console.print(Panel(choices_tree, title="Choices", border_style="bold"))
```

## 関数定義

まず、天気情報を取得する関数を定義します。これは、AIモデルが呼び出す外部関数の例です。

```python
# 天気情報を取得する関数を定義
# この関数はAIモデルによって呼び出されます
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "指定された場所の現在の天気を取得します",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "都市名と州名、例：San Francisco, CA",
                    },
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                },
                "required": ["location"],
            },
        },
    }
]
```

この`tools`リストは、AIモデルが利用可能な外部関数を定義しています。ここでは、`get_current_weather`という関数を定義し、場所と温度単位を引数として受け取り、天気情報を返す想定です。



## 最初の関数呼び出し

次に、ユーザーからの質問に基づいて、AIモデルに関数呼び出しを行わせます。

```python
# ユーザーからの質問を設定
messages = [
    {
        "role": "user",
        "content": "ボストンと東京の今日の天気は何度（華氏）ですか？",
    }
]

# AIモデルに関数呼び出しを行わせる
response = completion(
    model="anthropic/claude-3-5-sonnet-20240620",
    messages=messages,
    tools=tools,
    tool_choice="auto",
)

```

```python
# レスポンスを表示
display_rich_function_call_response(response)
```

このコードでは、ユーザーの質問をAIモデルに送信し、モデルが適切な関数（この場合は`get_current_weather`）を呼び出すように指示しています。



## 結果の可視化

最後に、AIモデルからの応答を見やすく表示するための関数を定義します。この関数は、Rich libraryを使用して、応答の詳細を整形して表示します。

```python
def display_rich_function_call_response(response: Dict[str, Any]) -> None:
    # モデル情報を表示するためのツリーを作成
    model_info = Tree("Function Call Response")
    model_info.add(f"ID: [cyan]{response['id']}[/cyan]")
    model_info.add(f"Created: [cyan]{response['created']}[/cyan]")
    model_info.add(f"Model: [cyan]{response['model']}[/cyan]")
    model_info.add(f"Object: [cyan]{response['object']}[/cyan]")
    model_info.add(f"System Fingerprint: [cyan]{response['system_fingerprint']}[/cyan]")

    # 使用量情報を表示するためのテーブルを作成
    usage_table = Table(title="Usage", show_header=True, header_style="bold magenta")
    usage_table.add_column("Metric", style="dim")
    usage_table.add_column("Value", justify="right")
    usage = response['usage']
    usage_table.add_row("Prompt Tokens", str(usage['prompt_tokens']))
    usage_table.add_row("Completion Tokens", str(usage['completion_tokens']))
    usage_table.add_row("Total Tokens", str(usage['total_tokens']))

    # 選択肢（Choices）情報を表示するためのツリーを作成
    choices_tree = Tree("Choices")
    for idx, choice in enumerate(response['choices']):
        choice_tree = choices_tree.add(f"Choice {idx}")
        choice_tree.add(f"Finish Reason: [green]{choice['finish_reason']}[/green]")
        choice_tree.add(f"Index: [green]{choice['index']}[/green]")

        message = choice['message']
        message_tree = choice_tree.add("Message")
        message_tree.add(f"Role: [blue]{message['role']}[/blue]")
        content_syntax = Syntax(message['content'], "markdown", theme="monokai", line_numbers=True)
        message_tree.add(Panel(content_syntax, title="Content", border_style="blue"))

        if message['tool_calls']:
            tool_calls_tree = choice_tree.add("Tool Calls")
            for tool_call in message['tool_calls']:
                tool_call_tree = tool_calls_tree.add(f"Tool Call {tool_call['index']}")
                tool_call_tree.add(f"ID: [yellow]{tool_call['id']}[/yellow]")
                tool_call_tree.add(f"Type: [yellow]{tool_call['type']}[/yellow]")
                function_tree = tool_call_tree.add("Function")
                function_tree.add(f"Name: [red]{tool_call['function']['name']}[/red]")
                args_syntax = Syntax(tool_call['function']['arguments'], "json", theme="monokai")
                function_tree.add(Panel(args_syntax, title="Arguments", border_style="red"))

    # 作成したツリーとテーブルを表示
    console.print(Panel(model_info, title="Function Call Response", border_style="bold"))
    console.print(usage_table)
    console.print(Panel(choices_tree, title="Choices", border_style="bold"))
```

この関数は、AIモデルからの応答を構造化し、色分けして表示します。これにより、応答の内容を視覚的に理解しやすくなります。

## まとめ

以上で、LiteLLMを使用してAnthropicのパラレル関数呼び出し機能を試す方法を紹介しました。この方法を使うことで、AIモデルにより詳細な情報を提供し、より正確な回答を得ることができます。

実際のアプリケーションでは、外部APIとの連携や、より複雑な関数の定義など、さまざまな拡張が可能です。AIモデルの能力を最大限に活用するために、この機能を活用してみてください。

ぜひ、このコードを実行して、AIモデルがどのように外部関数を呼び出し、その結果を使って回答を生成するかを体験してみてください。AIの可能性は無限大です！

## 📒ノートブック

https://colab.research.google.com/drive/1X8zjE18rqeoV_ml3_bv1-jLG9JlyVsp-?usp=sharing

## 参考サイト

https://litellm.vercel.app/docs/providers/anthropic#parallel-function-calling