LoginSignup
3
4

GPTのFunction callingを使って周辺情報を取得してみた.

Posted at

初めに

2023年6月13日にGPT Function callingがリリースされました.
入力した文字列に応じて関数の呼び出しが可能にとの事ですが,いまいちよく分からなかったので,とりあえず実装してみました.

参考記事のほとんどが天気情報の関数呼び出しをしているため,今回は周辺情報を取得する関数を使ってみたいと思います.

実装

今回はPythonを使って開発していきます.
また,周辺情報の取得に関してはGoogleが提供しているPlacesAPIを使います.
PlacesAPIの使い方に関しては,メインではないので説明を省きます.

関数の定義

まずはFunction callingで呼び出す関数を作成する必要があります.

getPlace.py
def get_location(latitude, longitude, radius, keyword):

    base_url = 'https://maps.googleapis.com/maps/api/place/nearbysearch/json'
    api_key = '自分のAPIKey'

    parameters = {
      'location': f'{latitude},{longitude}',
      'radius': radius,
      'keyword': keyword,
      'language': 'ja',
      'key': api_key
    }

    response = requests.get(base_url, params=parameters)
    if response.status_code == 200:
        data = response.json()
        # 名前の情報を格納するリスト
        name_list = []
        # 出力結果から名前を取り出してリストに追加
        for result in data['results']:
            name = result['name']
            name_list.append(name)
        return json.dumps(name_list)
    else:
        return None

必須のパラメーターはlocation radius keyの3つです.

keywordには地名・住所・施設のカテゴリを入力することができます.これにより検索対象を絞ることができます.languageは返答分の言語を指定しています.

他のパラメータについて知りたい場合は以下のリンクからご覧ください.
PlaceAPIのパラメータ

出力結果のresult['name']には検索した施設の名称が含まれています.
この施設名称をChatGPTの入力値として使います.

注意
ChatGPTに入力する最大文字数は4096文字です.
そのため,入力値が多すぎる場合はエラーとなります.

Functionプロパティの定義

place_function =  {
    "name": "get_location",
      "description": "経度緯度の情報から周辺の場所を取得",
      "parameters": {
          "type": "object",
          "properties": {
              "latitude": {
                  "type": "string",
                  "description": "経度の情報",
              },
              "longitude": {
                  "type": "string",
                  "description": "緯度の情報",
              },
              "radius": {
                  "type": "string",
                  "description": "半径の情報",
              },
              "keyword": {
                  "type": "string",
                  "description": "キーワード",
              },
          },
          "required": ["latitude","longitude","radius","keyword"],
      },
}

name に先ほど作成した関数名を記述してください.
descriptionは任意の項目ですが,関数呼び出しの際に使っている可能性があるため,一応記述しておきます.
parametersには関数呼び出しに必要となるパラメータを記述します.
requiredには必須のパラメーターを記述します.

Functionプロパティを定義することで,ユーザーの入力内容から自動でパラメーターの値を生成してくれます.

OpenAI API

main.py
import openai
import json
import requests

# OpenAI APIキーの準
openai.api_key = "自分のAPIKey"

def main(text):
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-0613",
        messages=[{"role": "user", "content": text}],
        #Functionプロパティ
        functions=[place_function],
        function_call="auto",
    )
    message = response["choices"][0]["message"]
    if message.get("function_call"):
        function_name = message["function_call"]["name"]
        arguments=json.loads(message["function_call"]["arguments"])
        function_response = get_location(
            latitude=arguments.get("latitude"),
            longitude=arguments.get("longitude"),
            radius=arguments.get("radius"),
            keyword=arguments.get("keyword"),
        )
        second_response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo-0613",
            messages=[
                {"role": "user", "content": text},
                message,
                {
                    "role": "function",
                    "name": function_name,
                    "content": function_response,
                },
            ],
        )
        return second_response.choices[0]["message"]["content"].strip()
    #Function callingを使わない場合
    return response.choices[0]["message"]["content"].strip()

現在関数呼び出しに対応しているモデルはgpt-4-0613もしくはgpt-3.5-turbo-0613のみです.

処理の流れは以下の通りです.

  1. 入力内容から関数呼び出しが必要かどうか判断
  2. 必要だと判断した場合,関数のパラメーターを入力内容から生成
  3. 生成したパラメーターを使って関数を実行
  4. 実行結果をmessagesに含めて回答文を生成

実行結果

周辺情報を聞いた場合

入力内容:スカイツリーから100メートル以内でおすすめのレストランを5件教えて

以下の内容はmessageの内容で,function_callが実行され,パラメータが生成されているのがわかります

{
  "role": "assistant",
  "content": null,
  "function_call": {
    "name": "get_location",
    "arguments": "{\n  \"latitude\": \"35.710063\",\n  \"longitude\": \"139.8107\",\n  \"radius\": \"100\",\n  \"keyword\": \"\u30ec\u30b9\u30c8\u30e9\u30f3\",\n}"
  }
}

実行結果は以下の通りです.

1. Sky Restaurant 634
2. パラッツォ サン グスト
3. おぼんdeごはん 東京スカイツリータウン・ソラマチ店
4. スペイン料理&ワイン パエリア東京スカイツリータウン・ソラマチ
5. 炭焼きLamp

どれも美味しい食事を楽しむことができるレストランです。ぜひ訪れてみてください!

日常会話を入力した場合

次は入力内容を日常会話にしてみます.
入力内容:今日は暑いね

{
  "role": "assistant",
  "content": "\u306f\u3044\u3001\u672c\u5f53\u306b\u6691\u3044\u3067\u3059\u306d\u3002\u5916\u306b\u51fa\u308b\u969b\u306f\u71b1\u4e2d\u75c7\u5bfe\u7b56\u3092\u3057\u3063\u304b\u308a\u3068\u884c\u3044\u307e\u3057\u3087\u3046\u3002\u6c34\u5206\u88dc\u7d66\u3084\u65e5\u5098\u306e\u4f7f\u7528\u306a\u3069\u3001\u6ce8\u610f\u304c\u5fc5\u8981\u3067\u3059\u3002"
}

function_callが実行されていません.
実行結果は以下の通りです.

はい、本当に暑いですね。外に出る際は熱中症対策をしっかりと行いましょう。水分補給や日傘の使用など、注意が必要です。

終わりに

関数呼び出しを行うことで,chatGPTの精度はかなり向上できると思われます.
しかし,APIで取得した結果もトークンとしてカウントされるため,トークン量の削減などが今後は必要になってくるでしょう.

また,現在の方法では1つの関数しか呼び出しできません.
実際にアプリなどに組み込む場合は,LangChainなどを利用して複数の関数呼び出しに対応させる必要があります.

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4