Vertex AIのFunction Callingを再帰呼び出しして算数の問題を解かせてみた。

こんにちは。SCSKの島村です。

Vertex AI(Gemini API)にて利用できる『関数呼び出し機能(Function Calling API )』についてご存知でしょうか??
関数呼び出しを利用することで、LLMから関連性の高いコンテキストに沿った回答を提供することが可能となります。

本記事では、
Function Calling API』について色々と調査し、実際に触ってみましたので、その魅力について少しだけご紹介させていただければと思います。

Function Calling APIとは??

『Function Calling』とは、
 LLMが質問の内容や文脈から必要な関数(外部の関数やAPI)を判断し呼び出すことで、回答の幅をさらに広げる機能
です。

従来のLLMは、与えられたプロンプトに対して、既に学習しているデータに基づき回答を生成することが主な役割でした。
しかし、Function Callingによって、LLMは単なるテキスト生成にとどまらず、以下のようなことができるようになります。

  • 外部データの取得: 天気予報、株価、ニュース記事など、リアルタイムの情報を取得
  • 計算: 複雑な計算やデータの分析を実行
  • 外部サービスとの連携: 翻訳サービス、画像生成サービスなど、様々な外部サービスと連携してより高度なタスクを実行

Fanction Calling(関数呼び出し)を使用することで、生成 AI モデルに提供するための情報を外部もから取得可能となります。

関数呼び出しのインタラクション

Function Call(関数呼び出し)とモデル返答までのフロー:Google Cloudドキュメントより

詳細については、以下、Google Cloud公式ドキュメントからご確認ください。
関数呼び出し  |  Vertex AI の生成 AI  |  Google Cloud

利用ステップ

Verte AI Geminiにて『Fanction Calling』を利用する手順は以下となります。

  1. モデルを初期化する
  2. ユーザー プロンプトを定義する
  3. 関数宣言を使用して、使用可能な一連の関数を定義、記述する
  4. ユーザーのプロンプトと関数宣言をモデルに送信する
  5. モデルから出力された構造化データを使用して、関数を呼び出す
  6. 関数の出力をモデルに提供する
 

Function Callingを実際に試してみた。

今回は「Function Calling API」を利用して、あらかじめ用意した簡単な関数を呼び出すことを試してみます。
実際の出力結果の一部を先にお見せします。

簡単な算数の問題をLLMに解かせてみました。

外部の関数を参考にして、LLMは回答を生成していることが分かります。
今回は簡単な算数の問題を例に試してみましたが、LLMに複雑な計算を実行してもらう場合、ハルシネーションの抑制にもつながる機能だと感じました。

Fanction Callingを実装してみる(コード例)

今回はコードについても少しだけ解説してみます。

1. 必要なモジュールのインポート

import requests
from vertexai.generative_models import (
    Content,
    FunctionDeclaration,
    GenerationConfig,
    GenerativeModel,
    Part,
    Tool,
)

2. プロジェクトの設定と言語モデル(Vertex AI)を使うための準備

import vertexai
PROJECT_ID = ! gcloud config get-value project
PROJECT_ID = PROJECT_ID[0]
LOCATION = "us-central1" # @param {type:"string"}
vertexai.init(project=PROJECT_ID, location=LOCATION)

3. LLMから呼び出す関数を定義(今回は簡単に「加算」「乗算」を実施する関数を作成します。)

def add_fun(x,y):
    print("---加算関数を呼び出しました.---")
    return int(x)+int(y)  def multiply_func(x,y):
    print("---乗算関数を呼び出しました.---")
    return int(x)*int(y)

4. LLMから呼び出すための関数宣言
・入力から判断するための「説明」と「取得する変数」を定義します。
詳細はリンクをご確認ください。:関数宣言の例

add_function = FunctionDeclaration(
    name="add",
    description="質問から計算方法を判別し、加算を算出します。",
    parameters={
        "type": "object",
        "properties": {
            "x": {"type": "string", "description": "x."},
            "y": {"type": "string", "description": "y."},
        },
    },
)

multiply_function = FunctionDeclaration(
    name="multiply",
    description="質問から計算方法を判別し、乗算を算出します。",
    parameters={
        "type": "object",
        "properties": {
            "x": {"type": "string", "description": "x."},
            "y": {"type": "string", "description": "y."},
        },
    },
)

5. Geminiモデル側の設定

tool = Tool(
    function_declarations=[
        add_function,
        multiply_function,
    ],
)

model = GenerativeModel(
    model_name="gemini-1.5-pro-001",
    generation_config=GenerationConfig(temperature=0),
    system_instruction=[
        """
        計算に関する質問の場合、自分で計算を行わないでください。
        その他の質問の場合、ユーザーの質問に正しく答えてください。
        """,
    ],
    tools=[tool],
)

6. おまけ)定義した2つの関数を直列に利用したい場合を想定して、レスポンスを再帰的に呼び出すための設定

def handle_response(response):
    if response.candidates[0].function_calls:
        function_call = response.candidates[0].function_calls[0]
    else:
        print(response.text)
        return
    if function_call.name == "add":
        x_args = function_call.args.get('x')
        y_args = function_call.args.get('y')
        z_add = add_fun(x_args,y_args)  # Assuming a single string argument
        response = chat.send_message(
            Part.from_function_response(
                name=function_call.name,
                response={
                    "content": z_add,
                },
            ),
        )
        return handle_response(response)
    elif function_call.name == "multiply":
        x_args = function_call.args.get('x')
        y_args = function_call.args.get('y')
        # Call your function
        z_add = multiply_func(x_args,y_args)
        response = chat.send_message(
            Part.from_function_response(
                name=function_call.name,
                response={
                    "content": z_add,
                },
            ),
        )
        return handle_response(response)
    else:
        print(function_call)
7. チャットモデルの開始
chat = model.start_chat()

以上で作成は完了です。

作成したモデルを利用して、実際にいくつか試してみます。↓↓↓

質問の内容を理解し、計算(「乗算」「加算」)が必要な場合には適切に外部関数を呼び出していることが確認できます。

また、Fanction Callされた際のレスポンスを覗いてみると、、、、
利用した関数名( function_call { name: “multiply” } ・・・)が記載されていることが分かります。

 

最後に

今回は『Function Calling API』について実際のデモともにご紹介させていただきました。
簡単な計算問題を外部関数として定義し、LLMから呼び出して回答を補足する。 そんなデモを実感頂けたと思います。

外部データに対してAPIを経由してアクセスすることもでき、LLMの回答も大きく広がるそんな機能ではないでしょうか。
色んな関数を定義し、LLMのからの回答の幅を広げていくことができる『Function Calling API』のご紹介でした。

今後とも、AIMLに関する情報やGoogle CloudのAIMLサービスのアップデート情報を掲載していきたいと思います。
最後まで読んでいただき、ありがとうございました!!!

著者について

SCSK株式会社のクラウド専門部隊に所属
Google Cloudの
・AI MLサービス選定/導入コンサルティング/導入サポート/AI 基盤・運用構築 まで多く案件を担当
Google Cloud Partner Top Engineer 2024 受賞 カテゴリ:Cloud AI/ML
Google Cloud Next Tokyo 出展
Google Cloud Day ’23 Tour 登壇
「AI は選んで組み込んで実装!最新 AI を道具として有効利用するためには!?」
■好きな Google Cloud サービス:Vertex AI / Dialogflow CX / Visual Inspection AI / Cloud Run

島村裕哉をフォローする

クラウドに強いによるエンジニアブログです。

SCSKクラウドサービス(Google Cloud)は、Google Cloudの多彩なAIや各種サービスを活用したワンストップソリューションを提供します。SCSKのノウハウや体制を有効活用し、業務課題の解決に必要な全体検討と組み合わせで、最適な業務実装まで支援します。

AI・MLGoogle Cloudクラウドソリューション
シェアする
タイトルとURLをコピーしました