Vercel AI SDKを使ってChatGPTライクなアプリケーションを簡単に構築する

## Vercel AI SDKについて
Vercel AI SDKはAIを使ったチャットUIを構築するためのライブラリです。
みなさんご存知のChatGPTのようなWebアプリケーションを比較的簡単に構築することができます。

## 特徴
公式ドキュメントによると、下記のような特徴があります。
- SWRを利用した React、Svelte、Vue、Solid ヘルパーにより、テキストのレスポンスをストリーミングし、チャットやQAのようなUIを構築できます。
- OpenAI、LangChain、Anthropic、Cohere、Hugging Faceをサポート
- Node.js、サーバーレス、およびエッジ ランタイムのサポート
- 完了したストリーミング応答をデータベースに保存するためのコールバック (同じリクエスト内)

APIリファレンスのコードサンプルを見ても、React,Svelte,Vue.jsが用意されており、複数のJSライブラリから使用することができるようです。またNext.jsでの導入手順についてはApp RouterとPages Routerのものと両方あるのも嬉しいです。

## 実装例
### ChatGPTライクなチャットアプリの例
下記はChatGPTのようなユーザーの入力に対して、AIが応答してという流れを繰り返し行うようなチャットアプリを構築するコード例です。
#### 実行サンプル
![CleanShot 2023-07-23 at 21.42.38.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2656439/d0b30805-f7ff-deac-42a9-9af5195d69a1.gif)

#### フロントの実装

```jsx
'use client'

import { useChat } from 'ai/react'

export default function Chat() {
  const { messages, input, handleInputChange, handleSubmit } = useChat()

  return (
    <div className="flex flex-col w-full max-w-md py-24 mx-auto stretch">
      {messages.length > 0
        ? messages.map(m => (
            <div key={m.id} className="whitespace-pre-wrap">
              {m.role === 'user' ? 'User: ' : 'AI: '}
              {m.content}
            </div>
          ))
        : null}

      <form onSubmit={handleSubmit}>
        <input
          className="fixed bottom-0 w-full max-w-md p-2 mb-8 border border-gray-300 rounded shadow-xl"
          value={input}
          placeholder="Say something..."
          onChange={handleInputChange}
        />
      </form>
    </div>
  )
}

```

Vercel AI SDKが提供してくれている、`useChat`というカスタムフックを使うことでシンプルなコードでUIのチャットを作成することができます。本筋とは関係ないのですが、公式ドキュメントのサンプルでスタイリングにTailwind CSSを使っているところも推せますね👀

`useChat`カスタムフックから得られる`messages`という変数にユーザの入力とAIの返答を配列形式で格納されてます。

https://sdk.vercel.ai/docs/api-reference/use-chat


この記事では詳しく紹介しませんが、AIモデルを使用してプロンプトの補完を返すようなUIを実装するための`useCompletion`フックも用意されています。

https://sdk.vercel.ai/docs/api-reference/use-completion

#### APIの実装
```jsx
import { Configuration, OpenAIApi } from 'openai-edge'
import { OpenAIStream, StreamingTextResponse } from 'ai'

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

export const runtime = 'edge'

export async function POST(req: Request) {
  const { messages } = await req.json()

  const response = await openai.createChatCompletion({
    model: 'gpt-3.5-turbo',
    stream: true,
    messages: messages.map((message: any) => ({
      content: message.content,
      role: message.role
    }))
  })

  // ↓↓　以下がVercel AI SDKによる実装部分 ↓↓
  const stream = OpenAIStream(response) 
  return new StreamingTextResponse(stream) 
}
```

環境変数`OPENAI_API_KEY`で取得したOpenAI APIのシークレットキーを指定しています。

`messages`にこれまでの会話のやり取りが配列で格納されてます。クライアント側のuseChatで扱うmessagesと同じ形式です。`OpenAIApi.createChatCompletion`メソッドにこれまでの使用するモデルやメッセージ履歴を渡すことでレスポンスとして続きの内容が得られます。オプションの`stream: true`を指定することで、応答内容をストリーミング形式で返してくれます。

ここまでのAIモデルとのやり取りの実装自体はOpenAIが提供してくれているライブラリを使用しています。ストリーム処理の扱いについてはOpenAIのライブラリでもネイティブにサポートされておらず、各々の実装に任せられる部分になるのですが、ここをVercel AI SDKを使用することで、簡単に実装できます。（API実装の下から2行です）

**※補足：**
OpenAI SDKのissueにSDKの次期バージョンでストリームの扱いをネイティブにサポートするというやり取りがありました。Vercel AI SDK以外を使用するといった場合はいずれ選択肢に入るのかもしれません✨

https://github.com/openai/openai-node/issues/18

## まとめ
Vercel AI SDKを使用することで、AIを使用したWebアプリケーション構築において、フロント側の実装の大半やバックエンド側の実装で現状ネイティブのAPIだけでは大変なストリーム処理を非常にスマートに行うことができます！

## 参考文献
- https://github.com/vercel-labs/ai/
- https://sdk.vercel.ai/docs/
- https://github.com/openai/openai-node/