ChatGPT と ROS – 文書生成 ROS ラッパー生成編(Chat Completion API)

著者:yamamoto.yosuke

ChatGPT と ROS – 文書生成 ROS ラッパー生成編(Chat Completion API)

本シリーズ前回の記事 ChatGPT と ROS – 文書生成 ROS ラッパー利用編(Completion API) では OpenAI API の ROS ラッパーの中で Completion API を利用している ROS1 の Python ラッパ https://github.com/davesarmoury/openai_ros を使ってみました.

今回は OpenAI の Chat Completion API を利用した ROS ラッパ Python プログラムを Web サービスの方の ChatGPT の助けをかりながら作成した様子を紹介します.

OpenAI の文書生成 API 概要

本シリーズ第1回の記事 ChatGPT と ROS – 調査編 でもふれましたが OpenAI の文書生成 API について簡単にまとめますと,「1問1答形式」の Completion API と,「対話した文脈を含むチャット対話形式」の Chat Completion API の2つがあります.

  • OpenAI の文書生成 API
    • Completion API : 1問1答形式
    • Chat Completion API : 文脈を含むチャット対話形式

前回の記事ではこの2つのうち「1問1答」形式の Completion API を利用ました.今回の記事ではもう一方の「チャット対話」形式のインタフェースである Chat Completion API を ROS から利用してみます.

開発・実行環境

今回は Web サービスの ChatGPT に Chat Completion API を使ったプログラムを生成してもらいながら進めましたのでそれも含めて開発・実行環境の構成は次のようになっています.

  • Ubuntu 20.04
  • ROS Noetic
  • OpenAI ChatGPT のアカウントを持っている(今回筆者は ChatGPT-4 を利用)
  • OpenAI API の利用が有効なアカウントを持っている
    • API Key を取得済

ChatGPT でのプログラム生成

まずは ChatGPT の Web サービスに ChatGPT の Python API にアクセスするための Python プログラムを書いてもらいました.

User

ChatGPT の Python API を用いたアクセスプログラムを書いてください.


ChatGPT

まず,OpenAIのPythonクライアントライブラリをインストールする必要があります.次のコマンドでインストールできます.

pip install openai

そして,以下はOpenAIのGPTを使用するための基本的なPythonコードです.この例では,プロンプトとして”Translate the following English text to French: ‘{}'”を使用し,その'{}’の部分に翻訳したい英文を挿入しています.

import openai

openai.api_key = 'your-api-key'

response = openai.ChatCompletion.create(
  model="gpt-4.0-turbo",
  messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Translate the following English text to French: '{}'"}
    ]
)

print(response['choices'][0]['message']['content'])

上記のコードは,APIキーを設定し,特定のモデル(この場合は”gpt-4.0-turbo”)を指定して,ChatCompletion APIを呼び出す基本的な構造を示しています.messagesパラメータは会話の履歴を表し,最初のメッセージは通常,モデルに役割(この場合は”helpful assistant”)を設定するためのシステムメッセージです.ユーザーメッセージはその後に続きます.

注意: ‘your-api-key’の部分は,OpenAIから提供される実際のAPIキーに置き換える必要があります.また,APIの使用は料金が発生しますので,公式ドキュメンテーションを確認して使用制限とコストを理解することが重要です.

なお,GPT-4のリリース後もAPIの基本的な使い方はこれまでと同様ですが,詳細な情報や更新内容についてはOpenAIの公式ドキュメンテーションをご覧ください.

次にこの ChatGPT にアクセスする Python コードを ROS の Service に対応させたプログラムを作成してもらいました.

User

この Python プログラムから ROS の service プログラムラッパーを作成してください.


ChatGPT

ROS (Robot Operating System)は,ロボットのためのフレームワークで,様々なハードウェアやソフトウェアの要素を組み合わせて使うことができます.ここでは,PythonのOpenAI GPT-4クライアントをROSサービスとしてラップする基本的な例を示します.

まず,適切なメッセージタイプを使用するためのsrvファイルを作成します.この例では,リクエストとレスポンスが共に一つの文字列を持つシンプルなサービスを定義します.

# GptService.srv
string input
---
string output

次に,このサービスを実装するPythonのROSノードを作成します.このノードは,指定された文字列を翻訳するサービスを提供します.

#!/usr/bin/env python
import rospy
from openai_ros.srv import GptService, GptServiceResponse
import openai

def handle_gpt_request(req):
    openai.api_key = 'your-api-key'
    
    response = openai.ChatCompletion.create(
        model="gpt-4.0-turbo",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": "Translate the following English text to French: '{}'".format(req.input)}
        ]
    )

    return GptServiceResponse(response['choices'][0]['message']['content'])

def gpt_service():
    rospy.init_node('gpt_service')
    s = rospy.Service('gpt_service', GptService, handle_gpt_request)
    print("Ready to translate English text to French.")
    rospy.spin()

if __name__ == "__main__":
    gpt_service()

このPythonスクリプトは,ROSノードgpt_serviceを作成し,それがGptServiceサービスを提供するようにします.サービスリクエストが来ると,handle_gpt_request関数が呼び出され,その中でOpenAIのGPT-4クライアントが使われてリクエストされたテキストを翻訳します.

このスクリプトをROSノードとして実行するためには,そのファイルに実行可能なパーミッションを与える必要があります.以下のコマンドで実行可能なパーミッションを与えることができます:

chmod +x gpt_service.py

また,OpenAIのAPIキーを設定する部分では,実際のキーに’your-api-key’を置き換える必要があります.そして,APIの使用は料金が発生しますので,公式ドキュメンテーションを確認して使用制限とコストを理解することが重要です.

なお,上記のコードはあくまで一例であり,具体的な使用シーンや要件によりますので,適宜修正や拡張を行ってください.

ChatGPT に最初に生成してもらった Python プログラムにおいてプロンプトの内容が固定されているため,それを基に生成した ROS ラッパープログラムも固定プロンプトへの応答結果を出すだけになってしまいました.

そこでプロンプトを変更可能なようにプログラムを変更してもらいました.

User

ChatGPT に問うプロンプトを変えられるようにプログラムを変更してください.


ChatGPT

もちろんです.以下に,GPTサービスリクエストにプロンプトを含めるように改変したROSサービスの例を示します.

まず,新たなsrvファイルを作成します.この例では,リクエストにプロンプトとインプットの2つの文字列を持つサービスを定義します.

# GptService.srv
string prompt
string input
---
string output

次に,このサービスを実装するPythonのROSノードを作成します.

#!/usr/bin/env python
import rospy
from openai_ros.srv import GptService, GptServiceResponse
import openai

def handle_gpt_request(req):
    openai.api_key = 'your-api-key'
    
    response = openai.ChatCompletion.create(
        model="gpt-4.0-turbo",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": "{} '{}'".format(req.prompt, req.input)}
        ]
    )

    return GptServiceResponse(response['choices'][0]['message']['content'])

def gpt_service():
    rospy.init_node('gpt_service')
    s = rospy.Service('gpt_service', GptService, handle_gpt_request)
    print("Ready to handle GPT-4 requests.")
    rospy.spin()

if __name__ == "__main__":
    gpt_service()

このPythonスクリプトは,ROSノードgpt_serviceを作成し,それがGptServiceサービスを提供するようにします.サービスリクエストが来ると,handle_gpt_request関数が呼び出され,その中でOpenAIのGPT-4クライアントが使われてリクエストされたプロンプトとテキストを処理します.

上記のコードを実行する前に,Pythonスクリプトに実行可能なパーミッションを与えることを忘れないでください.

ここまでの ChatGPT の応答で ROS の Python プログラムとして動きそうな感じのソースコードが生成されたように思いましたので実際に実行しながら修正してみることにしました.

ChatGPT が生成したプログラムの修正

今回は ChatGPT と ROS – 文書生成 ROS ラッパー利用編(Completion API) で利用した ROS パッケージ https://github.com/davesarmoury/openai_ros をベースに Chat Completion API を利用する機能を付け加えるかたちで進めました.

ChatGPT が生成した Chat Completion API を利用する ROS Python プログラムを使って Chat Completion API を利用できるよう ROS パッケージに変更を加えた箇所をまとめると次のようになります.

  • openai_chat_node.py の追加
    • ChatGPT が生成したコードからの修正点
      • #!/usr/bin/env python
        • → Python3 に #!/usr/bin/env python3
      • openai.api_key = 'your-api-key'
        • → ROS パラメータから取得する方法に変更
          openai.api_key = rospy.get_param('~key')
      • model="gpt-4.0-turbo",
        • → GPT 3.5 に変更 model="gpt-3.5-turbo",
      • print("Ready to handle GPT-4 requests.")
        • → GPT 3.5 に変更 print("Ready to handle GPT-3.5 requests.")
  • GptService.srv の追加
    • ChatGPT が生成したコードをそのまま利用
  • CMakeLists.txs 内に GptService.srv の記述追加
  • openai_chat.launch の追加
    • 主に OpenAI API Key を ROS パラメータとするために作成

openai_chat_node.py

#!/usr/bin/env python3
import rospy
from openai_ros.srv import GptService, GptServiceResponse
import openai

def handle_gpt_request(req):
#    openai.api_key = 'your-api-key'
    openai.api_key = rospy.get_param('~key')
    
    response = openai.ChatCompletion.create(
#        model="gpt-4.0-turbo",
        model="gpt-3.5-turbo",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": "{} '{}'".format(req.prompt, req.input)}
        ]
    )

    return GptServiceResponse(response['choices'][0]['message']['content'])

def gpt_service():
    rospy.init_node('gpt_service')
    s = rospy.Service('gpt_service', GptService, handle_gpt_request)
#    print("Ready to handle GPT-4 requests.")
    print("Ready to handle GPT-3.5 requests.")
    rospy.spin()

if __name__ == "__main__":
    gpt_service()

プログラムの本筋の部分は ChatGPT が生成したコードから修正の必要はありませんでした.

GptService.srv

# GptService.srv
string prompt
string input
---
string output

CMakeLists.txt

add_service_files(
  FILES
  Completion.srv
  GptService.srv
)

GptService.srv のサービスが利用できるように CMakeLists.txt に加筆しました.このあたりの修正箇所の洗い出しも ChatGPT に問うてみるのも修正規模が大きい場合にはありかもしれません.

openai_chat.launch

<launch>
  <arg name="key" default="$(env OPENAI_API_KEY)" />
  <arg name="max_tokens" default="256" />
  <arg name="model" default="gpt-4.0-turbo" />

  <node pkg="openai_ros" type="openai_chat_node.py" name="openai_chat" output="screen">
    <param name="key" value="$(arg key)" />
    <param name="max_tokens" value="$(arg max_tokens)" />
    <param name="model" value="$(arg model)" />
  </node>  
</launch>

モデルを GPT-3.5 と GPT-4 で launch オプションで切り替えて使おうかと思っていたのですが,Web と API への課金は別らしく今回は API では GPT-3.5 のみ利用可能な状況でしたので openai_chat_node.py にモデル名を直書きしたまま使ってしまいました.

修正したプログラム実行の様子

roslaunch openai_ros openai_chat.launch を起動してからもう1つのターミナルで ROS サービスで rosservice call /gpt_service '{prompt: "(プロンプト)", input: "(内容)"}'
output: "Mon nom est Robotuser."
のように利用します.

ターミナル1

robotuser@robotuser-PC:~/openai_ws$ source ~/openai_ws/devel/setup.bash
robotuser@robotuser-PC:~/openai_ws$ roslaunch openai_ros openai_chat.launch 
... logging to /home/robotuser/.ros/log/9d61ced2-f54d-11ed-b5ca-c10df8d90fa9/roslaunch-robotuser-PC-41157.log
Checking log directory for disk usage. This may take a while.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.

started roslaunch server http://robotuser-PC:35595/

SUMMARY
========

PARAMETERS
 * /openai_chat/key: sk-3JDluBbxsNuIhi...
 * /openai_chat/max_tokens: 256
 * /openai_chat/model: gpt-4.0-turbo
 * /rosdistro: noetic
 * /rosversion: 1.16.0

NODES
  /
    openai_chat (openai_ros/openai_chat_node.py)

auto-starting new master
process[master]: started with pid [41165]
ROS_MASTER_URI=http://localhost:11311

setting /run_id to 9d61ced2-f54d-11ed-b5ca-c10df8d90fa9
process[rosout-1]: started with pid [41175]
started core service [/rosout]
process[openai_chat-2]: started with pid [41182]
Ready to handle GPT-3.5 requests.

ターミナル2

robotuser@robotuser-PC:~/openai_ws$ source ~/openai_ws/devel/setup.bash
robotuser@robotuser-PC:~/openai_ws$ rosservice call /gpt_service '{prompt: "Translate following to French:", input: "My name is Robotuser."}'
output: "Mon nom est Robotuser."
robotuser@robotuser-PC:~/openai_ws$ rosservice call /gpt_service '{prompt: "Translate following to Spanish:", input: "My name is Robotuser."}'
output: "Mi nombre es Robotuser."
robotuser@robotuser-PC:~/openai_ws$ rosservice call /gpt_service '{prompt: "Translate following to Japanese:", input: "My name is Robotuser."}'
output: "\u79C1\u306E\u540D\u524D\u306F\u30ED\u30DC\u30C3\u30C8\u30E6\u30FC\u30B6\u30FC\u3067\
  \u3059\u3002"
robotuser@robotuser-PC:~/openai_ws$ 
  • 注)コマンド全体は横スクロールにて表示してください.

このサービス利用例では “My name is Robotuser.” をフランス語,スペイン語,日本語に翻訳するよう各プロンプトを送りました.
日本語への翻訳指示した output が文字コード化していたので Unicode 変換すると次のようになりました.

私の名前はロボットユーザーです.

このように ChatGPT の Web サービスを利用してコードを生成してもらい,OpenAI の Chat Completion API を ROS から利用できるようになりました.

しかし今回のプログラムは Chat Completion API を用いているものの「1問1答」形式の使い方をしていて,それは Completion API を利用している場合と大きく変わらず, “文脈” をふまえた「チャット」形式ではありませんでした.

本シリーズ次回の記事では今回の Chat Completion API を利用する ROS サービスプログラムを文脈をふまえた「チャット」をする ROS プログラムに改造した様子をお伝えする予定です.

ChatGPT と ROS - 文書生成 ROS ラッパー利用編(Completion API)
ChatGPT と ROS – ROS Service プログラムの文脈をふまえたチャット対応

著者について

yamamoto.yosuke administrator

コメントを投稿するにはログインしてください。