😃

Next.js を使用して Vercel AI SDK と LangChain JS を実装してみた

2023/10/02に公開

はじめに

ChatGPTのAPIを使用してNext.jsで簡単なチャットページを実験的に実装してみます。
今回はVercel AI SDKを使用しますが、同時にLangChainも簡単に試してみようと思います。

※ 実装内容が古くなりましたので、新しく記事を書きました。(2024年7月19日)
https://zenn.dev/nari007/articles/9c178246dfafd5

読者対象

  • Next.js開発の経験者

事前準備

  • OpenAI プラットフォームから API キーを作成します。

https://platform.openai.com/

コードを書く

ステップ

  • Next.js + Typescript を作成する
  • env.localにOPENAI_API_KEYを記述する
  • /api/aiSdkChat.ts と /api/langChainChat.ts を作成し、index.tsx を編集する

Next.js + Typescript を作成

yarn create next-app sample-ai --typescript
cd sample-ai
yarn add ai openai-edge
yarn add langchain

SDKの実装
/api/aiSdkChat.ts

import { OpenAIStream, StreamingTextResponse } from "ai";
import { Configuration, OpenAIApi } from "openai-edge";
import { NextRequest } from "next/server";

export const runtime = "edge";

const config = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(config);

export default async function handler(req: NextRequest) {
  const { messages } = await req.json();

  const response = await openai.createChatCompletion({
    model: "gpt-3.5-turbo",
    stream: true,
    temperature: 0.9,
    messages: messages.map((message: any) => ({
      content: message.content,
      role: message.role,
    })),
  });
  const stream = OpenAIStream(response);
  return new StreamingTextResponse(stream);
}

/api/langChainChat.ts

import { StreamingTextResponse, LangChainStream, Message } from "ai";
import { ChatOpenAI } from "langchain/chat_models/openai";
import { AIMessage, HumanMessage } from "langchain/schema";
import { NextRequest } from "next/server";

export const runtime = "edge";

export default async function handler(req: NextRequest) {
  const { messages } = await req.json();
  const { stream, handlers } = LangChainStream();

  const llm = new ChatOpenAI({
    modelName: "gpt-3.5-turbo",
    streaming: true,
    temperature: 0.9,
  });

  llm
    .call(
      (messages as Message[]).map((m) =>
        m.role == "user"
          ? new HumanMessage(m.content)
          : new AIMessage(m.content)
      ),
      {},
      [handlers]
    )
    .catch(console.error);
  return new StreamingTextResponse(stream);
}

index.tsx
useChatではVercel AI SDKまたはLangChainのどちらかを指定するようにしてみました。
(どちらを指定してもチャットページの動作は同じです)

import type { NextPage } from "next";
import { useChat } from "ai/react";

const Home: NextPage = () => {
  const aiSdkChat = `/api/aiSdkChat`;
  const langChainChat = `/api/langChainChat`;

  const { messages, input, isLoading, stop, handleInputChange, handleSubmit } =
    useChat({
      api: aiSdkChat,
    });

  if (!isLoading) console.log(messages);

  return (
    <>
      <div className="mx-auto w-full max-w-md py-24 flex flex-col">
        <p className="font-bold text-lg">ChatGPT</p>
        <br />
        {messages.map((m) => (
          <div key={m.id} className="w-96 mb-2 p-2">
            {m.role === "user" ? "Human: " : "AI: "}
            {m.content}
          </div>
        ))}

        <br />
        <form onSubmit={handleSubmit}>
          <input
            name="box"
            className="w-96 flex rounded bottom-0 border border-gray-300 text-gray-700 mb-2 p-2"
            value={input}
            onChange={handleInputChange}
          />
          {isLoading ? (
            <button
              type="submit"
              className="opacity-50 cursor-not-allowed w-96 rounded bg-sky-500 hover:bg-sky-700 mb-2 p-2"
              disabled
            >
              Send
            </button>
          ) : (
            <button
              type="submit"
              className="w-96 rounded bg-sky-500 hover:bg-sky-700 mb-2 p-2"
            >
              Send
            </button>
          )}
        </form>
        <p className="w-96 text-slate-500 text-xs">
          開発ツールのコンソールからメッセージ変数の値を確認して、値がどのように格納されているかを確認できます。
        </p>
      </div>
    </>
  );
};

export default Home;

動作確認

yarn devして、
起動させたURL(localhost:3000など)をPCブラウザで確認します。

会話をしてみます。

動作しているようです。

まとめ

Vercel AI SDKを使うと、このようなシンプルなチャットページを実装するのは非常に簡単でした。
さらにご自分でエラーハンドリングを追加してみると、より理解が深まる機会になると思います。

また、LangChain JSには、プロンプトテンプレートやエージェントなど機能がたくさんありますので、いろいろ試してみたいと思います。

参考サイト
https://sdk.vercel.ai/docs/api-reference/use-chat
https://sdk.vercel.ai/docs/api-reference/langchain-stream
https://js.langchain.com/docs/get_started

Discussion