見出し画像

楽天レシピとfunction calling

取得したデータの構造がいまいちよくわかってないので おおざっぱな実装になったけど成功しました。

You : パスタが食べたいな
    recipeId recipeTitle ... categoryId categoryName
0 1770001825 牛乳で簡単♪明太子クリームパスタ ... 15 パスタ
1 1370003029 簡単♪納豆パスタ★バター醤油味 ... 15 パスタ
2 1140057627 今話題の!悪魔のパスタ ... 15 パスタ
3 1340012013 豚ひき肉と玉ねぎだけで簡単ボロネーゼ ... 15

パスタ [4 rows x 8 columns] 以下は、おすすめのパスタレシピです。
1. ペペロンチーノ
- 材料:
- スパゲッティ: 200g
- オリーブオイル: 50ml
- ニンニク: 2片(みじん切り)
- 唐辛子: 1本(みじん切り)
- 塩: 少々 - パルメザンチーズ: 好みで(お好みでかける)
- 手順:
1. スパゲッティを表示された時間通りに茹で、茹で汁を少し残しておく。
2. フライパンにオリーブオイルを熱し、ニンニクと唐辛子を炒める。
3. 茹で汁を加え、塩をふって調味する。
4. 茹でたスパゲッティを加え、よく絡める。
5. 器に盛り、パルメザンチーズをかけて完成。

2. カルボナーラ
- 材料:
- スパゲッティ: 200g
- ベーコン: 100g(細切り)
- 卵黄: 2個
- パルメザンチーズ: 50g(お好みでかける)
- 塩: 少々
- 黒こしょう: 少々
- 手順: 1. スパゲッティを表示された時間通りに茹で、茹で汁を少し残しておく。 2. フライパンでベーコンをカリカリに焼く。
3. 卵黄をボウルに入れ、パルメザンチーズを加えてよく混ぜる。
4. 茹で汁を少しだけ加え、さらに混ぜる。
5. 茹でたスパゲッティを加え、よく絡める。
6. 器に盛り、黒こしょうをふりかけて完成。
3. トマトソーススパゲッティ
- 材料:
- スパゲッティ: 200g
- トマト: 2個(皮をむいてみじん切り)
- 玉ねぎ: 1個(みじん切り)
- ニンニク: 2片(みじん切り)
- オリーブオイル: 50ml
- 塩: 少々 - こしょう: 少々
- バジル: 適量(お好みでかける)
- 手順:
1. スパゲッティを表示された時間通りに茹で、茹で汁を少し残しておく。
2. フライパンにオリーブオイルを熱し、ニンニクと玉ねぎを炒める。
3. トマトを加え、よく煮込む。
4. 茹でて茹で汁を加え、塩とこしょうで調味する。
5. 茹でたスパゲッティを加え、よく絡める。
6. 器に盛り、バジルをかけて完成。
これらのレシピを参考に、おいしいパスタを作ってください!

こんな感じの出力になりました。
レシピの詳細の方はchatgptが考えて出したレシピで取得した データから出力しているわけではなさそうです。

2023/06/20 追記 参考にしたテキスト
quiita https://qiita.com/konitech913/items/7ffa7907a6c03c8909fc コニタ ナオヤさん
Developers.IO 平野重利さん https://dev.classmethod.jp/articles/understand-openai-function-calling/

import json
import os
import requests
import time
import pandas as pd
from pprint import pprint
import openai

# APIキーの設定
openai_key = os.environ.get("OPENAI_API_KEY")

# 引数で質問を受ける
question = input("You : ")

# 関数の実装
def get_recipe(a_food):
    # 1. 楽天レシピのレシピカテゴリ一覧を取得する
    print("20秒ほどお待ちください。。。\n")
    res = requests.get(
        'https://app.rakuten.co.jp/services/api/Recipe/CategoryList/20170426?applicationId=1064593445227237376')
    json_data = json.loads(res.text)

    parent_dict = {}  # mediumカテゴリの親カテゴリの辞書
    df = pd.DataFrame(columns=['category1', 'category2', 'category3', 'categoryId', 'categoryName'])

    for category in json_data['result']['large']:
        df = df._append({'category1': category['categoryId'], 'category2': "", 'category3': "",
                         'categoryId': category['categoryId'], 'categoryName': category['categoryName']},
                        ignore_index=True)

    for category in json_data['result']['medium']:
        df = df._append(
            {'category1': category['parentCategoryId'], 'category2': category['categoryId'], 'category3': "",
             'categoryId': str(category['parentCategoryId']) + "-" + str(category['categoryId']),
             'categoryName': category['categoryName']}, ignore_index=True)
        parent_dict[str(category['categoryId'])] = category['parentCategoryId']

    for category in json_data['result']['small']:
        df = df._append(
            {'category1': parent_dict[category['parentCategoryId']], 'category2': category['parentCategoryId'],
             'category3': category['categoryId'], 'categoryId': parent_dict[category['parentCategoryId']] + "-" + str(
                category['parentCategoryId']) + "-" + str(category['categoryId']),
             'categoryName': category['categoryName']}, ignore_index=True)

    # 2. キーワードからカテゴリを抽出する
    df_keyword = df.query(f'categoryName.str.contains("{a_food}")', engine='python')
    if df_keyword.empty:
        print("検索結果がありませんでした。")
        exit()
    # 3. 人気レシピを取得する
    df_recipe = pd.DataFrame(
        columns=['recipeId', 'recipeTitle', 'foodImageUrl', 'recipeMaterial', 'recipeCost', 'recipeIndication',
                 'categoryId', 'categoryName'])

    for index, row in df_keyword.iterrows():
        url = 'https://app.rakuten.co.jp/services/api/Recipe/CategoryRanking/20170426?applicationId=1064593445227237376&categoryId=' + \
              row['categoryId']
        res = requests.get(url)
        json_data = json.loads(res.text)
        recipes = json_data['result']

        for recipe in recipes[:4]:  # 上位4位だけを取得
            df_recipe = df_recipe._append({'recipeId': recipe['recipeId'], 'recipeTitle': recipe['recipeTitle'],
                                           'foodImageUrl': recipe['foodImageUrl'],
                                           'recipeMaterial': recipe['recipeMaterial'],
                                           'recipeCost': recipe['recipeCost'],
                                           'recipeIndication': recipe['recipeIndication'],
                                           'categoryId': row['categoryId'], 'categoryName': row['categoryName']},
                                          ignore_index=True)

        time.sleep(1)  # 連続でアクセスすると先方のサーバに負荷がかかるので少し待つのがマナー

    pprint(df_recipe.head(4))
    return "ランキングのレシピを表示します"


# AIが使うことができる関数を羅列する
functions = [
    {
        "name": "get_recipe",
        "description": "ランキング上位4位のレシピの情報を得る",
        "parameters": {
            "type": "object",
            "properties": {
                # food引数の情報
                "a_food": {
                    "type": "string",
                    "description": "食べ物の単語です",
                },
            },
            "required": ["recipe"],
        },
    }
]

# 1段階目の処理
# AIが質問に対して使う関数と、その時に必要な引数を決める
# 特に関数を使う必要がなければ普通に質問に回答する
response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-0613",
    messages=[
        {"role": "user", "content": question},
    ],
    functions=functions,
    function_call="auto",
)
#print(json.dumps(response), file=sys.stderr)

message = response["choices"][0]["message"]

if message.get("function_call"):
    # 関数を使用すると判断された場合

    # 使うと判断された関数名
    function_name = message["function_call"]["name"]
    # その時の引数dict
    arguments = json.loads(message["function_call"]["arguments"])

    # 2段階目の処理
    # 関数の実行
    function_response = get_recipe(a_food=arguments["a_food"])
#    print(function_response, file=sys.stderr)

    # 3段階目の処理
    # 関数実行結果を使ってもう一度質問
    second_response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-0613",
        messages=[
            {"role": "user", "content": question},
            message,
            {
                "role": "function",
                "name": function_name,
                "content": function_response,
            },
        ],
    )

#    print(json.dumps(second_response), file=sys.stderr)
    print(second_response.choices[0]["message"]["content"])

この記事が気に入ったらサポートをしてみませんか?