ChatGPTで自然言語からスクリプトを生成するツールをChatGPTに作ってもらった

# 背景

https://qiita.com/hirokidaichi/items/6d568d5ddcb02a91edf4

こちらの記事にかなりインスパイアされています。この記事を読んで「なるほど便利そうだ」と思い、そのまま成果物を使わせてもらうのも良かったのですが、ふと思い立ってChatGPT自身にそのようなツールを作らせてみました。

# 結果

ちゃんと動くものができました。デモ:

```shell-session
$ python3 gpt_exec.py "Find hoge.txt in the current directory and its subdirectories"
Command: find . -name hoge.txt
Do you want to run this command? (y/n) y
./foo/hoge.txt
```

注意点:

* [ChatGPTは完璧ではありません](https://qiita.com/ko1nksm/items/7b17eefdec57640c2bfd)。実行する前にかならずコマンドを確認しましょう。
* 使ったのは話題のGPT-4ではなくGPT-3.5です。
* 元記事の`wanna`コマンドほど多機能ではありません。必要最低限。
* このコマンドは英語での入力を想定しています。日本語を入れてもだいたい動きそうですが。
* コマンドが使っているエンジンは`text-davinci-003`です。`gpt-3.5-turbo`のほうがコスト的には良いのですが、まだ試していません。

# ソースコード

```python:gpt_exec.py
import sys
import openai
import subprocess

# Set up OpenAI API credentials
openai.api_key = "YOUR_API_KEY_HERE"

# Define a function to get a Unix command from ChatGPT
def get_unix_command(prompt):
    # Set up the prompt for ChatGPT
    prompt_text = f"Convert the following English text to a Unix command:\n{prompt}\nCommand:"

    # Call OpenAI's GPT-3 to generate a Unix command
    response = openai.Completion.create(
        engine="text-davinci-003",
        prompt=prompt_text,
        temperature=0.5,
        max_tokens=50,
        top_p=1,
        frequency_penalty=0,
        presence_penalty=0
    )

    # Return the generated Unix command
    return response.choices[0].text.strip()

# Define a function to execute a Unix command
def execute_unix_command(command):
    # Print the command for the user to confirm
    print(f"Command: {command}")
    confirm = input("Do you want to run this command? (y/n) ")
    if confirm.lower() == "y":
        # Use subprocess to run the Unix command in the terminal
        subprocess.run(command, shell=True)

# Get the prompt from the command line argument
if len(sys.argv) < 2:
    print("Please provide a prompt as a command line argument.")
    sys.exit()
prompt = sys.argv[1]

# Get a Unix command from ChatGPT
command = get_unix_command(prompt)

# Execute the Unix command if the user confirms
execute_unix_command(command)
```

記事の最後のChatGPTとのやりとりを読むとわかりますが、このコードはChatGPTの最終的な出力ほぼそのままです。1点だけ、`engine`を`davinci`から`text-davinci-003`に書き換えました。そのほうが新しいらしいので…。

コードクオリティ的にもぱっと見、問題はないのではないでしょうか。まああえて言うなら:

* コメントがくどい。サンプルコードだと思えばこんなものか。
* `import`の順序が謎。何順？

# ChatGPTとのやりとり

以下に全文を貼っておきます。日本語でもできるかもしれませんが、まずは英語でやってみました。以下のような流れになっています:

* 要求を伝えてChatGPTに初期コードを生成してもらう。
* コード修正依頼1: 実行する前にユーザに確認すること
* コード修正依頼2: 標準入力ではなくコマンドライン引数からプロンプトを受け取ること

## 全文

**Me:** Give me a Python script which takes English text describing what to do as an argument (e.g., "count the number of lines in hoge.txt") and ask ChatGPT for a Unix command doing it, and then execute the command

**ChatGPT:** Here's a Python script that uses the openai and subprocess modules to take an English text input from the user, convert it to a Unix command using ChatGPT, and then execute the command:

```python
import openai
import subprocess

# Set up OpenAI API credentials
openai.api_key = "YOUR_API_KEY_HERE"

# Define a function to get a Unix command from ChatGPT
def get_unix_command(prompt):
    # Set up the prompt for ChatGPT
    prompt_text = f"Convert the following English text to a Unix command:\n{prompt}\nCommand:"

    # Call OpenAI's GPT-3 to generate a Unix command
    response = openai.Completion.create(
        engine="davinci",
        prompt=prompt_text,
        temperature=0.5,
        max_tokens=50,
        top_p=1,
        frequency_penalty=0,
        presence_penalty=0
    )

    # Return the generated Unix command
    return response.choices[0].text.strip()

# Define a function to execute a Unix command
def execute_unix_command(command):
    # Use subprocess to run the Unix command in the terminal
    subprocess.run(command, shell=True)

# Get English text input from the user
prompt = input("What do you want to do? ")

# Get a Unix command from ChatGPT
command = get_unix_command(prompt)

# Execute the Unix command
execute_unix_command(command)
```

To use this script, save it as a .py file on your computer and run it from the command line. When prompted, enter the English text describing what you want to do (e.g., "count the number of lines in hoge.txt"). The script will then use ChatGPT to generate a Unix command to accomplish that task, and execute the command in the terminal.

**Me:** It looks risky to run the command immediately. I don't trust you that much. Can you update the code to print the command and ask the user for confirmation before running the command?

**ChatGPT:** Certainly! Here's an updated version of the script that prints the generated Unix command and asks the user to confirm before executing it:

```python
import openai
import subprocess

# Set up OpenAI API credentials
openai.api_key = "YOUR_API_KEY_HERE"

# Define a function to get a Unix command from ChatGPT
def get_unix_command(prompt):
    # Set up the prompt for ChatGPT
    prompt_text = f"Convert the following English text to a Unix command:\n{prompt}\nCommand:"

    # Call OpenAI's GPT-3 to generate a Unix command
    response = openai.Completion.create(
        engine="davinci",
        prompt=prompt_text,
        temperature=0.5,
        max_tokens=50,
        top_p=1,
        frequency_penalty=0,
        presence_penalty=0
    )

    # Return the generated Unix command
    return response.choices[0].text.strip()

# Define a function to execute a Unix command
def execute_unix_command(command):
    # Print the command for the user to confirm
    print(f"Command: {command}")
    confirm = input("Do you want to run this command? (y/n) ")
    if confirm.lower() == "y":
        # Use subprocess to run the Unix command in the terminal
        subprocess.run(command, shell=True)

# Get English text input from the user
prompt = input("What do you want to do? ")

# Get a Unix command from ChatGPT
command = get_unix_command(prompt)

# Execute the Unix command if the user confirms
execute_unix_command(command)
```

Now, when you run the script and enter the English text describing what you want to do, the script will generate a Unix command and print it to the console. The script will then ask you to confirm whether you want to run the command or not. If you enter "y", the script will execute the command. If you enter "n", the script will exit without executing the command.

**Me:** Looks better. Can you also take the prompt as a command line argument rather than the standard input?

**ChatGPT:** Sure! Here's the updated script that takes the prompt as a command line argument:

```python
import sys
import openai
import subprocess

# Set up OpenAI API credentials
openai.api_key = "YOUR_API_KEY_HERE"

# Define a function to get a Unix command from ChatGPT
def get_unix_command(prompt):
    # Set up the prompt for ChatGPT
    prompt_text = f"Convert the following English text to a Unix command:\n{prompt}\nCommand:"

    # Call OpenAI's GPT-3 to generate a Unix command
    response = openai.Completion.create(
        engine="davinci",
        prompt=prompt_text,
        temperature=0.5,
        max_tokens=50,
        top_p=1,
        frequency_penalty=0,
        presence_penalty=0
    )

    # Return the generated Unix command
    return response.choices[0].text.strip()

# Define a function to execute a Unix command
def execute_unix_command(command):
    # Print the command for the user to confirm
    print(f"Command: {command}")
    confirm = input("Do you want to run this command? (y/n) ")
    if confirm.lower() == "y":
        # Use subprocess to run the Unix command in the terminal
        subprocess.run(command, shell=True)

# Get the prompt from the command line argument
if len(sys.argv) < 2:
    print("Please provide a prompt as a command line argument.")
    sys.exit()
prompt = sys.argv[1]

# Get a Unix command from ChatGPT
command = get_unix_command(prompt)

# Execute the Unix command if the user confirms
execute_unix_command(command)
```

To use this script, save it as a .py file on your computer and run it from the command line with the prompt as a command line argument. For example:

```shell
python my_script.py "count the number of lines in hoge.txt"
```

The script will generate a Unix command to accomplish the task described by the prompt and print it to the console. The script will then ask you to confirm whether you want to run the command or not.

# 蛇足

この記事を書くにあたり、ChatGPTがやった主な仕事はコードを書くこと、人間がやった主な仕事はChatGPTとのやりとりをコピペしてMarkdownで整形することでした。🤷‍♂️