AI SDK by Vercelの初め📚
AI SDKとは
AI機能を持つアプリケーションやエージェントの構築TypeScript製のツールキットのことを指します。これを使うことでWebアプリやモバイルアプリにAI機能(チャットボット、テキスト生成、画像認識など)を簡単に組み込めるようになります。
https://ai-sdk.dev/docs/foundations/overview
なぜAI SDKを使うのか?
大規模言語モデル(LLM)をアプリケーションに組み込むのは複雑で、モデル提供者(OpenAI、Anthropic、Googleなど)ごとに異なるAPIや実装方法を覚える必要があります。AI SDKを用いることによって統一されたインターフェースを提供することできます。例えば、通常なら各社のAPIごとに異なるコードを書く必要があるところを、AI SDKを使えば同じ書き方でどのモデルでもテキスト生成ができる、ということですね。
簡単な使い方
app/api/chat/route.ts
import { openai } from "@ai-sdk/openai";
import { streamText, UIMessage, convertToModelMessages } from "ai";
export const maxDuration = 30;
export async function POST(req: Request) {
const { messages }: { messages: UIMessage[] } = await req.json();
const result = streamText({
model: openai("gpt-3.5-turbo"),
messages: convertToModelMessages(messages),
});
return result.toUIMessageStreamResponse();
}
streamText
: リアルタイムでテキストを生成・配信する関数
UIMessage
: フロントエンド用のメッセージ型
convertToModelMessages
: UIメッセージをAIモデル用の形式に変換
次にフロントエンドの設定をする
'use client';
import { useChat } from '@ai-sdk/react';
import { useState } from 'react';
export default function Chat() {
const [input, setInput] = useState('');
const { messages, sendMessage } = useChat();
return (
<div className="flex flex-col w-full max-w-md py-24 mx-auto stretch">
{messages.map(message => (
<div key={message.id} className="whitespace-pre-wrap">
{message.role === 'user' ? 'User: ' : 'AI: '}
{message.parts.map((part, i) => {
switch (part.type) {
case 'text':
return <div key={`${message.id}-${i}`}>{part.text}</div>;
}
})}
</div>
))}
<form
onSubmit={e => {
e.preventDefault();
sendMessage({ text: input });
setInput('');
}}
>
<input
className="fixed dark:bg-zinc-900 bottom-0 w-full max-w-md p-2 mb-8 border border-zinc-300 dark:border-zinc-800 rounded shadow-xl"
value={input}
placeholder="Say something..."
onChange={e => setInput(e.currentTarget.value)}
/>
</form>
</div>
);
}
上記はAI SDKのuseChat
フックを使ったReactチャットコンポーネント。先ほどのAPIエンドポイントと連携して動作します。
useChat()
内部で何をしているのか
const { messages, sendMessage } = useChat();
messages
: チャット履歴が入ります
sendMessage
を呼ぶと:
- 自動的に
/api/chat
エンドポイントにPOSTリクエスト - メッセージ履歴を含むJSONデータを送信
- ストリーミングレスポンスを受信
- リアルタイムで
messages
配列を更新される
{messages.map(message => (
<div key={message.id}>
{message.role === 'user' ? 'User: ' : 'AI: '}
{message.parts.map((part, i) => {
switch (part.type) {
case 'text':
return <div key={`${message.id}-${i}`}>{part.text}</div>;
}
})}
</div>
))}
解説
- チャット履歴を順番に表示
- ユーザーメッセージとAIメッセージを区別
message.parts
でテキスト、画像などに対応
Toolsの活用
LLMが特定のタスクを実行するために呼び出せるオブジェクト。toolsを用いることで個別のタスク (数学など) や外部情報(天気の取得など)を取得して、LLMに返してその情報をレスポンスに使用することができる。
https://ai-sdk.dev/docs/foundations/tools#tools
使用方法
generateText
や streamText
の tools
パラメータで使用
Tool の以下の3つの構成要素
description
inputSchema
execute
1. description
AIがいつこのツールを使うべきかの判断材料
description: "Get the weather in a location"
inputSchema: z.object({ location: z.string() })
2. inputSchema
(入力の型定義)
AIにどんな入力が必要かを教える
AIから来た入力が正しいかチェック
description: "Get the weather in a location"
inputSchema: z.object({ location: z.string() })
3. execute(実際の処理)
AIから指示されたときに実行される関数
execute: async ({ location }) => { // 実際の天気取得処理 return { temperature: 24 }; }
実際に天気予報のAPIを上記の方法で呼び出し天気に関する情報を聞くと専用の情報を返すチャットを検証してみました。
