5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Function callingで検索エンジンを切り替えてみる

Posted at

表題の通り、Function callingでYahoo検索とYoutube検索を切り替えて遊んでみました。

Jupyter Notebook on Visual Studio Codeで実験した内容なので見辛い点などは何卒ご了承くださいませ...🙇‍♂️

さっそくやってみよう

必要なモジュールをインストール

python
#%%
pip install openai
pip install google-search-results

WEB検索するAPIはこちらを使います。
無料利用枠もあるので登録してAPIキーを取得しておきます。

python
#%%
import json
import os
import sys
import openai
from typing import Dict
from serpapi import GoogleSearch

openai.api_key="********" #Openaiのkey
search_api_key="********" #serpapiのKey

yahoo検索用の関数を作成しておきます。
必要そうなプロパティの上位3つだけ適当に格納しておきます。

python
#%%
def yahoo_search(query: str) -> Dict[str, str]:  
  search = GoogleSearch({
    "engine": "yahoo",
    "p": query, 
    "api_key": search_api_key
  })
  result = search.get_dict()
  top3_result = result["organic_results"][:3]

  res = {
    "snippet":"",
    "link":""
    }

  for i in top3_result:
    res["snippet"] += i["snippet"] + ","
    res["link"] += i["link"] + " "

  return res

次にyoutube検索用の関数です。

python
#%%
def youtube_search(query: str) -> Dict[str, str]:
  
  search = GoogleSearch({
    "engine": "youtube",
    "search_query": query, 
    "api_key": search_api_key
  })
  result = search.get_dict()
  top3_result = result["video_results"][:3]

  res = {
    "title":"",
    "link":""
    }

  for i in top3_result:
    res["title"] += i["title"] + ","
    res["link"] += i["link"] + " "

  return res

関数の準備ができたので、AIにどの関数が使えるのかを教えます。

python
#%%
# AIが、質問に対してどの関数を使うかどうかの判断基準、
# また使う時の引数は何にするかを判断するための情報を与える。
functions = [
    {
        "name": "yahoo_search",
        # 通常では答えられないような情報が必要な場合は、ウェブで情報を検索してください。
        # ユーザーの質問に「ウェブ検索」などの言葉が含まれている場合は、必ずこの機能を使用してください。
        "description": "If you need information that cannot normally be answered, search the web for information. If a user's question includes words such as 「search the web.」 be sure to use this function.",
        "parameters": {
            "type": "object",
            "properties": {
                # 引数の情報
                "query": {
                    "type": "string",
                    "description": "Search information from users. Split by the word to be searched.",
                },
            },
            "required": ["query"],
        },
    },
    {
        "name": "youtube_search",
        # 動画に関する情報が必要な場合は、youtube_searchで検索してください。
        # ユーザーの質問に「youtube検索」や「youtubeで検索」という言葉が含まれている場合は、
        # 必ずこの機能を使ってください。
        "description": "If you need information on a video, please use youtube_search to search for information. If the user's question includes the words 「youtube search」 or 「search on youtube」, be sure to use this function.",
        "parameters": {
            "type": "object",
            "properties": {
                # 引数の情報
                "query": {
                    "type": "string",
                    "description": "Search information from users. Split by the word to be searched.",
                },
            },
            "required": ["query"],
        },
    }
]

さて、ここまでで役者(?)は揃いました!!
質問はこちらにします。

python
#%%
query = "推しの子ってどんなアニメ?関連する動画を教えて"

関連動画をおしえてほしいと懇願します🙏

python
#%%
# AIが質問に対して使う関数と、その時に必要な引数を決める
# 特に関数を使う必要がなければfunction_callプロパティは返されない
response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-0613",
    messages=[
        {"role": "user", "content": query},
    ],
    functions=functions,
    function_call="auto",
)

こんな感じで返ってきます。

json
{
  "id": "chatcmpl-7UsLEEaXynP2MSC4Sn6cv835nZUYK",
  "object": "chat.completion",
  "created": 1687593084,
  "model": "gpt-3.5-turbo-0613",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": null,
        "function_call": {
          "name": "youtube_search",
          "arguments": {"query": "推しの子 アニメ"}
        }
      },
      "finish_reason": "function_call"
    }
  ],
  "usage": {
    "prompt_tokens": 186,
    "completion_tokens": 20,
    "total_tokens": 206
  }
}

どの関数が選ばれたかをチェックします。
もしどの関数も選ばれなければ通常実行させときます。

python
#%%
# 選ばれた関数名をチェック
function_call = message.get("function_call")
function_name = ""

if function_call:
  function_name = message["function_call"]["name"]
  print(function_name)
# 何も選ばれてなければ通常実行
else:
  print("function_call is None")
  response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-0613",
    messages=[
        {"role": "user", "content": query},
    ],
    )
  print(response.choices[0]["message"]["content"].strip())

選ばれた関数名は…

youtube_search

引数はどうなっているかというと…

python
#%%
arguments = json.loads(message["function_call"]["arguments"])
print(arguments)
{'query': '推しの子 アニメ'}

ちゃんと単語で分割してくれてる。偉い!
それでは、選ばれた関数を実行しましょう。

python
#%%
# 関数の実行
if function_name == "youtube_search":
  function_response = youtube_search(
      query=arguments.get("query"),
  )
  func_content = function_response["title"] + ' You can read more at: ' + function_response["link"]

elif function_name == "yahoo_search":
  function_response = yahoo_search(
    query=arguments.get("query"),
  )
  func_content = function_response["snippet"] + ' You can read more at: ' + function_response["link"]

func_contentの中身はこんな状態です。

TVアニメ『【推しの子】』本予告【2023年4月より放送開始】,YOASOBI「アイドル」 Official Music Video,MAD ライブ音響【推しの子】B小町「サインはB」4K60fps高画質, You can read more at: https://www.youtube.com/watch?v=BQ28u-8c-hI https://www.youtube.com/watch?v=ZRtdQ81jPUQ https://www.youtube.com/watch?v=WI8NiVbVF1Q

最後に、関数の実行結果を渡してもう一度質問してみましょう。

python
#%%
# 関数実行結果を使ってもう一度質問
second_response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-0613",
    messages=[
        {"role": "user", "content": query},
        {"role": "assistant", "content": f"You respond with the information {func_content} given. If the information has a url, you will also provide the url as the source of the information."},
        message,
        {
            "role": "function",
            "name": function_name,
            "content": func_content,
        },
    ],
)

print(second_response.choices[0]["message"]["content"].strip())
『推しの子』は、2023年4月に放送が開始されるテレビアニメです。具体的な内容やストーリーについては、本予告をご覧ください。

本予告:TVアニメ『【推しの子】』本予告【2023年4月より放送開始】
URL:https://www.youtube.com/watch?v=BQ28u-8c-hI

また、アニメの中で使用される主題歌「アイドル」はYOASOBIによって歌われています。公式のミュージックビデオも公開されています。

YOASOBI「アイドル」 Official Music Video
URL:https://www.youtube.com/watch?v=ZRtdQ81jPUQ

さらに、推しの子関連のエピソード1から8までのアニメ動画も視聴することができます。

推しの子 アニメ 1-8話
URL:https://www.youtube.com/watch?v=ZIWy3FVkTwM

詳細情報は上記のURLからご確認ください。

なるほど!
ここまで動かしてみて、なんとなく流れがわかりました!
Function callingとはLLMにどの関数を実行させるか判断させ、かつ引数の加工をおこなってくれる感じなんですねえ。偉い。

ちなみに、以下のように尋ねると、
通常通りの実行となり、思ってたんとちがーう!という答えが返ってきました👀

python
query = "推しの子ってどんなアニメ?"
「推しの子」は、ユーザーがアイドル育成ゲームをプレイしながら応援しているキャラクターを指すことが一般的です。
これに関連して、2020年には「推しが武道館いってくれたら死ぬ」(通称:推し武道)というテレビドラマも放送されました。
ただし、アニメとしては「推しの子」という具体的な作品は存在しないようです。
もし推しの子が登場するアニメを探しているのであれば、具体的なキャラクター名や作品名などを教えていただければ、情報を提供できるかもしれません。

そこで、「ウェブで検索して答えて」と付け足す事で、Yahoo検索を選択してくれるようになりました。

python
query = "推しの子ってどんなアニメ?ウェブで検索して答えて"
「推しの子」は、2023年4月から放送が開始されたTVアニメです。Blu-ray&DVDも発売されており、関連イベントや劇場上映も行われています。

ストーリーは、赤坂アカ氏と横槍メンゴ氏による人気漫画作品です。詳細な情報については、以下のウェブサイトで確認することができます。

- 公式ウェブサイト: https://ichigoproduction.com/
- YouTubeチャンネル: https://www.youtube.com/@anime_oshinoko
- Abema TIMES: https://times.abema.tv/articles/-/10056142

以上が「推しの子」に関する情報です。

おおお、これは、なんだか楽しいぞ😆
あらゆるものに応用できそうなので、今後も色々試してみます!

参考にさせて頂いた記事

https://platform.openai.com/docs/guides/gpt/function-calling
https://dev.classmethod.jp/articles/understand-openai-function-calling/

5
5
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
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?