ChatGPTのみで簡単なAPIを作成してみたかった

# ChatGPT君の性能を図るためとAPIが作りたかったのでやってみた
なお、今回ChatGPTを使用するにあたって、使用したモデルはGPT-3.5で、すべての命令文の前に
```
これからの会話は、英語で調べて日本語で解説をお願いします。加えて、段階的かつ論理的に考えてください。
```
を追加しています。

## APIの作成
というわけで最初の命令とその返信。
#### 命令
```
PythonでAPIを作成しようと考えています。
APIにテキストを与えるとそのテキストをjson形式で返してくれるようなプログラムを考えてください。なお、使用するパッケージにはFlaskを使用してください。
```

帰ってきたコマンドがこれ。
```python:app.py
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/api/convert_text', methods=['GET'])
def convert_text():
    text = request.args.get('text')
    json_text = {'text': text}
    return jsonify(json_text)

if __name__ == '__main__':
    app.run(debug=True)
```

実行して問題なく動作。
```text:送信したURL
http://localhost:5000/api/convert_text?text=Hello%20World
```
```text:返ってきたjson
{
  "text": "Hello World"
}
```

## 動作環境の作成
Docker及びnginxとuWSGIを使ってこのAPIをDocker上で動作させる。

ここで筆者はまだAPIをちゃんと作ったことがないためちょっと勉強の要素も追加してみる。
```text:命令文
このプログラムをDockerfileとDocker-composeを使って環境構築をして、コンテナ上で動作させたいと考えています。
Webサーバーにはnginxを、APサーバーにはuWSGIを使用し、この2つはソケット通信させます。
また、APIのプログラムはubuntuで動作させたいと考えています。
ですが、私はAPIの作成の知識に乏しく、できれば答えを出力するのではなく、やるべきことを問題形式にしてこちらが勉強できるようにしてほしいです。これは可能ですか？
```
#### 回答文
1. まず、Dockerfileを作成します。このDockerfileは、APIのPythonコードを含むイメージを作成するために使用されます。以下の手順に従って、Dockerfileを作成してください。

    - Ubuntu 18.04をベースイメージとして使用します。
    - 必要なパッケージをインストールするために、apt-getを使用します。必要なパッケージは、python3, python3-pip, nginx, uwsgi, uwsgi-plugin-python3です。
    - APIのPythonコードを /app ディレクトリにコピーします。
    - 依存関係をインストールするために、pip3を使用して、 Flaskをインストールします。
    - ENTRYPOINT コマンドを使用して、APIのPythonコードを実行します。

2. 次に、Docker Composeファイルを作成します。このファイルは、APIのDockerコンテナを起動し、nginxとuWSGIの設定を行います。以下の手順に従って、Docker Composeファイルを作成してください。

    - 2つのサービスを定義します。1つはAPIのサービスで、もう1つはnginxのサービスです。
    - APIサービスは、先に作成したDockerfileを使用して、コンテナを起動します。
    - nginxサービスは、nginxの設定ファイルをマウントします。これにより、nginxの設定を変更できます。また、APIサービスとの通信に使用するuWSGIソケットを指定します。
    - APIサービスは、ポート5000で公開されます。

3. 最後に、APIのPythonコードを作成します。このPythonコードは、Flaskを使用してAPIを作成します。APIは、JSON形式でテキストを受け取り、JSON形式で返します。

以上の手順に従って、APIをDockerコンテナで実行することができます。

ちゃんと問題が出力された。

## 実際に作成したコードと出力されていた回答
想定していた環境とはちょっと違ったのと、途中で気が変わったので出された問題の解答とはかなり違うコードになった。

また、こちらの問題設定が悪いのか、あるいは理解が足りないのかこの辺なくていいの？ってファイルがいくつあった。

### wsgi.py
#### 実装
```python:wsgi.py
from app import app 

if __name__ == '__main__':
    app.run()

```
#### 回答
wsgi.pyは回答に存在しなかった。

### uwsgi.ini
#### 実装
```ini:uwsgi.ini
[uwsgi]
module = wsgi:app
master = true
socket = /tmp/uwsgi.sock
chmod-socket = 666
wsgi-file = /app/wsgi.py
logto = /log/uwsgi.log
```
#### 回答
uwsgi.iniは回答に存在しなかった。

### Dockerfile
#### 実装
途中で気が変わったのでだいぶ違くなった。
```Dockerfile:Dockerfile
FROM python:3.9.12

WORKDIR /app
ENV FLASK_APP=app

COPY ./requirements.txt /app

RUN pip3 install -r requirements.txt
```
#### 回答
```Dockerfile:Dockerfile
# Base image
FROM ubuntu:18.04

# Install necessary packages
RUN apt-get update && \
    apt-get install -y python3 python3-pip nginx uwsgi uwsgi-plugin-python3

# Copy the code into the container
COPY . /app

# Install dependencies
RUN pip3 install Flask

# Set working directory
WORKDIR /app

# Run the Python script
ENTRYPOINT ["python3", "app.py"]
```

### docker-compose.yaml
#### 実装
```yaml:docker-compose.yaml
version: '3'
services:
  api:
    build: .
    volumes:
      - ./app:/app
      - ./log:/log
      - socket:/tmp
    command: uwsgi --ini /app/uwsgi.ini

  nginx:
    image: nginx
    ports:
      - "8080:80"
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
      - socket:/tmp

volumes:
  socket:

```
#### 回答
```yaml:docker-compose.yaml
version: '3'

services:
  api:
    build: .
    ports:
      - "5000:5000"

  nginx:
    image: nginx
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - api
    ports:
      - "80:80"
```
### default.conf
#### 実装
```conf:default.conf
server {
    listen 80;
    server_name localhost;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:///tmp/uwsgi.sock;
    }
}

```
#### 回答
```conf:default.conf
events {}

http {
    upstream uwsgi {
        server api:5000;
    }

    server {
        listen 80;

        location / {
            uwsgi_pass uwsgi;
            include uwsgi_params;
        }
    }
}

```


## 感想
### いいと思うところ
- どういう原理で動いているのかわからない時などの質問は有効だと感じた。
- 今回のプログラムのような単一で動作する、あるいは使うパッケージが決まっているようなプログラムを書かせるのも有効だと感じた。
- また、新しい技術を学んだはいいけれど作るものが思い浮かばない場合に、今回みたいに問題を出させて解くのは有効だと感じた。
- プログラムの解説もある程度は有効だと感じた。ただ、より詳しい解説を引き出すにはある程度プロンプトの工夫が必要だと思う。また、長く書かせようとするとtoken制限に引っかかったり、timeoutしたりするので、その辺が結構めんどくさい。

### 微妙だと思うところ
- Dockerの設定をやらせるのは結構しんどく感じた。どんなimageを使うのかなどが決まっていても、自分の想定している環境と出してくれる環境が異なることが多かった。もしかしたら自分の知らないやり方を出してくれているのかもしれないが、現状やはり自分の理解が足りないとそれがうまくいくのかわからないし、思った通りの環境を構築させるのはかなりちゃんとしたプロンプトを書いてあげる必要があると思った。この辺は仕様書などを書いた経験があるともっとうまくできるのかもしれない。
- timeoutとかnetwork errorとかで途中で生成が止まったときに、やり直すと書いてあることが変わるのが結構めんどくさい。こちらも、いろいろな書き方があるDocker関連のファイルでよく見られた。あとは特定の部分を修正してもらおうとすると、全体が変わったりすることもたまにあった。
- 問題形式で出すことはできるが、その問題が正しいのかわからないので理解を深めるのに問題を出してもらうのに、理解していないと問題が正しいかわからないってことになりそう。

## 結論
結局今回使っているのはChatGPT3.5君なのでGPT-4君ならすべて解決してくれているかもしれない。また、まだまだGPTの使用経験が足りないだけでもっと使いこなせればすいすい開発できるようになるような気もした。

ただ、環境構築はともかくとしてPythonの単純なアプリケーションはものすごく簡単に実装できるようになるだろなとも思った。