【ROS2/Python】ChatGPTのAPIと連携するROS2ノードを作った

# はじめに
ROS 2でChatGPTを使える`chatgpt_ros`を作って公開しました。
使い方等をまとめます。

https://github.com/koichirokato/chatgpt_ros

# 環境
以下の環境で動作を確認しています。

| 項目 | バージョン |
|:-: | :-:|
| Windows |  11 |
| WSL | 2 |
| Ubuntu | 22.04 |
| ROS2 | Humble |

# 準備
OpenAIのAPIの取得と、ROSノードのインストールを行います。

## OpenAIのAPIの取得

OpenAI APIを利用するためには、OpenAIの公式サイトからAPI Keyを取得する必要があります。
API Keyの取得方法については、OpenAIのドキュメントを参照してください。

https://platform.openai.com/

取得したAPIは`ChatGPT_API`という環境変数に設定してください。

```shell
export ChatGPT_API=XXX
```

## パッケージのインストール

以下のコマンドを実行して、ChatGPT ROS2パッケージをインストールします。

```shell
$ cd ~/ros2_ws/src
$ git clone https://github.com/koichirokato/chatgpt_ros
$ cd ..
$ colcon build --symlink-install --packages-select chatgpt_ros
$ source install/setup.bash
$ source install/local_setup.bash
```

# ROSノードの実行
## Publish/Subscribe通信の使用
`chatgpt_ros`ノードは、`/input_text` トピックに対して質問をsubscribeし、`/output_text` トピックに回答をpublishします。
この場合、APIから取得する回答の長さを意味するmax_tokensは50で固定です。

```shell
$ ros2 run chatgpt_ros chatgpt_ros
```

以下のコマンドを実行して、`/input_text` トピックにメッセージを送信し、ChatGPT ROS2パッケージからの回答を取得します。

```shell
$ ros2 topic pub /input_text std_msgs/String "data: 'Hello, ChatGPT.'" -1
```

```shell
$ ros2 topic echo /output_text
```

```shell:ros2 topic echoの出力例
data: '


  Hello there! How can I assist you today?'
```


## サービスの実行
`chatgpt_ros_service`ノードは、`/chat_gpt_service`サービスに対して質問と回答の長さを指定して送信し、回答を取得します。

```shell
$ ros2 run chatgpt_ros chatgpt_ros_service
```

以下のコマンドを実行して、/chat_gpt_service サービスに質問を送信し、ChatGPT ROS2パッケージからの回答を取得します。
lengthにはAPIからの回答の文字列の長さを入力します。

```
$ ros2 service call /chatgpt_service chatgpt_ros_interfaces/srv/ChatGptService "{text: 'What is your name?', length: 50}"
```

```shell:ros2 service callの出力例
waiting for service to become available...
requester: making request: chatgpt_ros_interfaces.srv.ChatGptService_Request(text='What is your name?', length=50)

response:
chatgpt_ros_interfaces.srv.ChatGptService_Response(response='\n\nAs an AI language model, I do not have a name. You can call me OpenAI. How may I assist you?')
```


要するに、以下の会話をしていますね。
ROS2側：
What is your name?

API：
As an AI language model, I do not have a name. You can call me OpenAI. How may I assist you?

### サンプルのサービスクライアント（チャットボット形式）

また、サンプルのサービスクライアントも用意しました。
`chatgpt_ros_service`ノードが立ち上がっている状態で以下のコマンドを実行してください。
チャットボットのような形でAPIと会話することができます。

```
$ ros2 run chatgpt_ros client_sample
```

#### 実行例
ROS2のノードの使い方を教えてもらいました。サービス呼び出し時のlength(max_tokens)は500です。

```
$ ros2 run chatgpt_ros client_sample
[INFO] [1678279970.949053631] [chat_gpt_service_client]: Please enter your prompt for ChatGPT API. If you want to exit, please enter "quit"
> How do I make ROS2 node?
As an AI language model, I cannot provide the exact steps for creating a ROS2 node as it requires technical knowledge and coding skills. However, I can provide a brief overview of the process:

1. Install ROS2 on your system and set up the environment.

2. Create a new ROS2 package using the command line tool 'ros2 pkg create'.

3. Create a new node file within the package directory using a text editor or an Integrated Development Environment (IDE).

4. Define the node's name, namespace, and any required parameters.

5. Implement the node's functionality using ROS2 APIs such as Publishers, Subscribers, Services, and Actions.

6. Build the package using the command 'colcon build'.

7. Run the node using the command 'ros2 run <package_name> <node_name>'.

For more detailed information and tutorials on creating ROS2 nodes, please refer to the official ROS2 documentation.
```

#### 実行例その2
ROS2のTwistメッセージのサンプルをJSON形式で渡してもらいました。サービス呼び出し時のlength(max_tokens)は同じく500です。

```
> Please show me sample Twist message for ROS2. Format is JSON.
Response:

{
   "header":{
      "seq":0,
      "stamp":{
         "sec":0,
         "nanosec":0
      },
      "frame_id":""
   
   "twist":{
      "linear":{
         "x":0.0,
         "y":0.0,
         "z":0.0
      },
      "angular":{
         "x":0.0,
         "y":0.0,
         "z":0.0
      }
   }
}

This is a sample Twist message for ROS2 in JSON format. It contains information about the linear and angular velocities of a robot. The "header" field includes a sequence number, timestamp, and frame ID. The "twist" field includes the linear and angular velocities of the robot. The "linear" field includes the x, y, and z components of the velocity, while the "angular" field includes the x, y, and z components of the angular velocity.
> Please show sample Twist message for stop command in ROS2. Format is JSON And you dont have to explain anything, your response is only JSON message.
Response:

{"op": "publish", "topic": "/cmd_vel", "msg": {"linear": {"x": 0.0, "y": 0.0, "z": 0.0}, "angular": {"x": 0.0, "y": 0.0, "z": 0.0}}}
```


# まとめ
ROS2でChatGPT APIを使用するROSノードを作成しました。可能性は無限大だと思います。
今後は、APIをもっと活用するべく、APIのリクエストに入れるパラメータの精査を行おうと思います。


# 関連情報
- ROS2で音声対話システムができるという情報もあります！！！

https://twitter.com/hakuturu583/status/1633267040575438848?s=20

- ROS1のC++で作成されたChatGPT APIを使用するROSノード 

https://github.com/Autumn60/chatgpt_ros

- APIの公式ページ

https://openai.com/blog/introducing-chatgpt-and-whisper-apis

[2023/3/11]
ROS newsで取り上げていただきました！

https://twitter.com/OpenRoboticsOrg/status/1634277559566495745

https://discourse.ros.org/t/ros-news-for-the-week-of-march-6th-2023/30233