Utilitaires de Scorer
Mastra fournit des fonctions utilitaires qui facilitent l'extraction et le traitement des données issues des entrées et sorties d'exécution des Scorers. Ces utilitaires sont particulièrement utiles lors de l'étape preprocess des Scorers personnalisés.
ImportLien direct vers Import
import {
getAssistantMessageFromRunOutput,
getReasoningFromRunOutput,
getUserMessageFromRunInput,
getSystemMessagesFromRunInput,
getCombinedSystemPrompt,
extractToolCalls,
extractInputMessages,
extractAgentResponseMessages,
compareTrajectories,
createTrajectoryTestRun,
} from '@mastra/evals/scorers/utils'
Les fonctions d'extraction des trajectoires sont disponibles depuis @mastra/core/evals :
import {
extractTrajectory,
extractWorkflowTrajectory,
extractTrajectoryFromTrace,
} from '@mastra/core/evals'
Extraction des messagesLien direct vers Extraction des messages
getAssistantMessageFromRunOutputLien direct vers getassistantmessagefromrunoutput
Extrait le contenu textuel du premier message de l'assistant dans la sortie d'exécution.
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?:
Renvoie : string | undefined - Le texte du message de l'assistant, ou undefined si aucun message de l'assistant n'est trouvé.
getUserMessageFromRunInputLien direct vers getusermessagefromruninput
Extrait le contenu textuel du premier message utilisateur dans l'entrée d'exécution.
.preprocess(({ run }) => {
const userMessage = getUserMessageFromRunInput(run.input);
return { userMessage };
})
input?:
Renvoie : string | undefined - Le texte du message utilisateur, ou undefined si aucun message utilisateur n'est trouvé.
extractInputMessagesLien direct vers extractinputmessages
Extrait sous forme de tableau le contenu textuel de tous les messages d'entrée.
.preprocess(({ run }) => {
const allUserMessages = extractInputMessages(run.input);
return { conversationHistory: allUserMessages.join("\n") };
})
Renvoie : string[] - Tableau de chaînes de texte provenant de chaque message d'entrée.
extractAgentResponseMessagesLien direct vers extractagentresponsemessages
Extrait sous forme de tableau le contenu textuel de tous les messages de réponse de l'assistant.
.preprocess(({ run }) => {
const allResponses = extractAgentResponseMessages(run.output);
return { allResponses };
})
Renvoie : string[] - Tableau de chaînes de texte provenant de chaque message de l'assistant.
Extraction du raisonnementLien direct vers Extraction du raisonnement
getReasoningFromRunOutputLien direct vers getreasoningfromrunoutput
Extrait le texte de raisonnement de la sortie d'exécution. Cette fonction est particulièrement utile pour évaluer les réponses de modèles de raisonnement tels que deepseek-reasoner, qui produisent un raisonnement en chaîne de pensée.
Le raisonnement peut être stocké à deux emplacements :
content.reasoning- un champ chaîne du contenu du messagecontent.parts- sous forme de parties avectype: 'reasoning'contenantdetails
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?:
Renvoie : string | undefined - Le texte de raisonnement, ou undefined si aucun raisonnement n'est présent.
Extraction des messages systèmeLien direct vers Extraction des messages système
getSystemMessagesFromRunInputLien direct vers getsystemmessagesfromruninput
Extrait tous les messages système de l'entrée d'exécution, notamment les messages système standard et ceux comportant des tags, tels que les prompts spécialisés d'instructions de mémoire.
.preprocess(({ run }) => {
const systemMessages = getSystemMessagesFromRunInput(run.input);
return {
systemPromptCount: systemMessages.length,
systemPrompts: systemMessages
};
})
Renvoie : string[] - Tableau de chaînes de messages système.
getCombinedSystemPromptLien direct vers getcombinedsystemprompt
Combine tous les messages système en une seule chaîne de prompt, séparés par deux retours à la ligne.
.preprocess(({ run }) => {
const fullSystemPrompt = getCombinedSystemPrompt(run.input);
return { fullSystemPrompt };
})
Renvoie : string - Chaîne combinée du prompt système.
Extraction des appels de ToolLien direct vers Extraction des appels de Tool
extractToolCallsLien direct vers extracttoolcalls
Extrait des informations sur tous les appels de Tool de la sortie d'exécution, notamment les noms des Tools, les identifiants des appels et leur position dans le tableau de messages.
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
})
Renvoie :
{
tools: string[]; // Array of tool names
toolCallInfos: ToolCallInfo[]; // Detailed tool call information
}
Où ToolCallInfo est :
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
}
Utilitaires de testLien direct vers Utilitaires de test
Ces utilitaires facilitent la création de données de test pour le développement des Scorers.
createTestMessageLien direct vers createtestmessage
Crée un objet MastraDBMessage destiné aux tests.
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',
},
],
})
createAgentTestRunLien direct vers createagenttestrun
Crée un objet d'exécution de test complet pour tester les Scorers.
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,
})
Utilitaires de trajectoireLien direct vers Utilitaires de trajectoire
extractTrajectoryLien direct vers extracttrajectory
Extrait une Trajectory des messages de sortie de l'Agent (MastraDBMessage[]). Convertit les invocations de Tool en objets ToolCallStep. Le pipeline runEvals l'appelle automatiquement pour les Scorers de trajectoire : vous n'en avez besoin que pour les tests directs.
Disponible depuis @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
Renvoie : Trajectory : contient steps: TrajectoryStep[], totalDurationMs et rawOutput.
extractWorkflowTrajectoryLien direct vers extractworkflowtrajectory
Extrait une Trajectory des résultats d'étapes du Workflow. Convertit les enregistrements StepResult en objets WorkflowStepStep, dans l'ordre du chemin d'exécution.
Disponible depuis @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
Renvoie : Trajectory : contient steps: TrajectoryStep[], totalDurationMs et rawWorkflowResult.
extractTrajectoryFromTraceLien direct vers extracttrajectoryfromtrace
Construit une Trajectory hiérarchique à partir des spans d'une Trace d'Observability (SpanRecord[]). Reconstruit l'arborescence parent-enfant des spans et associe chaque span au type union discriminé TrajectoryStep approprié, avec des children imbriqués.
Il s'agit de la méthode d'extraction privilégiée lorsque le stockage est disponible. Le pipeline runEvals l'appelle automatiquement lorsque l'instance Mastra de la cible dispose d'un backend de stockage configuré. Elle produit des trajectoires plus riches que extractTrajectory ou extractWorkflowTrajectory, car elle capture l'intégralité de l'arborescence d'exécution, notamment les exécutions d'Agents imbriquées, les appels de Tool et les générations de modèles.
Disponible depuis @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
Paramètres :
spans(SpanRecord[]) : tableau d'enregistrements de spans provenant d'une requête de Trace.rootSpanId(string, facultatif) : identifiant du span à utiliser comme point de départ. Lorsqu'il est omis, utilise les spans sans parent.
Renvoie : Trajectory : contient steps: TrajectoryStep[] avec des children récursifs et totalDurationMs.
Correspondance des types de spanLien direct vers Correspondance des types de span
| Type de span | Type d'étape de trajectoire | Principaux champs extraits |
|---|---|---|
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 (depuis l'identifiant de l'entité) |
WORKFLOW_RUN | workflow_run | workflowId (depuis l'identifiant de l'entité) |
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 |
Les spans de type GENERIC, MODEL_STEP, MODEL_CHUNK et WORKFLOW_CONDITIONAL_EVAL sont ignorés, car ils constituent du bruit.
compareTrajectoriesLien direct vers comparetrajectories
Compare une trajectoire réelle à une trajectoire attendue et renvoie un résultat de comparaison détaillé. Utilisée en interne par createTrajectoryAccuracyScorerCode.
Le paramètre expected accepte soit une Trajectory (trajectoire réelle), soit { steps: ExpectedStep[] }. Lorsque vous utilisez ExpectedStep[], vous pouvez établir la correspondance uniquement par nom ou par nom + stepType. Vous pouvez également inclure des données à comparer. Consultez les étapes attendues pour plus de détails.
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
Renvoie : TrajectoryComparisonResult
createTrajectoryTestRunLien direct vers createtrajectorytestrun
Crée un objet d'exécution de test pour les Scorers de trajectoire. Enveloppe une Trajectory dans le format ScorerRun attendu.
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)
checkTrajectoryEfficiencyLien direct vers checktrajectoryefficiency
Évalue l'efficacité d'une trajectoire par rapport aux budgets d'étapes, de tokens et de durée. Détecte également les appels redondants, c'est-à-dire au même Tool avec les mêmes arguments.
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
Renvoie : TrajectoryEfficiencyResult
checkTrajectoryBlacklistLien direct vers checktrajectoryblacklist
Vérifie si une trajectoire contient des Tools ou des séquences d'appels de Tool interdits.
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
Renvoie : TrajectoryBlacklistResult
analyzeToolFailuresLien direct vers analyzetoolfailures
Détecte les modèles d'échec des Tools, notamment les nouvelles tentatives, les solutions de repli et les corrections d'arguments.
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)
Renvoie : ToolFailureAnalysisResult
Exemple completLien direct vers Exemple complet
Voici un exemple complet qui montre comment utiliser plusieurs utilitaires ensemble :
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(', ')}.`
})