结构化输出允许您约束 AI 模型响应以匹配特定的 JSON 模式,从而确保一致且类型安全的数据提取。TanStack AI 使用 标准 JSON Schema 规范,允许您使用任何兼容的模式库。
当您向 chat() 函数提供 outputSchema 时,TanStack AI 会
这对于
TanStack AI 使用 标准 JSON Schema,这意味着您可以使用任何实现该规范的模式库
注意: 请参阅您的模式库的文档,了解有关定义模式和使用诸如 .describe() 之类功能的详细信息。TanStack AI 会自动将您的模式转换为 JSON Schema 格式。
以下是如何使用 Zod 模式使用结构化输出
import { chat } from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai";
import { z } from "zod";
// Define your schema
const PersonSchema = z.object({
name: z.string().describe("The person's full name"),
age: z.number().describe("The person's age in years"),
email: z.string().email().describe("The person's email address"),
});
// Use it with chat()
const person = await chat({
adapter: openaiText("gpt-5.2"),
messages: [
{
role: "user",
content: "Extract the person info: John Doe is 30 years old, email john@example.com",
},
],
outputSchema: PersonSchema,
});
// person is fully typed as { name: string, age: number, email: string }
console.log(person.name); // "John Doe"
console.log(person.age); // 30
console.log(person.email); // "john@example.com"
chat() 的返回类型会根据 outputSchema 属性而变化
| 配置 | 返回类型 |
|---|---|
| 没有 outputSchema | AsyncIterable<StreamChunk> |
| 有 outputSchema | Promise<InferSchemaType<TSchema>> |
当您提供 outputSchema 时,TanStack AI 会自动从您的模式中推断 TypeScript 类型
import { z } from "zod";
// Define a complex schema
const RecipeSchema = z.object({
name: z.string(),
prepTime: z.string(),
servings: z.number(),
ingredients: z.array(
z.object({
item: z.string(),
amount: z.string(),
})
),
instructions: z.array(z.string()),
});
// TypeScript knows the exact return type
const recipe = await chat({
adapter: openaiText("gpt-5.2"),
messages: [{ role: "user", content: "Give me a recipe for scrambled eggs" }],
outputSchema: RecipeSchema,
});
// Full type safety - TypeScript knows all these properties exist
recipe.name; // string
recipe.prepTime; // string
recipe.servings; // number
recipe.ingredients[0].item; // string
recipe.instructions.map((step) => step.toUpperCase()); // string[]
模式字段描述有助于 AI 理解要提取的数据。大多数模式库都支持 .describe() 方法
const ProductSchema = z.object({
name: z.string().describe("The product name"),
price: z.number().describe("Price in USD"),
inStock: z.boolean().describe("Whether the product is currently available"),
categories: z
.array(z.string())
.describe("Product categories like 'electronics', 'clothing', etc."),
});
这些描述包含在发送到提供商的 JSON Schema 中,为 AI 提供有关每个字段的上下文。
您可以定义深度嵌套的结构
const CompanySchema = z.object({
name: z.string(),
founded: z.number().describe("Year the company was founded"),
headquarters: z.object({
city: z.string(),
country: z.string(),
address: z.string().optional(),
}),
employees: z.array(
z.object({
name: z.string(),
role: z.string(),
department: z.string(),
})
),
financials: z
.object({
revenue: z.number().describe("Annual revenue in millions USD"),
profitable: z.boolean(),
})
.optional(),
});
const company = await chat({
adapter: anthropicText("claude-sonnet-4-5"),
messages: [
{
role: "user",
content: "Extract company info from this article: ...",
},
],
outputSchema: CompanySchema,
});
// Access nested properties with full type safety
console.log(company.headquarters.city);
console.log(company.employees[0].role);
结构化输出与代理工具循环无缝协作。当同时提供 outputSchema 和 tools 时,TanStack AI 将
import { chat, toolDefinition } from "@tanstack/ai";
import { z } from "zod";
const getProductPrice = toolDefinition({
name: "get_product_price",
description: "Get the current price of a product",
inputSchema: z.object({
productId: z.string(),
}),
}).server(async ({ input }) => {
// Fetch price from database
return { price: 29.99, currency: "USD" };
});
const RecommendationSchema = z.object({
productName: z.string(),
currentPrice: z.number(),
reason: z.string(),
});
const recommendation = await chat({
adapter: openaiText("gpt-5.2"),
messages: [
{
role: "user",
content: "Recommend a product for a developer",
},
],
tools: [getProductPrice],
outputSchema: RecommendationSchema,
});
// The AI will call the tool to get prices, then return structured output
console.log(recommendation.productName);
console.log(recommendation.currentPrice);
console.log(recommendation.reason);
如果您不想使用模式库,可以传递纯 JSON Schema 对象
import type { JSONSchema } from "@tanstack/ai";
const schema: JSONSchema = {
type: "object",
properties: {
name: { type: "string", description: "The person's name" },
age: { type: "number", description: "The person's age" },
},
required: ["name", "age"],
};
const result = await chat({
adapter: openaiText("gpt-5.2"),
messages: [{ role: "user", content: "Extract: John is 25 years old" }],
outputSchema: schema,
});
// Note: With plain JSON Schema, TypeScript infers `unknown` type
// You'll need to cast or validate the result yourself
const person = result as { name: string; age: number };
注意: 使用纯 JSON Schema 时,TypeScript 无法推断返回类型。结果将被类型化为 unknown。为了获得完整的类型安全,请使用 Zod 等模式库。
结构化输出通过其本机 API 受所有主要提供商的支持
| 提供者 | 实现 |
|---|---|
| OpenAI | 使用 response_format 与 json_schema |
| Anthropic | 使用基于工具的提取 |
| Google Gemini | 使用 responseSchema |
| Ollama | 使用带有模式的 JSON 模式 |
TanStack AI 会自动处理提供商特定的实现细节,因此您可以在不同的提供商中使用相同的代码。
使用描述性的字段名称和描述 - 这有助于 AI 理解要提取的数据
保持模式聚焦 - 仅提取您需要的数据;更简单的模式会产生更可靠的结果
适当使用可选字段 - 当数据可能不存在于源中时,将字段标记为可选
验证边缘情况 - 使用各种输入进行测试,以确保模式正确处理边缘情况
对受限值使用枚举 - 当字段具有有限的有效值集时,使用枚举
const schema = z.object({
status: z.enum(["pending", "approved", "rejected"]),
priority: z.enum(["low", "medium", "high"]),
});
如果 AI 响应与您的模式不匹配,TanStack AI 将抛出验证错误
try {
const result = await chat({
adapter: openaiText("gpt-5.2"),
messages: [{ role: "user", content: "..." }],
outputSchema: MySchema,
});
} catch (error) {
if (error instanceof Error) {
console.error("Structured output failed:", error.message);
}
}
该错误将包括有关哪些字段验证失败的详细信息,帮助您调试模式不匹配。