Week 11 of 12 · The Lead

Triage Against a Taxonomy

Build the router that turns a pile of flagged outputs into clean labels — sorting true violations from over-refusals and sending the hard ones where they belong.

Day 53 ~60 minutes Build Day

Day 53 of 66

From taxonomy to a working triage step

You have a taxonomy (Day 51) and you understand the helpful/harmless tension (Day 52). Today you make them operate. A flagged-output queue is never uniform: some items are clear violations, some are over-refusals masquerading as violations, some are genuinely ambiguous, and a few are severe enough that no single annotator should rule on them alone. Triage is the routing logic that sorts them — and it's the difference between a safety queue that runs and one that drowns.

This is a build day — the code is in the Try This box

The full safety_triage.py lives in the "Try This" box below (injected for build days). Type it in rather than pasting; the point is to read every branch and ask "is this where I'd route that item?" The thinking is the exercise — the syntax is trivial.

The four outcomes a triage step must produce

Every flagged item exits triage as exactly one of these. If your router can't produce all four, it's not safe to run.

OutcomeWhenWhy it matters
Label directlyClear category, confidentThe throughput case — most items, fast.
Over-refusalBenign item the model refusedCaptured as preference data, not discarded (Day 52).
AdjudicateAmbiguous / low confidenceGoes to consensus, not a guess — disagreement is data (Week 3).
EscalateHighest-severity categoriesSenior review + annotator support; never a solo call (Day 51).
The order of the checks is the whole design

Triage rules are checked top to bottom, so severity must be checked before confidence. A high-severity item that happens to be low-confidence should still escalate — not silently fall into the adjudication bucket. Get the order wrong and your most dangerous items take your least careful path. Read the branch order in the code and confirm it escalates first.

Confidence thresholds — where the routing line goes

The triage step leans on a confidence score (from a model classifier, a first-pass annotator, or both). The threshold you set is a real decision with real costs.

Core Theory

The threshold trades adjudication load against label noise

Set the confidence cutoff high (say, only auto-label above 0.9) and you route lots of items to adjudication — cleaner labels, but a heavier, slower, more expensive human queue. Set it low (auto-label above 0.5) and you save human effort but let borderline calls through as automatic labels — cheaper, noisier. There's no universal right answer; the right cutoff depends on the cost of a wrong label in that category. High-severity categories get a stricter threshold because the cost of being wrong is higher.

Severity and confidence are different axes — don't collapse them

A common rookie error is to treat "low confidence" and "high severity" as the same dial. They aren't. Severity is how bad it is if true; confidence is how sure you are it's true. A confident low-severity item labels directly. An unsure high-severity item escalates. The triage logic has to read both axes independently.

The escalation SOP behind the code

The code routes a severe item to "escalate," but a label string isn't a process. Behind that branch sits a standard operating procedure a lead writes once and the team follows every time.

What an escalation SOP must specify
  1. Who reviews — a named senior reviewer or a small panel, not "whoever's free."
  2. How fast — highest-severity items get a response-time commitment, not a backlog slot.
  3. What support — the annotator who surfaced it gets the well-being measures from Day 54 immediately, not at week's end.
  4. What feeds back — every escalation that revealed a taxonomy gap updates the taxonomy. Escalations are how the doc improves.

The build

Run safety_triage.py from the Try This box on the sample batch, then extend it with what you learned today.

Extend the triage router

Make it yours in three steps

  1. Run it as-is and confirm each sample item exits to the right bucket. Trace why each one routed where it did — say the branch out loud.
  2. Add a per-category confidence threshold (a dict): high-severity categories require a higher confidence to auto-label, everything else uses a lower default. This is the "different costs" idea in code.
  3. Write the four-step escalation SOP above as a comment block at the top of the file, so the code and the process live together. The next person to touch this queue should see both.

Then test on five real flagged items from your own work (scrub anything sensitive first). Did any route to "adjudicate" that you'd have silently guessed on before? That's the queue catching a guess — exactly its job.

The lead move

An annotator works items as they come. A lead designs the router that decides which path each item takes — and gets the branch order right so severity is checked before confidence, because a router that lets a high-severity item fall into adjudication sends your most dangerous data down your least careful path.

Say this in an interview: "My triage logic checks severity before confidence — they're different axes and collapsing them is how a dangerous item slips through. And 'escalate' isn't a label, it's an SOP: who reviews, how fast, what support, and what feeds back into the taxonomy."

Today's Takeaways