haihai Blog

Next.js の Server Actions を利用して Claude チャットを作成する

2024-07-23

はじめに

Next.js の Server Actions を利用して Anthropic API の Claude へ質問します。

プロジェクト作成

プロジェクトを作成します。

npx create-next-app@latest

プロジェクト名は、 claude-chat-app を入力し、その他の質問はデフォルトを選択しました。エンター連打です。

 What is your project named? claude-chat-app
 Would you like to use TypeScript? No / Yes
 Would you like to use ESLint? No / Yes
 Would you like to use Tailwind CSS? No / Yes
 Would you like to use `src/` directory? No / Yes
 Would you like to use App Router? (recommended) … No / Yes
 Would you like to customize the default import alias (@/*)? … No / Yes

Anthropic TypeScript API インストール

cd claude-chat-app
npm install @anthropic-ai/sdk

スタイルの初期化

/app/globals.css を以下に修正します。

@tailwind base;
@tailwind components;
@tailwind utilities;

API キーを環境変数へ設定

.env.local へ以下を追加します。

API_KEY='{自分の API キー}'

Server Actions 作成

/app/actions.tsx を作成します。 Form から取得した model, message を API のパラメータへ指定します。

'use server'

import { Anthropic } from '@anthropic-ai/sdk'

type State = {
  response: string
}

export async function callAI(prevState: State, formData: FormData) {
  const rawFormData = {
    model: formData.get('model'),
    message: formData.get('message')
  }
  console.log(rawFormData)

  const anthropic = new Anthropic({
    apiKey: process.env['API_KEY']
  })

  const msg = await anthropic.messages.create({
    model: rawFormData.model as string,
    max_tokens: 1024,
    messages: [{ role: 'user', content: rawFormData.message as string }]
  })
  // console.log(msg)
  const answer = (msg.content[0] as Anthropic.TextBlock).text

  return {
    response: answer
  }
}

トップページ修正

/app/page.tsx を修正します。Form のアクションへ Server Actions を指定します。
Claude からの回答は <pre>{formState.response}</pre> の部分へ表示されます。

'use client'

import { useFormState } from 'react-dom'
import { callAI } from '../app/actions'

export default function Home() {
  const model = 'claude-3-5-sonnet-20240620'
  const [formState, formAction] = useFormState(callAI, {
    response: 'ここへ返答が表示されます。'
  })

  return (
    <main>
      <div>
        <h1 className='text-2xl'>Claude Chat App</h1>
        <pre>{formState.response}</pre>
        <form action={formAction}>
          <div>
            <input type='hidden' name='model' value={model} />
            <textarea
              name='message'
              defaultValue=''
              placeholder='メッセージを入力してください'
            ></textarea>
          </div>
          <button>送信</button>
        </form>
      </div>
    </main>
  )
}

動作確認

npm run dev

参考 URL