Skip to content

Implementation / Field notes

Build a held-out evaluation set from support tickets

Split support evaluation data by customer issue or conversation family so paraphrases and follow-ups do not leak into both tuning and held-out tests.

By DriftRail · Updated

Build a held-out support evaluation set by defining tasks and scoring rules, removing unnecessary personal data, and splitting related conversations together. Randomly splitting individual messages can place the same customer problem in both prompt-tuning and evaluation sets.

Keep an issue family in one partition

A ticket may have follow-up messages, a translated copy, and a paraphrased knowledge question. Treat these as related records for splitting. If examples from the same issue appear on both sides, the apparent improvement may reflect familiarity rather than performance on new tasks.

Prepare the evaluation records

  1. Collect examples under an appropriate purpose and minimize customer identifiers and confidential content.
  2. Assign a family identifier using a documented grouping rule; manually inspect near duplicates.
  3. Write expected outcomes and escalation criteria before using the held-out partition.
  4. Version the split and retain a separate challenge set for rare, consequential failures.

Check leakage before scoring

The runnable fixture contains two differently worded cases from the same issue family. It detects an overlapping family in a deliberately bad split and verifies that the repaired split keeps family identifiers disjoint. It does not claim to discover every semantic duplicate automatically.

Avoid turning the holdout into another training set

Repeatedly reading failures and adjusting a prompt to each exact case can reduce the usefulness of the holdout. Record tuning cycles, preserve a genuinely unused subset where practical, and compare representative task groups. A perfectly separated split can still be unrepresentative if it omits the support work the product actually receives.

Run the worked example

Save the synthetic Node.js example and run node build-held-out-support-evaluation-set.mjs with Node.js 22 or newer. The assertions check the illustrated records and calculations; they do not test a deployed provider, SDK, or access control. No credentials or network connection are needed.

// Synthetic teaching fixture. No credentials, network calls, or production verification.
import assert from 'node:assert/strict';

const cases = [
  { id: 'ticket-a', family: 'refund-issue-1' },
  { id: 'ticket-a-followup', family: 'refund-issue-1' },
  { id: 'ticket-b', family: 'shipping-issue-2' },
];
const overlaps = (train, holdout) => holdout.filter(h => train.some(t => t.family === h.family));
assert.equal(overlaps([cases[0]], [cases[1], cases[2]]).length, 1);
assert.equal(overlaps([cases[0], cases[1]], [cases[2]]).length, 0);
console.log('Split related ticket families together; repaired holdout has no family overlap.');

References and further reading

Maintained by DriftRail. AI assisted the October 2026 content and template revision. Examples are illustrative; they are not measured product benchmarks. Suggest a correction.

From understanding to evidence

Observe your AI in production.

Explore event logging, detections, and review workflows in DriftRail.

Open DriftRail ↗Read the documentation →