虎の穴開発室ブログ

虎の穴ラボ株式会社所属のエンジニアが書く技術ブログです

MENU

Next.jsで作る!カスタマイズ可能なプライベートAIチャット環境!!

こんにちは。虎の穴ラボ エンジニアの古賀です!

本記事は虎の穴ラボ2024年夏の連載ブログ 7日目の記事です。次回はT.Hさんのブログが公開されますので、ご期待ください!

今回、私が書くテーマは「AI関連」で、タイトルは「Next.jsで作る!カスタマイズ可能なプライベートAIチャット環境!!」になります!

はじめに

AIチャットボットは、ユーザーとインタラクティブにコミュニケーションを取るための強力なツールです。しかし、プライバシーを重視したり独自のカスタマイズをしたい場合には、外部サービスに依存せず、自分専用のAIチャット環境を構築することも必要になります。

このブログでは、Vercel公式のNext.js向で構築されたai-chatbotを使ったプライベートなAIチャット環境の構築方法を説明します。

また、本来はai-chatbotはVercel/KV(データベースサービス)が必要ですが、serverless-redis-http(別のデータベースサービス)に置き換えて、アカウント登録の手間を省いています。 紹介する手順はDocker DesktopやNode.jsの環境があれば構築可能で、Vercelやその他の外部アカウントの登録は不要です。

Vercel AI Chatbotテンプレートの概要

Vercelのai-chatbotテンプレートは、Next.jsの最新技術を使って作られた強力なリファレンス実装でもあります。次の技術が使用されています。

  • Next.js v14の最新技術:App Router, Server Actions, React Server Components (RSCs), Suspense
  • Vercel AI SDK:強力で簡単に使用できるAI API、生成AIでUIの生成が可能
  • NextAuth.js:メールアドレスとパスワードでのアカウント作成やログインが可能
  • shadcn/ui:美麗でカスタマイズ性の高いUIコンポーネント

このテンプレートを使えば、最新技術で簡単に自分だけのAIチャットボットを構築でき、ソースコードを読んでNext.jsの最新技術を学ぶこともできる一石二鳥のテンプレートです。

Vercel AI Chatbotテンプレートを使った初期設定

0. 前提条件と事前準備

Node.js / pnpmのインストールはVoltaを使うとvolta install nodeとかvolta install pnpmでインストールもできます。

また、volta pin node@versionでpackage.jsonベースでnodeバージョンなどの固定もできます。よろしければこちらもご利用ください。

1. プロジェクトのクローン

まずはVercelが提供するai-chatbotをGitHubからクローンします。

$ git clone https://github.com/vercel/ai-chatbot.git
$ cd ai-chatbot

2. .envを作成

次に .env ファイルを作成してOPENAI_API_KEYとAUTH_SECRET、KV_REST_API_URL/TOKENを設定します。

OPENAI_API_KEY="sk-で始まるAPIキー"

AUTH_SECRET="任意の文字列"

KV_REST_API_URL="http://localhost:8079"
KV_REST_API_TOKEN="任意の文字列"

OPENAI_API_KEYは、OpenAI API Keysで作成したsk-で始まるAPIキーを設定してください。

AUTH_SECRET(NextAuth認証用の秘密の文字列)とKV_REST_API_TOKEN(データベース認証用の秘密の文字列)は Vercelのツールの値を使うか、openssl rand -base64 32コマンドを実行した結果を設定してください。これらのシークレットやトークンはローカルで動かすだけならどんな値でも構いません。セキュアなランダムな値が欲しい場合は、コマンドやツールを使ってランダムな値を個別に作成してください。

3. docker-compose.ymlを作成

データベース環境を立ち上げるためのdocker-compose.ymlを作成します。

version: '3.1'

services:
  redis:
    image: redis
    ports:
      - '6379:6379'

  serverless-redis-http:
    ports:
      - '8079:80'
    image: hiett/serverless-redis-http:latest
    environment:
      SRH_MODE: env
      SRH_TOKEN: 'KV_REST_API_TOKENと同じ値'
      SRH_CONNECTION_STRING: 'redis://redis:6379'

SRH_TOKEN(データベース認証用の秘密の文字列)は.envのKV_REST_API_TOKENと同じ値を設定してください。これでserverless-redis-http(Upstash Redis)を利用できます。

Vercel/KVはこちらのIssueで議論もされており、非公式ではありますがUpstash Redisへの置き換えが可能です。

4. 起動とインストール

リポジトリはpnpmを使用して構築されています。

Dockerを起動した後にpnpmで開発サーバを起動してください。

$ docker-compose up -d
$ pnpm install
$ pnpm dev

5. 動作確認

起動後、 http://localhost:3000 を開いてください。何か入力してみると分かりますが最初の状態では、システムプロンプトなどで制約されているため株価しかやり取りできません。

次のステップでテンプレートを修正していきます。

株価に関することしかやり取りできない

システムプロンプトの変更方法と新機能の追加手順

1. システムプロンプトの除去

lib/chat/actions.tsx の130行目あたりにあるシステムプロンプトを下記のように除去します。gpt-4o(OpenAIの最新の言語モデル)が使える場合はモデルを変えても良いと思います。

  const result = await streamUI({
    model: openai('gpt-4o'),
    initial: <SpinnerMessage />,
    system: "あなたは特に指定がない限り、日本語で応答します。", // 元々のプロンプトはコメントアウトまたは削除する

github.com

2. 生のHTMLを出力するコンポーネントの追加

lib/chat/actions.tsx の179行目にあるtools属性を下記に置き換えます。本来はもっと天気予報や業務データなど、特定の機能に特化したコンポーネントを作っても良いですが、テスト的にHTMLを描画するコンポーネントとしました。

    tools: {
      render_raw_html: {
        description: '生のHTMLソースの文字列をUIとして描画します',
        parameters: z.object({
          rawHtml: z.string().describe('生のHTMLソース文字列')
        }).required(),
        generate: async function* ({ rawHtml }) {
          yield <BotCard>Loading...</BotCard>

          await sleep(1000)
          const toolCallId = nanoid()

          aiState.done({
            ...aiState.get(),
            messages: [
              ...aiState.get().messages,
              {
                id: nanoid(),
                role: 'assistant',
                content: [
                  {
                    type: 'tool-call',
                    toolName: 'render_raw_html',
                    toolCallId,
                    args: { rawHtml }
                  }
                ]
              },
              {
                id: nanoid(),
                role: 'tool',
                content: [
                  {
                    type: 'tool-result',
                    toolName: 'render_raw_html',
                    toolCallId,
                    result: rawHtml
                  }
                ]
              }
            ]
          })
          return <div dangerouslySetInnerHTML={{ __html: rawHtml }} />
        }
      }
    },

github.com

完成したコードは下記のリポジトリで公開しています。 よろしければ、ご利用ください。

github.com

動作確認

システムプロンプトの変更と新機能の追加の動作確認を行います。

電卓のUI生成

テーブルのUI生成

UIを生成するとなぜかヒストリーが消えてしまう(まだ原因は未調査)という問題はありますが、UIの生成を含むカスタムコンポーネントを使ったAIとのチャットができていると思います。

このようなカスタムコンポーネントを追加することで、生成AIでUIを生成できるのはテンプレートで利用されているVercel AI SDKの機能になります。

比較対象としてのopenai-assistants-quickstart

Vercelのai-chatbotの構築やコードが複雑すぎると感じる方にはopenai/openai-assistants-quickstartがおすすめです。こちらはUIの生成はできませんがファイルのアップロードが可能です。

  • 簡単なセットアップ:RedisやDockerなどの複雑な設定が不要
  • 素のNext.jsに近い:Next.jsやOpenAI APIの基本を理解しているだけで構築可能

セットアップは下記のように行います。

$ git clone https://github.com/openai/openai-assistants-quickstart.git
$ cd openai-assistants-quickstart

次に.envを作成します

OPENAI_API_KEY="sk-から始まるOpenAIのAPIキーを入れる"

その後、起動を行います。

$ npm i
$ npm run dev

その後、localhost:3000を開くと下記のようにAIアシスタント作成を促されるので、ボタンを押して作成する。

表示されたasst_から始まる値をコピーし、app/assistant-config.tsを次のコードに置き換えます。

export let assistantId = "asst_cYSQaeajGPyMuYp2AM5GxIPV";

if (assistantId === "") {
  assistantId = process.env.OPENAI_ASSISTANT_ID;
}

その後、画面が切り替わるのでALLというボタンを押すと利用できます。

次のように天気を聞くと、天気と温度が表示されPDFをアップロードするとその内容について要約などができます。 (PDFはOpenAIの「OpenAI and Apple announce partnership to integrate ChatGPT into Apple experiences」という記事をPDF化して使いました)

次のリンクのソースコードを見ると、単にopenaiのアシスタントAPIを発行している様子で素のNext.jsに近く、Vercelのai-chatbotに比べるとOpenAIのアシスタントAPIとNext.jsが分かればコードを読めるので触りやすいと思います。

github.com

まとめ

自分専用のAIチャット環境を構築することで、プライバシーを保ちつつ高いカスタマイズ性を実現できます。VercelのAIチャットボットテンプレートは最新技術を駆使した高度なツールですが、openai-assistants-quickstartはよりシンプルでReactやNext.jsの初心者にも扱いやすいです。

用途に応じて、最適なテンプレートを選んで、自分だけのAIチャット環境を構築してみましょう。

採用情報

虎の穴ラボでは一緒に働く仲間を募集中です!
この記事を読んで、興味を持っていただけた方はぜひ弊社の採用情報をご覧ください。
toranoana-lab.co.jp