プロンプトエンジニアリングにおける初歩中の初歩のテクニックを実践してみる

# はじめに

ChatGPTに代表されるLMやLLMといった言語モデル、または大規模言語モデルに対して効率的に意図を伝えるための手法として、最近ではプロンプトエンジニアリングの需要が高まってきています。

今回は、プロンプトエンジニアリングにとって重要な構成要素を中心に紹介し、それらを使ってプロンプティングを行う方法を簡単に紹介します。

# 前提条件

TypeScriptやNode.jsを使用するため、それらの環境と知識が必要です。

使用するライブラリとしては、`ts-chatgpt`を使用します。お好きなプロジェクトにインストールしてください。

:::note warn
プロジェクトの作成方法等については、この記事の範囲外となるため説明致しませんので、ご了承ください。
:::

https://github.com/takagimeow/ts-chatgpt

```shell
npm install ts-chatgpt
```

# プロンプトを構成する主な４要素

効率的に意図を伝えることができるプロンプトは、主に次の要素によって構成されています。

:::note warn
すべての要素が必ず一つのプロンプトに含まれるわけではありません。プロンプトによって得たい結果によって構成される要素は異なります。あくまで、一般的なプロンプトにおける構成要素だと捉えてください。
:::

## インストラクション（指示）

インストラクションは、指定したモデルに対して実行させたいと考えている、具体的なタスクの内容や指示を表します。

ここで注意が必要なのは、インストラクションの位置です。
インストラクションは、必ずプロンプトの一番上に記述されなければいけません。

```
Instruction: 与えられたテキストを中立、否定、肯定の３種類に分類しなさい
...
```

## コンテキスト（文脈）

コンテキストは、モデルがもっとユーザーが求める答えに近づけるようにするための情報や話の前後のことを表します。

基本的な位置は、インストラクション以下の位置で問題ないです。
そして、インストラクションとコンテキストは、必ずわかりやすい形式で分けられなければなりません。

わかりやすい形式とは、次のように`"""`や、`###`を使ってどこからがコンテキストなのかを区切るという意味です。

```
与えられたテキストを中立、否定、肯定の３種類に分類しなさい

Example: ###
Text: ハンバーグが大好きです。
Sentiment: 肯定
Text: 虫が苦手です。
Sentiment: 否定
Text: 空が青い
Sentiment: 肯定
###
```

## インプット（入力）

インプットとは、この値に対してChatGPTから応答を得たい場合の質問や書きかけの文章などを表します。
例えば、次のようにインストラクションとコンテキストが与えられた状態では`Text: 明日は会社だ。`が入力に該当します。

```
与えられたテキストを中立、否定、肯定の３種類に分類しなさい

Example: ###
Text: ハンバーグが大好きです。
Sentiment: 肯定
Text: 虫が苦手です。
Sentiment: 否定
Text: 空が青い
Sentiment: 肯定
###

Text: 明日は会社だ。
```

## アウトプットインジケーター（出力インジケーター）

ChatGPTに対して、どのような形式で結果を出力して欲しいかを示すのがアウトプットインジケーターです。

例えば、`TypeScript Version: `や、`Answer: `などをプロンプトの末尾に置くことができます。

次のプロンプトでは、`Sentiment: ***`という形式で出力しなさいということを意図しています。

```
Text: 明日は会社だ。
Sentiment:
```

# メッセージの概要

ChatGPTにおいて、メッセージを作成するには、あらかじめ3つのロールについて知っておく必要があります。

## SYSTEM

`system`ロールを割り当てられたメッセージは、会話のはじまりから終わりまでの流れの中でのモデルの動作を導くための内容を指定します。

なので、インストラクションやコンテキストを指定することができます。

```ts
const systemMessage = {
  role: "system",
  content: `
    Prismaライブラリに熟知したソフトウェア開発者として行動してほしい。
    私がウェブアプリの要件について具体的な情報を提供するので、TypeScriptで安全なアプリを開発するためのアーキテクチャとコードを考えるのがあなたの仕事です。

    Library: ###
      Prisma: https://github.com/prisma/prisma
    ###

    Example: ###
      model User {
        id Int @id @default(autoincrement())
        name String
        email String @unique
        posts Post[]
    }
  ###
  `,
}
```

## ASSISTANT

`assistant`ロールを割り当てられたメッセージは、ユーザーの発言に対してのモデルの応答を指定します。

つまり、ユーザーの発言に答えるChatGPT自身の応答であるメッセージを表します。

```ts
const assistantMessage = {
  role: 'assistant',
  content: '以下のように、Postモデルを作成することができます。\n' +
    '\n' +
    '```\n' +
    'model Post {\n' +
    '  id Int @id @default(autoincrement())\n' +
    '  title String\n' +
    '  text String\n' +
    '  author User @relation(fields: [authorId], references: [id])\n' +
    '  authorId Int\n' +
    '}\n' +
    '```\n' +
    '\n' +
    'このモデルには、id、title、text、author、authorIdの5つのフィールドがあります。idは自動的にインクリメントされるプライマリキーです。titleとtextはそれぞれ投稿のタイトルと本文を表します。authorとauthorIdは、投稿を作成したユーザーを表すためのフィールドです。Userモデルとの関係を定義するために、@relationディレクティブを使用しています。'
}
```

## USER

`user`ロールを割り当てられたメッセージは、ユーザーの発言を指定します。

なので、このメッセージにはインプットやインストラクションなどを指定することができます。

```ts
const userMessage = {
    role: "user",
    content: `
      タイトルとテキストを持つPostモデルを作成しなさい。
      schema.prisma:
    `,
}
```

# 例） schema.prismaにてPostモデルを作成したい場合のプロンプト

Prismaライブラリを活用している開発者が、`Post`モデルを作成したいが、具体的な書き方を思い出せずChatGPTに聞いて答えを取得したいというシナリオを想定します。

まず、`System`ロールとして具体的にどういった立ち回りをChatGPTにして欲しいのかを指示します。
そして、コンテキストを与えて、Prismaとはどういうライブラリなのか、そして開発者がどういったモデルを`schema.prisma`で定義してきたかを教えてあげます。

```ts
const systemMessage: Message = {
  role: "system",
  content: `
    Prismaライブラリに熟知したソフトウェア開発者として行動してほしい。
    私がウェブアプリの要件について具体的な情報を提供するので、TypeScriptで安全なアプリを開発するためのアーキテクチャとコードを考えるのがあなたの仕事です。

    Library: ###
      Prisma: https://github.com/prisma/prisma
    ###

    Example: ###
      model User {
        id Int @id @default(autoincrement())
        name String
        email String @unique
        posts Post[]
    }
  ###
  `,
};
```

次に、ユーザーとしてChatGPTに何を答えてもらいたいかを具体的な内容で教えてあげます。
ここでは、タイトルとテキストを持つような`Post`モデルを定義してもらいたいことを指示しています。
そして、それは`schema.prisma`のフォーマットで返して欲しいことを伝えています。

```ts
const userMessage: Message = {
  role: "user",
  content: `
    タイトルとテキストを持つPostモデルを作成しなさい。
    schema.prisma:
  `,
};
```

最終的には、次のようなコードになります。

```ts
import { prompt } from "ts-chatgpt";
import type { Message } from "ts-chatgpt";

const systemMessage: Message = {
  role: "system",
  content: `
    Prismaライブラリに熟知したソフトウェア開発者として行動してほしい。
    私がウェブアプリの要件について具体的な情報を提供するので、TypeScriptで安全なアプリを開発するためのアーキテクチャとコードを考えるのがあなたの仕事です。

    Library: ###
      Prisma: https://github.com/prisma/prisma
    ###

    Example: ###
      model User {
        id Int @id @default(autoincrement())
        name String
        email String @unique
        posts Post[]
    }
  ###
  `,
};
const userMessage: Message = {
  role: "user",
  content: `
    タイトルとテキストを持つPostモデルを作成しなさい。
    schema.prisma:
  `,
};
const res = await prompt({
  model: "gpt-3.5-turbo-0301",
  messages: [systemMessage, userMessage],
});
console.log(res);
```

実行した結果、次のような結果を得ることができました。

```bash
[
  {
    message: {
      role: 'assistant',
      content: '以下のように、Postモデルを作成することができます。\n' +
        '\n' +
        '```\n' +
        'model Post {\n' +
        '  id Int @id @default(autoincrement())\n' +
        '  title String\n' +
        '  text String\n' +
        '  author User @relation(fields: [authorId], references: [id])\n' +
        '  authorId Int\n' +
        '}\n' +
        '```\n' +
        '\n' +
        'このモデルには、id、title、text、author、authorIdの5つのフィールドがあります。idは自動的にインクリメントされるプライマリキーです。titleとtextはそれぞれ投稿のタイトルと本文を表します。authorとauthorIdは、投稿を作成したユーザーを表すためのフィールドです。Userモデルとの関係を定義するために、@relationディレクティブを使用しています。'
    },
    finish_reason: 'stop',
    index: 0
  }
]
```

文脈として指定した内容から、ChatGPTは`User`モデルと`Post`モデルには`1:n`の関係があるのだろうと推論を行い、`author User @relation(fields: [authorId], references: [id])`フィールドが`Post`モデルに存在することが確認できます。

# まとめ

プロンプトエンジニアリングのテクニックとしては、テキストの要約やテキストの分類、そして質疑応答といったテクニックがまだまだ存在しますが、今回は基本的かつどのような問題にも対応できる初歩のテクニックに絞って紹介しました。

プロンプトエンジニアリングを理解し意識しながら行うことで、今度は普段のコーディングに対してもより良いフィードバックを得ることができるようになるかと思います。

# 参考にした記事

https://www.promptingguide.ai/tools

https://help.openai.com/en/articles/7042661-chatgpt-api-transition-guide