Constrain model responses with prefilling and stop sequences, then validate the result.
Download the runnable notebook
This complete lesson was converted from the matching notebook stored locally in the TechClub repository. Outputs are cleared; never add API keys or private data.
Goal, prerequisites, and setup
Learn two prompt-level controls for predictable output and verify the result instead of trusting valid-looking text. Complete the system-prompt lesson first; know Python dictionaries, JSON, and exceptions. Install anthropic and python-dotenv, set ANTHROPIC_API_KEY and ANTHROPIC_MODEL, and keep all generated data synthetic.
Run the plain-text example, then the prefilled and stop-sequence examples. Parse the result, test malformed output, and record validation failures rather than silently repairing them.
"""
CONTROLLING MODEL OUTPUT
-> It allows for more dynamic and interactive applications.
TWO TECHNIQUES:
-> prefilled assistant messages: Guide the model's behavior by providing example assistant messages in the conversation history.
-> stop sequences: Define specific sequences of text that, when generated by the model, will signal it to stop generating further content.
"""
# Load environment variables
from dotenv import load_dotenv
load_dotenv()
# Create an API client
import os
from anthropic import Anthropic
client = Anthropic()
model = os.getenv("ANTHROPIC_MODEL")
# Helpers
def add_message(messages, content, role):
message = {"role": role, "content": content}
messages.append(message)
"""
Stop Sequences
-> Force Claude to stop generating further content when it produces specific sequences of text.
-> Useful for controlling the length and format of the output.
"""
def chat(messages, system=None, stop_sequences=None):
params = {
"model": model,
"max_tokens": 1000,
"messages": messages,
}
if system:
params["system"] = system
if stop_sequences:
params["stop_sequences"] = stop_sequences
message = client.messages.create(**params)
return message.content[0].text
"""
Message Prefilling
-> Provide the start of an assistant message as your last message
-> Claude will continue the response from there
-> This will greatly steer Claude's response
"""
messages = []
add_message(messages,
"Is tea or coffee better at breakfast?",
role="user")
# Prefill assistant message
add_message(messages,
# "Coffee is better because",
# "Tea is better because",
# "Both tea and coffee have their own unique benefits for breakfast. ",
'Neigther tea nor coffee is better because',
role="assistant")
answer = chat(messages)
answer
"""
Stop Sequences
"""
messages = []
add_message(messages,
"Count from 1 to 10",
role="user")
answer = chat(messages, stop_sequences=[", 5"])
answer
"""
Both prefilled messages and stop sequences give you fine-grained control over Claude's behavior, making them essential tools for
building reliable AI applications.
"""
Evidence and references
- Submit the notebook, one valid and one invalid output, the parser/validation result, and a note about limitations.
- Anthropic Messages API
- Python
jsonmodule
This technique works by:
- The user message tells Claude what to generate
- The prefilled assistant message makes Claude think it already started a markdown code block
- Claude continues by writing just the JSON content
- When Claude tries to close the code block with ```, the stop sequence immediately ends generation
"""
Structured data
-> Ask Claude to output data in a structured format like JSON, CSV, bullet points, etc.
"""
messages = []
add_message(messages,
"List 5 popular programming languages and their main use cases in JSON format.",
role="user")
# prefill assistant message
add_message(messages, "```json", role="assistant"),
# Stop sequence to end JSON block
answer = chat(messages, stop_sequences=["```"])
print(answer)
import json
data = json.loads(answer.strip())
data
Structured Data Exercise
- Use message prefilling and stop sequence only to get three different commands in a single response
- There shouldn’t be any comments or explanation
- Hint: message prefilling isn’t limited to just characters like ```
messages = []
prompt = """
Generate exactly three different AWS CLI commands.
Requirements:
- output only commands
- one command per line
- no bullets, numbering, comments, or explanation
- after the third command, output <END>
"""
add_message(messages, prompt, role="user")
# Prefill assistant message to force plain command lines
add_message(messages, "aws ", role="assistant")
# Stop at a non-whitespace marker
text = chat(messages, stop_sequences=["<END>"])
text = "aws " + text
text.strip()
from IPython.display import Markdown
Markdown(text)
# SOLUTION
messages = []
prompt = """
Generate exactly three different AWS CLI commands.
Requirements:
- output only commands
- one command per line
- no bullets, numbering, comments, or explanation
- after the third command, output <END>
"""
add_message(messages, prompt, role="user")
# Prefill and stop sequence for structured plain-text output
add_message(messages, "aws ", role="assistant")
text = chat(messages, stop_sequences=["<END>"])
text = "aws " + text
text.strip()