redact-09-evaluation, after redact-08-failure-recovery
How do you score a suggestion?
Start with a page where a person has already marked every private field. Run the app on it, and compare what it proposed with what the person marked. Two things can go wrong, and they need separate numbers. Precision asks: of everything Redact proposed, how much was right? Recall asks: of everything that should have been proposed, how much did Redact find? For a privacy tool, recall matters most. A wrong suggestion costs one click on Reject; a missed account number is the whole failure. F1 combines the two into one number, so neither can hide behind the other.When is a box “the same” box?
A suggestion and a person’s mark will never line up to the pixel. So we measure overlap: the area they share divided by the area they cover together. That’s called intersection over union, or IoU. Two identical boxes score 1.0, and boxes that don’t touch score 0. Redact counts a suggestion as correct when its label matches and its IoU with a marked region is at least 0.45. More on what these numbers can and can’t tell you: About measuring suggestions.Why four versions of the same chat?
Real documents aren’t clean. The evaluation uses the same fictional chat four ways: clear, rotated a quarter turn, low-contrast, and partly covered. Each has the same six labelled fields: name, email, address, phone, account and reference. The rotated one matters most here. OCR on a sideways page tends to return many short vertical fragments, one per word. This lesson also teaches the analyzer to notice that, read the page upright, and keep whichever reading has whole lines.1. Get this lesson’s code
Stop the app and the service if they’re running. From the repository root,redact-course, bring in this lesson’s commit:
2. Read the scoring rules
Openqvac-service/evaluation.ts.
The pass mark is in one place:
rotateClockwise turns each answer box a quarter turn, the same way the image was turned:
3. Read the rotated-page retry
Openqvac-service/qvac-analyzer.ts.
First the analyzer decides whether a page looks sideways:
mapCounterClockwiseRetryToOriginal then moves the upright boxes back onto the sideways page, so marks still land in the right place (OCR boxes and rotation).
4. Read the runner
Openqvac-service/evaluation-cli.ts.
For each case it sends the image through exactly the same analyzer the app uses:
5. Run the evaluation
The OCR model and Laya must already be cached from earlier lessons. Stop the service, so the evaluation has the models to itself, then run:--silent keeps npm’s own banner out of the file.
The terminal shows one progress line per page as it goes, named by condition rather than case ID: Evaluating clear…, Evaluating rotated…, Evaluating low-contrast… and Evaluating partially-obscured….
The whole run takes about two minutes.
When it ends, check the exit status:
0 means every case passed.
6. Read the receipt
Openevaluation-receipt.json.
Near the top you’ll see "passed": true.
Under results, each case has its scores in a nested result object, results[].result, with precision, recall and f1:
On the first three, Laya found all six fields and proposed one more line:
keep the amount confidential., which the evaluation’s direction asks it to consider.
On the partly covered page, one field is missed and one extra line is proposed.
Look in matches to see which regions were found, and with what IoU.
Run it again.
The numbers are identical, because Laya gives the same answer for the same input.
7. Run one case on its own
When one case fails, run it alone:chat-clear, chat-low-contrast and chat-partially-obscured.
If something goes wrong
QVAC cache is empty: runnpm run qvac:ocr-smokeand one analysis in the app first, so both models are downloaded.QVAC evaluation failed: …saying a model couldn’t load: the service may be holding the models; stopnpm run qvac:serviceand try again.Unknown evaluation case: check the spelling ofREDACT_EVALUATION_CASE.
8. Check your work
npm test ends with Tests 82 passed (82).
You can leave evaluation-receipt.json where it is: this lesson’s .gitignore ignores any *-receipt.json file.
So what just happened?
You turned “it looks right” into numbers that a script can check. The same command now fails if a change makes Redact miss fields or propose nonsense on these four pages. Four fictional images are a course gate, not proof of accuracy on your own documents.Try it yourself
Openqvac-service/evaluation.ts and change minimumPrecision: 0.7 to 0.9, then run the evaluation.
Every case now fails, and echo $? prints 1, even though the suggestions haven’t changed: one extra suggestion out of seven is no longer allowed.
Put it back to 0.7 afterwards.
Then run the lesson 02 OCR script on the sideways image, npm run qvac:ocr-smoke -- public/test-files/redact/evaluation/chat-rotated.png.
The script has no upright retry, so you’ll see the short vertical word blocks that this lesson’s retry exists to fix.
Where to next
- Every file in this checkpoint:
redact/atredact-09-evaluation - About measuring suggestions and the Evaluation reference