第301回 SORACOM公式ブログ

ソラコム公式ブログ

IoTが産み出すデータを「生成系AI」で活かすテクニックセッションのアップデート【SORACOM Discovery 2023】

  • この記事をはてなブックマークに追加
  • 本文印刷

こんにちは、ソリューションアーキテクトの内田(ニックネーム:jet)です。

7/5(水)・7/6(木)に開催したIoTカンファレンス「SORACOM Discovery 2023」はお楽しみいただけましたでしょうか? 7/6(木)は久しぶりのオフライン開催となり、多くの方に会場にお越しいただき、実際にIoTデバイスを見て触れていただいておりました。ありがとうございました。

このブログでは「SORACOM Discovery 2023」で、私が担当した以下のセッションについての内容を少しフォローしたいと思います。

IoTが産み出すデータを「生成系AI」で活かすテクニック

7/5(水)のオンラインセッションの内容は、5/30(火)に開催した、IoTや周辺技術の知見をエンジニア向けに共有するイベント「IoT-Tech Meetup 第1回【ChatGPT × IoT】」でお話ししたものをブラッシュアップした内容です。

7/5(水)のオンラインセッションでは、セッションの中で時系列データを扱う時にはトークンの上限に注意が必要なことと、チャットの回答結果を例えばJSON形式にしたいという場合は、プロンプトを工夫すれば指定した出力形式になる場合があるが、ダメな時はダメなのでシステム連携で使う場合には、さらにひと工夫が必要というまとめを行っていました。

ChatGPT の機能アップデート

ここまでで、普段からChatGPTを使っている方はご存知かもしれませんが、以下のような機能アップデートがありました。

アップデート内容をピックアップしてみると

new function calling capability in the Chat Completions API

Chat Completions APIに関数呼び出し機能が追加された

updated and more steerable versions of gpt-4 and gpt-3.5-turbo

gpt-4とgpt-3.5-turboのモデルに新しいバージョンが追加された

new 16k context version of gpt-3.5-turbo (vs the standard 4k version)

トークンの上限が今までの4倍になった

などが、大きな変更点かと感じました。

モデルのアップデート

ドキュメント にも記載があるように、GPT-4、GTP-3.5に0613が付いたバージョンが追加されています。

加えて、GTP-3.5には16kが付いたバージョンも追加されています。これはトークンの上限がこれまでの4倍になったバージョンです。

LATEST MODEL MAX TOKENS
gpt-3.5-turbo-0613 4,096 tokens
gpt-3.5-turbo-16k-0613 16,384 tokens
引用:https://platform.openai.com/docs/models/gpt-3-5

上限が大きくなったので、使える幅が増えるのは嬉しいのですが同時に料金が別設定になっているので、本格的に利用する前には確認を行なってください。

Function calling

0613が付いたバージョン以降で利用できる機能で、自分で定義した関数呼び出しができる機能です。関数が定義してあると、AIへの問いかけで、AIが判断して関数呼び出しを行うための返答をしてくれます。Web版のplugin機能とは違い、関数を自動で呼び出してくれるわけではない点は認識する必要があります。

アップデートされた機能を試してみる

というわけで、本題へ。これまではプロンプトの工夫やSystem roleを利用してAIに制約を付けることで、API連携に必要なJSON形式の回答を生成していました。

 Function calling機能を使うことで、連携先のJSON形式へ対応できるのではないか?という部分を実際に試してみようと思います。

Function を定義する

Chat Completions APIを呼び出す引数に、定義した関数の情報を渡す必要があります。関数の定義は、ドキュメントにあるようにJSON Schemaでの定義が必要です。

今回は、過去の時系列データから1日後の同じ時間帯のデータを予測することを試してみました。JSONの入れ子や配列などを定義しています。

AIはこれを関数呼び出しのために必要な情報だと認識するので、関数へのインプット情報として指定したJSON形式のデータが得られるかどうかを実際に試してみます。

functions = [     {         "name": "predict_data",         "description": "添付された元データを使って今後の未来予測を実行する関数",         "parameters": {             "type": "object",             "required": [                 "predictions",                 "summary",                 "chat_type"             ],             "properties": {                 "predictions": {                     "type": "array",                     "description": "未来の予測時間, 未来の予測温度, 未来の予測湿度がそれぞれ有効な値で記載されていること。それが複数個のリストとになっている。例: predictions:[{time:予測値,temp:予測値,humi:予測値}]",                     "items": {                         "type": "object",                         "required": [                             "time",                             "temp",                             "humi"                         ],                         "properties": {                             "time": {                                 "type": "string",                                 "description": "未来の予測日時の文字列。AIが予測日時を記載する。例: 2023-06-17 15:52:15",                             },                             "temp": {                                 "type": "number",                                 "description": "未来の予測温度の数値。AIが予測温度を記載する。例: 24.5",                             },                             "humi": {                                 "type": "number",                                 "description": "未来の予測湿度の数値。AIが予測湿度を記載する。例: 65.5",                             },                         },                     },                 },                 "summary": {                     "type": "object",                     "description": "予測をした理由, 予測についてコメントや補足を含む。例: {reason:AIの返答,note:AIの返答}",                     "required": [                         "reason",                         "note"                     ],                     "properties": {                         "reason": {                             "type": "string",                             "description": "予測した経緯や理由をAIが記載する。例: 添付されたデータを利用して未来を予測しました。",                         },                         "note": {                             "type": "string",                             "description": "予測した際にコメントや補足があればAIが記載する。例: 季節や場所の内容を考慮していますが、予測が正しいとは限りません。",                         },                     },                 },                 "chat_type": {                     "type": "string",                     "description": "予測を実行したことの識別子。例: prediction",                     "enum": [                         "prediction"                     ],                 },             },         },     } ]

Function calling を設定する

ChatGPTの呼び出しにはPythonライブラリのopenai / openai-pythonを利用しています。openai / openai-pythonMIT ライセンスで提供されていています。

実際にの呼び出し部分は以下の通りで、変更点は定義した関数を functions=functionsで渡しているところと、 関数呼び出しの function_call="auto"が追加されているだけです。関数呼び出しは、コメントアウトしてあるように関数名を直接していして呼び出すこともできます。

response = openai.ChatCompletion.create(     model=selected_model,     messages=[         {"role": "user", "content": user_content},     ],     functions=functions,     function_call="auto",     # function_call={"name": "predict_data"}, )

あとは、結果が見えるようにして実際に実行してみます。

message = response["choices"][0]["message"] pprint.pprint(message)  if message.get("function_call"):         function_name = message["function_call"]["name"]         arguments = json.loads(message["function_call"]["arguments"])         pprint.pprint(arguments)     else:         print('# 🤖 reply = ', message.content.strip()) 

ChatGTPに与えているのは、以下のグラフの時系列データです。データはGPS マルチユニット SORACOM Editionを利用して収集した、日時・温度・湿度の1時間のデータです。

Function calling を設定して ChatGPT を呼び出す

プロンプトには以下のように入力しました。今回はuser roleのみを利用しました。

- 添付したデータから既存の関数を呼び出して今後の未来予測を実行する - 予測の `間隔` は `添付したデータと同じ間隔` で必ず予測すること  - 予測する期間は、`1日後` の `同一の時間帯` とする - 予測期間のすべての予測データを欠けることなく必ず回答すること - 予測には`時間`,`温度`,`湿度`を有効な値で必ず含めること - 予測の`温度`,`湿度` は季節と場所を考慮した値であること - 予測の内容を導き出した理由を必ず含めること - その他のコメントがある場合は含めること - 現在の季節は `夏`  - 場所は `日本` の `東京` - `季節` と `場所` の情報を必ず加味して予測すること

実際に呼び出してみたところ、ChatGPTからの返答はfunctionを呼び出すための引数として、定義したJSON形式での返答を受け取ることができました。

出力されたJSONデータの内容を確認すると、ちょっと気温が高すぎるきがしますが、これはChatGPTが不得意な分野であるためです。実際にはこの予測も含めて自分の関数や他の特化型AIと連携するような仕組みにしてあげるのが良いかと感じました。

{'chat_type': 'prediction',  'predictions': [{'humi': 64.0, 'temp': 33.0, 'time': '2023-07-05 18:47:31'},                  {'humi': 67.0, 'temp': 33.1, 'time': '2023-07-05 18:46:36'},                  {'humi': 63.0, 'temp': 33.2, 'time': '2023-07-05 18:45:30'},                  {'humi': 64.0, 'temp': 33.3, 'time': '2023-07-05 18:44:30'},                  {'humi': 62.0, 'temp': 33.4, 'time': '2023-07-05 18:43:30'},                  {'humi': 63.0, 'temp': 33.5, 'time': '2023-07-05 18:42:30'},                  {'humi': 61.0, 'temp': 33.6, 'time': '2023-07-05 18:41:35'},                  {'humi': 64.0, 'temp': 33.7, 'time': '2023-07-05 18:40:30'},                  {'humi': 62.0, 'temp': 33.8, 'time': '2023-07-05 18:39:30'},                  {'humi': 63.0, 'temp': 33.9, 'time': '2023-07-05 18:38:30'},                  {'humi': 65.0, 'temp': 34.0, 'time': '2023-07-05 18:37:31'},                  {'humi': 61.0, 'temp': 34.1, 'time': '2023-07-05 18:36:29'},                  {'humi': 64.0, 'temp': 34.2, 'time': '2023-07-05 18:35:29'},                  {'humi': 62.0, 'temp': 34.3, 'time': '2023-07-05 18:34:29'},                  {'humi': 63.0, 'temp': 34.4, 'time': '2023-07-05 18:33:29'},                  {'humi': 65.0, 'temp': 34.5, 'time': '2023-07-05 18:32:29'},                  {'humi': 62.0, 'temp': 34.6, 'time': '2023-07-05 18:31:34'},                  {'humi': 64.0, 'temp': 34.7, 'time': '2023-07-05 18:30:29'},                  {'humi': 63.0, 'temp': 34.8, 'time': '2023-07-05 18:29:28'},                  {'humi': 65.0, 'temp': 34.9, 'time': '2023-07-05 18:28:28'},                  {'humi': 62.0, 'temp': 35.0, 'time': '2023-07-05 18:27:28'},                  {'humi': 64.0, 'temp': 35.1, 'time': '2023-07-05 18:26:33'},                  {'humi': 63.0, 'temp': 35.2, 'time': '2023-07-05 18:25:28'},                  {'humi': 62.0, 'temp': 35.3, 'time': '2023-07-05 18:24:28'},                  {'humi': 64.0, 'temp': 35.4, 'time': '2023-07-05 18:23:28'},                  {'humi': 61.0, 'temp': 35.5, 'time': '2023-07-05 18:22:28'},                  {'humi': 63.0, 'temp': 35.6, 'time': '2023-07-05 18:21:32'},                  {'humi': 59.0, 'temp': 35.7, 'time': '2023-07-05 18:20:27'},                  {'humi': 62.0, 'temp': 35.8, 'time': '2023-07-05 18:19:27'},                  {'humi': 61.0, 'temp': 35.9, 'time': '2023-07-05 18:18:27'},                  {'humi': 64.0, 'temp': 36.0, 'time': '2023-07-05 18:17:27'},                  {'humi': 60.0, 'temp': 36.1, 'time': '2023-07-05 18:16:32'},                  {'humi': 63.0, 'temp': 36.2, 'time': '2023-07-05 18:15:28'},                  {'humi': 62.0, 'temp': 36.3, 'time': '2023-07-05 18:14:26'},                  {'humi': 65.0, 'temp': 36.4, 'time': '2023-07-05 18:13:26'},                  {'humi': 60.0, 'temp': 36.5, 'time': '2023-07-05 18:12:26'},                  {'humi': 63.0, 'temp': 36.6, 'time': '2023-07-05 18:11:32'},                  {'humi': 62.0, 'temp': 36.7, 'time': '2023-07-05 18:10:27'},                  {'humi': 65.0, 'temp': 36.8, 'time': '2023-07-05 18:09:27'},                  {'humi': 61.0, 'temp': 36.9, 'time': '2023-07-05 18:08:26'},                  {'humi': 64.0, 'temp': 37.0, 'time': '2023-07-05 18:07:26'},                  {'humi': 62.0, 'temp': 37.1, 'time': '2023-07-05 18:06:31'},                  {'humi': 63.0, 'temp': 37.2, 'time': '2023-07-05 18:05:26'},                  {'humi': 65.0, 'temp': 37.3, 'time': '2023-07-05 18:04:26'},                  {'humi': 61.0, 'temp': 37.4, 'time': '2023-07-05 18:03:25'},                  {'humi': 64.0, 'temp': 37.5, 'time': '2023-07-05 18:02:24'},                  {'humi': 63.0, 'temp': 37.6, 'time': '2023-07-05 18:01:29'},                  {'humi': 62.0, 'temp': 37.7, 'time': '2023-07-05 18:00:24'},                  {'humi': 65.0, 'temp': 37.8, 'time': '2023-07-05 17:59:24'},                  {'humi': 61.0, 'temp': 37.9, 'time': '2023-07-05 17:58:24'},                  {'humi': 64.0, 'temp': 38.0, 'time': '2023-07-05 17:57:24'},                  {'humi': 63.0, 'temp': 38.1, 'time': '2023-07-05 17:56:28'},                  {'humi': 65.0, 'temp': 38.2, 'time': '2023-07-05 17:55:23'},                  {'humi': 62.0, 'temp': 38.3, 'time': '2023-07-05 17:54:23'},                  {'humi': 64.0, 'temp': 38.4, 'time': '2023-07-05 17:53:23'},                  {'humi': 61.0, 'temp': 38.5, 'time': '2023-07-05 17:52:23'},                  {'humi': 63.0, 'temp': 38.6, 'time': '2023-07-05 17:51:23'},                  {'humi': 62.0, 'temp': 38.7, 'time': '2023-07-05 17:50:23'},                  {'humi': 65.0, 'temp': 38.8, 'time': '2023-07-05 17:49:23'},                  {'humi': 61.0, 'temp': 38.9, 'time': '2023-07-05 17:48:22'}],  'summary': {'note': '夏の季節として予測', 'reason': '気温と湿度の上昇傾向'}} 

更なるアップデート

ブログを書いている間に、更なるアップデートがありました。アップデートのスピードが早いので、気がついたら機能や仕組みが追加されている感じですね。こちらも普段からChatGPTを使っている方はご存知かもしれませんが、内容はGTP-4がGAになりました。詳細は以下をご確認ください。

また、プラグインのCode Interpreterがベータ提供ではありますが、ChatGPT Plus利用者に開放されました。

Code interpreter とは

Code interpreterはChatGPTで利用できるプラグインのひとつで、Webブラウザで利用できるChatGPT上で、コードの実行やデータをファイルとしてアップロードして、データの分析などが実行できます。

利用するには、設定からCode interpreterをONにし、プラグインを利用するためにGPT-4を選択してプラグインとしてCode interpreterをチェックしてください。

Code interpreter 試してみる

SORACOM Harvest Dataに保存されているデータをCSV形式でダウンロードして、そのCSVファイルをChatGPTにアップロードして、Code interpreterを試してみます。

今回はGPS マルチユニット SORACOM Editionを利用しているので、ChatGTPにはインプットするデータのデータフォーマットも一緒にインプットします。現時点ではCode interpreterはインターネットアクセスが行えないようなので、データフォーマットはURLではなく、文字列としてインプットしています。

CSVファイルとデータフォーマットを受け取ったあとは、ChatGPTによりデータ内容の確認が行われました。

Code interpreterの便利なところのひとつは、実際に実行されたコードや実行結果を確認できるところです。コードがあれば、ローカル環境でいろいろ試したい時に活用できそうです。

その後は、ChatGPTと会話をしながらデータについて分析や集計を行えます。グラフを描写することもできるので、可視化をしながら色々試していくのも便利かもしれません。

JSON 形式での出力を指定してみる

最後にこれまでと同じように出力をJSON形式でお願いしてみました。分析した結果がJSON形式に適さない部分は変更して出力してくれたようです。

Code interpreterを利用することで、手軽にデータを分析して可視化することができました。また他のサービスやAPIにインプットするためのJSON形式の結果を作成することもできました。まだまだベータということなので制約もあるのですが、手軽に使えるのは魅力ですし、ChatGPTのWebで完結できるようなデータ分析については利用してみると手軽に新しい発見が得られるかもしれませんね。

まとめ

ChatGPTの様々なアップデートによって、より手軽にAPIへの連携ができるようになってきました。また、トークン数の上限も大きくなり、これまで普通に渡せなかったデータや文章が渡せるようになってきました。

それでも、トークン数には上限があるため引き続き大きすぎるデータや文章を渡すための工夫や、Function calling利用時に想定していない返答がある可能性はゼロではないので、そういった部分にうまく折り合いをつけながら、AIが得意な部分で利用していくことが必要となってきます。

また、Code interpreterのような高機能なプラグインを利用することで、データの分析や可視化も簡単に行えるようになっています。

どちらの場合も、利用する場合にはChatGPTの有償ライセンスが必要となりますので、手軽にIoTの時系列データとAIの組み合わせを体験したい人は、今回発表された「SORACOM Harvest Data Intelligence」をまずはお試しいただければと思います。

まだまだこれからもアップデートや新機能の追加は続きそうなので、楽しみに待ちつつ、IoTとAIの新しい活用方法にチャレンジしてもらえるきっかけのひとつになれば嬉しいです。

― ソラコム内田(jet)@uchimanajet7

投稿 IoTが産み出すデータを「生成系AI」で活かすテクニック セッションのアップデート【SORACOM Discovery 2023】SORACOM公式ブログ に最初に表示されました。

過去記事アーカイブ

2024年
01月
02月
03月
04月
2023年
01月
02月
03月
04月
05月
06月
07月
08月
09月
10月
11月
12月
2022年
01月
02月
03月
04月
05月
06月
07月
08月
09月
10月
11月
12月
2021年
01月
02月
03月
04月
05月
06月
07月
08月
09月
10月
11月
12月