Master's thesis · University of Kaiserslautern-Landau

ParityLM

Real-time Task Verification using Expert Demonstration Priors

Motivation

Mistakes are cheap to catch, expensive to miss

A lot of human work is procedural: a fixed sequence of steps where both the order and the manner matter. Mistakes get expensive not because they are hard to see, but because nobody is watching.

Vocational trainingQuality assuranceProcedural complianceAssistive guidance
The setting

Scarce supervision, live and first-person

01

One demonstration

One correct execution and a written instruction. No collection of recordings.

02

No error examples

No recordings of the ways the procedure can go wrong.

03

A live egocentric stream

Head-mounted, partial, moving. Every judgement is made while the task is still happening.

04

A different person

Their pace, habits and tool order all differ from the demonstrator's.

Related work

Existing methods need what we don't have

Supervised classifiers

Trained on a fixed set of tasks, usually with error labels.

Assembly101 · IndustReal · CaptainCook4D · HoloAssist

Needs labelled errors

Task-graph reasoning

Flag executions that break an explicit procedure structure.

EgoPED · video-mined task graphs

Needs many runs to mine the graph

Anomaly detection

Model only correct execution; flag anything novel.

ATA · PREGO

Alarms it can't explain

And most report results with the true step boundaries supplied, which leaves open who finds the segments in the first place.

Research question
Can a general-purpose vision-language model, given one expert demonstration and no error supervision, follow a worker through a live stream and speak up when they deviate?
One-way stream. Frames arrive once, in order. No step boundaries are given.
One reference. Every expected duration belongs to someone else.
Opposite failure costs. A false alarm is worse than a miss: the system gets switched off.
Dataset

EgoPER

Egocentric recordings of people cooking, with every moment labelled as correct or as a type of error.

Recipescoffee · tea · oatmeal · pinwheels · quesadilla
Clips396 annotated, dense in time
Error typesSlipCorrectionAdditionModification
EgoPER sample frames: normal vs. error executions
Task representation

One demonstration becomes an Activity Graph

"Spread Nutella onto tortilla"
criteriashort observable conditions
dvexpected duration, from the expert
typesetup · manipulation · inspection · terminal

No visual templates, no reference frames, no learned parameters. Step names are the annotator's own words.

  1. Place tortilla on cutting board
  2. Use knife to scoop Nutella
  3. Spread Nutella onto tortilla
  4. Sprinkle cinnamon onto tortilla
  5. Put banana slices on tortilla
  6. Fold tortilla
  7. Slice using knife
  8. Place tortilla wedges on plate
A subtle trap

Build the reference from a normal run

If an error clip's graph is built from its own annotation, only the Normal segments become steps. The steps done wrong disappear, and the system can't flag a step it doesn't know exists.

The fix is the one-shot assumption taken literally: each recipe's procedure comes from one normal clip.

Consequence: durations belong to another person. The reference allows 3.3 s to place the tortilla; this participant took 10.1 s.

quesadilla_u1_a2_error_028SelfRef.
Place tortilla on cutting board
Use knife to scoop Nutella
Spread Nutella onto tortilla
Sprinkle cinnamon onto tortilla
Put banana slices on tortilla
Fold tortilla
Slice using knife
Place tortilla wedges on plate
Steps in graph28
Evaluation

Built on 15 clips, reported on 187

Development set
15 clips

8 normal, 7 error, all five recipes. Used to compare system versions.

EgoPER test split
187 clips

170 error, 17 normal · 11.9 h of video · 2,125 reference steps. The official held-out set.

Streaming only: frames once, in order, at 3 fps, with no oracle boundaries. No parameter changed between the two sets.

Architecture

Separate seeing from thinking

Activity Graph+ video stream at 3 fps
L2 · perception
Fast probesmultiple-choice, read from log-probs
~0.24 s per probe
candidate →
L1 · reasoning
Adjudicatordescribe, then verdict
3–30 s, on demand
MISTAKE → reportOK → discardDESYNC → move cursor

Both tiers run the same checkpoint, Qwen3.6-35B-A3B (FP8), served by vLLM with one GPU each. They differ in what they're asked and how the answer is read, not in their weights.

Perception · 1

Read the answer, don't generate it

Constrain the answer to one letter and read the model's first-token distribution. Renormalise over the options and take the margin between the top two as confidence.

p̃(a) = p(a) / Σa′∈A p(a′)     c = p̃(a1) − p̃(a2)

One forward pass, one token: a generative model becomes a classifier with a usable confidence score.

Renormalised option probabilities (illustrative)
A · not finished0.14
B · just completed0.69
C · on next step0.12
D · cannot tell0.05
margin c = 0.69 − 0.14 = 0.55 ≥ 0.5 → confident
Perception · 2

Make "done" beat a stated "not done"

Before: yes / no

"Has step n been completed?"

Probabilities cluster around 0.53 / 0.47, close to a coin flip. At threshold 0.65 there are no false positives but also no detections; at 0.51, one detection and two false positives.

After: four-way contrast

A not finished · B just completed
C already on the next step · D cannot tell

On the first clip tested, all 8 steps were found.

7.7 s 0.7 s

median boundary error

The single most important design choice in the system.

What the model sees

Two buffers for two questions

Dense recent windowlast 30 frames ≈ 10 s

"What is happening right now?" Feeds the completion and step probes.

Sparse per-step buffer≤ 32 frames spanning the whole step

"Was this step done right?" Thinned evenly as the step grows. Feeds the correctness probe.

An earlier version cleared all frames at every step change, throwing away the evidence exactly when it was needed. Capping the buffer also caps the cost of the most expensive call.

Perception probes

Three questions, three rhythms

Completion · every 2 s

Is the step finished?

Dense window, options A–D. B or C counts as evidence; an explicit A resets the count. The backbone of tracking.

Step · every 4 s

Which step is this?

Previous, current or next step, or "none of these". A moving average (ω = 0.35) is compared with a per-clip baseline to catch skipped steps and off-task activity.

Correctness · once per step

Was it done as described?

Sparse buffer, deliberately neutral wording. Returns a short reading plus a yes/no.

Completion-driven tracking

Advance only on sustained evidence

  1. Hysteresis. 2 confident probes in a row (margin ≥ 0.5).
  2. Minimum time in step. At least 0.3 · dv must pass, capped at 20 s.
  3. Boundary attribution. The step end is placed at the first confident probe, when the evidence first appeared.
Why a minimum time?

On look-alike steps (pour grounds → pour water) the tracker raced several steps ahead in seconds.

Checking against the step probe didn't separate true from false completions. Time in step did.

26.8 s 16.9 s

mean boundary error

Reasoning tier

Candidates are not reports

Correctnessstep not done as described
Stallno completion after 3 · dv (at least 20 s)
Skipped stepsustained evidence of a later step
Off-tasksustained "none of these"

20 s cooldown. Nothing reaches the user without L1's verdict.

L1 describes first, then commits

Two rules carry most of the precision:

1 · "The alert that woke you is not evidence."

2 · "A slow step is never a mistake by itself."

Stall verdicts went from 5 mistakes to 1 mistake + 8 ok. Telling the model that idling is normal didn't work; changing the decision rule did.

Contribution

Let the judge blame the tracker

MISTAKE

The frames clearly contradict the step. The only verdict that reaches the user.

OK

No clear evidence of a deviation. Logged, then discarded.

DESYNC, step

The worker is fine; the tracker is on the wrong step. The cursor jumps silently.

Every false alarm in an earlier version began with the tracker losing sync, followed by the adjudicator blaming the worker. On the test split DESYNC fired 82 times across 70 clips: 82 false alarms that never reached the user.

Implementation

One small interface

system  = ParityLM(PipelineConfig())
monitor = system.start_activity("clip.activity.json")
for frame in frame_source:
    monitor.process_frame(frame)
    if monitor.task_complete: break
report  = monitor.summary()

The frame source is any iterable, so a file and a live camera differ only in the iterator.

Serving lessons · vLLM, 2 endpoints
  • Limit the image size, or the multimodal memory check at startup fails and the server never starts.
  • Weeks of mid-run crashes were our own 32 GiB container memory limit (OOM killer), not the cluster.
  • FP8 needs compute capability ≥ 8.9. Ampere GPUs get scheduled, then can't serve the model.
  • Temperature 0: borderline verdicts used to flip between identical runs.
Reproducibility

Every run recorded with real timing

Every process_frame call is timed. The loop is synchronous, so a window containing an L1 call is a window in which the stream was blocked, and its duration is that call's true cost.

Resumable across cluster jobs: a clip counts as done once its record exists, resuming requires matching settings, and no new clip starts close to the time limit.

<clip>.mp4the monitored video
.activity.jsonthe graph it was checked against
.timeline.jsonannotation, used only for scoring
.run.jsondecisions, verdicts, per-window timing
The inspection tool

Review

  • The clip next to the step the system believed was current.
  • A multi-lane timeline: the reference lane on its own axis, the tracker lane on the clip's clock, with steps colour-matched.
  • The full decision log (every probe, candidate and verdict), scrubbable at will.

Opens a run-set folder directly. No server.

Screenshot: Review view (video · step lanes · decision log)
Screenshot: Replay view during an L1 reasoning call
The inspection tool

Replay the stream as the model saw it

Driven by the measured timing: probes tick at their real rhythm, and when L1 is called the video stops while its reasoning appears over the seconds it actually took.

Drawing the pipeline honestly caught two mistakes: an expert-video panel (the system never sees expert footage) and an annotation labelled "ground truth" beside the tracker.

How we got here

A sequence of measured changes

Yes / no probes

Coin-flip regime. ~74% of boundaries, 7.7 s error.

Contrastive MCQ

Median boundary error 0.7 s on the first clip.

Min. time in step

Mean error 26.8 s → 16.9 s. No more racing ahead.

Verdict rules + DESYNC

Stall mistakes 5 → 1. False alarms caused by the tracker are gone.

v1 → v3

Smooth tracking, clean normal clips… and 0/7 errors detected.

v4

Reference graph + correctness probe: 6/7 errors detected.

Development set · 15 clips

v1 → v4

v1v2v3v4
Normal clips clean8/88/88/84/8
False alarms00010
Error clips detected1/70/70/76/7
Clip-level outcome9/158/158/1510/15
Median boundary error6.3 s11.3 s8.7 s6.1 s*
Reasoning calls202051

v1–v3 differ in hardware and buffer settings. v2's shorter dense window caused its boundary regression (confirmed by an A/B test) and was restored in v3.

v4 adds the reference graph and the correctness probe, and is carried to the test split unchanged.

* normal clips only

A counter-intuitive result

Tracking improved, detection fell

v1's single "detection" was luck: the tracker had stalled near an error, and the stall check happened to look at the right frames.

Once tracking was smooth, L1 was called 20 times in about 2 h of video, and almost never at an error.

v3 is an honest baseline: excellent tracking, and no way at all to notice wrong execution. Measure tracking and reporting separately, or artefacts look like progress.

1/7 0/7

error clips detected, v1 → v3

Upper-bound diagnostic

Can the model even see the errors?

26 annotated error moments. The exact frames are supplied, the model is the same, and only the wording changes.

It wasn't perception, it was the question. The caution that keeps false alarms low also hides real mistakes, so checking alarms and checking correctness need different prompts.

Errors detected, of 26
Cautious
"only flag clear evidence"
2
Neutral
"done as described?"
17
Neutral, by type: wrong tool / technique 14/16 · slips 3/6 · additions 0/4
v4

Detection returns, at a price

0/7 6/7

error clips detected

8 10 /15

clips judged correctly

0 10

false alarms, on 4 of 8 normal clips

Both changes come from one component. The correctness probe raised 25 of 51 L1 calls and 16 of them came back as mistakes, while stall checks behaved (17 of 19 ok). The precision loss is contained in one gate.

Results · EgoPER test split

83.1% EDA, the only streaming method

EgoPED sup.57.0
AMNAR sup.64.4
AEM sup.66.7
GTG2Vid sup.79.7
ZeProM-M 0-shot80.1
ParityLM streaming83.1
ZeProM-L 0-shot84.1
ParityLM per recipe
Coffee91.0 best published
Oatmeal85.1
Tea83.9
Pinwheels79.2
Quesadilla76.1

All other methods process the whole video offline. ZeProM-M uses a 35B model from the same family as ours; ZeProM-L uses 397B.

What it catches

Detection by error type

Modification 99/26337.6%
Addition 36/10434.6%
Slip 30/14321.0%
Correction 8/4219.0%
All error segments: 173 / 552 = 31.3%. Bar length is the detection rate, on a 0–100% scale.
L1 called 743 times
213 reports
  • 88% of reports come from the correctness probe.
  • Correctness → mistake in 57% of calls (188/329).
  • Stall → mistake in just 2% (5/223).
  • DESYNC fixed the cursor 82 times.
Tracking

Tracking works, with a long tail

88.5%

of 2,125 reference steps confirmed

98%

on normal clips, where every step happens

8.4 s

median boundary error

42%

within 10 s of the true end

The error is one-sided: 84% of boundaries fire early and carry 87% of the total error. The tracker falls more than 10 s behind the worker on only 7% of steps. 153 of 187 runs reach the final step.

Measured cost · 2× H200

1.8× real time, and it stops to think

0.24 s

per perception probe

3–30 s

per reasoning call, blocking the stream

Cost comes from images, not answer length. A 481-character verdict took 26.6 s; a 648-character one took 9.3 s. One correctness check at median cost leaves ~32 live frames unexamined.

L1 triggerCallsMedianMax
Correctness32910.7 s30.4 s
Off-task1636.1 s17.2 s
Skipped step285.9 s17.8 s
Stall2235.6 s22.9 s
What's still wrong

Four open issues

Completion cascades

In one coffee clip, all 14 steps were confirmed within the first 200 s of 985 s, although the activity only starts at 492 s.

Long timing tail

34 of 203 boundaries on normal clips are off by more than 60 s, even though the reference is correct.

Someone else's pace

30% of L1 calls were stall checks, and 181 of 223 said "ok". The worker was just slower.

Invisible errors

Additions belong to no step, and "too short" slips can't be seen in still frames.

Next steps

Ordered by gain over effort

  1. Sharpen the correctness gate. Add a second, independently worded check; use the confidence margin; let L1 argue against the probe's reading.
  2. Stop cascades. Require the step probe to agree before accepting a second completion.
  3. Pace-adaptive stalls. Estimate the worker's pace from the first few steps.
  4. Non-blocking reasoning. Keep perception running during L1 calls.
  5. Reach invisible errors. A probe not tied to any step; timer-aware slip checks.
  6. Live camera. Just a different iterator on the same interface.
Conclusion

The answer is split, and that is the result

Tracking
88.5% confirmed · 8.4 s median
Detection
83.1% EDA · online · no task training
  • Contrastive questions took tracking out of the coin-flip regime.
  • Prompt wording, not perception, limited error detection.
  • DESYNC turns false alarms into silent corrections.
  • Measure tracking and reporting separately.
THEEND
Thank you · questions welcome
← → navigate · R camera roll1 / 33