私は何が聞きたいんだ?ChatGPTに「関連する質問」を考えてもらった

2023.03.21

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

あなたは質問が得意でしょうか?自分が知りたいことを知るために、どんな風に聞いたら良いかわかるでしょうか?

私は質問が苦手です。何がわからないかをうまく言語化できないし、自分でも何が聞きたいか曖昧だったり、本当に知りたいことを知るにはどんな質問をしたらいいのかわからなかったりします。

この記事では、ある質問をもとに「関連する質問」をChatGPTを使って生成してみるという内容になります。

具体的には、

  • ユーザの質問に対して回答をする
  • その質問をしたユーザが知りたそうな他の質問を考える
  • さらにそれに対しても回答をする

といったことをChatGPTにやってもらいます。

可能かどうか確認

定番の流れ(?)ですが、やろうとしていることができるのかまずChatGPTに聞いてみました。

できるそうです。

ChatGPTのWebブラウザでやりとりしてもいいのですが、せっかくなのでOpenAI APIのチュートリアルも兼ねて、Node.jsで簡単なアプリを作成しました。

作ってみた

OpenAI APIキーの取得

アプリからChatGPTを使うためにはAPIキーが必要になります。APIキーの取得については当ブログにたくさん記事がありますので、ここでは割愛します。以下の記事などをご覧ください。

OpenAI Platformことはじめ 〜Organizationメンバーに招待されたら

プロジェクトフォルダの作成

適当な場所にプロジェクトフォルダを作成します。

モジュールのインストール

カレントをプロジェクトフォルダに移動し、以下のコマンドを実行します。

npm install openai

これでOpenAIのモジュールが利用できるようになりました。

また、APIキーを環境変数にするためにdotenvもインストールしておきます。

npm install dotenv

コーディング

まず、プロジェクトフォルダ直下に.envファイルを作成します。APIキーを以下のように設定します。

OPENAI_API_KEY=自分のAPIキー

プロジェクトフォルダ直下にindex.jsを作成します。コードの全貌は以下のようになります。

const { Configuration, OpenAIApi } = require("openai");
const readline = require('readline');
require('dotenv').config();

const configuration = new Configuration({
    apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration)

/**
 * メイン処理
 */
const main = async() => {
    let aiOutput = "何か質問はありますか?"
    for(;;){
        const input = await getUserInput(`${aiOutput}\n> `);
        if(input==='end') break
        aiOutput = await sendRequest(input)
    }
};

/**
 * ユーザのキー入力を取得する
 * @param {string} aiOutput 
 * @returns 
 */
const getUserInput = (aiOutput) => {
  const readlineInterface = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  });
  return new Promise((resolve) => {
    readlineInterface.question(aiOutput, (answer) => {
      resolve(answer);
      readlineInterface.close();
    });
  });
};

/**
 * OpenAIにリクエストを送信する
 * @param {string} input 
 * @returns 
 */
const sendRequest = async (input) => {
    const completion = await openai.createChatCompletion({
        model: "gpt-3.5-turbo",
        messages: [
          {role: "system", content: "質問に回答をした上で、この質問をした人が興味をもちそうな別の質問を1~5個教えてください。まず「回答」というヘッダーをつけて回答を述べ、そのあとで「関連する質問」というヘッダーをつけて別の質問を挙げてください。"},
          {role: "user", content: input}
        ],
    })

    const response = completion.data.choices[0].message.content
    return response.trim()
}

// 起動
(async () => {
  await main();
})();

「メイン処理」と「ユーザのキー入力を取得する」の部分はやりたいことの本質ではないため、細かい解説は割愛させて頂きます。ユーザとChatGPTの対話をループし、ユーザが「end」と入力すれば対話が終わるようにしています。

重要なのは「OpenAIにリクエストを送信する」の部分です。

OpenAIにはいくつかモデルの種類がありますが、ChatGPTを使う場合はmodelgpt-3.5-turboを指定します。

そして、送信するメッセージはmessagesに記載します。

messagesの中身は配列になっており、それぞれのオブジェクトにはrolecontentがあります。

rolesystemを指定すると、ChatGPTに対話の目的や前提事項などをインプットさせることができます。ここではユーザの質問への回答と、ユーザが興味のありそうな質問を列挙するように指示しています。

roleuserを指定して、実際にChatGPTと対話させたい内容を入力します。このコードではユーザがキーボードで入力した文字列をそのまま渡しています。

もう一つ、assistantというroleがありますが、以前の会話履歴を保持しておくためのロールです。ここでは以前の会話履歴は必要ない(質問に対して、都度回答と関連する質問を考えてくれれば良い)ため使用していません。

動かしてみる(実際のストーリー)

では上記のコードを動かしてみます。

node index.js

ここからは、私がプログラミングを始めたての初心者だとします。文法は一通り理解したものの、もっと上達したいと漠然と思っています。そこで、「プログラミングを上達させるにはどうしたらいいですか?」と質問してみます。

回答が返ってきました。

何か質問はありますか?
> プログラミングを上達させるにはどうしたらいいですか?
プログラミングを上達するためには、以下のような方法があります。

1. 繰り返し練習する:プログラミングは継続的なトレーニングが必要です。新しいコンセプトや技術を習得するためには、繰り返し練習することが大切
です。

2. コードレビューに参加する:コードレビューに参加することで、自分の書いたコードについてフィードバックを受け、改善することができます。    

3. 他人のコードを読んで学ぶ:他人が書いたコードを読み、その中から新しいアイデアやテクニックを学ぶことができます。

4. 技術書を読む:技術書を読むことで、より深い理解を得ることができます。また、新しい技術についての知識を得ることができます。

5. 個人プロジェクトに取り組む:個人プロジェクトを通じて、新しい技術やコンセプトを習得することができます。また、自分自身で問題を解決するこ
とで、より効果的な学習が可能です。

関連する質問:
- プログラミング初心者向け、独学で上達するための方法はありますか?
- Web開発を学ぶために何を勉強すれば良いですか?
- ソフトウェアエンジニアになるために必要なことは何ですか?
- プログラムの品質を上げるためにはどうしたらいいですか?
- 時短でプログラミングを学ぶために効果的な方法はありますか?

回答を読みますが、なんとなく私の欲しい情報ではありませんでした。「まぁそれはそうなんだけど~」と思いつつ、「関連する質問」に目を通します。「そうだ、私は単に動くコードを書くだけじゃなく、もっと品質の高いプログラムを書くにはどうしたらいいのかを知りたかったんだ!」と気づきます。

そこで、「関連する質問」の中から「プログラムの品質を上げるためにはどうしたらいいですか?」を入力します。

> プログラムの品質を上げるためにはどうしたらいいですか?
プログラムの品質を上げるためには、以下のことを行うことが重要です。

1. コードレビューを実施する:別の開発者によるコードレビューを行い、コードの品質、バグの検出、保守性の改善などを実施します。
2. ユニットテストの実施:プログラムの機能をテストするユニットテストを実施し、バグの検出や修正を行い、品質を上げます。
3. コーディング規約の導入:一定のルールに従ってコーディングを行い、可読性や保守性の向上、複数人での開発時のコミュニケーションの円滑化など
を図ります。
4. リファクタリングの実施:コードの構造やクラスの分割を見直し、保守性やスケーラビリティの向上を図ります。
5. ドキュメンテーションの整備:プログラムの機能や仕様、コードの意図などを明確にし、プログラムの保守性を高めます。

関連する質問:
- コードレビューの実施方法は?
- ユニットテストと統合テストの違いは?
- コーディング規約の参考になる書籍は?
- リファクタリングのベストプラクティスは?
- ドキュメンテーションの重要性とは?

なるほど、確かにこれらによって品質が上がりそうです。そして関連する質問を見て、「今まで私が書いたプログラムをリファクタリングしてみたい!どうやって直せばいいんだろう?」と思い当たります。

そこで、「リファクタリングのベストプラクティスは?」を質問してみます。

> リファクタリングのベストプラクティスは?
リファクタリングのベストプラクティスは以下の通りです。

1. コードの意図を明確化する
2. オブジェクト指向プログラミングを適用する
3. コードの可読性を向上させる
4. リグレッションテストを実施する
5. 小さくて単一の変更を行う

関連する質問:

1. リファクタリングとは何ですか?
2. リファクタリングを行う際の注意点は?
3. リファクタリングによって期待できる効果は何ですか?
4. リファクタリングに適したツールは何ですか?
5. テスト駆動開発においてリファクタリングはどのような役割を持ちますか?

この辺にしておきますが、最初の「プログラミングを上達させるにはどうしたらいいですか?」から始まり、関連する質問をたどっていくことで、自分が本当に知りたいこと、やりたいことをはっきりさせることができました。

…と、実際はこんなに単純ではないかもしれませんが、関連する質問を生成してくれることにより、自分自身も気づかなかった潜在的な興味・関心や、本当に知りたいと思っていたことが何かを知ることができると考えられます。

Webサービスの運営者は自分のサイトに組み込むことで、ユーザがどんな関連する質問を選択するかをウォッチし、興味・関心に合わせたより適切な提案ができるようになるかもしれません。

これまで、Q&Aは誰かが質問と回答を用意する必要がありましたが、ChatGPTを使えばあらかじめ用意せずともAIが導いてくれるのがすごいですね。(厳密に言えば膨大な学習データを元にしているので、「用意せずとも」は語弊があるかもしれません)

ここまで書いて気づきましたが、「まず「回答」というヘッダーをつけて回答を述べ、」という指示が完全に無視されていますね。もっとプロンプトエンジニアリングを学ぶ必要がありそうです。

【徹底解説】これからのエンジニアの必携スキル、プロンプトエンジニアリングの手引「Prompt Engineering Guide」を読んでまとめてみた

おわりに

注意点として、ChatGPTは「プログラミングの上達方法は?」「朝食におすすめのメニューは?」といった一般的な事項については学習データを持っていますが、ある特定のサービスや商品について質問する場合は、知識がないためそのままでは使えません。よって、もし特定のサービスや商品について質問を自動生成をしたい場合は、学習させるための工夫が必要になりそうです。

また、どんどん関連させていった結果、最初の質問とは関係のない質問につながっていく可能性もあります。例えばこの記事で実施した中でも「ドキュメンテーションの重要性とは?」という質問が生成されましたが、この質問はプログラミング特有のものではありません。「プログラミング関係からは離れたくない」といった場合は、あらかじめシステムメッセージなどでガードレールを設けておく必要がありそうです。

この記事がどなたかの参考になれば幸いです。