Skip to content

Extending AI Eval

What a module can add to AI Eval, and where each extension point plugs into a run. For PHP developers writing a module that sits alongside ai_eval.

There are four extension points, plus two plugin-definition alters. Everything here is discovered from any enabled module, so nothing below needs a patch to ai_eval itself.

Extension point Mechanism Contract
Grader Plugin in Plugin/AiEvalGrader GraderInterface
Dataset source Plugin in Plugin/AiEvalDatasetSource DatasetSourceInterface
Check executor Service tagged ai_eval.check_executor CheckExecutorInterface
Run event Event subscriber EvalRunCompleteEvent

Where each one sits in a run

flowchart TD
  DS["Dataset source plugin<br/>load(ref)"] --> Q["Question rows"]
  Q --> RUN["EvalRunner"]
  RUN --> INV["Invoke target<br/>agent mode or chat mode"]
  INV --> RESP["Response text<br/>plus tool-call record"]
  RESP --> GR["Grader plugins<br/>grade(input, response, context)"]
  GR --> RCG["rubric_checks grader"]
  RCG --> RCE["RubricCheckEvaluator"]
  RCE --> EX["Check executor services"]
  GR --> SC["Scorer<br/>composite score and gate"]
  SC --> ROW["ai_eval_result row"]
  ROW --> EV["EvalRunCompleteEvent"]

A grader scores a whole response on one dimension. A check executor runs one declarative check inside a rubric, and reaches the run only through the rubric_checks grader, which resolves the question's rubric_ref and combines the per-check outcomes into a single grade.

Plugin discovery

Both plugin types use a DefaultPluginManager subclass with attribute discovery. Put the class in your module's Plugin/AiEvalGrader or Plugin/AiEvalDatasetSource namespace, add the attribute, and clear caches.

Manager service Namespace scanned Attribute
ai_eval.grader_manager Plugin/AiEvalGrader Drupal\ai_eval\Attribute\AiEvalGrader
ai_eval.dataset_source_manager Plugin/AiEvalDatasetSource Drupal\ai_eval\Attribute\AiEvalDatasetSource

Check executors are ordinary services collected on a tag, so they are declared in your *.services.yml and need no attribute.

Altering definitions you do not own

The two managers each raise an alter hook, documented with example implementations in ai_eval.api.php at the module root:

  • hook_ai_eval_grader_info_alter(array &$definitions)
  • hook_ai_eval_dataset_source_info_alter(array &$definitions)

These are the only two hooks ai_eval invokes.

Services worth knowing

Injectable services a plugin or subscriber commonly needs.

Service ID Class What it does
ai_eval.grader_manager GraderPluginManager Grader discovery, plus actionObservingGraders()
ai_eval.dataset_source_manager DatasetSourcePluginManager Dataset source discovery
ai_eval.dataset_loader Service\DatasetLoader Resolves a target's dataset through its source
ai_eval.dataset_validator Service\DatasetValidator Validates a dataset document against dataset.schema.json
ai_eval.rubric_validator Service\RubricValidator Validates a rubric, including executor-provided check kinds
ai_eval.rubric_loader Service\RubricLoader Resolves a rubric_ref to a rubric document
ai_eval.rubric_check_evaluator Service\RubricCheckEvaluator Dispatches checks to executors and combines outcomes
ai_eval.check_template_resolver Service\CheckTemplateResolver Resolves metadata. and expected. dot-paths from a question
ai_eval.grader_scale_resolver Service\GraderScaleResolver Reads a grader's declared score scale from its definition
ai_eval.rate_limit_handler Service\RateLimitHandler Throttle and retry around provider calls
ai_eval.judge_config_store Service\JudgeConfigStore Stored per-judge prompt overrides
logger.channel.ai_eval Logger channel The module's log channel

Value objects have no service: GradeResult, CheckOutcome and ScoreScale are plain classes in the Drupal\ai_eval namespace.

The portable schemas

Dataset, rubric and judge YAML are described by public JSON Schemas that ai_eval ships and implements. If you are writing a tool that reads or writes eval content rather than a Drupal plugin, start at the schemas.