AI for beginnersGuide
Label every document in a prompt so the model won't mix them up
How to give each pasted text a name and a role, with a before/after prompt and a working chat completion request in Python and curl.

On this page
You pasted two texts into one message and asked the model to compare them. Unless you said which is which, it has to guess. The fix is small: give every text a name and a job, and wrap each one in its own tag. Anthropic's prompting guide (a living page, checked 31 October 2026) recommends tagging each type of content so the model doesn't misread what is an instruction, what is background and what is the input. Below is a before/after prompt and a working chat completion request you can send to the CheapTokens API.
What goes wrong when you just paste#
Take the plainest case. A supplier sends a new product description, and you want to know what changed against the one on your shop page. You paste both under "What changed?" and press send. For you the order is obvious. For the model it's two blocks of text with nothing between them, and the question never says which one is old. It may guess right. It may also call the new text the old one and hand you a list of changes running backwards, in a perfectly confident voice.
The same trap hides in everyday jobs:
- two versions of a contract, and you ask what the other side changed;
- three meeting notes, and you ask which decisions contradict each other;
- a style sample plus a draft: which one to imitate, which one to rewrite?
- an error log pasted together with the code, and the question is "fix this".
In each of them the model needs two things per text: a name (what it is and where it came from) and a role (what you want done with it).
Give each text a name and a job#
Three small moves:
- Put each text in its own tag. Anthropic's guide suggests a
<documents>wrapper with one<document index="1">per text, and inside it a<source>for the name and<document_for the text itself.content> - Say what each one is in the instruction, outside the tags: "Document 1 is the OLD text from our shop. Document 2 is the NEW text from the supplier."
- Ask the question in the same words. "List every fact that changed, as old -> new" now has an old and a new to point at.
Here is the bottle example before and after:
Compare
Same request, before and after
Before
What changed?
Steel water bottle, 500 ml. Keeps drinks cold for 12 hours. Dishwasher safe.
Steel water bottle, 750 ml. Keeps drinks cold for 24 hours. Hand wash only.After
Document 1 is the OLD text from our shop. Document 2 is the NEW text from the supplier. List every fact that changed, one per line, as old -> new.
<documents>
<document index="1">
<source>old description (current shop page)</source>
<document_content>
Steel water bottle, 500 ml. Keeps drinks cold for 12 hours. Dishwasher safe.
</document_content>
</document>
<document index="2">
<source>new description (from the supplier)</source>
<document_content>
Steel water bottle, 750 ml. Keeps drinks cold for 24 hours. Hand wash only.
</document_content>
</document>
</documents>
The labels cost a few tokens and take the guessing out. Anthropic wrote this advice for its Claude models, but the labels are plain text, so nothing stops you from sending the same layout to another chat model.
Send it as a real request#
Here is the "after" prompt as an API call. The address is https:/, the API is OpenAI-compatible, and the model is deepseek-. Take model ids from the CheapTokens docs: names differ between providers. DeepSeek-V4-Flash has a 380K context window and up to 32,768 output tokens per answer, which leaves room for a pile of long texts. The key comes from an environment variable, never from the code.
The same request in two tools
Python
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
)
old = "Steel water bottle, 500 ml. Keeps drinks cold for 12 hours. Dishwasher safe."
new = "Steel water bottle, 750 ml. Keeps drinks cold for 24 hours. Hand wash only."
prompt = f"""Document 1 is the OLD text from our shop. Document 2 is the NEW text from the supplier. List every fact that changed, one per line, as old -> new.
<documents>
<document index="1">
<source>old description (current shop page)</source>
<document_content>
{old}
</document_content>
</document>
<document index="2">
<source>new description (from the supplier)</source>
<document_content>
{new}
</document_content>
</document>
</documents>"""
response = client.chat.completions.create(
model="deepseek-ai/DeepSeek-V4-Flash-0731",
messages=[{"role": "user", "content": prompt}],
max_tokens=300,
)
print(response.choices[0].message.content)
print(response.usage)curl
curl https://api.cheaptokens.dev/v1/chat/completions \
-H "Authorization: Bearer $CHEAPTOKENS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-ai/DeepSeek-V4-Flash-0731",
"max_tokens": 300,
"messages": [{
"role": "user",
"content": "Document 1 is the OLD text from our shop. Document 2 is the NEW text from the supplier. List every fact that changed, one per line, as old -> new.\n\n<documents>\n<document index=\"1\">\n<source>old description (current shop page)</source>\n<document_content>\nSteel water bottle, 500 ml. Keeps drinks cold for 12 hours. Dishwasher safe.\n</document_content>\n</document>\n<document index=\"2\">\n<source>new description (from the supplier)</source>\n<document_content>\nSteel water bottle, 750 ml. Keeps drinks cold for 24 hours. Hand wash only.\n</document_content>\n</document>\n</documents>"
}]
}'The reply is plain text in choices[0]., and usage next to it counts the tokens. A good answer lists three changes: 500 ml -> 750 ml, 12 hours -> 24 hours, dishwasher safe -> hand wash only. If the arrows run the other way, the model lost track of the labels. Check that the instruction calls the documents the same thing the tags do.
What the labels cost#
Tags are text, and text is billed. Say a team lead feeds in three meeting notes of about 2,000 tokens each and asks which decisions conflict. Three notes: 3 × 2,000 = 6,000 tokens. Add about 150 tokens for the instruction and the tags (an assumption) and the request carries 6,150 tokens in, with a 300-token answer out. On DeepSeek-V4-Flash that one request costs $0.00012, and the tags themselves are a rounding error next to the notes. Here is the same request sent 1,000 times, with OpenRouter alongside:
| Model | Input $/1M | Output $/1M | Per request | 1,000 requests | OpenRouter, 1,000 requests |
|---|---|---|---|---|---|
| GLM-5.3-Flash | $0.02 | $0.04 | $0.00014 | $0.135 | $0.231 |
| DeepSeek-V4-Flash | $0.015 | $0.10 | $0.00012 | $0.122 | $0.473 |
| MiniMax-M2.7 | $0.05 | $0.15 | $0.00035 | $0.353 | $4.23 |
6,150 input and 300 output tokens per request. Prices per 1M tokens are current and change together with our tariffs; the OpenRouter column shows reference prices for the same workload.
All 6,150 tokens fit into the 380K window with room to spare (what a context window is). Counted in total, input and output together, the request comes out cheaper than OpenRouter. Input and output are billed at different rates, and input vs output tokens explains why. Current numbers for every model are on the pricing page.
Habits for bigger piles of text#
Once there are more than two texts, numbers alone are not enough: each one needs its own name. The picture below shows the layout from the example: the instruction with the question first, then each document in its own tag.

- Name by content, not by number alone.
<source>contract v2, sent by the client</beatssource> document 2when the answer quotes it back to you. - Keep your instruction outside the tags, so a line inside a pasted text isn't taken for an order.
- One text, one tag. A long file is still one tag; two files are two.
- Reuse the names in the question: "which decisions in monday-notes contradict wednesday-notes?"
- Give roles to examples too. "Document 1 is a style sample: copy its tone, not its facts. Document 2 is the draft to rewrite."
Try it yourselfTry it: you have an error log and the code that produced it in one prompt. What do you add to each?Show answer
A name and a job. For the log: <source>error log from the last run</ plus "this is the symptom, don't edit it". For the code: <source>app. plus "this is what to fix". Then ask for the fix by those names.
For the basics of the rest of the prompt (goal, context, format), see how to write a good prompt.



