無料Gemini と LiteLLM で Tool Calling を使いこなそう！～初心者向け徹底解説～

## はじめに

### Gemini とは？

Google AI Studio が提供する、最先端の大規模言語モデル (LLM) です。高度な言語処理能力を持ち、人間のような自然な文章生成、翻訳、要約など、様々なタスクをこなします。Gemini-Pro はその中でも特に高性能なモデルです。

### LiteLLM とは？

複数の LLM を簡単に利用できる Python ライブラリです。LiteLLM を使うことで、Gemini を含む様々な LLM を統一的なインターフェースで呼び出すことができます。

### Tool Calling とは？

LLM に外部ツールを使わせる技術です。LLM 単体ではできない計算やデータ取得などを、外部ツールに依頼することで、LLM の可能性を大きく広げます。

## 準備

###  必要なライブラリのインストール

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

```python
!pip install litellm google-generativeai loguru
```

- **litellm**: 様々な LLM を利用するためのライブラリです。
- **google-generativeai**: Google AI Platform の API を利用するためのライブラリです。
- **loguru**: ログ出力を見やすくしてくれるライブラリです。

### API キーの取得

Google AI Studio から API キーを取得します。API キーは、Google AI Platform のサービスを利用する際に必要となる、あなた専用の鍵のようなものです。

1. [Google AI Studio](https://aistudio.google.com/) にアクセスします。
2. 画面の指示に従って、API キーを作成します。
3. 作成した API キーは、後ほどプログラム内で使用しますので、安全な場所に保管しておいてください。

##  Gemini-Pro を使ってみよう！

### コード例

以下のコードは、LiteLLM を使って Gemini-Pro を呼び出し、「LiteLLM からこんにちは」と表示するプログラムです。

```python
from litellm import completion
import os

# 取得した API キーを設定します
os.environ['GEMINI_API_KEY'] = "YOUR_API_KEY"

# Gemini-Pro を呼び出して、メッセージを生成します
response = completion(
    model="gemini/gemini-pro", 
    messages=[{"role": "user", "content": "write code for saying hi from LiteLLM"}]
)

# 結果を出力します
print(response)
```

### コード解説

1.  **ライブラリのインポート**:  `litellm` と `os` ライブラリをインポートします。
2. **API キーの設定**:  取得した API キーを環境変数 `GEMINI_API_KEY` に設定します。
3. **Gemini-Pro の呼び出し**:  `completion` 関数を使って Gemini-Pro を呼び出します。
    - `model`: 利用するモデルを指定します。ここでは `gemini/gemini-pro` を指定しています。
    - `messages`:  LLM に送信するメッセージを指定します。ここでは、ユーザーの役割で「LiteLLM からこんにちはと表示するコードを書いて」という内容を送信しています。
4.  **結果の出力**: 生成されたメッセージを `print` 関数で出力します。

##  Tool Calling を使ってみよう！

### Tool Calling の仕組み

Tool Calling は、LLM に外部ツールを使わせることで、LLM 単体ではできない処理を実現する技術です。

例えば、「今日の東京の天気は？」という質問に対して、LLM 単体では最新の情報にアクセスできません。そこで、天気予報 API という外部ツールを呼び出すことで、最新の天気情報を取得し、「今日の東京の天気は晴れです」のように、適切な回答を生成することができます。

### コード例

以下のコードは、Tool Calling を使って、ボストン市の現在の天気を取得するプログラムです。

```python
# Tool Calling
from litellm import completion
from google.colab import userdata
import os
from loguru import logger
import json
from typing import Any, Dict

# モデルの応答をログ出力する関数
def log_model_response(response: Dict[str, Any]) -> None:
    logger.info("ModelResponse:")
    logger.info(f"ID: {response['id']}")
    logger.info(f"Created: {response['created']}")
    logger.info(f"Model: {response['model']}")
    logger.info(f"Object: {response['object']}")
    logger.info(f"System Fingerprint: {response['system_fingerprint']}")

    logger.info("Usage:")
    usage = response['usage']
    logger.info(f"  Prompt Tokens: {usage['prompt_tokens']}")
    logger.info(f"  Completion Tokens: {usage['completion_tokens']}")
    logger.info(f"  Total Tokens: {usage['total_tokens']}")

    logger.info("Choices:")
    for idx, choice in enumerate(response['choices']):
        logger.info(f"  Choice {idx}:")
        logger.info(f"    Finish Reason: {choice['finish_reason']}")
        logger.info(f"    Index: {choice['index']}")

        message = choice['message']
        logger.info(f"    Message:")
        logger.info(f"      Content: {message['content']}")
        logger.info(f"      Role: {message['role']}")

        if message['tool_calls']:
            logger.info(f"    Tool Calls:")
            for tool_call in message['tool_calls']:
                logger.info(f"      Index: {tool_call['index']}")
                logger.info(f"      ID: {tool_call['id']}")
                logger.info(f"      Type: {tool_call['type']}")
                logger.info(f"      Function:")
                logger.info(f"        Name: {tool_call['function']['name']}")
                logger.info(f"        Arguments: {tool_call['function']['arguments']}")

# API キーの設定
os.environ["GEMINI_API_KEY"] = userdata.get('GEMINI_API_KEY')

# 利用するツールの定義
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather", # ツール名
            "description": "Get the current weather in a given location", # 説明
            "parameters": { # パラメータ
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city and state, e.g. San Francisco, CA",
                    },
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                },
                "required": ["location"],
            },
        },
    }
]

# LLMへの質問
messages = [{"role": "user", "content": "What's the weather like in Boston today?"}]

# Gemini-Pro を呼び出して、メッセージを生成します
response = completion(
    model="gemini/gemini-1.5-flash",
    messages=messages,
    tools=tools,
)

# 結果を出力します
print(response)
log_model_response(response)
```

### コード解説

1. **ツールの定義**: `tools` 変数に、利用するツールを定義します。
   - `type`: ツールの種類を指定します。ここでは `function` を指定しています。
   - `function`: ツールの詳細情報を指定します。
     - `name`: ツール名を指定します。ここでは `get_current_weather` としています。
     - `description`: ツールの説明を記述します。
     - `parameters`: ツールが受け取るパラメータを定義します。
       - `type`: パラメータのデータ型を指定します。
       - `properties`: 各パラメータの詳細情報を定義します。
         - `location`: 都市と州を指定します。
         - `unit`: 温度の単位を指定します。
       - `required`: 必須パラメータを指定します。

2. **LLMへの質問**:  `messages` 変数に、ユーザーの質問を設定します。ここでは、「ボストン市の今日の天気は？」と聞いています。

3. **Gemini-Proの呼び出し**:  `completion` 関数を使って Gemini-Pro を呼び出します。
   - `model`: 利用するモデルを指定します。ここでは `gemini/gemini-1.5-flash` を指定しています。
   - `messages`:  LLM に送信するメッセージを指定します。ここでは、ユーザーの役割で「ボストン市の今日の天気は？」という質問を送信しています。
   - `tools`: 利用するツールを指定します。

4. **結果の出力**:  生成されたメッセージを `print` 関数で出力します。`log_model_response` 関数は、モデルの応答の詳細をログ出力します。


## より複雑な Tool Calling を使ってみよう！

### 掃除ロボットを操作する例

以下のコードは、Tool Calling を使って、ルンバのような掃除ロボットを操作する例です。

```python
tools = [
    {
        "type": "function",
        "function": {
            "name": "start_cleaning",
            "description": "Start cleaning in a specified room",
            "parameters": {
                "type": "object",
                "properties": {
                    "room": {
                        "type": "string",
                        "description": "The room to clean, e.g. living room, kitchen",
                    },
                },
                "required": ["room"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "stop_cleaning",
            "description": "Stop the Roomba's current cleaning operation",
            "parameters": {
                "type": "object",
                "properties": {
                    "confirm": {
                        "type": "boolean",
                        "description": "Confirm to stop cleaning",
                    },
                },
                "required": ["confirm"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "set_cleaning_mode",
            "description": "Set the Roomba's cleaning mode",
            "parameters": {
                "type": "object",
                "properties": {
                    "mode": {
                        "type": "string",
                        "enum": ["auto", "spot", "edge"],
                        "description": "The cleaning mode to set",
                    },
                },
                "required": ["mode"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "schedule_cleaning",
            "description": "Schedule a cleaning operation",
            "parameters": {
                "type": "object",
                "properties": {
                    "time": {
                        "type": "string",
                        "description": "The time to start cleaning, in HH:MM format",
                    },
                    "days": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "enum": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
                        },
                        "description": "The days of the week to schedule cleaning",
                    },
                },
                "required": ["time", "days"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_battery_level",
            "description": "Get the current battery level of the Roomba",
            "parameters": {
                "type": "object",
                "properties": {
                    "format": {
                        "type": "string",
                        "enum": ["percentage", "raw"],
                        "description": "The format of the battery level",
                    },
                },
                "required": ["format"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "control_wheels",
            "description": "Control the Roomba's wheel movements",
            "parameters": {
                "type": "object",
                "properties": {
                    "direction": {
                        "type": "string",
                        "enum": ["forward", "backward", "left", "right"],
                        "description": "The direction to move the Roomba",
                    },
                    "duration": {
                        "type": "number",
                        "description": "The duration of the movement in seconds",
                    },
                },
                "required": ["direction", "duration"],
            },
        },
    },
]

messages = [{"role": "user", "content": "ルンバをリビングで掃除させて、その後キッチンに移動させてください。"}]

# LLMへの指示
messages = [{"role": "user", "content": "ルンバをリビングで掃除させて、その後キッチンに移動させてください。"}]

response = completion(
    model="gemini/gemini-1.5-flash",
    messages=messages,
    tools=tools,
)

# 結果を出力します
print(response)
log_model_response(response)
```

### コード解説

このコードでは、掃除ロボットを操作するための複数のツールを定義しています。

-  `start_cleaning`: 指定された部屋の掃除を開始します。
-  `stop_cleaning`: 掃除を停止します。
-  `set_cleaning_mode`: 掃除モードを設定します。
-  `schedule_cleaning`: 掃除のスケジュールを設定します。
-  `get_battery_level`: バッテリー残量を取得します。
-  `control_wheels`: 車輪を制御します。

これらのツールを組み合わせることで、LLM はユーザーの複雑な指示を理解し、掃除ロボットを思い通りに操作することができます。

## まとめ

この記事では、LiteLLM を使った Gemini の基本的な使い方と、Tool Calling の活用方法について解説しました。Tool Calling を使うことで、LLM の可能性は大きく広がります。ぜひ、あなたのアイデアを活かして、LLM を使った新しいアプリケーション開発に挑戦してみてください！

## 📒ノートブック

https://colab.research.google.com/drive/1yrKJb1SG5kcSszGWiGukzzdX-BHv2XDY?usp=sharing