評分器工具函式
Mastra 提供工具函式,協助從評分器執行的輸入與輸出擷取及處理資料。這些工具在自訂評分器的 preprocess 步驟中特別實用。
匯入「匯入」的直接連結
import {
getAssistantMessageFromRunOutput,
getReasoningFromRunOutput,
getUserMessageFromRunInput,
getSystemMessagesFromRunInput,
getCombinedSystemPrompt,
extractToolCalls,
extractInputMessages,
extractAgentResponseMessages,
compareTrajectories,
createTrajectoryTestRun,
} from '@mastra/evals/scorers/utils'
可從 @mastra/core/evals 使用軌跡擷取函式:
import {
extractTrajectory,
extractWorkflowTrajectory,
extractTrajectoryFromTrace,
} from '@mastra/core/evals'
訊息擷取「訊息擷取」的直接連結
getAssistantMessageFromRunOutput「getassistantmessagefromrunoutput」的直接連結
從此次執行輸出的第一則 assistant 訊息中擷取文字內容。
const scorer = createScorer({
id: 'my-scorer',
description: 'My scorer',
type: 'agent',
})
.preprocess(({ run }) => {
const response = getAssistantMessageFromRunOutput(run.output)
return { response }
})
.generateScore(({ results }) => {
return results.preprocessStepResult?.response ? 1 : 0
})
output?:
傳回: string | undefined——assistant 訊息文字;若找不到 assistant 訊息,則為 undefined。
getUserMessageFromRunInput「getusermessagefromruninput」的直接連結
從此次執行輸入的第一則使用者訊息中擷取文字內容。
.preprocess(({ run }) => {
const userMessage = getUserMessageFromRunInput(run.input);
return { userMessage };
})
input?:
傳回: string | undefined——使用者訊息文字;若找不到使用者訊息,則為 undefined。
extractInputMessages「extractinputmessages」的直接連結
以陣列形式擷取所有輸入訊息的文字內容。
.preprocess(({ run }) => {
const allUserMessages = extractInputMessages(run.input);
return { conversationHistory: allUserMessages.join("\n") };
})
傳回: string[]——各輸入訊息文字字串的陣列。
extractAgentResponseMessages「extractagentresponsemessages」的直接連結
以陣列形式擷取所有 assistant 回應訊息的文字內容。
.preprocess(({ run }) => {
const allResponses = extractAgentResponseMessages(run.output);
return { allResponses };
})
傳回: string[]——各 assistant 訊息文字字串的陣列。
推理擷取「推理擷取」的直接連結
getReasoningFromRunOutput「getreasoningfromrunoutput」的直接連結
從此次執行輸出擷取推理文字。評估 deepseek-reasoner 這類會產生思維鏈推理的推理模型回應時,此函式特別實用。
推理可儲存在兩個位置:
content.reasoning——訊息內容上的字串欄位content.parts——含有details且type: 'reasoning'的部分
import {
getReasoningFromRunOutput,
getAssistantMessageFromRunOutput,
} from '@mastra/evals/scorers/utils'
const reasoningQualityScorer = createScorer({
id: 'reasoning-quality',
name: 'Reasoning Quality',
description: 'Evaluates the quality of model reasoning',
type: 'agent',
})
.preprocess(({ run }) => {
const reasoning = getReasoningFromRunOutput(run.output)
const response = getAssistantMessageFromRunOutput(run.output)
return { reasoning, response }
})
.analyze(({ results }) => {
const { reasoning } = results.preprocessStepResult || {}
return {
hasReasoning: !!reasoning,
reasoningLength: reasoning?.length || 0,
hasStepByStep: reasoning?.includes('step') || false,
}
})
.generateScore(({ results }) => {
const { hasReasoning, reasoningLength } = results.analyzeStepResult || {}
if (!hasReasoning) return 0
// Score based on reasoning length (normalized to 0-1)
return Math.min(reasoningLength / 500, 1)
})
.generateReason(({ results, score }) => {
const { hasReasoning, reasoningLength } = results.analyzeStepResult || {}
if (!hasReasoning) {
return 'No reasoning was provided by the model.'
}
return `Model provided ${reasoningLength} characters of reasoning. Score: ${score}`
})
output?:
傳回: string | undefined——推理文字;若沒有推理,則為 undefined。
系統訊息擷取「系統訊息擷取」的直接連結
getSystemMessagesFromRunInput「getsystemmessagesfromruninput」的直接連結
從此次執行輸入擷取所有系統訊息,包括標準系統訊息與加上標籤的系統訊息(例如記憶體指示這類專用提示詞)。
.preprocess(({ run }) => {
const systemMessages = getSystemMessagesFromRunInput(run.input);
return {
systemPromptCount: systemMessages.length,
systemPrompts: systemMessages
};
})
傳回: string[]——系統訊息字串陣列。
getCombinedSystemPrompt「getcombinedsystemprompt」的直接連結
將所有系統訊息合併成單一提示詞字串,並以兩個換行字元連接。
.preprocess(({ run }) => {
const fullSystemPrompt = getCombinedSystemPrompt(run.input);
return { fullSystemPrompt };
})
傳回: string——合併後的系統提示詞字串。
Tool 呼叫擷取「Tool 呼叫擷取」的直接連結
extractToolCalls「extracttoolcalls」的直接連結
從此次執行輸出擷取所有 Tool 呼叫的資訊,包括 Tool 名稱、呼叫 ID,以及它們在訊息陣列中的位置。
const toolUsageScorer = createScorer({
id: 'tool-usage',
description: 'Evaluates tool usage patterns',
type: 'agent',
})
.preprocess(({ run }) => {
const { tools, toolCallInfos } = extractToolCalls(run.output)
return {
toolsUsed: tools,
toolCount: tools.length,
toolDetails: toolCallInfos,
}
})
.generateScore(({ results }) => {
const { toolCount } = results.preprocessStepResult || {}
// Score based on appropriate tool usage
return toolCount > 0 ? 1 : 0
})
傳回:
{
tools: string[]; // Array of tool names
toolCallInfos: ToolCallInfo[]; // Detailed tool call information
}
其中 ToolCallInfo 為:
type ToolCallInfo = {
toolName: string // Name of the tool
toolCallId: string // Unique call identifier
messageIndex: number // Index in the output array
invocationIndex: number // Index within message's tool invocations
}
測試工具「測試工具」的直接連結
這些工具可協助建立用於評分器開發的測試資料。
createTestMessage「createtestmessage」的直接連結
建立用於測試的 MastraDBMessage 物件。
import { createTestMessage } from '@mastra/evals/scorers/utils'
const userMessage = createTestMessage({
content: 'What is the weather?',
role: 'user',
})
const assistantMessage = createTestMessage({
content: 'The weather is sunny.',
role: 'assistant',
toolInvocations: [
{
toolCallId: 'call-1',
toolName: 'weatherTool',
args: { location: 'London' },
result: { temp: 20 },
state: 'result',
},
],
})
createAgentTestRun「createagenttestrun」的直接連結
建立用於測試評分器的完整測試執行物件。
import { createAgentTestRun, createTestMessage } from '@mastra/evals/scorers/utils'
const testRun = createAgentTestRun({
inputMessages: [createTestMessage({ content: 'Hello', role: 'user' })],
output: [createTestMessage({ content: 'Hi there!', role: 'assistant' })],
})
// Run your scorer with the test data
const result = await myScorer.run({
input: testRun.input,
output: testRun.output,
})
軌跡工具「軌跡工具」的直接連結
extractTrajectory「extracttrajectory」的直接連結
從 Agent 輸出訊息(MastraDBMessage[])擷取 Trajectory。將 Tool invocation 轉換為 ToolCallStep 物件。runEvals pipeline 會為軌跡評分器自動呼叫此函式,只有直接測試時才需要自行呼叫。
可從 @mastra/core/evals 使用。
import { extractTrajectory } from '@mastra/core/evals'
const trajectory = extractTrajectory(agentOutputMessages)
// trajectory.steps — ToolCallStep[] extracted from toolInvocations
// trajectory.rawOutput — the original MastraDBMessage[] array
傳回: Trajectory:包含 steps: TrajectoryStep[]、totalDurationMs 與 rawOutput。
extractWorkflowTrajectory「extractworkflowtrajectory」的直接連結
從 Workflow 步驟結果擷取 Trajectory。將 StepResult 記錄轉換為 WorkflowStepStep 物件,並遵循執行路徑順序。
可從 @mastra/core/evals 使用。
import { extractWorkflowTrajectory } from '@mastra/core/evals'
const trajectory = extractWorkflowTrajectory(
workflowResult.steps, // Record<string, StepResult>
workflowResult.stepExecutionPath, // string[] (optional)
)
// trajectory.steps — WorkflowStepStep[] in execution order
傳回: Trajectory:包含 steps: TrajectoryStep[]、totalDurationMs 與 rawWorkflowResult。
extractTrajectoryFromTrace「extracttrajectoryfromtrace」的直接連結
從可觀測性 Trace span(SpanRecord[])建立階層式 Trajectory。它會重建父子 span 樹狀結構,並將每個 span 對應至適當的 TrajectoryStep 可辨識聯集型別,且包含巢狀 children。
若儲存空間可用,這是首選的擷取方法。target 的 Mastra 執行個體已設定儲存後端時,runEvals pipeline 會自動呼叫此函式。相較於 extractTrajectory 或 extractWorkflowTrajectory,它能擷取完整執行樹,包括巢狀 Agent 執行、Tool 呼叫與模型產生作業,因此會產生更豐富的軌跡。
可從 @mastra/core/evals 使用。
import { extractTrajectoryFromTrace } from '@mastra/core/evals'
// After fetching a trace from the observability store
const traceData = await observabilityStore.getTrace({ traceId })
const trajectory = extractTrajectoryFromTrace(traceData.spans, rootSpanId)
// trajectory.steps — hierarchical TrajectoryStep[] with children
參數:
spans(SpanRecord[]):Trace 查詢傳回的 span 記錄陣列。rootSpanId(string,選填):作為起點的 span ID。省略時,使用沒有 parent 的 span。
傳回: Trajectory:包含具遞迴 children 的 steps: TrajectoryStep[],以及 totalDurationMs。
Span 型別對應「Span 型別對應」的直接連結
| Span 型別 | 軌跡步驟型別 | 擷取的主要欄位 |
|---|---|---|
TOOL_CALL | tool_call | toolArgs、toolResult、success |
MCP_TOOL_CALL | mcp_tool_call | toolArgs、toolResult、mcpServer、success |
MODEL_GENERATION | model_generation | modelId、promptTokens、completionTokens、finishReason |
AGENT_RUN | agent_run | agentId(來自 entity ID) |
WORKFLOW_RUN | workflow_run | workflowId(來自 entity ID) |
WORKFLOW_STEP | workflow_step | output |
WORKFLOW_CONDITIONAL | workflow_conditional | conditionCount、selectedSteps |
WORKFLOW_PARALLEL | workflow_parallel | branchCount、parallelSteps |
WORKFLOW_LOOP | workflow_loop | loopType、totalIterations |
WORKFLOW_SLEEP | workflow_sleep | sleepDurationMs、sleepType |
WORKFLOW_WAIT_EVENT | workflow_wait_event | eventName、eventReceived |
PROCESSOR_RUN | processor_run | processorId |
GENERIC、MODEL_STEP、MODEL_CHUNK 與 WORKFLOW_CONDITIONAL_EVAL 型別的 span 會視為雜訊而略過。
compareTrajectories「comparetrajectories」的直接連結
將實際軌跡與預期軌跡進行比較,並傳回詳細的比較結果。createTrajectoryAccuracyScorerCode 會在內部使用此函式。
expected 參數接受 Trajectory(實際軌跡)或 { steps: ExpectedStep[] }。使用 ExpectedStep[] 時,可以只依名稱比對,也可依名稱 + stepType 比對。你也能加入要比較的資料。詳情請參閱預期步驟。
import { compareTrajectories } from '@mastra/evals/scorers/utils'
// Using ExpectedStep[] (recommended for expectations)
// Data fields (e.g. toolArgs) are auto-compared when present on expected steps
const result = compareTrajectories(
actualTrajectory,
{ steps: [{ name: 'search' }, { name: 'summarize', stepType: 'tool_call' }] },
{ allowRepeatedSteps: true },
)
// result.score — 0.0 to 1.0
// result.missingSteps — step names not found
// result.extraSteps — unexpected step names
// result.outOfOrderSteps — steps found but in wrong order
傳回: TrajectoryComparisonResult
createTrajectoryTestRun「createtrajectorytestrun」的直接連結
為軌跡評分器建立測試執行物件。將 Trajectory 包裝成預期的 ScorerRun 格式。
import { createTrajectoryTestRun } from '@mastra/evals/scorers/utils'
const run = createTrajectoryTestRun({
steps: [
{ stepType: 'tool_call', name: 'search', toolArgs: { q: 'test' } },
{ stepType: 'tool_call', name: 'summarize' },
],
})
const result = await trajectoryScorer.run(run)
checkTrajectoryEfficiency「checktrajectoryefficiency」的直接連結
依據步驟、token 與持續時間預算評估軌跡效率,也會偵測重複呼叫(以相同引數呼叫相同 Tool)。
import { checkTrajectoryEfficiency } from '@mastra/evals/scorers/utils'
const result = checkTrajectoryEfficiency(trajectory, {
maxSteps: 5,
maxTotalTokens: 2000,
maxTotalDurationMs: 5000,
noRedundantCalls: true,
})
// result.score — 1.0 if within all budgets, lower with penalties
// result.redundantCalls — duplicate tool+args combos
// result.overStepBudget — true if maxSteps exceeded
// result.overTokenBudget — true if maxTotalTokens exceeded
// result.overDurationBudget — true if maxTotalDurationMs exceeded
傳回: TrajectoryEfficiencyResult
checkTrajectoryBlacklist「checktrajectoryblacklist」的直接連結
檢查軌跡是否包含禁止的 Tool 或 Tool 呼叫序列。
import { checkTrajectoryBlacklist } from '@mastra/evals/scorers/utils'
const result = checkTrajectoryBlacklist(trajectory, {
blacklistedTools: ['deleteAll', 'admin-override'],
blacklistedSequences: [['escalate', 'admin-override']],
})
// result.score — 1.0 if no violations, 0.0 if any found
// result.violatedTools — blacklisted tools that were called
// result.violatedSequences — blacklisted sequences that were detected
傳回: TrajectoryBlacklistResult
analyzeToolFailures「analyzetoolfailures」的直接連結
偵測 Tool 失敗模式,包括重試、後援與引數修正。
import { analyzeToolFailures } from '@mastra/evals/scorers/utils'
const result = analyzeToolFailures(trajectory, {
maxRetriesPerTool: 2,
})
// result.score — 1.0 if no failure patterns, lower if patterns detected
// result.patterns — detected patterns (retry, fallback, arg_correction)
傳回: ToolFailureAnalysisResult
完整範例「完整範例」的直接連結
以下完整範例示範如何搭配使用多個工具函式:
import { createScorer } from '@mastra/core/evals'
import {
getAssistantMessageFromRunOutput,
getReasoningFromRunOutput,
getUserMessageFromRunInput,
getCombinedSystemPrompt,
extractToolCalls,
} from '@mastra/evals/scorers/utils'
const comprehensiveScorer = createScorer({
id: 'comprehensive-analysis',
name: 'Comprehensive Analysis',
description: 'Analyzes all aspects of an agent response',
type: 'agent',
})
.preprocess(({ run }) => {
// Extract all relevant data
const userMessage = getUserMessageFromRunInput(run.input)
const response = getAssistantMessageFromRunOutput(run.output)
const reasoning = getReasoningFromRunOutput(run.output)
const systemPrompt = getCombinedSystemPrompt(run.input)
const { tools, toolCallInfos } = extractToolCalls(run.output)
return {
userMessage,
response,
reasoning,
systemPrompt,
toolsUsed: tools,
toolCount: tools.length,
}
})
.generateScore(({ results }) => {
const { response, reasoning, toolCount } = results.preprocessStepResult || {}
let score = 0
if (response && response.length > 0) score += 0.4
if (reasoning) score += 0.3
if (toolCount > 0) score += 0.3
return score
})
.generateReason(({ results, score }) => {
const { response, reasoning, toolCount } = results.preprocessStepResult || {}
const parts = []
if (response) parts.push('provided a response')
if (reasoning) parts.push('included reasoning')
if (toolCount > 0) parts.push(`used ${toolCount} tool(s)`)
return `Score: ${score}. The agent ${parts.join(', ')}.`
})