In a few-shot prompt that extracts structured fields from invoices, why is a distinctive stop sequence (like a custom END_INVOICE marker) better than a paragraph break or the natural end of response?
You're an LLM engineer designing a few-shot prompt that extracts structured fields (vendor, total, line items) from invoice text. You're picking how the model should signal the end of each extracted record. Why a distinctive stop sequence (like a custom END_INVOICE marker) is better than a paragraph break or relying on the model's natural end of response, and what properties make a stop sequence robust.
A marker like END_INVOICE is collision-safe, self-anchoring through few-shot demos, decoupled from format changes, and composable across tasks. Pair it with the API's stop_sequences for byte-level enforcement.
Imagine you are training a friend to read invoices and write down what they see. You could tell them 'stop when you reach a blank line' but invoices have blank lines inside them. Instead you say 'when you are done with each invoice, write THE END on its own line'. Now you have a clear signal that will not be confused with anything inside the invoice. You also show them ten example invoices that all end with THE END, so they pick up the habit. And you tell the machine reading their notes to ignore anything after THE END. That is three layers and one clean signal.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Stop-sequence design looks like a small implementation detail and is one of the highest-impact decisions in a structured-extraction prompt. Get it right and the pipeline produces clean records with high reliability. Get it wrong and the long tail of edge cases (records truncated mid-field, premature termination on internal blank lines, downstream parsers choking on commentary) compounds into a quality problem. The problem is hard to diagnose because each individual failure looks like a different bug.
The terminator is a contract between three layers: the few-shot demonstrations that train the model to emit the marker, the model's actual generation behavior, and the API's stop_sequences parameter that enforces the boundary at the byte level. The contract works only if all three layers agree on what the marker is and what it means.
What makes a stop sequence robust
Four properties work together. First, collision safety: the marker is very unlikely to appear inside legitimate output. Paragraph breaks fail this because real invoices have blank lines between address lines, line items, and totals blocks. Single common words like END fail because they appear inside English text. The marker should be a multi-character distinctive sequence (END_INVOICE, </invoice>, ###RECORD_END###) that is very unlikely to appear inside a real record.
Second, self-anchoring: the marker appears in every few-shot demonstration in the prompt. The model treats the demonstrations as the strongest signal of what the output should look like. A marker that appears in every demonstration becomes part of the shape the model learns to produce. A marker that is only described in the system-prompt instruction is much weaker. The model may or may not emit it depending on phrasing.
Third, decoupling from the format: the marker should not depend on the structure of the record. A closing brace as a terminator couples the termination contract to the JSON format. Changing to a plain list of fields needs a new terminator. A custom sentinel does not change when the format does.
Fourth, composability: in a multi-task prompt, each record type gets its own terminator. The boundaries between records then stay unambiguous when outputs are concatenated. Reusing one terminator across record types loses this advantage.
Situations where this technique stops working.
2–4 min · Everything important, quickly.
Real products, models, and research that use this idea.
- Anthropic recommends XML tags to separate the parts of a prompt. A closing tag such as </invoice>, shown in every few-shot example, then doubles as a natural stop sequence.
- OpenAI's Chat Completions API accepts up to 4 stop sequences and returns text that does not contain the matched sequence. The o3 and o4-mini models do not support stop.
What an interviewer would ask next. Try answering before peeking at the approach.
QHow would you handle a case where the model genuinely needs to emit content containing your terminator?
Pick a sentinel that is even less likely to collide (a long uppercase identifier like END_INVOICE_RECORD_V1), or escape conflicts in few-shot demonstrations, or switch to a structured-output mode where the field text sits inside a JSON string that does the escaping for you.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Using a paragraph break as the terminator on a structured-extraction prompt, then watching extractions get truncated whenever the model produces a blank line inside a multi-line address or line-item block.
60 second bullets to scan on the way to the call.
Why paragraph breaks are unsafe as terminators on structured extraction
The self-anchoring property and how few-shot examples create it
Primary sources. Browse if you want the original framing.
Same topic, related formats. Practice these next.