前回の記事では、サンプルのコードをそのまま動かしてみました。このサンプルに含まれているコードを見ながら動作を確認していきたいと思います。
サンプルコードの確認
前回は起動して動作確認をしただけですが、実際にはいくつかのページが含まれている形です。以下の一覧の api 以外が個別のページを持っています。
全て紹介をすると長くなるので、基本動作を理解できるようにいくつかピックアップして確認をしていきます。
useChat
まずホームで動作しているコードは非常にシンプルでようになっています。
'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.map(m => (
<div key={m.id} className="whitespace-pre-wrap">
{m.role === 'user' ? 'User: ' : 'AI: '}
{m.content}
</div>
))}
<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>
);
}
チャットの文字が表示されるエリアを message.map で処理をしており、またフォームが用意されているシンプルなコードです。そしてフォームに入力された処理を実行しているのが以下のコードになります。
const { messages, input, handleInputChange, handleSubmit } = useChat();
useChat が入力された文字をして message に結果を返している形です。動作に関しては以下のページで紹介されています。
標準の呼び出しをしている際には、api としては /api/chat を呼び出しており、サンプルコードの app/api/chat/route.ts を呼び出しています。そしてこの route.ts の中で、ChatGPT に問い合わせをして回答を取得している流れとなります。この呼び出しの部分を Azure Open AI につなげる場合の手順は以下のページで紹介されています。
この手順は、今回の主なテーマからは外れるのでまた別の記事で紹介したいと思います。
useCompletion
続いて URL に completion を追加してアクセスをすると以下のような画面になります。
コードを見ると、上記のサンプルと異なり useCompletion で呼び出しています。
const { completion, input, handleInputChange, handleSubmit, error, data } = useCompletion();
この呼び出しの場合は、テキストを補完して回答を生成するという形で回答を得る形になります。詳細な情報は以下のページで用意されています。
デフォルトでは app/api/completion/route.ts に用意されている API を呼び出す形となっています。
これを利用しているサンプルは別にも用意されており、spell-check が該当します。コードを参照すると以下のように呼び出しています。
const { complete } = useCompletion({
api: '/api/spell-check',
});
api としては別のコードを呼び出していることがわかります。実際に、ページを表示してみると以下のような画面が表示されます。
試しに以下のような文章を入れてみます。
Publish のボタンをクリックすると、スペルエラーがあるかも?とダイアログが表示されます。
単にチャットをするというだけでなく、こういった用途にも利用できるようになっています。
experimental_StreamData
上記の動作以外で、特徴的なものが stream-react-response での呼び出し方法です。app/stream-react-response/chat.tsx のファイルを見ると、 API ではなく以下のように useChat を呼び出す時に handler を利用しています。
const { messages, input, handleInputChange, handleSubmit } = useChat({
api: handler,
});
page.tsx のファイルを全て紹介すると以下のようなコードになっています。
import { handler } from './action';
import { Chat } from './chat';
export default function Page() {
return <Chat handler={handler} />;
}
export const runtime = 'edge';
chat.tsx のファイルを Chat という形で呼び出し、handler として action.tsx で定義している handler を渡している形です。handler の定義を見ると、
export async function handler({ messages }: { messages: Message[] }) {
const data = new experimental_StreamData();
ここで experimental_StreamData を利用しています。これを利用することで、OpenAI 都連携するデータを設定することが可能となります。このサンプルでは天気を聞くと回答が返ってくる仕組みです。
この仕組みを次回以降、カスタムデータを利用するために活用したいと思います。
まとめ
Next.js OpenAI Starter のサンプルを眺めただけですが、実装の方法のヒントが見えてきました。次回はこれを整理していきたいと思います。