ChatGPTにQiitaの記事を書いてもらう(深津式プロンプト・システム)

# はじめに

Pythonのプログラムに関するQiita記事をChatGPTに書いてもらうと、どれほどのクオリティのものができるのか試してみました。

題材は、形態素解析とマルコフ連鎖のライブラリを利用して文章を自動生成をするという、機械学習の入門としてよく利用される簡単なプログラムです。

最後に[**深津式プロンプト・システム**](https://qiita.com/Guruguru_Brain/items/e61e360db04e94969322#%E6%B7%B1%E6%B4%A5%E5%BC%8F%E3%83%97%E3%83%AD%E3%83%B3%E3%83%97%E3%83%88%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0)を活用した[**ChatGPTに良質な文章を作成してもらうコツ**](https://qiita.com/Guruguru_Brain/items/e61e360db04e94969322#chatgpt%E3%81%AB%E8%89%AF%E8%B3%AA%E3%81%AA%E6%96%87%E7%AB%A0%E3%82%92%E6%9B%B8%E3%81%84%E3%81%A6%E3%82%82%E3%82%89%E3%81%86%E3%82%B3%E3%83%84)を記載しております。

:::note warn
コードブロックの配置は主が行っています。**あくまで記事の構成と見出し、解説文をChatGPTに考えてもらった**という内容になりますので、あしからず。
なお、文章生成の基となるテキストファイルは[青空文庫](https://www.aozora.gr.jp/index.html)から著作権が切れたものを使用させていただきました。
:::

# <font color="Gray">↓ ここからChatGPTが書いた記事 ↓</font>


## 目標成果物と実行結果
Pythonプログラムで、指定されたフォルダ内のテキストファイルを読み込み、MeCabを使って形態素解析を行います。分割されたテキストをマルコフ連鎖モデルに入力し、ランダムな文章を生成します。

```python:paperback_writer.py
import os
import MeCab
import ipadic
import markovify


folder_path = 'C:/PythonWorkspace/paperback text/'

def main():
    # フォルダ内のすべての.txtファイルを読み込み
    for file_name in os.listdir(folder_path):
        if file_name.endswith('.txt'):
            file_path = os.path.join(folder_path, file_name)
            with open(file_path, 'r', encoding='utf-8') as f:
                text = f.read()

    mecab = MeCab.Tagger(ipadic.MECAB_ARGS)

    # 上手く解釈できない文字列を定義しておく
    breaking_chars = ['(', ')', '[', ']', '"', "'", '《', '》']
    # 最終的に1文に収めるための変数
    splitted_text = ''

    for line in text:
        print(line)
        # lineの文字列をパースする
        parsed_nodes = mecab.parseToNode(line)

        while parsed_nodes:
            try:
                # 上手く解釈できない文字列を飛ばす
                if parsed_nodes.surface not in breaking_chars:
                    splitted_text += parsed_nodes.surface
                # 句読点以外であればスペースを付与して分かち書き
                if parsed_nodes.surface != '。' and parsed_nodes.surface != '、':
                    splitted_text += ' '
                # 句点が出てきたら文章の終わりと判断して改行を付与
                if parsed_nodes.surface == '。':
                    splitted_text += '\n'
            except UnicodeDecodeError as error:
                print('Error : ', line)
            finally:
                # 次の形態素に上書きする。なければNone
                parsed_nodes = parsed_nodes.next

    print('解析結果 :\n', splitted_text)

    # マルコフ連鎖のモデルを作成
    model = markovify.NewlineText(splitted_text, state_size=2)

    # 文章を生成する
    sentence = model.make_sentence(tries=100)
    if sentence is not None:
        # 分かち書きされているものを結合し出力する
        print(''.join(sentence.split()))
    else:
        print('None')

if __name__ == "__main__":
    main()
```

```text:C:/PythonWorkspace/paperback text/gacha_gacha.txt
がちゃがちゃ

夢野久作 著

草の中で虫が寄り合って相談を始めました。
　蟋蟀が立ち上って、
「鈴虫さん、オケラさん、スイッチョさん。もっとこちらへお寄りなさい。だんだん涼しくなりますから、みんなで合奏会をやってお月様にきかせようではありませんか。きっと御ほうびを下さいますよ」
　と言いますと、皆パチパチと手をたたきました。
　虫たちはそれからすぐに合奏を始めました。
　まず･･･
```

```markdown:実行結果
草の中で虫が飛び込んで来ました、虫たちもみんなで合奏を始めました。
```

#### 形態素解析とは
形態素解析とは、文を形態素と呼ばれる最小単位に分割し、それぞれの形態素に品詞を付与することです。たとえば、「私はピーマンを食べる」という文を形態素解析すると、「私」「は」「ピーマン」「を」「食べる」という形態素に分割され、それぞれの形態素に「代名詞」「助詞」「名詞」「助詞」「動詞」といった品詞が付与されます。形態素解析を行うことで、テキストデータをより細かく分析することができ、自然言語処理の分野で広く用いられています。

#### マルコフ連鎖とは
マルコフ連鎖とは、次に来る単語が、前に来た単語によって決まる確率的なモデルです。たとえば、「私はピーマンを食べる。私は犬と猫を飼った。」という文章があった場合、マルコフ連鎖を使って文章の生成を行うことができます。つまり、「私は」という単語に続く単語は、「ピーマンを」「犬と猫を」のいずれかであり、それぞれの単語に続く単語が決まります。このように、前に来た単語によって次に来る単語を決めることで、文章を自動的に生成することができます。

## テキストファイルの読み込み処理
以下のコードは、指定されたフォルダ内にあるすべての.txtファイルを読み込む方法を示しています。この処理には、Pythonの組み込みモジュールである`os`と`open`を使用します。
```python:paperback_writer.py
folder_path = 'C:/PythonWorkspace/paperback text/'

def main():
    # フォルダ内のすべての.txtファイルを読み込み
    for file_name in os.listdir(folder_path):
        if file_name.endswith('.txt'):
            file_path = os.path.join(folder_path, file_name)
            with open(file_path, 'r', encoding='utf-8') as f:
                text = f.read()
```
`folder_path`には、読み込むファイルのあるフォルダのパスが含まれています。
`os.listdir`を使用して、指定されたフォルダ内のすべてのファイルとディレクトリを取得し、forループを使用して、ファイルのリストの各要素に対して処理を実行します。if文を使用して、ファイルが.txtファイルであることを確認し、ファイルのパスを生成します。最後に`with`を使用して、ファイルを開き、その中身を読み込みます。

## 文章を分かち書きする処理
```python:paperback_writer.py
mecab = MeCab.Tagger(ipadic.MECAB_ARGS)

# 上手く解釈できない文字列を定義しておく
breaking_chars = ['(', ')', '[', ']', '"', "'", '《', '》']
# 最終的に1文に収めるための変数
splitted_text = ''
```
まず、`mecab = MeCab.Tagger(ipadic.MECAB_ARGS)` で、`MeCab`を用いて形態素解析するためのインスタンスを生成しています。また、上手く解釈できない文字列を除外するために `breaking_chars` というリストに除外したい文字列を格納しています。

```python:paperback_writer.py
for line in text:
    # lineの文字列をパースする
    parsed_nodes = mecab.parseToNode(line)

    while parsed_nodes:
        try:
            # 上手く解釈できない文字列は飛ばす
            if parsed_nodes.surface not in breaking_chars:
                splitted_text += parsed_nodes.surface
            # 句読点以外であればスペースを付与して分かち書きをする
            if parsed_nodes.surface != '。' and parsed_nodes.surface != '、':
                splitted_text += ' '
            # 句点が出てきたら文章の終わりと判断して改行を付与する
            if parsed_nodes.surface == '。':
                splitted_text += '\n'
        except UnicodeDecodeError as error:
            print('Error : ', line)
        finally:
            # 次の形態素に上書きする。なければNoneが入る
            parsed_nodes = parsed_nodes.next

print('解析結果 :\n', splitted_text)
```
文章を分かち書きする処理は、形態素解析によって、文章を単語や形態素に分割する処理です。この処理によって、文章を扱いやすい単位に分割することができます。
また、上手く解釈できない文字列を除外するため、定義したリスト内の文字列を含む単語や形態素は除外されます。また、句読点以外はスペースで区切り、句点が出てきたら改行を付与することで、分かち書きされた文章を出力しています。

## マルコフ連鎖モデルの構築
```python:paperback_writer.py
# マルコフ連鎖のモデルを作成
model = markovify.NewlineText(splitted_text, state_size=2)
```
ここでは、マルコフ連鎖を使ったモデルを作成します。具体的には、`markovify`というライブラリを用いて、文章を読み込んで、分かち書きされた単語の系列を元に、状態数を2とするマルコフ連鎖モデルを作成します。このモデルを用いることで、自然言語処理による文章生成を行うことができます。

## 文章生成処理
```python:paperback_writer.py
# 文章を生成する
sentence = model.make_sentence(tries=100)
if sentence is not None:
    # 分かち書きされているのを結合して出力する
    print(''.join(sentence.split()))
else:
    print('None')
```
`model.make_sentence()`関数で文章を生成します。`tries`パラメータは、文章生成の最大試行回数を設定するために使用されます。
次に、if文を使って、生成された文章がNoneでないことを確認します。文章がNoneでない場合、生成された文章は分かち書きされているので、`join()`関数を使って単語を結合し、出力します。`join()`関数は、文字列のリストを結合して1つの文字列にします。
`split()`関数は、文字列を単語のリストに分割します。
このようにして、生成された文章を分かち書きされた状態から、結合された状態に変換して出力することができます。

## プログラムを組んだ感想
このプログラムを組んで得た知見としては、マルコフ連鎖を用いた文章生成の実装方法を学びました。特に、MeCabという形態素解析エンジンを使って、日本語の文章を適切に分かち書きする方法が重要であることを学びました。また、マルコフ連鎖のモデルを構築する際には、状態の大きさ（`state_size`）を適切に設定することが必要であることを認識しました。さらに、生成された文章の品質を向上するためには、モデルの調整や生成条件の設定が重要であることを知りました。このプログラムを通じて、文章生成の面白さと難しさを実感し、今後のプログラミングに生かしていきたいと思います。

# <font color="Gray">↑ ここまでChatGPTが書いた記事 ↑</font>


# ChatGPTに良質な文章を書いてもらうコツ
以下の記事を参考にし、ChatGPTに指示を出しました。

https://delaymania.com/202302/webservice/chatgpt-fukatsu-prompt/

### 深津式プロンプト・システム
<iframe width="0" height="500" src="https://www.youtube.com/embed/ReoJcerYtuI" title="あなたの仕事が劇的に変わる!? チャットAI使いこなし最前線" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

noteのCXOを務める深津貴之さんが動画配信をした際に紹介した、ChatGPTの使いこなし術。

どうやらChatGPTを賢くさせるには「**“可能性空間”とでもいうべきものを限定すること**」が重要で、質問を投げる際には以下のことを意識するといいそうです。

:::note
<dl>
  <dt>1.役割を与える</dt>
  <dd>例:〇〇の観点で答えて</dd>
  <dt>2.文脈,前提条件を与える</dt>
  <dd>例:改善点教えて/危険度チェックして</dd>
  <dt>3.マークアップ言語で書き分け</dt>
</dl>
:::

これらの使いこなし術に則ったChatGPTへの指示方法が以下

```markup
# 命令書:
あなたはプロの編集者です。
以下の制約条件と入力文をもとに、最高の要約を出力してください。

# 制約条件:
・文字数は300文字程度。
・小学生にもわかりやすく。
・重要なキーワードを取り残さない。
・文章を簡潔に。

# 入力文:

# 出力文:
```
**「あなたは〇〇です。」**
すごい、こんな使い方があったとは...

このテンプレを活かしてChatGPTに指示を出し、Qiita記事を作っていきましょう。
### 1.まずは記事の見出しを考えてもらう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982328/3a27a3dd-38f4-1677-e85d-dccc074da91b.png)
これで記事の大まかな構成と見出しが出来上がります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982328/690ccc25-43eb-fa96-655e-15a186bed63e.png)
厳しめな制約をかけましたが、条件通りの見出しを考えてくれました。

### 2.見出しごとに解説文を考えてもらう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982328/b7ae77ac-dd12-2887-a5e0-72e78bd681e2.png)
解説文も深津式プロンプト・システムのテンプレを利用して依頼を投げます。
詳細に書くよう制約条件を付けました。
図などを出力してもらうことはできませんが、十分に理解できる文章が返ってきます。

### 3.必要に応じてより精度の高いものに
最高の回答をだすために、追加の情報が必要な場合は、質問をしてより精度の高い文章を求めましょう。
例:見出し1をもう少し簡潔なものにしてください。

# さいごに
ChatGPTが書いてくれた文章は、やはり機械っぽさが否めない印象を持ちました。
とはいえ、記事を書く前の大まかな構成を考えたり、本文を書くヒントを得るため大いに活用できそうですね。

### 動作環境
Windows11 Pro, Python3.11.1, mccabe0.7.0, markovify0.9.4, ipadic1.0.0

### 参考文献
 - [ChatGPTが賢くなる！noteの深津さん考案「深津式汎用プロンプト」でChatGPTが劇的に使いやすくなった！](https://delaymania.com/202302/webservice/chatgpt-fukatsu-prompt/)
 - [【Python初心者向け】形態素解析とマルコフ連鎖を使ってひろゆきっぽい文章を生成してみた](https://gakogako.com/python_hiroyuki/)
 - [青空文庫](https://www.aozora.gr.jp/index.html)