> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-HK/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-HK/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-HK/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 有自己的記憶,而請求上下文帶有資源 ID(`MASTRA_RESOURCE_ID_KEY`,可由驗證中介軟件、實驗或項目的 `requestContext`,或 Studio **Run Experiment** 表單設定)時,實驗執行器會為每個項目注入新的記憶對話串。請求上下文中的資源 ID 表示「以此資源的身分執行」:每個項目的對話會以該資源下的對話串形式保存,而重試的項目每次嘗試都會使用新的對話串,避免較早失敗嘗試的內容滲入重試上下文。 注入的對話串會加上標籤,讓你能將其對應至執行記錄:對話串 metadata 會包含 `experimentId`,以及以 `experimentItemId` 表示的數據集項目 ID。系統不會為這些對話串產生標題。 由於對話串屬於呼叫者的資源,資源範圍的記憶功能會在執行期間讀取和寫入該資源的狀態: - 資源範圍的工作記憶更新會保存至資源,而同一次執行中較後的項目會看到較早項目作出的更新。 - 資源範圍的語意回憶可向實驗呈現該資源過往的對話,而實驗的對話記錄亦可在該資源其後的對話中被回憶。 如要根據真實使用者累積的上下文評估 Agent,這項功能便很有用。如不希望實驗執行過程觸及真實使用者狀態,請改用專用的評估資源 ID 執行實驗。 以下情況會略過對話串注入: - 如果請求上下文亦設定了 `MASTRA_THREAD_ID_KEY`,執行器會直接使用該對話串,因此每個項目(包括重試)都會共用同一段對話。 - 如果 Agent 沒有記憶,或請求上下文沒有資源 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-HK/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 儲存空間。 當 `startExperimentAsync()` 使用 `experiments: 'none'` 執行時,不會保存實驗記錄、進度更新或項目結果。評分保存仍由 `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 會中止餘下的執行,並以 `MastraError` 拒絕 `runExperiment()`,其 `id` 為 `EXPERIMENT_EVENT_OBSERVER_FAILED`。系統不會透過失敗的觀察器傳送終結事件。對於 `startExperimentAsync()`,分離式觀察器失敗時該方法已經傳回,因此如呼叫者需要直接錯誤報告,請在觀察器內處理傳送失敗。 Mastra 會等待 `experiment.run.finished` 事件完成,才保存實驗的最終狀態。停用實驗保存時,應將該事件視為具權威性的終結訊號,但不要將它用作儲存空間的寫入後讀取訊號。 匯出的事件類型包括 `ExperimentEvent`、`ExperimentRunStartedEvent`、`ExperimentItemCompletedEvent` 和 `ExperimentRunFinishedEvent`。讀取事件專屬屬性前,請使用可辨識聯合的 `type` 欄位收窄事件類型。 ## Tool mock 當實驗執行會呼叫具副作用 Tool 的 Agent 時,可將靜態 Tool 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 會按次序消耗:第一次呼叫取得第一個 mock,下一次呼叫取得第二個,如此類推。系統會按每個 `(toolName, args)` 群組追蹤次序,不同引數之間則互相獨立。 ### 配對模式 每個 mock 預設會嚴格根據其 `args` 配對。設定 `matchArgs: 'ignore'` 即可只根據 Tool 名稱配對;系統不會比較 mock 的 `args`,並會提供該 Tool 下一個尚未消耗的 mock,而不論 Agent 如何呼叫: ```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 的形式提供給上層,而其引數包括由 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,包括原本會即時執行且未模擬的具副作用 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-HK/docs/studio/overview) 中,你可以編輯數據集項目,以 JSON 陣列編寫 Tool mock,並開啟實驗結果查看同一份報告。 ### 限制 - **模擬呼叫不會產生 Tool span。** 模擬呼叫會在 Tool 執行前傳回輸出,因此不會建立 Tool span。由已儲存 Trace 支援的軌跡評分器可能因此無法看到模擬的 Tool 呼叫。回退至 Agent 訊息輸出的軌跡擷取仍能看到這些呼叫,因此軌跡評分可能會因可觀測性設定而有所不同。 - **儲存支援。** LibSQL、PostgreSQL、MongoDB 和 Spanner 適配器均可保存 Tool mock 和 Tool mock 報告。MySQL 適配器不支援這些內容,並會拒絕帶有 Tool mock 或 Tool mock 報告的寫入操作。所有數據集儲存適配器均會保存 `unmockedToolPolicy`。 ## 非同步實驗 `startExperiment()` 會阻塞直至每個項目完成。對於需長時間執行的數據集,請使用 [`startExperimentAsync()`](https://mastra.zisheng.pro/zh-HK/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-HK/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 數據集和實驗 Workflow](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-HK/reference/datasets/startExperiment),查看完整的參數及傳回類型文件。 ## 相關內容 - [數據集概覽](https://mastra.zisheng.pro/zh-HK/docs/datasets/overview) - [評分器概覽](https://mastra.zisheng.pro/zh-HK/docs/evals/overview) - [`startExperiment` 參考資料](https://mastra.zisheng.pro/zh-HK/reference/datasets/startExperiment) - [`listExperimentResults` 參考資料](https://mastra.zisheng.pro/zh-HK/reference/datasets/listExperimentResults)