OpenAIのAPIのfunction_callを試してみる
Google Colabでやる。
言語はPython。
下準備
APIキーを受け取って、必要なライブラリをインストールする。
from getpass import getpass
secret = getpass('Enter the secret value: ')
!pip install openai
import openai
openai.api_key = secret
function定義付きでAPIを呼び出す
今日の運勢を占うメソッドを定義する。
def completion(prompt):
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=[{"role": "user", "content": prompt}],
functions=[
{
"name": "birthday_horoscope",
"description": "誕生日で今日の運勢を占えるよ",
"parameters": {
"type": "object",
"properties": {
"year": {
"type": "integer",
"description": "年",
},
"month": {
"type": "integer",
"description": "月(1はじまり)",
},
"day": {
"type": "integer",
"description": "日",
},
},
"required": ["year","month","day"],
},
}
],
function_call="auto",
)
return response["choices"][0]["message"]
functions=[
{
"name": "birthday_horoscope",
"description": "誕生日で今日の運勢を占えるよ",
"parameters": {
"type": "object",
"properties": {
"year": {
"type": "integer",
"description": "年",
},
"month": {
"type": "integer",
"description": "月(1はじまり)",
},
"day": {
"type": "integer",
"description": "日",
},
},
"required": ["year","month","day"],
},
}
],
ここがメソッド定義。OpenAPI(≠OpenAI)のAPI定義に準ずる。
nameでメソッド名、descriptionで説明を与える。
そしてpropertiesで引数を説明する。
説明は自然言語で良い。
いったん実行してみる
print(completion("サンフランシスコ講和条約を結んだ日本の総理大臣の運勢を教えて"))
結果
{
"role": "assistant",
"content": null,
"function_call": {
"name": "birthday_horoscope",
"arguments": "{\n \"year\": 1951,\n \"month\": 9,\n \"day\": 8\n}"
}
}
function_callに定義通りのJSONがしっかり入っている。
吉田茂の誕生日を引数に設定してほしかったが、これは誕生日ではなくサンフランシスコ講和条約締結日な気がする。吉田茂が戦後生まれなわけがない。
ちなみにメソッドを呼び出す必要がないプロンプトを与えると、function_callには何も入らず普通にcontentに答えが返ってくる。
print(completion("Nintendo64がPlayStationに負けた理由を英語で教えて"))
{
"role": "assistant",
"content": "There were several reasons why the Nintendo 64 lost to the PlayStation:\n\n1. CD-ROM Format: The PlayStation used CDs as its storage medium, while the N64 used cartridges. CDs had larger storage capacity and were cheaper to produce, allowing for more complex and longer games on the PlayStation.\n\n2. Third-Party Support: Many game developers chose to support the PlayStation platform due to its CD format and larger market share. This led to a wider library of games available on the PlayStation, while the N64 had a more limited selection.\n\n3. Cost: The N64 was more expensive to produce than the PlayStation. The higher price point made it less accessible to a wider audience, especially when compared to the more affordable PlayStation.\n\n4. Marketing: Sony's aggressive marketing strategy helped establish the PlayStation brand as a household name. They targeted a broader demographic, including older gamers and non-traditional gaming audiences, which helped to expand the PlayStation's market share.\n\n5. Game Titles: The PlayStation had several highly acclaimed and popular game titles, such as \"Final Fantasy VII\" and \"Metal Gear Solid,\" which attracted a large number of players. While the N64 had its own iconic titles like \"Super Mario 64\" and \"The Legend of Zelda: Ocarina of Time,\" it couldn't match the breadth and diversity of the PlayStation's game library.\n\nOverall, the combination of factors such as the CD-ROM format, third-party support, cost, marketing, and game titles contributed to the Nintendo 64's loss to the PlayStation."
}
占いを返す
import json
def uranai(message):
if message["function_call"]["name"] == "birthday_horoscope":
arguments = json.loads(message["function_call"]["arguments"])
year = arguments["year"]
month = arguments["month"]
day = arguments["day"]
num = (year + month + day) % 3
if num == 0 :
return "大吉"
if num == 1:
return "吉"
if num == 2:
return "凶"
結果
message = completion("サンフランシスコ講和条約を結んだ日本の総理大臣の運勢を教えて")
if message.get("function_call"):
print(uranai(message))
if message.get("function_call"):
print(message["content"])
大吉
うん大吉。
占いの結果を踏まえて更にプロンプトを投げる
占いの結果を踏まえてプロンプトを投げてみる。
最後の結果は自然言語で返してほしいので、function関連のパラメータは渡さない。
def completion2(prompt):
message = completion(prompt)
if message.get("function_call"):
kekka = uranai(message)
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=[
{"role": "user", "content": prompt},
message,
{"role": "function", "name":"birthday_horoscope", "content": kekka},
],
)
return response["choices"][0]["message"]["content"]
messages=[
{"role": "user", "content": prompt},
message,
{"role": "function", "name":"birthday_horoscope", "content": kekka},
],
ここがミソ。
{"role": "user", "content": prompt},
には最初のプロンプトが入る。
messageにはAPIからの結果(functionを呼び出すためのJSON)が入っているのだが、これはそのままメッセージ履歴として使える。
{
"role": "assistant",
"content": null,
"function_call": {
"name": "birthday_horoscope",
"arguments": "{\n \"year\": 1951,\n \"month\": 9,\n \"day\": 8\n}"
}
}
最後にこれ。プロンプトの結果を格納する。新たにfunctionというroleが登場する。
{"role": "function", "name":"birthday_horoscope", "content": kekka},
結果
print(completion2("サンフランシスコ講和条約を結んだ日本の総理大臣の運勢をハイテンションで教えて❤❤❤"))
サンフランシスコ講和条約を結んだ日本の総理大臣は、運勢が大吉となります!ハイテンションで、素晴らしい未来が待っています❤❤❤成功への道が開け、幸運な出来事や好機が訪れるでしょう。周囲の人々からも信頼と尊敬を集め、絶大な支持を得ることができます。また、リーダーシップと決断力を発揮することで、大きな成果を上げることができますよ。自信を持って前に進み、困難を乗り越えることができるでしょう。さらに、幸福な家庭生活や健康な身体も享受できるはずです。この期間は、大きな目標を追い求め、夢を実現するチャンスとなりますので、積極的に行動してください!
吉田茂の人生はバラ色だ。