💬

Next.JSでGeminiとチャットしてみる

に公開

Next.JSを使ってGeminiとチャットしてみるコードを書いたので覚え書き

最初に

https://github.com/google-gemini/generative-ai-js
ここを参考に実行していく。まずはライブラリのインストール
$ npm install @google/generative-ai

そしてその後、APIのキーが必要なのでこれを発行しておく。
https://ai.google.dev/gemini-api/docs/api-key?hl=ja

Gemini通信部

クライアント側で直接やりとりしても良いが、Gemini以外のAIを利用したときや、利用トークン数の管理、出力した内容の保持など考えるとGeminiとの通信部はNext.JSのRoute Handler側に置いておきたい。
https://nextjs.org/docs/app/building-your-application/routing/route-handlers

src/app/api/generateContent/route.tsを作成する

import { GoogleGenerativeAI } from '@google/generative-ai';

const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY ?? '');

export async function POST(request: Request) {
  const { prompt } = await request.json()
  const model = genAI.getGenerativeModel({ model: 'gemini-2.0-flash-lite' })

  const result = await model.generateContentStream(prompt)
  return new Response(new ReadableStream({
    async pull(controller) {
      const { done, value } = await result.stream.next()
      if (done) {
        controller.close()
      } else {
        controller.enqueue(value.text())
      }
    },
  }))
}

リクエスト時にプロンプトを受け取ってそれをそのままGeminiに渡すシンプルなPOST関数を用意する。
最初に発行していたAPIのキーはGEMINI_API_KEYという名前の環境変数に入れておく。
ストリームで返して欲しいのでReadableStreamを利用してレスポンスをしている。

チャット表示部

src/components/GeminiSample/index.tsxとファイルを作成

'use client'
import { useEffect, useState } from "react"

export default function GeminiSample() {
  const [ apiResult, setApiResult ] = useState('')
  useEffect(() => {
    (async () => {
      const res = await fetch('/api/generateContent', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ prompt: 'Hello, Gemini!' }),
      })
      const reader = res.body?.getReader()
      if (!reader) return
      const decoder = new TextDecoder()
      while (true) {
        const { done, value } = await reader?.read()
        if (done) break
        setApiResult(apiResult => apiResult + decoder.decode(value))
      }
    }
    )()
  }, [])
  return (
    <div>
      {apiResult}
    </div>
  )
}

こちらも先ほど作成したAPIにプロンプトを渡して返却をストリームで受け取って処理をしている。

最後に

ストリームまわりが不慣れなこともあり手間取ったがなんとか通信できるようになった。この後はinput用意してWeb上でpromptを入力できるようにすれば、一旦はチャットの形にできるはず。

Discussion