metamorphic_check
Reference-free stability primitive: instead of comparing an answer to a ground truth, it checks that an assistant's answer stays INVARIANT when the QUESTION is transformed (typo, casing, paraphrase, reordering, translation). Catches the failure class no reference answer can expose — an assistant that handles one phrasing well and a trivial variant of it badly. You bring the outputs (no model is called), so it is deterministic and free in tfidf mode. Relations: case (θ .95), typo (.90), paraphrase (.80), reorder (.80), translation (.75, embeddings only), specialization (.60, ADVISORY — directional, never gated). Returns PASS / FAIL / INVALID, where INVALID means the BASE answer was a refusal or too short so invariance was never measurable — an assistant that refuses every variant would otherwise score a perfect 1.0. Use run_semantic_tests alongside it: invariance without a correctness floor is a green light for a broken assistant.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| base | Yes | The reference run: the original question and the answer your system produced for it. | |
| mode | No | tfidf (default): free, lexical, deterministic — but a genuine paraphrase rarely reaches 0.80, so gate on case/typo and treat paraphrase as a trend. embeddings: OpenAI text-embedding-3-small, true semantic similarity, requires api_key. translation requires this mode. | |
| api_key | No | OpenAI API key — required only when mode is embeddings. | |
| variants | Yes | Answers produced for transformed versions of the same question, each tagged with the relation that was applied. | |
| thresholds | No | Per-relation threshold overrides. Calibrate on your own corpus before gating — the defaults are starting points, not measurements. | |
| require_all | No | If true (default), every gated variant must pass. KEEP THE DEFAULT for any run you gate on. Setting it false is not a tolerance dial but an off switch: relations have asymmetric pass rates (a typo variant usually scores ~1.0 because the answer really is identical), so one trivial row is enough to hold the whole run at PASS while a paraphrase fails. When that happens the result carries an explicit warning naming the failed rows. | |
| baseline_guard | No | Correctness floor applied to the BASE answer before anything is scored. Failing it returns INVALID, not FAIL. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | ||
| summary | No | ||
| verdict | No | ||
| weakest | No | ||
| baseline | No | ||
| variants | No | ||
| warnings | No | ||
| thresholds | No |