【chatGPT】旅行オタクのチャットbotを作成する【AIチャットbot】

Next.jsでchatGPTのAPIを使う

はじめに

以前、簡単なNext.jsでのchatGPTのAPIの使い方を紹介しました。
まだご覧になっていない方はこちらをご覧ください。

以前説明した環境を前提に説明します。
以下が簡単な環境です。

  • Next.js
  • appルーター
  • tailwindCSS

今回はそれに少し変更を加えて、もう少し実用的なチャットbotを作成していきます。

基本的な環境作成

ローカルで環境を作成していきます。
NodeやvsCodeは入っているものとします。

まず以下のコマンドでプロジェクトを作成します。

npx create-next-app@latest

以下のように設定します。

次にopenAIのライブラリをインストールします。

npm install ai openai

次にapiルートにchatGPTとやり取りをするためのエンドポイントを作成します。
まずappフォルダの下にapi/chatAPI/route.tsを作成します。

ここにAPIのプログラムを作成します。
基本的には以前の記事と同じです。

import { OpenAIStream, StreamingTextResponse } from 'ai'
import OpenAI from 'openai'


export async function POST(req: Request) {
    try {
        const { messages } = await req.json()

        const initialMessages = messages.slice(0, -1)
        const currentMessage = messages[messages.length - 1]
        const openai = new OpenAI({
        apiKey: process.env.OPENAI_API_KEY || '',
        })

        const response = await openai.chat.completions.create({
            model: 'gpt-4o-mini',
            stream: true,
            max_tokens: 100,
            messages: [
            ...initialMessages,
            {
                ...currentMessage
            },
            ],
        })
        const stream = OpenAIStream(response);
        return new StreamingTextResponse(stream);

    } catch (error) {
        // エラーレスポンスを返す
        return new Response(JSON.stringify({ error: 'API request failed' }), {
        status: 500,
        headers: { 'Content-Type': 'application/json' },
        });
    }
}

次はフロントのプログラムを作成します。

page.tsx

'use client'

import { useChat } from 'ai/react';
import { Message } from 'ai/react';

export default function Home() {
  const prompt = '';

  const initialMessages: Message[] = [
    { id: 'initial-1', role: 'system', content: prompt }
  ];

  const { messages, input, handleSubmit, setInput } = useChat({
    api: '/api/chatAPI',
    initialMessages: initialMessages
  });

  return (
    <div className="flex flex-col items-center justify-center min-h-screen py-2 bg-gray-100">
      <main className="flex flex-col items-center justify-center w-full flex-1 px-4 md:px-20 text-left">
        <div className="bg-white shadow-md rounded-lg px-8 pt-6 pb-8 mb-4 w-full md:w-1/2">
          <div id="chatArea" className="mb-4 h-96 overflow-y-scroll p-4 border border-gray-300 rounded-lg bg-gray-50">
            {messages.map((message, index) => (
              message.role === 'assistant' || message.role === 'user'?
              <div key={index} className={`mb-4 ${message.role === 'assistant' ? 'flex justify-start' : 'flex justify-end'}`}>
                <div className={`rounded-lg p-3 max-w-xs shadow-md ${message.role === 'assistant' ? 'bg-blue-500 text-white' : 'bg-gray-300 text-gray-800'}`}
                  style={{ whiteSpace: 'pre-wrap' }}>
                  <span>{message.role === 'assistant' ? 'AI: ' : 'USER: '}{message.content}</span>
                </div>
              </div>:null
            ))}
          </div>

          <div className="flex items-center">
            <form className="flex w-full" onSubmit={(e) => {
              e.preventDefault();
              handleSubmit(e);
              setInput('');
            }}>
              <input
                className="shadow appearance-none border rounded-l-lg w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
                id="message"
                type="text"
                placeholder="メッセージを入れてください"
                value={input}
                onChange={(e) => setInput(e.target.value)}
              />
              <button
                className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-r-lg focus:outline-none focus:shadow-outline"
                type="submit">
                送信
              </button>
            </form>
          </div>
        </div>
      </main>
    </div>
  );
}

プロンプトの調整

ここから本題です。
プロンプトを調整してAIに性格を与えていきます。

性格の定義

page.tsxのプロンプトを修正します。

const prompt = 'あなたは旅行オタクです。何を聞かれてもオタクの領域になぞらえて回答します。';

こうすると以下のような回答が返ってきます。

さらにプロンプトを調整することで細かい性格まで設定できます。

出力形式の指定

特に出力形式を指定することでそのとおり出力してくれるようになります。

content: `あなたは旅行オタクです。何を聞かれてもオタクの領域になぞらえて回答します。
            回答形式は以下でお願いします。
            [あいさつ]
            [今の日時]
            [旅行の行き先]
            [詳細]`,  // AIの性格を定義

このように定義すると次のように返ってきます。

JSON形式での出力

次に返答の形式をJSONで指定する方法について説明します。
JSONでデータを取得することで、その後のデータの扱いも楽になります。
まずはプロンプトにJSONで返すように入れます。

あなたは旅行オタクです。何を聞かれてもオタクの領域になぞらえて回答します。
  回答形式はJSONでお願いします。
  [あいさつ]
  [旅行の行き先]
  [詳細]

次にAPIへの送信パラメータに以下を追加します

 response_format:{"type": "json_object"},

パラメータ全体は以下になります。

const response = await openai.chat.completions.create({
            model: 'gpt-4o-mini',
            stream: true,
            max_tokens: 100,
            response_format:{"type": "json_object"},
            messages: [
            ...initialMessages,
            {
                ...currentMessage
            },
            ],
        })

返答は以下のようになります。

チャットにおいてはこのままではいけませんが、旅行先のリストを出してもらって、そのデータを使いたい場合など、JSONで取得した方が良いかと思います。

おわりに

このように、プロンプトの調整や出力形式の調整でAIを自分の思い通りにすることができます。
今回は旅行オタクというテーマで作成しましたが、旅行以外にも料理、映画、小説など変えればどう言った内容でも対応できます。
ぜひいろんな性格のAIを作成してみてください。

また、2024年8月にjson_schemaという機能が追加されました。

これはAIが考える過程を見ることができたり、出力の形式をより細かく指定できる機能となっています。
いずれこの機能についても説明できればと思います。

コメント

タイトルとURLをコピーしました