🙌

【GPT3.5turbo】NextJsで動くGPT3.5turbo【#5Send Prompt】

2023/04/21に公開

【#5Send Prompt】

YouTube:https://youtu.be/Np7kgQ0IaJQ

https://youtu.be/Np7kgQ0IaJQ

今回はhandleSubmitの関数を完成させて、
フォームに入力したデータを送信して、
レスポンスを受け取る部分について実装を進めていきます。

pages/index.tsx
import { ChangeEvent, SyntheticEvent, useState } from 'react'

interface Log {
  prompt: string
  role: string
  content: string
}

export default function Home() {
  const [prompt, setPropmt] = useState('')
  const [isLoading, setIsLoading] = useState(false)
  const [logs, setLogs] = useState<Log[]>([])

  const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => {
    setPropmt(e.target.value)
  }

  const handleSubmit = async (e: SyntheticEvent) => {
    e.preventDefault()
    setIsLoading(true)

    const res = await fetch('/api/chat', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ prompt: prompt }),
    })
    const data = await res.json()
    if (res.status === 200) {
      console.log(data)
      const logData = {
        prompt: prompt,
        ...data.message,
      }
      setLogs([...logs, logData])
      setIsLoading(false)
    } else {
      console.log(data)
      setIsLoading(false)
    }
  }

  return (
    <main className="flex min-h-screen flex-col items-center px-2">
      <h1 className="my-6 text-3xl font-bold tracking-tight text-white sm:text-4xl">
        Hello Chat-GPT
      </h1>
      <div className="max-w-xl overflow-hidden bg-gray-900 py-4 sm:py-6 lg:py-8">
        <div className="mx-auto max-w-3xl px-6 lg:px-8">
          <div>
            <div className="max-w-xl lg:max-w-lg mb-3">
              <h2 className="text-3xl mb-3 font-bold tracking-tight text-white sm:text-4xl">
                Please Enter Your Message.
              </h2>
            </div>
          </div>
          <div>
            <form
              onSubmit={handleSubmit}
              className="flex flex-col items-center justify-center"
            >
              <textarea
                name="prompt"
                value={prompt}
                onChange={handleChange}
                cols={20}
                rows={4}
                className="w-full flex-auto rounded-md border-0 bg-white/5 px-3.5 py-2 text-white shadow-sm ring-1 ring-inset ring-white/10 focus:ring-2 focus:ring-inset focus:ring-indigo-500 sm:text-sm sm:leading-6"
              ></textarea>
              <button
                disabled={isLoading || !prompt}
                type="submit"
                className="flex-none rounded-md bg-indigo-500 mt-3 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500"
              >
                Send Message
              </button>
            </form>
          </div>
        </div>
      </div>
    </main>
  )
}

ここまでできましたら、
フォームから送られてきた「prompt」を取得して、
「content」の部分に設定を行います。

pages/api/chat.tsx
import type { NextApiRequest, NextApiResponse } from 'next'
import { Configuration, OpenAIApi } from 'openai'

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

const openai = new OpenAIApi(configuration)

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const { prompt } = req.body
  switch (req.method) {
    case 'POST':
      try {
        const completion = await openai.createChatCompletion({
          model: 'gpt-3.5-turbo',
          messages: [{ role: 'user', content: `${prompt}` }],
        })

        res.status(200).send({
          message: completion.data.choices[0].message,
        })
      } catch (error) {
        console.log(error)
        res.status(500).send(error || 'Something went wrong')
      }
      break
    default:
      res.setHeader('Allow', ['POST'])
      res.status(405).end(`Method ${req.method} Not Allowed.`)
  }
}

Discussion