【ツール開発】OpenAIのGPT-3によってデータの加工処理や可視処理のコードを自動生成する🛠コマンドを作成してみた

昨今話題となっている**OpenAI**によって公開された[**ChatGPT**](https://chat.openai.com/)が話題となっておりますが、ソースコードも生成させることができるようです。このモデル(GPT-3 text-davinci-003)を使ってデータの加工処理や可視化の処理など**データに関係する処理を自動生成するコマンド**を作成し公開してみた話です。



# 作成したコマンドのデモ
いい感じで使えるコードを出力してくれます。**是非使ってみてください。**
![dim_generate_from_file_path.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46662/1b639a52-7832-203f-899f-b216955dabac.gif)

今回開発したコマンドは以前Qiitaにも紹介した[**オープンデータパッケージマネージャ dim**](https://github.com/c-3lab/dim)というツールに組み込んだ形で公開しました。

**コマンドのインストール手順は以下の[記事のインストール手順](https://qiita.com/ryo-ma/items/0505f7790ad2b12bcdc2#dim%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)かリポジトリの[READMEのInstall the dim](https://github.com/c-3lab/dim#install-the-dim)を参照してみてください。**

https://qiita.com/ryo-ma/items/0505f7790ad2b12bcdc2

### Githubリポジトリ

https://github.com/c-3lab/dim

# デモの流れと共にコマンドを解説

## 1. コード自動生成 コマンドの実行

※ 注意：実際にこのコマンドを実行するには[OpenAIのAPIKey](https://platform.openai.com/account/api-keys)を環境変数`OPENAI_API_KEY`に設定する必要があります。APIKeyは[OpenAI公式](https://platform.openai.com/account/api-keys)で無料で入手できます。
```bash
$ export OPENAI_API_KEY=xxxxxxxxx
```

コード生成機能は`dim generate`コマンドによって実行されます。
引数では`propmt`というGPT-3に命令するための文章を渡します。
今回は`「csvデータをgeojsonに変換するpythonコード」`という`prompt`を渡しています。

```bash
$ dim generate "python code that converts this csv data to geojson"
```
この`prompt`の記述がかなり重要となってくるので[**イイ感じに使えるprompt一覧**](#イイ感じに使えるコードを出力できるprompt一覧)を後述いたします。

## 2. 対象データの指定

このコマンドの存在価値となるのがこのプロセスです。ここでは**変換の対象となるデータ**を指定しております。
この**対象データ**と**先ほど渡したprompt**をイイ感じに組み合わせてGPT-3(completion API)に送信してくれます。
今回のケースでは指定したファイルを対象としてcsvからgeojsonに変換するPythonコードをGPT-3によって出力させます。

ここでは対話形式でファイルパスを聞かれます。 

```bash
 ? Enter the target data name or file path to send to GPT-3 API. › ./data.csv
```
今回はサンプルの`data.csv`というファイル名を指定しています。
`data.csv`の中身は適当に[G空間センター 131202_東京都_練馬区_学校教育施設](https://www.geospatial.jp/ckan/dataset/13120-008)の区立幼稚園データを使いました。

#### そのほかの指定
* コマンド実行時に`-t`で対象データのファイルパスを指定することも可能
    * `-t`を指定した場合は対話形式で聞かれなくなります
* ここの対話形式や`-t`で指定できるのはファイルパスだけではなく本ツール**オープンデータパッケージマネージャ dim**で管理された**データ名**を指定することも可能
    * dimの管理に関しては前の[Qiita記事](https://qiita.com/ryo-ma/items/0505f7790ad2b12bcdc2)を参照


#### 注意すべき点
* ファイルの**token数**(APIが計測する文字列の数)が多いとBad requestとなってしまうので対象データのデータ量には注意が必要
    * 一度に送信できるtokenの限界値が`4096`なのでpromptも含めて収まるようにしなければなりません。
* 対策としては、APIへの送信において**構造さえ伝われば良い**ので構造を保ったままデータの件数を減らして対象ファイルを指定する
(将来的には対象データの構造を読み取って簡略化する機能を実装したい)



## 3. 生成したコードを保存するかどうか

今回は以下のようなPythonコードが生成されました。
このまま生成されたコードをファイルに保存する機能があるので、対話形式で保存に進んで良いか確認されます。

```python
import csv
import json

csv_file = open('data.csv', 'r')
reader = csv.DictReader(csv_file)

geojson = {
    'type': 'FeatureCollection',
    'features': []
}

for row in reader:
    feature = {
        'type': 'Feature',
        'properties': {
            'name': row['名称'],
            'address': row['所在地'],
            'phone': row['電話']
        },
        'geometry': {
            'type': 'Point',
            'coordinates': [
                float(row['経度']),
                float(row['緯度'])
            ]
        }
    }
    geojson['features'].append(feature)

with open('data.geojson', 'w') as f:
    json.dump(geojson, f, indent=4)
```

生成されたコードが気に入ったら`y`を入力します。

```
 ? Hit to save the file. (Y/n) › Yes
```

#### 確認する理由
* `prompt`次第で微妙なコードを生成する場合がある
* 実行するたびに揺らぎ(変化)もあるので気に入らない処理が生成される可能性がある
    * 揺らぎはAPIへ送るパラメータで限界まで抑えていますが、それでも揺らぎが発生することがある


## 4. ファイルパスを指定してコードを保存

対話形式で保存するファイルパスを指定すると記載通りにコードが保存されます。

```
 ? Enter a output file path. › ./convert_to_geojson.py
```

## 5. 保存したコードの実行

今回は生成されるコードを予測してデータのファイルパスの配置なども準備しておいたので、そのまま実行できる状態でした。

```bash
$ python3 ./convert_to_geojson.py
```

#### 注意すべき点
+ 生成されたコード内に埋め込まれたファイルパス(ファイル名)が大体適当な`./data.csv`などになっているので状況に応じて変更が必要な場合がある
    + ファイル名をpromptでうまく指定することできそうですが、この程度であれば直接書き換えを行ってしまっても手間ではないかと思います
+ 地図の可視化などをpromptで命令すると外部ライブラリを前提としたコードを出力してくる


以上がデモの流れの解説でした。

リポジトリのREADMEでもコマンドの使用例が記載されていますのでご覧ください。

https://github.com/c-3lab/dim#generate

# イイ感じに使えるコードを出力できる`prompt`一覧

データ処理においてAPIへ送信する、いい感じのprompt一覧をまとめておきます。
* **言語**など**ファイルフォーマット**などはこのpromptをベースにいい感じで変更して応用してもらえればと思います。
* 日本語を使ったり、自作の文で挑むと余計な自然言語が含まれてしまう可能性もあるので、以下の`prompt`を参考にするのがオススメです。
* 他にもいい感じの`prompt`があったらコメントなどで報告してもらえると嬉しいです。


### csvデータをgeojsonに変換するPythonコード

```
Python code that converts this csv data to geojson
```

### csvデータからid列を削除するPythonコード

```
Python code that remove id column from this csv data
```


### csvデータを地図に可視化するPythonコード

```
Python code that visualizes this csv data as a map
```

### csvデータをグラフに可視化するPythonコード

```
Python code that visualizes this csv data as a map
```

### csvデータをHTMLページに可視化するPythonコード

```
Python code that visualizes this csv data as HTML page
```

### csvデータをPostgreSQLに保存するPythonコード

```
Python code that saves this csv data to PostgreSQL
```

### csvファイルの全角数字を半角数字に変換するPythonコード

```
Python code that converts full-width numbers in this csv file to half-width numbers
```

### csvファイルの半角カタカナを全角カタカナに変換するPythonコード
```
Python code to convert half-width katakana in this CSV file to full-width katakana
```


# 振り返り

## 作成した理由
最後に語るような内容でもないですが、本ツール**オープンデータパッケージマネージャ dim**はオープンデータを体系的に管理していくためのツールで、そのプロセスの中には**後処理**と呼ばれる加工処理(xlsxをcsvに変換、文字コード変換等)がありました。dimはこの後処理をいくつか内蔵していますが、あらゆる処理を汎用的に用意することが難しいと感じておりました。データごとに異なる**非汎用的な処理に関しては結局独自にコードを書く必要**がありました。
そこで今回、GPT-3を使えば**データごとの非汎用的な後処理を生成**できると思いコード生成機能をdimに実装することにしました。

実はこのIaCが生成できるツールにインスパイアされました。https://github.com/gofireflyio/aiac

## 作成してみて
思ったよりイイ感じに動いたというのが感想です。それもOpenAIによるGPT-3の精度おかげです。しかし、まだプログラマーが不要なレベルではなく、**ソースコードのたたき台を作成**してくれるイメージです。前述したようにケースによっては生成したコードの一部を修正する必要があったり、生成するコードには揺らぎがあり完璧ではない可能性もあります。それでもGoogleで検索して動く動かないの動作確認をするよりも楽にはなる気がします。

## 今後
本コマンドはもう少し便利になる気がするので今後も開発を継続していきます。
* 便利なpromptのエイリアス
* 対象データファイルの複数指定
* tokenの制限を回避するため、対象データファイルの簡略化機能
* dimの管理情報ファイル(dim.json)に生成したファイルを後処理として追記する機能


**コントリビューションもお待ちしております。**

https://github.com/c-3lab/dim