テキスト生成が有用である一方で、ユースケースは構造化データの生成を必要とする傾向があるでしょう。例えば、テキストから情報を抽出したり、データを分類したり、合成データを生成したい場合などです。
Vercel AI SDK 6 : AI SDK Core – 構造化データの生成
作成 : Masashi Okumura (@classcat.com)
作成日時 : 01/25/2026
バージョン : ai@6.0.49
* 本記事は ai-sdk.dev/docs の以下のページを参考にしています :
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

Vercel AI SDK 6.x : AI SDK Core – 構造化データの生成
テキスト生成が有用である一方で、ユースケースは構造化データの生成を必要とする傾向があるでしょう。例えば、テキストから情報を抽出したり、データを分類したり、合成データを生成したい場合などです。
多くの言語モデルは構造化データを生成することができて、”JSON modes” や “tools” の使用として定義される場合が多いです。けれども、LLM は不正確または不完全な構造化データを生成する可能性があるため、スキーマを手動で提供して生成データを検証する必要があります。
AI SDK は generateText と streamText の output プロパティを使用して、モデルプロバイダー間で構造化オブジェクト生成を標準化します。Zod スキーマ, Valibot や JSON スキーマ を使用して希望のデータの形状を指定できて、AI モデルはその構造に準拠したデータを生成します。
構造化出力の生成
Output.object() を備えた generateText を使用してプロンプトから構造化データを生成します。スキーマはまた生成データの検証にも使用され、型安全性と正確さを保証します。
Gateway
import { generateText, Output } from 'ai';
import { z } from 'zod';
const { output } = await generateText({
model: "openai/gpt-4o-mini",
output: Output.object({
schema: z.object({
recipe: z.object({
name: z.string(),
ingredients: z.array(
z.object({ name: z.string(), amount: z.string() }),
),
steps: z.array(z.string()),
}),
}),
}),
prompt: 'Generate a lasagna recipe.',
});
レスポンス・ヘッダ & ボディへのアクセス
モデルプロバイダーからの完全なレスポンスへのアクセスを必要とする場合があります、例えば、プロバイダー固有のヘッダやボディコンテンツへのアクセスです。
response プロパティを使用して本来のレスポンスヘッダとボディにアクセスできます :
import { generateText, Output } from 'ai';
const result = await generateText({
// ...
output: Output.object({ schema }),
});
console.log(JSON.stringify(result.response.headers, null, 2));
console.log(JSON.stringify(result.response.body, null, 2));
構造化出力のストリーミング
構造化データを返すという追加された複雑さにより、対話的なユースケースではモデルの応答時間が許容できない可能性があります。streamText と output を使用して、モデルの構造化レスポンスを生成と同時にストリーミングできます。
Gateway
import { streamText, Output } from 'ai';
import { z } from 'zod';
const { partialOutputStream } = streamText({
model: "openai/gpt-4o-mini",
output: Output.object({
schema: z.object({
recipe: z.object({
name: z.string(),
ingredients: z.array(
z.object({ name: z.string(), amount: z.string() }),
),
steps: z.array(z.string()),
}),
}),
}),
prompt: 'Generate a lasagna recipe.',
});
// use partialOutputStream as an async iterable
for await (const partialObject of partialOutputStream) {
console.log(partialObject);
}
useObject フックを使用して、クライアントで構造化出力を消費できます。
ストリーミングにおけるエラー処理
streamText は直ちにストリーミングを開始します。ストリーミング中にエラーが発生した場合、(ストリームのクラッシュを回避するために) 例外を投げるのではなく、ストリームの一部になります。
エラーを処理するには、onError コールバックを提供します :
import { streamText, Output } from 'ai';
const result = streamText({
// ...
output: Output.object({ schema }),
onError({ error }) {
console.error(error); // log to your error tracking service
},
});
For non-streaming error handling with generateText, see the Error Handling section below.
Output 型
AI SDK は、Output オブジェクト経由で生成データの想定される構造を指定する複数の方法をサポートしています。構造化/テキスト (データ) 生成と検証のために様々なストラテジーを選択できます。
Output.text()
Output.text() を使用してモデルから plain テキストを生成します。このオプションは結果にスキーマを強制しません : 単純にモデルのテキストを文字列として受け取ります。これは、output が指定されていない場合のデフォルトの動作です。
import { generateText, Output } from 'ai';
const { output } = await generateText({
// ...
output: Output.text(),
prompt: 'Tell me a joke.',
});
// output will be a string (the joke)
Output.object()
Output.object({ schema }) を使用して、スキーマ (例えば、Zod スキーマ) に基づいて構造化オブジェクトを生成できます。出力は型検証され、返された結果がスキーマに一致することを保証します。
import { generateText, Output } from 'ai';
import { z } from 'zod';
const { output } = await generateText({
// ...
output: Output.object({
schema: z.object({
name: z.string(),
age: z.number().nullable(),
labels: z.array(z.string()),
}),
}),
prompt: 'Generate information for a test user.',
});
// output will be an object matching the schema above
Output.array()
Output.array({ element }) を使用して、モデルから型付けされたオブジェクトの配列を想定するものを指定します、そこでは各要素は (element プロパティで定義された) スキーマに準拠する必要があります。
import { generateText, Output } from 'ai';
import { z } from 'zod';
const { output } = await generateText({
// ...
output: Output.array({
element: z.object({
location: z.string(),
temperature: z.number(),
condition: z.string(),
}),
}),
prompt: 'List the weather for San Francisco and Paris.',
});
// output will be an array of objects like:
// [
// { location: 'San Francisco', temperature: 70, condition: 'Sunny' },
// { location: 'Paris', temperature: 65, condition: 'Cloudy' },
// ]
streamText を使用して配列をストリーミングする場合、elementStream を使用して、生成された際に各完成した要素を受け取ることができます :
import { streamText, Output } from 'ai';
import { z } from 'zod';
const { elementStream } = streamText({
// ...
output: Output.array({
element: z.object({
name: z.string(),
class: z.string(),
description: z.string(),
}),
}),
prompt: 'Generate 3 hero descriptions for a fantasy role playing game.',
});
for await (const hero of elementStream) {
console.log(hero); // Each hero is complete and validated
}
Output.choice()
分類や固定列挙型の回答のような、特定の文字列オプションのセットからモデルが選択することを想定する場合、Output.choice({ options }) を使用します。
import { generateText, Output } from 'ai';
const { output } = await generateText({
// ...
output: Output.choice({
options: ['sunny', 'rainy', 'snowy'],
}),
prompt: 'Is the weather sunny, rainy, or snowy today?',
});
// output will be one of: 'sunny', 'rainy', or 'snowy'
任意の文字列オプションのセットを提供することができて、出力は常に指定されたオプションの一つに一致する単一の文字列値になります。AI SDK は結果がオプションの一つに一致することを検証し、モデルが無効なものを返す場合には例外を投げます。
これは、分類スタイルの生成をする場合や API 互換性のために有効な値を強制する場合に特に役立ちます。
Output.json()
特定のスキーマを強制することなく、モデルから非構造化 JSON 値を生成して解析したい場合には Output.json() を使用します。これは、任意のオブジェクトや柔軟な構造を捕捉したい場合や、厳格な検証ではなくモデルの自然な出力に依存したい場合に役立ちます。
import { generateText, Output } from 'ai';
const { output } = await generateText({
// ...
output: Output.json(),
prompt:
'For each city, return the current temperature and weather condition as a JSON object.',
});
// output could be any valid JSON, for example:
// {
// "San Francisco": { "temperature": 70, "condition": "Sunny" },
// "Paris": { "temperature": 65, "condition": "Cloudy" }
// }
Output.json を使用すれば、AI SDK はレスポンスが有効な JSON であることだけを確認し、値の構造や型は検証しません。スキーマ検証を必要とする場合は、代わりに .object や .array 出力を使用します。
For more advanced validation or different structures, see the Output API reference.
ツールによる構造化出力の生成
generateText や streamText で構造化出力を使用する主な利点の一つはツール呼び出しと組み合わせられる機能です。
Gateway
import { generateText, Output, tool, stepCountIs } from 'ai';
import { z } from 'zod';
const { output } = await generateText({
model: "openai/gpt-4o-mini",
tools: {
weather: tool({
description: 'Get the weather for a location',
inputSchema: z.object({ location: z.string() }),
execute: async ({ location }) => {
// fetch weather data
return { temperature: 72, condition: 'sunny' };
},
}),
},
output: Output.object({
schema: z.object({
summary: z.string(),
recommendation: z.string(),
}),
}),
stopWhen: stepCountIs(5),
prompt: 'What should I wear in San Francisco today?',
});
以上