Aller au contenu principal

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.

Import
Lien 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 messages
Lien direct vers Extraction des messages

getAssistantMessageFromRunOutput
Lien 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?:

ScorerRunOutputForAgent
Sortie d'exécution du Scorer (tableau de MastraDBMessage)

Renvoie : string | undefined - Le texte du message de l'assistant, ou undefined si aucun message de l'assistant n'est trouvé.

getUserMessageFromRunInput
Lien 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?:

ScorerRunInputForAgent
Entrée d'exécution du Scorer contenant les messages d'entrée

Renvoie : string | undefined - Le texte du message utilisateur, ou undefined si aucun message utilisateur n'est trouvé.

extractInputMessages
Lien 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.

extractAgentResponseMessages
Lien 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 raisonnement
Lien direct vers Extraction du raisonnement

getReasoningFromRunOutput
Lien 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 :

  1. content.reasoning - un champ chaîne du contenu du message
  2. content.parts - sous forme de parties avec type: 'reasoning' contenant details
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?:

ScorerRunOutputForAgent
Sortie d'exécution du Scorer (tableau de MastraDBMessage)

Renvoie : string | undefined - Le texte de raisonnement, ou undefined si aucun raisonnement n'est présent.

Extraction des messages système
Lien direct vers Extraction des messages système

getSystemMessagesFromRunInput
Lien 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.

getCombinedSystemPrompt
Lien 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 Tool
Lien direct vers Extraction des appels de Tool

extractToolCalls
Lien 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
}

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 test
Lien direct vers Utilitaires de test

Ces utilitaires facilitent la création de données de test pour le développement des Scorers.

createTestMessage
Lien 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',
},
],
})

createAgentTestRun
Lien 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 trajectoire
Lien direct vers Utilitaires de trajectoire

extractTrajectory
Lien 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.

extractWorkflowTrajectory
Lien 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.

extractTrajectoryFromTrace
Lien 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 span
Lien direct vers Correspondance des types de span

Type de spanType d'étape de trajectoirePrincipaux champs extraits
TOOL_CALLtool_calltoolArgs, toolResult, success
MCP_TOOL_CALLmcp_tool_calltoolArgs, toolResult, mcpServer, success
MODEL_GENERATIONmodel_generationmodelId, promptTokens, completionTokens, finishReason
AGENT_RUNagent_runagentId (depuis l'identifiant de l'entité)
WORKFLOW_RUNworkflow_runworkflowId (depuis l'identifiant de l'entité)
WORKFLOW_STEPworkflow_stepoutput
WORKFLOW_CONDITIONALworkflow_conditionalconditionCount, selectedSteps
WORKFLOW_PARALLELworkflow_parallelbranchCount, parallelSteps
WORKFLOW_LOOPworkflow_looploopType, totalIterations
WORKFLOW_SLEEPworkflow_sleepsleepDurationMs, sleepType
WORKFLOW_WAIT_EVENTworkflow_wait_eventeventName, eventReceived
PROCESSOR_RUNprocessor_runprocessorId

Les spans de type GENERIC, MODEL_STEP, MODEL_CHUNK et WORKFLOW_CONDITIONAL_EVAL sont ignorés, car ils constituent du bruit.

compareTrajectories
Lien 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

createTrajectoryTestRun
Lien 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)

checkTrajectoryEfficiency
Lien 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

checkTrajectoryBlacklist
Lien 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

analyzeToolFailures
Lien 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 complet
Lien 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(', ')}.`
})