Unit 01.02: Where the non-determinism has to stop
The uncertainty belongs in exactly one step, and everything after the validation is ordinary software again.
One non-deterministic step out of seven
A realistic pipeline with each step marked.
The code lists them.
PIPELINE = [
("validate the request", "deterministic"),
("build the prompt", "deterministic"),
("call the model", "NON-DETERMINISTIC"),
("parse the response", "deterministic"),
("validate against a schema", "deterministic"),
("decide what to do next", "deterministic"),
("perform the action", "deterministic"),
]
print(f"{'step':30} kind")
for step, kind in PIPELINE:
print(f"{step:30} {kind}")
nd = sum(1 for _, k in PIPELINE if k.startswith("NON"))
print(f"\n{nd} of {len(PIPELINE)} steps are non-deterministic")
print("everything after the parse is code you can test exhaustively")
# Confine the uncertainty to one step. The validation immediately after it is
# the wall: past that point the app is ordinary software again, and everything
# downstream can be tested without an API key.
Six of the seven steps are deterministic. The validation immediately after the model call is the wall: past that point you have a known shape and known values, and everything downstream can be tested exhaustively without a key.
That structure is what makes Module 11's offline test suite possible, and it is a design decision rather than a consequence.
The mistake this prevents
The mistake is letting model output flow into several places before it is validated. The uncertainty then spreads through the app, and every downstream component needs to handle malformed input separately.
Takeaway
Confine the non-determinism to one step and validate immediately after it. Everything past the validation is testable software.
