> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-TW/llms.txt # 執行實驗 **新增於:** `@mastra/core@1.4.0` 實驗會讓資料集中的每個項目通過一個目標(Agent、Workflow 或評分器),再視需要為輸出評分。若要評估 LLM 判定器本身,請使用評分器作為目標。結果預設會保存至儲存區,讓你比較不同提示詞、模型或程式碼變更下的執行結果。 **給 AI Agent:** 執行 `npx mastra api experiment run dataset_123 '{"name":"translation-baseline"}'` 可直接啟動實驗,不必開啟 Studio 或撰寫暫用指令碼。請以 `npx mastra api dataset list` 傳回的資料集 ID 取代範例 ID。此指令需要執行中的 Mastra 伺服器,且已設定資料集儲存區並註冊實驗目標;可使用 `npx mastra dev` 啟動本機伺服器,或透過 `--url` 傳入可連線伺服器的基底 URL。建構不同輸入前,請執行 `npx mastra api experiment run --schema`;實驗可能會呼叫模型,因此啟動前應取得使用者核准。使用 `npx skills add mastra-ai/skills --skill mastra` 安裝 Mastra Skill,即可取得完整的 API CLI 探索、目標指定、結構描述、驗證與錯誤處理指引。 ## 基本實驗 呼叫 [`startExperiment()`](https://mastra.zisheng.pro/zh-TW/reference/datasets/startExperiment),並傳入目標與評分器: ```typescript import { mastra } from '../index' const dataset = await mastra.datasets.get({ id: 'translation-dataset-id' }) const summary = await dataset.startExperiment({ name: 'gpt-5.1-baseline', targetType: 'agent', targetId: 'translation-agent', scorers: ['accuracy', 'fluency'], }) console.log(summary.status) // 'completed' | 'failed' console.log(summary.succeededCount) // number of items that ran successfully console.log(summary.failedCount) // number of items that failed ``` `startExperiment()` 會封鎖至所有項目完成。若要啟動後不等待結果,請參閱[非同步實驗](#async-experiments)。 ## Studio 你也可以在 [Studio](https://mastra.zisheng.pro/zh-TW/docs/studio/overview) 中執行實驗。新增資料集項目後,開啟該項目並選取 **Run Experiment**,再設定目標、評分器與選項。 執行實驗後,**Experiments** 分頁會顯示該資料集的所有執行記錄(包括狀態、數量與時間戳記)。選取實驗即可查看逐項結果、分數與執行 Trace。 在 **Experiments** 分頁中選取 **Compare**,再選擇兩個以上的實驗,即可並排比較其分數與結果。 ## 實驗目標 實驗可指向已註冊的 Agent、Workflow 或評分器。 ### 已註冊的 Agent 指向 Mastra 執行個體上已註冊的 Agent: ```typescript const summary = await dataset.startExperiment({ name: 'agent-v2-eval', targetType: 'agent', targetId: 'translation-agent', scorers: ['accuracy'], }) ``` 每個項目的 `input` 都會直接傳給 `agent.generate()`,因此必須是 `string`、`string[]` 或 `CoreMessage[]`。 #### 啟用記憶體的 Agent 當目標 Agent 擁有自己的記憶體,且 request context 帶有資源 ID(`MASTRA_RESOURCE_ID_KEY`,由驗證中介軟體、實驗或項目的 `requestContext`,或 Studio **Run Experiment** 表單設定)時,實驗執行器會為每個項目注入新的記憶體討論串。request context 中的資源 ID 表示「以此資源執行」:各項目的對話會保存為該資源下的討論串,而重試項目每次嘗試都會取得新討論串,避免先前失敗嘗試的內容洩漏至重試 context。 注入的討論串會加上標記,以便對應回該次執行:討論串中繼資料包含 `experimentId`,並以 `experimentItemId` 保存資料集項目 ID。系統不會為這些討論串產生標題。 由於討論串屬於呼叫者的資源,資源範圍記憶體功能在執行期間會讀寫該資源的狀態: - 資源範圍工作記憶體的更新會保存至資源,同次執行中的後續項目可看到較早項目所做的更新。 - 資源範圍語意回憶可向實驗提供該資源先前的對話;實驗逐字稿也能在該資源後續的對話中被回憶。 若要使用真實使用者累積的 context 評估 Agent,此功能很實用。若不希望實驗執行接觸真實使用者狀態,請改用專用的評估資源 ID 執行實驗。 下列情況會略過討論串注入: - 若 request context 也設定 `MASTRA_THREAD_ID_KEY`,執行器會直接使用該討論串,因此所有項目(及重試)都共用同一段對話。 - 若 Agent 沒有記憶體,或 request context 沒有資源 ID,執行過程不會使用記憶體,也不會保存任何內容。 ### 已註冊的 Workflow 指向 Mastra 執行個體上已註冊的 Workflow: ```typescript const summary = await dataset.startExperiment({ name: 'workflow-eval', targetType: 'workflow', targetId: 'translation-workflow', scorers: ['accuracy'], }) ``` Workflow 會接收每個項目的 `input` 作為觸發資料。 ### 已註冊的評分器 指向評分器,以標準答案評估 LLM 判定器: ```typescript const summary = await dataset.startExperiment({ name: 'judge-accuracy-eval', targetType: 'scorer', targetId: 'accuracy', }) ``` 評分器會接收每個項目的 `input` 與 `groundTruth`。隨著底層模型變更,LLM 型判定器可能會逐漸偏移,因此必須定期以已知正確的標籤重新校準。資料集可提供穩定基準,用來偵測這類偏移。 ## 評分結果 每個項目的目標執行後,評分器會自動執行。請傳入評分器執行個體或已註冊的評分器 ID: **評分器 ID**: ```typescript // Reference scorers registered on the Mastra instance const summary = await dataset.startExperiment({ name: 'with-registered-scorers', targetType: 'agent', targetId: 'translation-agent', scorers: ['accuracy', 'fluency'], }) ``` **評分器執行個體**: ```typescript import { createAnswerRelevancyScorer } from '@mastra/evals/scorers/prebuilt' const relevancy = createAnswerRelevancyScorer({ model: 'openai/gpt-5-mini' }) const summary = await dataset.startExperiment({ name: 'with-scorer-instances', targetType: 'agent', targetId: 'translation-agent', scorers: [relevancy], }) ``` 每個項目的結果都包含各評分器的分數: ```typescript for (const item of summary.results) { console.log(item.itemId, item.output) for (const score of item.scores) { console.log(` ${score.scorerName}: ${score.score} — ${score.reason}`) } } ``` 如需可用及自訂評分器的詳情,請參閱[評分器概觀](https://mastra.zisheng.pro/zh-TW/docs/evals/overview)。 ## 控制每次執行的保存方式 使用 `persistence` 可略過特定執行的儲存區寫入。實驗記錄與分數記錄可分別停用: ```typescript const summary = await dataset.startExperiment({ targetType: 'agent', targetId: 'translation-agent', scorers: ['accuracy'], persistence: { experiments: 'none', scores: 'none', }, }) ``` 目標與評分器仍會執行,`startExperiment()` 也仍會在 `summary` 中傳回項目結果與分數。這些設定彼此獨立。例如,只設定 `scores: 'none'` 可保存實驗與項目結果,但不建立分數記錄。 省略的設定預設為 `'default'`,會保留標準儲存行為。此原則只控制該次執行建立的實驗與分數記錄,不會停用目標使用的儲存功能,例如 Agent 記憶體、向量、可觀測性或自訂 Tool 儲存區。 以 `experiments: 'none'` 執行 `startExperimentAsync()` 時,不會保存實驗記錄、進度更新或項目結果。分數保存仍由 `persistence.scores` 分別控制。若沒有實驗事件觀察器,此執行會啟動後即不再追蹤,實驗 API 無法回報完成或失敗。 呼叫者需要傳回的摘要時,請使用同步的 `startExperiment()`。實驗事件觀察器可接收生命週期事件與最終摘要。 ## 觀察實驗事件 使用 `onEvent` 可在實驗執行期間接收具版本且可安全轉為 JSON 的生命週期事件。此功能適用於 `startExperiment()`、`startExperimentAsync()` 與 `runExperiment()`。 ```typescript import type { ExperimentEvent } from '@mastra/core/datasets' const events: ExperimentEvent[] = [] await dataset.startExperimentAsync({ task: async ({ input }) => processItem(input), persistence: { experiments: 'none' }, onEvent: async event => { events.push(event) await publishEvent(event) }, }) ``` 觀察器會接收下列事件類型: - `experiment.run.started`:識別執行、目標、解析後的資料集版本與項目數量。 - `experiment.item.completed`:回報評分後已提交的項目結果,包括分數、錯誤、重試次數、Tool mock 詳情與穩定的項目識別資訊。 - `experiment.run.finished`:回報最終結果與摘要計數器。 Mastra 會等待每次觀察器呼叫完成後再傳遞下一個事件。這種序列化傳遞會施加背壓,並確保事件 `sequence` 值符合傳遞順序,同時仍可並行執行項目。 若觀察器擲回錯誤或拒絕,Mastra 會中止剩餘執行,並以 `id` 為 `EXPERIMENT_EVENT_OBSERVER_FAILED` 的 `MastraError` 拒絕 `runExperiment()`。系統不會透過失敗的觀察器傳送最終事件。對 `startExperimentAsync()` 而言,分離的觀察器失敗時方法已傳回,因此呼叫者需要直接錯誤回報時,請在觀察器內處理傳遞失敗。 Mastra 會等待 `experiment.run.finished` 事件完成後,才保存最終實驗狀態。停用實驗保存時,請將此事件視為具權威性的最終訊號,但不要將其當作儲存區的寫入後讀取訊號。 匯出的事件類型包括 `ExperimentEvent`、`ExperimentRunStartedEvent`、`ExperimentItemCompletedEvent` 與 `ExperimentRunFinishedEvent`。讀取事件特有屬性前,請使用可辨識的 `type` 欄位縮小事件類型。 ## Tool mock 當實驗執行會呼叫具副作用 Tool 的 Agent 時,請將靜態 Tool mock 附加至個別資料集項目,使執行結果具確定性。實驗期間,被 mock 的 Tool 會傳回宣告的輸出,而不會實際執行。項目上沒有 mock 的 Tool 預設會實際執行。 Mock 儲存在資料集項目上,因此會隨資料列建立版本並與測試案例一同移動。每個 mock 都會宣告 Tool 名稱、預期引數與要傳回的輸出: ```typescript await dataset.addItem({ input: 'What is the weather in Seattle?', toolMocks: [ { toolName: 'getWeather', args: { city: 'Seattle' }, output: { temperature: 60, conditions: 'rainy' }, }, ], }) ``` Tool mock 僅支援 `agent` 目標。 ### 封鎖未宣告的 Tool 在實驗上設定 `unmockedToolPolicy: 'deny'`,即可封鎖所有沒有 mock 的 Tool 呼叫。實際呼叫可能造成副作用時,此設定很實用: ```typescript const summary = await dataset.startExperiment({ targetType: 'agent', targetId: 'weather-agent', unmockedToolPolicy: 'deny', }) ``` 預設原則為 `'allow'`。你可以在個別已儲存或內嵌項目上覆寫實驗原則: ```typescript await dataset.addItem({ input: 'What is the weather in Seattle?', unmockedToolPolicy: 'allow', }) ``` 項目值的優先順序高於實驗值。遭拒的呼叫會在 Tool 執行前以 `TOOL_MOCK_NOT_DECLARED` 失敗;此失敗不會重試,也不會加入 `liveCalls`。 ### 比對與取用 引數採嚴格比對:物件鍵順序會忽略、陣列順序則具有意義,且不進行型別強制轉換。只有當 Agent 呼叫 Tool 的引數與 mock 的 `args` 深度相等時,才會提供該 mock。 若項目為相同 Tool 與引數宣告多個 mock,系統會依序取用:第一次呼叫取得第一個 mock,下一次取得第二個,依此類推。順序會按每個 `(toolName, args)` 群組追蹤,不同引數之間彼此獨立。 ### 比對模式 每個 mock 預設會嚴格比對其 `args`。設定 `matchArgs: 'ignore'` 可只比對 Tool 名稱;系統不會比較 mock 的 `args`,無論 Agent 如何呼叫,都會提供該 Tool 下一個尚未取用的 mock: ```typescript const subAgentMock = { toolName: 'agent-balanceAgent', args: { prompt: 'look up the balance for YJ' }, output: { text: "YJ's balance is $100." }, matchArgs: 'ignore', } ``` Tool 引數包含雜訊或由模型產生時,此設定很實用。最常見的情況是模擬**子 Agent 的回應**:委派的子 Agent 會以 `agent-` Tool 的形式提供給父 Agent,其引數包含 LLM 撰寫的 `prompt` 與執行階段注入欄位。模擬 `agent-` 會傳回預設回應,不執行子 Agent 及其內部 Tool。從 Trace 建立 mock 時,系統會自動以 `matchArgs: 'ignore'` 衍生子 Agent 委派呼叫;你可以改為 `'strict'` 以鎖定確切引數。 ### 失敗 Tool 呼叫違反 mock 設定時,該項目會失敗: - `TOOL_MOCK_MISMATCH`:呼叫 Tool 所用的引數沒有相符的 mock。 - `TOOL_MOCK_EXHAUSTED`:所有相符的 mock 都已取用。 - `TOOL_MOCK_NOT_DECLARED`:Tool 沒有 mock,且實際生效的 `unmockedToolPolicy` 為 `'deny'`。 發生上述任何失敗時,Agent 執行會立即中止,因此模型無法繼續呼叫任何 Tool,包括原本會實際執行且具副作用的未 mock Tool。這些失敗具有確定性,因此不會重試。已宣告但從未使用的 mock 不會使項目失敗,而會回報為尚未取用。 啟用 mock 攔截時,Agent 的 Tool 會依序執行,使重複的 `(toolName, args)` mock 按 Provider 的呼叫順序取用。項目宣告 mock 或實際生效的 `unmockedToolPolicy` 為 `'deny'` 時,攔截功能便會啟用。 ### 診斷 每個項目結果都帶有 `toolMockReport`,說明該次執行如何處理項目的 mock: ```typescript for (const item of summary.results) { const report = item.toolMockReport if (!report) continue console.log(report.served) // mocks matched and returned console.log(report.unconsumed) // mocks declared but never used console.log(report.liveCalls) // undeclared tools allowed to run live console.log(report.failure) // the first deterministic mock failure, if any } ``` 在 [Studio](https://mastra.zisheng.pro/zh-TW/docs/studio/overview) 中編輯資料集項目,即可以 JSON 陣列撰寫 Tool mock;開啟實驗結果可查看相同報告。 ### 限制 - **Mock 呼叫沒有 Tool span。** Mock 呼叫會在 Tool 執行前傳回輸出,因此不會建立 Tool span。由已儲存 Trace 支援的軌跡評分器可能看不到 mock Tool 呼叫;退回使用 Agent 訊息輸出的軌跡擷取仍能看到,因此軌跡評分結果可能會隨可觀測性設定而異。 - **儲存區支援。** LibSQL、PostgreSQL、MongoDB 與 Spanner 配接器會保存 Tool mock 及 Tool mock 報告。MySQL 配接器不支援這些資料,並會拒絕帶有 Tool mock 或 Tool mock 報告的寫入。所有資料集儲存配接器都會保存 `unmockedToolPolicy`。 ## 非同步實驗 `startExperiment()` 會封鎖至每個項目完成。對於長時間執行的資料集,請使用 [`startExperimentAsync()`](https://mastra.zisheng.pro/zh-TW/reference/datasets/startExperimentAsync) 在背景啟動實驗: ```typescript const { experimentId, status } = await dataset.startExperimentAsync({ name: 'large-dataset-run', targetType: 'agent', targetId: 'translation-agent', scorers: ['accuracy'], }) console.log(experimentId) // UUID console.log(status) // 'pending' ``` 使用 [`getExperiment()`](https://mastra.zisheng.pro/zh-TW/reference/datasets/getExperiment) 輪詢完成狀態: ```typescript let experiment = await dataset.getExperiment({ experimentId }) while (experiment.status === 'pending' || experiment.status === 'running') { await new Promise(resolve => setTimeout(resolve, 5000)) experiment = await dataset.getExperiment({ experimentId }) } console.log(experiment.status) // 'completed' | 'failed' ``` ## 設定選項 ### 並行處理 控制並行執行的項目數(預設:5): ```typescript const summary = await dataset.startExperiment({ targetType: 'agent', targetId: 'translation-agent', maxConcurrency: 10, }) ``` ### 逾時與重試 設定每個項目的逾時時間(毫秒)與重試次數: ```typescript const summary = await dataset.startExperiment({ targetType: 'agent', targetId: 'translation-agent', itemTimeout: 30_000, // 30 seconds per item maxRetries: 2, // retry failed items up to 2 times }) ``` 重試採用指數退避。中止錯誤一律不會重試。 ### 中止實驗 傳入 `AbortSignal` 以取消執行中的實驗: ```typescript const controller = new AbortController() // Cancel after 60 seconds setTimeout(() => controller.abort(), 60_000) const summary = await dataset.startExperiment({ targetType: 'agent', targetId: 'translation-agent', signal: controller.signal, }) ``` 其餘項目會在摘要中標示為已略過。 ### 鎖定資料集版本 針對資料集的特定快照執行: ```typescript const summary = await dataset.startExperiment({ targetType: 'agent', targetId: 'translation-agent', version: 3, // use items from dataset version 3 }) ``` ## 查看結果 ### 列出實驗 ```typescript const { experiments, pagination } = await dataset.listExperiments({ page: 0, perPage: 10, }) for (const exp of experiments) { console.log(`${exp.name} — ${exp.status} (${exp.succeededCount}/${exp.totalItems})`) } ``` ### 實驗詳細資料 ```typescript const experiment = await dataset.getExperiment({ experimentId: 'exp-abc-123', }) console.log(experiment.status) console.log(experiment.startedAt) console.log(experiment.completedAt) ``` > **📹 觀看影片:** 觀看 [Mastra 資料集與實驗工作流程](https://www.youtube.com/watch?v=R6pjAdGhxhQ),瞭解資料集與實驗如何協助提升可靠性。 ### 項目層級結果 ```typescript const { results, pagination } = await dataset.listExperimentResults({ experimentId: 'exp-abc-123', page: 0, perPage: 50, }) for (const result of results) { console.log(result.itemId, result.output, result.error) } ``` ## 瞭解摘要 `startExperiment()` 會傳回 `ExperimentSummary`,其中包含計數與逐項結果: - 實驗已完成但部分項目失敗時,`completedWithErrors` 為 `true`。 - 透過 `signal` 取消的項目會計入 `skippedCount`。 如需完整的參數與傳回類型文件,請參閱 [`startExperiment` 參考文件](https://mastra.zisheng.pro/zh-TW/reference/datasets/startExperiment)。 ## 相關內容 - [資料集概觀](https://mastra.zisheng.pro/zh-TW/docs/datasets/overview) - [評分器概觀](https://mastra.zisheng.pro/zh-TW/docs/evals/overview) - [`startExperiment` 參考文件](https://mastra.zisheng.pro/zh-TW/reference/datasets/startExperiment) - [`listExperimentResults` 參考文件](https://mastra.zisheng.pro/zh-TW/reference/datasets/listExperimentResults)