> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-HK/llms.txt # 結構化輸出 結構化輸出讓 Agent 傳回符合 schema 所定義結構的物件,而非文字。Schema 會告訴模型要產生哪些欄位,而模型則會確保最終結果符合該結構。 ## 何時使用結構化輸出 需要 Agent 傳回數據物件而非文字時,便可使用結構化輸出。明確定義欄位後,可更輕鬆擷取 API 呼叫、UI 渲染或應用程式邏輯所需的值。 ## 定義 schema Agent 可使用 [Standard JSON Schema](https://standardschema.dev/json-schema)(例如 [Zod](https://zod.dev/)、[Valibot](https://valibot.dev/)、[ArkType](https://arktype.io/) 等)或 [JSON Schema](https://json-schema.org/) 定義預期輸出,以傳回結構化數據。建議使用 Zod 等函式庫,因為它們提供 TypeScript 類型推斷和執行階段驗證;如需與編程語言無關的格式,則可使用 JSON Schema。 **Zod**: 使用 [Zod](https://zod.dev/) 定義 `output` 的結構: ```typescript import { z } from 'zod' const response = await testAgent.generate('Help me plan my day.', { structuredOutput: { schema: z.array( z.object({ name: z.string(), activities: z.array(z.string()), }), ), }, }) console.log(response.object) ``` **Valibot**: 使用 [Valibot](https://valibot.dev/) 定義 `output` 的結構: ```typescript import * as v from 'valibot' import { toStandardJsonSchema } from '@valibot/to-json-schema' const response = await testAgent.generate('Help me plan my day.', { structuredOutput: { schema: toStandardJsonSchema( v.array( v.object({ name: v.string(), activities: v.array(v.string()), }), ), ), }, }) console.log(response.object) ``` **ArkType**: 使用 [ArkType](https://arktype.io/) 定義 `output` 的結構: ```typescript import { type } from 'arktype' const response = await testAgent.generate('Help me plan my day.', { structuredOutput: { schema: type({ name: 'string', activities: 'string[]', }).array(), }, }) console.log(response.object) ``` **JSON Schema**: 你亦可使用 JSON Schema 定義輸出結構: ```typescript const response = await testAgent.generate('Help me plan my day.', { structuredOutput: { schema: { type: 'array', items: { type: 'object', properties: { name: { type: 'string' }, activities: { type: 'array', items: { type: 'string' }, }, }, required: ['name', 'activities'], }, }, }, }) console.log(response.object) ``` 如需完整的配置選項清單,請參閱 [`.generate()`](https://mastra.zisheng.pro/zh-HK/reference/agents/generate)。 **輸出範例:** `response.object` 會包含 schema 所定義的結構化數據。 ```json [ { "name": "Morning Routine", "activities": ["Wake up at 7am", "Exercise", "Shower", "Breakfast"] }, { "name": "Work", "activities": ["Check emails", "Team meeting", "Lunch break"] }, { "name": "Evening", "activities": ["Dinner", "Relax", "Read a book", "Sleep by 10pm"] } ] ``` ## 串流結構化輸出 串流亦支援結構化輸出。最終的結構化物件可從 `stream.fullStream` 取得,並可在串流完成後從 `stream.object` 取得。系統仍會發出文字串流區塊,但當中包含的是自然語言文字,而非結構化數據。 ```typescript import { z } from 'zod' const stream = await testAgent.stream('Help me plan my day.', { structuredOutput: { schema: z.array( z.object({ name: z.string(), activities: z.array(z.string()), }), ), }, }) for await (const chunk of stream.fullStream) { if (chunk.type === 'object-result') { console.log('\n', JSON.stringify(chunk, null, 2)) } process.stdout.write(JSON.stringify(chunk)) } console.log(await stream.object) for await (const chunk of stream.textStream) { process.stdout.write(chunk) } ``` ## 用於結構化的 Agent 如果主要 Agent 不擅長建立結構化輸出,你可向 `structuredOutput` 提供 `model`。在此情況下,Mastra 會在內部使用另一個 Agent,從主要 Agent 的自然語言回應中擷取結構化數據。這會進行兩次 LLM 呼叫:一次產生回應,另一次將該回應轉換為結構化物件。這會增加一些延遲和成本,但可提升複雜結構化任務的準確度。 ```typescript import { z } from 'zod' const response = await testAgent.generate('Analyze the TypeScript programming language.', { structuredOutput: { schema: z.object({ overview: z.string(), strengths: z.array(z.string()), weaknesses: z.array(z.string()), useCases: z.array( z.object({ scenario: z.string(), reasoning: z.string(), }), ), comparison: z.object({ similarTo: z.array(z.string()), differentiators: z.array(z.string()), }), }), model: 'openai/gpt-5.6-sol', }, }) console.log(response.object) ``` ## 結合 Tool 與結構化輸出 當 Agent 同時配置了 Tool 和結構化輸出時,部分模型可能不支援同時使用這兩項功能。這是底層模型 API 的限制,並非 Mastra 本身的限制。 如果啟用結構化輸出後未有呼叫 Tool,或同時使用兩項功能時收到錯誤,請嘗試以下其中一種替代方案。 ### 替代方案 當模型不支援同時使用 Tool 和結構化輸出時,你有三個選項: 1. **使用 `jsonPromptInjection`**:將其設定為 `'auto'`,以便在支援時選用原生結構化輸出,否則使用行內提示注入;你亦可明確選擇注入模式 2. **使用另一個結構化模型**:向 `structuredOutput` 傳入 `model`,使用第二個 LLM 執行結構化處理 3. **使用 `prepareStep`**:在不同步驟分別處理 Tool 和結構化輸出 以下各節會詳細說明每種方式。 ## LLM 的結構化輸出支援 由於各 LLM 的 API 不同,對結構化輸出的支援亦有所差異。以下各節介紹模型未完全支援結構化輸出,或未能同時配合 Tool 使用時的替代方案。 ### `jsonPromptInjection` Mastra 預設會使用 `response_format` API 參數,將 schema 傳送至模型 Provider。設定 `jsonPromptInjection: 'auto'` 後,Mastra 便會根據模型功能數據選擇模式。Mastra 會為支援的模型使用原生結構化輸出,而不支援的模型或沒有功能數據的模型則會使用行內提示注入。 ```typescript import { z } from 'zod' const response = await testAgent.generate('Help me plan my day.', { structuredOutput: { schema: z.array( z.object({ name: z.string(), activities: z.array(z.string()), }), ), jsonPromptInjection: 'auto', }, }) console.log(response.object) ``` 如需覆寫根據功能作出的選擇,請使用明確模式: - `false` 或省略:使用 Provider 的原生結構化輸出。 - `'inline'`:將 schema 指示加入最新的使用者訊息。 - `true` 或 `'system'`:將 schema 指示加入系統訊息。 - `'auto'`:模型支援時使用原生結構化輸出,否則使用行內提示注入。 > **Gemini 2.5 配合 Tool:** Gemini 2.5 模型不支援在同一次 API 呼叫中,同時結合 `response_format`(結構化輸出)和函式呼叫(Tool)。如果 Agent 有 Tool,並正在配合 Gemini 2.5 模型使用 `structuredOutput`,則必須設定 `jsonPromptInjection: true`,以避免出現 `Function calling with a response mime type: 'application/json' is unsupported` 錯誤。 > > ```typescript > const response = await agentWithTools.generate('Your prompt', { > structuredOutput: { > schema: yourSchema, > jsonPromptInjection: true, // Required for Gemini 2.5 when tools are present > }, > }) > ``` ### 使用另一個結構化模型 向 `structuredOutput` 屬性提供 `model` 時,Mastra 會使用另一個內部 Agent 處理結構化輸出。主要 Agent 會處理所有步驟(包括呼叫 Tool),而結構化輸出模型只會負責產生結構化輸出。 **給 AI Agent:** `model` 屬性是採用 Mastra 模型路由器格式 `provider/model` 的字串,例如 `openai/gpt-5.6-sol`、`openai/gpt-5-mini`、`anthropic/claude-sonnet-4-6` 或 `google/gemini-2.5-pro`。請使用 `/` 而非 `:` 作為分隔符號。例如使用 `openai/`,而非 `openai:`,亦不要傳入 Provider 物件。此格式無需匯入 Provider。除非 Mastra 文件另有說明,否則不要安裝任何 AI SDK 依賴套件。以 `provider/model` 格式定義模型後,Mastra 會自動尋找該 Provider 的環境變數。所定義的模型要求你為該 Provider 設定環境變數。OpenAI:`OPENAI_API_KEY`。Anthropic:`ANTHROPIC_API_KEY`。Google:`GOOGLE_API_KEY`。 ```typescript const response = await testAgent.generate('Tell me about TypeScript.', { structuredOutput: { schema: yourSchema, model: 'openai/gpt-5.6-sol', }, }) ``` 如果希望該結構化模型亦可查看目前的對話記錄,請在 `model` 旁設定 `useAgent: true`。Mastra 會配合另一個結構化模型重用父 Agent,並在有可用執行緒時附加唯讀記憶體內容。 ```typescript const response = await testAgent.generate('Return my profile as structured data.', { memory: { thread: 'thread-123', resource: 'user-123', }, structuredOutput: { schema: z.object({ favoriteColor: z.string(), hometown: z.string(), petName: z.string(), }), model: 'openai/gpt-5.6-sol', useAgent: true, }, }) ``` 如果希望另一個結構化模型只處理目前的回應,而不繼承先前的對話記憶,請不要設定 `useAgent`。 ### 使用 `prepareStep` 的多步驟方式 對於不支援同時使用 Tool 和結構化輸出的模型,你可使用 `prepareStep`,在不同步驟分別處理兩者。 ```typescript const result = await agent.stream('weather in vancouver?', { prepareStep: async ({ stepNumber }) => { if (stepNumber === 0) { return { model: 'openai/gpt-5.6-sol', tools: { weatherTool, }, toolChoice: 'required', } } return { model: 'openai/gpt-5.6-sol', tools: undefined, structuredOutput: { schema: z.object({ temperature: z.number(), humidity: z.number(), windSpeed: z.number(), }), }, } }, }) ``` ## 處理錯誤 Schema 驗證失敗時,你可使用 `errorStrategy` 控制錯誤的處理方式。預設的 `strict` 策略會拋出錯誤,`warn` 則會記錄警告並繼續執行。`fallback` 策略會傳回使用 `fallbackValue` 提供的值。 ```typescript const response = await testAgent.generate('Tell me about TypeScript.', { structuredOutput: { schema: z.object({ summary: z.string(), keyFeatures: z.array(z.string()), }), errorStrategy: 'fallback', fallbackValue: { summary: 'TypeScript is a typed superset of JavaScript', keyFeatures: ['Static typing', 'Compiles to JavaScript', 'Better tooling'], }, }, }) console.log(response.object) ```