FitBot — フィットネスチャットボットエージェント

FitBot - Fitness Chatbot Agent

OpenAIの関数呼び出しを活用したチャットボットエージェントの作成方法

写真:Gary Butterfield氏のUnsplashより

イントロダクション

健康意識が最優先になり、バランスの取れたライフスタイルを追求することが普遍的な目標になっている現代において、栄養は確かに中心的な要素として存在します。

しかし、食事プランの複雑さや豊富すぎる栄養データは、このバランスを実現するための障壁となります。糖尿病などの病気を持つ人々にとっても、血糖値を効果的に管理するためには一貫性のある正確な栄養指導が必要です。デジタル上で個別の栄養アシスタントを利用できると、一変するでしょう。

このような文脈では、栄養指導を支援するためにテクノロジーを活用することは、単なる利益にとどまらず、必須の要件となります。最先端の人工知能(AI)を包括的な栄養データベースと統合することで、個々の健康の旅を支援するための強力なツールを作成することが可能です。

**このプロジェクトのコードは、このGitHubリポジトリで入手できます:リンク**

プロジェクトの概要

このプロジェクトの中核は、チャットボット「FitBot」を構築することであり、OpenAIの関数を活用し、ReAct(Reasoning and Acting)フレームワーク(図1)に基づいています。

これは、ユーザーの食事習慣を解釈し、栄養データのAPIを統合することで、栄養情報とアドバイスを提供するように設計されています。

技術的なアプローチ

ReActフレームワークを活用することで、FitBotは会話の対話的な性質を維持し、提供するアドバイスごとに詳細な説明を行うことができます。また、外部の栄養データベースとも連携し、正確かつ最新の食事アドバイスを提供します。

図1:ReActは推論(例:思考の連鎖の促進)と行動を組み合わせます。画像の出典:リンク

FitBotの裏側

FitBotは、OpenAIのGPT-4の機能とReActのダイナミックな処理を組み合わせて、栄養クエリを理解し、適切な代替案を提案し、個別のアドバイスを提供します。その際、会話のトーンを維持し、栄養アドバイスをアクセスしやすく魅力的にします。

FitBotの特長は、外部の栄養データベースとのインターフェース機能です。これにより、FitBotはユーザーに正確かつ最新の情報を提供できますので、提供されるアドバイスは信頼性があり、正確なデータに基づいています。

次のセクションでは、コードを詳しく見て、FitBotのコンポーネントがどのように開発され、相互作用しているのかを探求します。この革新的なプロジェクトの内部動作について包括的に見ていきましょう。

FitBotの構築:コードの説明

このプロジェクトには、データを処理しUIに表示するために使用される4つの主要なスクリプトがあります:

  1. fitness_agent.py:このファイルにはFitnessAgentクラスが含まれており、FitBotで必要な機能を実現するためにOpenAIの関数を活用しています。
  2. chatbot.py:このファイルには、FitBotのユーザーインターフェースのコードが含まれており、Gradioライブラリを使用して実装されています。
  3. agents.py:このファイルにはAgentクラスが含まれており、OpenAI APIとの会話を処理するために使用されます。このコードは、funkagentライブラリでJames Briggsが開発したスクリプトに基づいています。
  4. parser.py:このファイルには、関数のドキュメントストリングをOpenAIの関数の説明にパースするためのコードが含まれています。

関数の定義

正確かつ有用な栄養およびフィットネスのアドバイスを提供できるチャットボットを作成するために、エンドユーザーにとって最も価値のある情報を考慮する必要がありました。これが以前に説明した関数を実装する理由です。

1. get_nutritional_info:この関数は、フィットネス志向のチャットボットにとって重要です。人々は食べ物の栄養成分について明確な情報を持っていないことがよくあります。API NinjasのNutritionエンドポイントを使用して、さまざまな食品のリアルタイムの栄養データを取得することで、ユーザーが栄養に関する情報に基づいた食事の決定をするのを助けることができます。返されるデータには、カロリー、タンパク質、炭水化物、脂肪などの詳細が含まれており、食品の栄養プロファイルを包括的に把握することができます。

def get_nutritional_info(self, query: str) -> dict:    """特定の食品の栄養情報を取得します    :param query: 栄養情報を取得する食品    :return: 食品の栄養情報    """    api_url = 'https://api.api-ninjas.com/v1/nutrition?query={}'.format(query)    response = requests.get(api_url, headers={'X-Api-Key': self.nut_api_key})    if response.status_code == requests.codes.ok:        return response.json()  # より構造化されたデータのためにtextの代わりにjsonを使用    else:        return {"エラー": response.status_code, "メッセージ": response.text}

2. calculate_bmr: 基礎代謝率(BMR)は個人の代謝を理解する上で重要な数値です。それは休息中に消費されるエネルギーの量であり、年齢、体重、身長、性別に密接に関連しています。BMRを計算する能力は、ユーザーが体力活動なしでもどれだけのカロリーが必要なのかを理解するために、チャットボットにベースラインを提供します。

def calculate_bmr(weight: float, height: float, age: int, gender: str, equation: str = 'mifflin_st_jeor') -> float:    """人物の基礎代謝率(BMR)を計算します    :param weight: 人物の体重(kg)    :param height: 人物の身長(cm)    :param age: 人物の年齢(歳)    :param gender: 人物の性別('male'または'female')    :param equation: BMRの計算に使用する方程式('harris_benedict'または'mifflin_st_jeor')    :return: 人物のBMR    """    if equation.lower() == 'mifflin_st_jeor':        if gender.lower() == 'male':            return (10 * weight) + (6.25 * height) - (5 * age) + 5        else:  # 'female'            return (10 * weight) + (6.25 * height) - (5 * age) - 161    else:  # 'harris_benedict'        if gender.lower() == 'male':            return 88.362 + (13.397 * weight) + (4.799 * height) - (5.677 * age)        else:  # 'female'            return 447.593 + (9.247 * weight) + (3.098 * height) - (4.330 * age)

3. calculate_tdee: 自分の1日の総エネルギー消費量(TDEE)を理解することは、個別のダイエットや運動計画を作成する上で重要です。TDEEはBMRだけでなく、日常の活動や運動で消費されるカロリーも考慮に入れます。自分のTDEEを知ることで、ユーザーは体重を維持、減量、増量するためにより効果的な食事と運動の計画を立てることができます。

def calculate_tdee(bmr: float, activity_level: str) -> float:    """人物の1日の総エネルギー消費量(TDEE)を計算します    :param bmr: 人物のBMR    :param activity_level: 人物の活動レベル('sedentary'、'lightly_active'、'moderately_active'、'very_active'、'super_active')    :return: 人物のTDEE    """    activity_factors = {        'sedentary': 1.2,        'lightly_active': 1.375,        'moderately_active': 1.55,        'very_active': 1.725,        'super_active': 1.9,    }    return bmr * activity_factors.get(activity_level, 1)

4. calculate_ibw: 理想的な体重(IBW)を知ることで、ユーザーは自分の身長と性別に対して健康的とされる目標体重を得ることができます。IBWは完璧な指標ではありません(筋肉量などの要素は考慮されていません)、しかしユーザーに健康的な体重の目安を提供します。

def calculate_ibw(height: float, gender: str) -> float:    """理想的な体重(IBW)を計算します    :param height: 人物の身長(インチ)    :param gender: 人物の性別("male"または"female")    :return: 理想的な体重(kg)    """    if gender.lower() == 'male':        if height <= 60:  # 5フィート = 60インチ            return 50        else:            return 50 + 2.3 * (height - 60)    elif gender.lower() == 'female':        if height <= 60:            return 45.5        else:            return 45.5 + 2.3 * (height - 60)    else:        raise ValueError("無効な性別です。'male'または'female'を指定してください。")

4. calculate_bmi: ボディマス指数(BMI)は、身長と体重を使った簡単な計算です。式はBMI = kg/m^2で、kgは体重(キログラム)、m^2は身長(メートル)の二乗です。BMIは直接的に体脂肪を測定するものではありませんが、研究によってBMIは体脂肪をより直接的に測定する方法と中程度に相関していることが示されています。BMIは、人が低体重、健康な体重、肥満、または肥満であるかを理解するのに役立つ目安を提供します。

def calculate_bmi(weight: float, height: float) -> float:    """人のボディマス指数(BMI)を計算する    :param weight: 人の体重(kg)    :param height: 人の身長(cm)    :return: 人のBMI    """    height_meters = height / 100  # cmをメートルに変換    bmi = weight / (height_meters ** 2)    return round(bmi, 2)  # 読みやすさのために小数点以下2桁で丸める

エージェントの構築:関数のラッピング

必要な関数が確立されたら、次のステップはこれらをチャットボットエージェントに統合することです。このカプセル化により、ボットは関数を活用し、ユーザーのクエリに基づいて関連性のある正確な応答を提供することができます。

以下の方法でエージェントを作成できます:

# エージェントをインスタンス化fitness_agent = FitnessAgent(openai_api_key, nut_api_key)

機能を確認できます:

# 処理された関数命令を表示するprint(fitness_agent.functions)

出力:

[   {      "name":"get_nutritional_info",      "description":"特定の食品アイテムの栄養情報を取得する",      "parameters":{         "type":"object",         "properties":{            "query":{               "description":"栄養情報を取得する食品アイテム",               "type":"string"            }         }      },      "required":[         "query"      ]   },   {      "name":"calculate_bmr",      "description":"人の基礎代謝率(BMR)を計算する",      "parameters":{         "type":"object",         "properties":{            "weight":{               "description":"人の体重(kg)",               "type":"number"            },            "height":{               "description":"人の身長(cm)",               "type":"number"            },            "age":{               "description":"人の年齢(歳)",               "type":"integer"            },            "gender":{               "description":"人の性別('male'または'female')",               "type":"string"            },            "equation":{               "description":"BMR計算に使用する式('harris_benedict'または'mifflin_st_jeor')",               "type":"string"            }         }      },      "required":[         "weight",         "height",         "age",         "gender",         "equation"      ]   },   {      "name":"calculate_tdee",      "description":"人の1日の総エネルギー消費量(TDEE)を計算する",      "parameters":{         "type":"object",         "properties":{            "bmr":{               "description":"人のBMR",               "type":"number"            },            "activity_level":{               "description":"人の活動レベル",               "type":"string"            }         }      },      "required":[         "bmr",         "activity_level"      ]   }]

エージェントとの対話:ユーザーの会話

定義した関数をFitnessAgent内にカプセル化した後、ボットとの会話をシミュレートできます。FitnessAgentクラスのask()メソッドを使用すると、簡単にユーザーのクエリをボットに入力し、生成される応答を表示することができます。

例えば、一般的な食品アイテムについて栄養情報をボットに尋ねてみましょう:

# 質問を定義するuser_input = "バナナの栄養価は何ですか?"# チャットの応答を取得するresponse = fitness_agent.ask(user_input)# 最終的な応答を表示するprint(response['choices'][0]['message']['content'])

出力:

バナナの100グラムの一食あたりの栄養価は次のとおりです:- カロリー:89.4- 総脂質:0.3グラム(内訳:飽和脂肪酸0.1グラム)- タンパク質:1.1グラム- ナトリウム:1ミリグラム- カリウム:22ミリグラム- コレステロール:0ミリグラム- 総炭水化物:23.2グラム(内訳:食物繊維2.6グラム、糖分12.3グラム)これらの値はバナナの正確なサイズと熟度によって異なる場合があります。また、バナナは食物のカリウムとビタミンCの良い源です。

この例では、FitBotはget_nutritional_info()関数を効果的に使用して、バナナの栄養価を取得して表示します。

FitBotはより複雑なリクエストにも対応できます。例えば、必要なデータが提供された場合、個人の1日の総エネルギー消費量(TDEE)を計算することができます:

# 質問を定義するuser_input = "30歳の男性で、身長180 cm、体重80 kgで週に3回運動する場合のTDEEは何ですか?"# チャットの応答を取得するresponse = fitness_agent.ask(user_input)# 最終的な応答を表示するprint(response['choices'][0]['message']['content'])

出力:

30歳の男性で、身長180 cm、体重80 kgで週に3回運動する場合の総エネルギー消費量(TDEE)は、ハリス・ベネディクトの式によると約2574カロリー/日になります。これはおおよその推定値であり、個々の結果は代謝速度、具体的な身体活動など複数の要因によって異なる場合があります。以下にプロセスの簡単な説明を示します:1. 基礎代謝量(BMR)の計算 - これは活動なしで存在するだけで燃焼するカロリーの数です。男性の場合、BMRを計算するためのハリス・ベネディクトの式はBMR = 88.362 + (13.397 * 体重(kg)) + (4.799 * 身長(cm)) - (5.677 * 年齢(歳))となります。与えられた値に対して、BMRは約1783カロリーとなります。2. 活動に対する調整 - BMRは次の乗数を使用して身体活動レベルに合わせて調整できます:- 運動量の少ない(ほとんどまたは全く運動しない)場合:BMR * 1.2- 軽度の運動(週に1〜3日の軽い運動/スポーツ)の場合:BMR * 1.375- 中程度の運動(週に3〜5日の適度な運動/スポーツ)の場合:BMR * 1.55- 非常に活発な運動(週に6〜7日の激しい運動/スポーツ)の場合:BMR * 1.725- 超活発な運動(非常に激しい運動/肉体労働および1日に2回の運動)の場合:BMR * 1.9週に3回運動する人の場合、乗数は1.55(中程度の活動)とします。したがって、TDEE = BMR * 活動乗数 = 1783 * 1.55 ≈ 2764カロリーです。注意:実際の総カロリー必要量は筋肉と脂肪の割合、特定の活動の種類などを考慮して多少高くまたは低くなる可能性があります。

この出力をGPT-4に基づく通常のChatGPTと比較してみましょう:

TDEEまたは1日の総エネルギー消費量は、身体活動レベルを考慮して、現在の体重を維持するために1日に摂取する必要のあるカロリーの総数を表します。まず、安静時のエネルギー消費量である基礎代謝量(BMR)を計算する必要があります。BMRを計算するためのいくつかの式がありますが、一般的に使用されるものの1つはミフリン-セントジョアの式です:男性の場合:BMR = 10 * 体重(kg)+ 6.25 * 身長(cm)- 5 * 年齢(y)+ 5したがって、あなたの場合:BMR = 10 * 80kg + 6.25 * 180cm - 5 * 30y + 5BMR = 800 + 1125 - 150 + 5 = 1780 kcal/日これは、安静時に身体が機能するために必要なカロリー量です。方程式に身体活動を含めるために、BMRに身体活動レベル(PAL)を乗じます。週に3回運動する人の場合、一般的なPALは1.375(適度な運動)です。したがって、TDEE = BMR * PALTDEE = 1780 kcal/日 * 1.375 = 2447.5 kcal/日したがって、30歳の男性で、身長180 cm、体重80 kgで週に3回運動する場合、現在の体重を維持するために約2448カロリー/日が必要です。実際のカロリー必要量は遺伝子や体組成などの多くの要因によって異なる場合がありますので、個別のアドバイスについては医療提供者または登録栄養士に相談してください。

ユーザーインターフェースとのチャットボットの統合

有用な機能を備えたフィットネスエージェントを構築しましたので、使いやすいインターフェースで表示したいと思います。

このために、我々はGradioというPythonのライブラリを使用して、迅速かつ便利に共有可能なウェブベースのユーザーインターフェースを作成します。このセクションでは、チャットボットをGradioのユーザーインターフェースに統合する方法を説明します。

以下は、インターフェースの全体的な構造です:

def main():    openai_api_key = gr.components.Textbox(        lines=1,        label="OpenAI APIキーを入力してください",        type="password",    )    nut_api_key = gr.components.Textbox(        lines=1,        label="栄養APIキーを入力してください",        type="password",    )    question = gr.components.Textbox(        lines=3,        label="メッセージを入力してください",    )    output_history = gr.outputs.HTML(        label="更新された会話",    )    inputs = [        openai_api_key,        nut_api_key,        question,    ]    iface = gr.Interface(        fn=partial(get_response),        inputs=inputs,        outputs=[output_history],        title="フィットネスエージェント",        description="フィットネスエージェントとGradioを使用したシンプルなチャットボットと会話履歴",        allow_flagging=False,    )    iface.launch()if __name__ == "__main__":    main()

これは私たちのmain関数であり、スクリプトのエントリーポイントです。最初に、ユーザーがOpenAI APIキーと栄養APIキーを入力するためのテキストボックスを作成します。キーは入力を非表示にするためにpasswordタイプに設定されています。次に、ユーザーが質問をするためのテキストボックスを提供します。ボットからの応答は、”更新された会話”というラベルの領域にHTMLとして表示されます。

次に、入力と出力をGradioインターフェースに渡し、スクリプトを実行するとインターフェースが起動されます。

get_response関数はフィットネスエージェントとやり取りします:

def get_response(openai_api_key, nut_api_key, user_input, action=None):    set_openai_api_key(openai_api_key)    set_nut_api_key(nut_api_key)    fitness_agent = FitnessAgent(openai_api_key, nut_api_key)    # 生のチャット応答を取得    fitness_agent.ask(user_input)    memory = fitness_agent.agent.chat_history    # ChatMessageHistoryのメッセージを反復処理し、出力をフォーマットする    updated_conversation = '<div style="background-color: hsl(30, 100%, 30%); color: white; padding: 5px; margin-bottom: 10px; text-align: center; font-size: 1.5em;">チャット履歴</div>'    logger.info(memory)    for i, message in enumerate(memory):        if i != 0:            if message['role'] == 'user':                prefix = "ユーザー: "                background_color = "hsl(0, 0%, 40%)"  # ダークグレーの背景                text_color = "hsl(0, 0%, 100%)"  # 白いテキスト            else:                prefix = "チャットボット: "                background_color = "hsl(0, 0%, 95%)"  # 白い背景                text_color = "hsl(0, 0%, 0%)"  # 黒いテキスト            updated_conversation += f'<div style="color: {text_color}; background-color: {background_color}; margin: 5px; padding: 5px;">{prefix}{message["content"]}</div>'    return updated_conversation

get_responseでは、OpenAIと栄養APIキーをset_openai_api_keyset_nut_api_keyの関数を使用して設定し、フィットネスエージェントを初期化します。次に、ユーザーの質問を使用してエージェントのaskメソッドを呼び出し、会話の履歴を保存します。会話履歴の各メッセージはHTML文字列としてフォーマットされ、updated_conversationに追加されます。このHTML文字列が返され、Gradioインターフェースで表示されます。

結果のインターフェースの一部

必要な計算と会話ロジックを統合し、Gradioで見栄えの良いユーザーインターフェースにカプセル化することで、FitBotを対話する準備が整いました!

最終的なインターフェースの見た目は次のようになります:

図2: チャットボットのためのGradio UI。画像作者提供

インターフェース上で、OpenAIとAPI Ninjas Nutritionエンドポイントの必要なキー、およびフィットネスエージェントへのユーザーメッセージを入力するための3つの入力ボックスが表示されます。

概要

この記事では、OpenAIのGPT-4を使用した包括的なフィットネスエージェントFitBotの作成方法について詳しく説明しています。GPT-4は、複雑なユーザーのクエリを理解し、応答することができる強力なAIモデルです。

まず、基礎代謝率(BMR)、1日のエネルギー消費量(TDEE)、体格指数(BMI)などの主要な健康指標を計算するための関数を作成しました。これらの計算は、フィットネスエージェントが正確かつ適切なフィットネスと栄養のアドバイスを提供する能力の基盤となります。

次に、API NinjasのNutritionエンドポイントとの統合を取り入れました。これにより、フィットネスエージェントは正確な栄養情報にアクセスし、提供することができるようになりました。これは包括的なフィットネスとダイエット計画にとって重要な要素です。

その後、フィットネスエージェントをよりインタラクティブにするための会話ロジックの構築方法を紹介しました。これにより、フィットネスエージェントは会話のフローを処理し、さまざまなユーザーの質問に答え、効果的にフィットネスの旅を案内することができるようになります。

最後に、これらの機能をGradioを使用して視覚的に魅力的なユーザーインターフェースにカプセル化しました。その結果、知識豊富で使いやすいフィットネスエージェントが実現し、わかりやすい形式でクリアかつ包括的なアドバイスを提供します。

要約: この記事では、OpenAIのGPT-4を使用したFitBotというフィットネスエージェントを構築しました。このエージェントは、個別のフィットネスと栄養のアドバイスを提供することができます。主要な健康指標(BMR、TDEE、BMI)の計算関数を実装し、正確な食事情報のためにNutrition APIと統合し、Gradioを使用して使いやすいインターフェースにまとめました。このプロジェクトは、健康とフィットネスの分野でAIの力を示しており、複雑な計算を簡素化し、個別のアドバイスを提供し、魅力的なユーザーインターフェースを通じてすべてを提供しています。

読んでいただきありがとうございました!

  • Linkedinで私をフォローしてください!

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

データサイエンス

「ジェンAIの時代:新たな始まり」

イントロダクション 急速に進化するテクノロジーの世界で、我々は新たな時代の予感に包まれています。それは、かつて人間にし...

AI研究

マイクロソフトリサーチは、競合モデルよりも大幅に小さいサイズで、Pythonコーディングに特化した新しい大規模言語モデルphi-1を紹介しました

トランスフォーマーのデザインが発見されて以来、大規模な人工ニューラルネットワークのトレーニングの技術は飛躍的に進歩し...

コンピュータサイエンス

量子コンピューティングの進歩は新しい時代の幕開け、IBMが発表

量子コンピューターは、従来のスーパーコンピューターよりも物理問題に対してより良い答えを導き出しました

機械学習

Meet ChatGLM2-6B:オープンソースのバイリンガル(中国語-英語)チャットモデルChatGLM-6Bの第2世代バージョンです

OpenAIの革命的なChatGPTの導入以来、自然言語対話エージェントの分野ではかなりの進歩が見られています。研究者たちは、チャ...

AIニュース

混合現実で測定された没入型エンゲージメントの反応時間

「マサチューセッツ大学アムハースト校の研究者は、リアクションタイムが混合現実技術との存在感(没入型エンゲージメント)...

機械学習

「GPS ガウシアンと出会う:リアルタイムにキャラクターの新しい視点を合成するための新たな人工知能アプローチ」

マルチビューカメラシステムの重要な機能の1つは、ソースの写真を使用して新しい視点から写真のような画像を生成する新規ビュ...