في هذه الصفحة
الدّرس 5 من 6
المخرَج المنظّم
ما ستتعلّمه
- إجبار النّموذج على JSON ينتجه بانتظام
- استعمال المخططات للفشل سريعًا ورفض المخرج المشوّش
- تخطيط إعادة المحاولة دون كسر ميزانيّة التّأخير
In a tutorial, the model's output is read by a human. In production, it is parsed by code. The moment your application depends on the shape of the model's response — a JSON object with specific keys, an array of exactly three items, a number between 1 and 10 — you need structured output. This lesson covers how to get it reliably.
Why structured output matters
Consider a product extraction pipeline. You send the model a product description and need back:
{
"name": "string",
"price_usd": "number",
"in_stock": "boolean",
"categories": ["string"]
}
If the model returns this as prose — "The product is called Widget Pro, it costs $29.99..." — your downstream code breaks. If it returns JSON but with price instead of price_usd, your code breaks. Structured output is not a nice-to-have; it is the contract between the model and the rest of your system.
Technique 1: Explicit schema in the prompt
The simplest approach is to include the exact schema you expect in the prompt:
import anthropic
import json
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=256,
system="You are a product data extractor. Return only valid JSON, no markdown.",
messages=[
{
"role": "user",
"content": """Extract product data from this description.
<description>
The Widget Pro 3000 is our best-selling gadget at $29.99.
Currently in stock. Great for home automation and IoT projects.
</description>
Return JSON matching this exact schema:
{
"name": "string",
"price_usd": number,
"in_stock": boolean,
"categories": ["string"]
}"""
}
]
)
data = json.loads(message.content[0].text)
This works well for Claude, which follows structural instructions reliably. Two tips: include "Return only valid JSON, no markdown" in the system message to prevent the model from wrapping the output in a code fence, and show the schema with example types rather than descriptions.
Technique 2: XML tags for structured prompts AND outputs
Claude has a particular strength with XML tags. You can use them to structure both your input and the expected output:
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=512,
system="""Extract entities from text. Always respond using this exact format:
<entities>
<entity type="person|org|location" confidence="high|medium|low">name</entity>
</entities>""",
messages=[
{
"role": "user",
"content": """<text>
Sarah Chen, CTO of Meridian Labs, announced the opening
of their new research facility in Austin, Texas.
</text>"""
}
]
)
XML is particularly useful when your output has nested structure or when you need attributes alongside values. It is also easier to parse partially — if the model stops mid-response, you can still extract complete entities up to that point.
Technique 3: Prefilling the assistant response
A powerful Claude-specific technique is to start the assistant's response for it. This forces the model to continue in the format you specify:
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=256,
messages=[
{
"role": "user",
"content": "Extract the name and price from: 'Widget Pro costs $29.99'"
},
{
"role": "assistant",
"content": '{"name": "'
}
]
)
# The model continues from '{"name": "' and produces valid JSON
By prefilling the opening of the JSON object, you eliminate the risk of the model adding preamble like "Here is the extracted data:" before the JSON.
Validation and retry patterns
Even with perfect prompting, structured output can fail. The production pattern is: generate, validate, retry if needed.
import Anthropic from "@anthropic-ai/sdk";
import { z } from "zod";
const ProductSchema = z.object({
name: z.string(),
price_usd: z.number().positive(),
in_stock: z.boolean(),
categories: z.array(z.string()).min(1),
});
async function extractProduct(
client: Anthropic,
description: string,
maxRetries = 1
): Promise<z.infer<typeof ProductSchema>> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const message = await client.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 256,
system:
"Extract product data. Return only valid JSON, no markdown fences.",
messages: [
{
role: "user",
content:
"<description>" + description + "</description>\n" +
'Return JSON: {"name": string, "price_usd": number, "in_stock": boolean, "categories": string[]}',
},
],
});
try {
const parsed = JSON.parse(message.content[0].text);
return ProductSchema.parse(parsed);
} catch (error) {
if (attempt === maxRetries) throw error;
// Retry — the next attempt often succeeds
}
}
throw new Error("Unreachable");
}
Key points about retries:
- One retry is usually enough. If the model fails twice with the same prompt, a third attempt rarely helps. Change the prompt instead.
- Validate structurally, not just syntactically.
JSON.parsesucceeding is not enough. Use a schema validator (Zod, Pydantic, JSON Schema) to check that the keys, types, and constraints are correct. - Budget for retries in your latency. If your SLA is 2 seconds and the model takes 1.5 seconds, you cannot afford a retry. Design your latency budget to include one retry from the start.
Common failure modes
Structured output fails in predictable ways:
- Markdown wrapping: The model wraps JSON in
```json ```code fences. Fix by saying "no markdown" in the system message or by stripping fences in your parser. - Extra text: "Here is the extracted data:" followed by the JSON. Fix with assistant prefilling or a stricter system message.
- Missing keys: The model omits a field it considers irrelevant. Fix by making the schema explicit and adding "all fields are required."
- Wrong types: Price as "$29.99" (string) instead of 29.99 (number). Fix by showing the types in the schema and adding a type-correct example.
What's next
You now know how to get reliable shapes out of the model. But what happens when things go wrong at a deeper level — the model hallucinates, drifts from its persona, or falls victim to prompt injection? The final lesson, Failure modes, covers the five production failures you must know how to detect and recover from.
في الدّروس، يقرأ الإنسان مخرج النّموذج. في الإنتاج، يحلّله الكود. لحظة اعتماد تطبيقك على شكل استجابة النّموذج — كائن JSON بمفاتيح محدّدة، مصفوفة من ثلاثة عناصر بالضّبط، رقم بين واحد وعشرة — تحتاج مخرجًا منظّمًا. هذا الدّرس يغطّي كيف تحصل عليه بشكل موثوق.
لماذا يهمّ المخرج المنظّم
لو أرسلت وصف منتج للنّموذج وتحتاج JSON بمفاتيح محدّدة، وأعاد النّموذج نثرًا بدلًا من ذلك — كودك ينكسر. لو أعاد JSON لكن بمفتاح price بدل price_usd — كودك ينكسر. المخرج المنظّم ليس ترفًا؛ إنّه العقد بين النّموذج وبقيّة نظامك.
التّقنيّة الأولى: المخطّط الصّريح في المطالبة
أبسط طريقة هي تضمين المخطّط الدّقيق المتوقّع في المطالبة. نصيحتان: أضف "أعد JSON صالحًا فقط، بدون markdown" في رسالة النّظام، وأظهر المخطّط بأنواع مثاليّة لا بأوصاف.
التّقنيّة الثّانية: وسوم XML
Claude يتميّز بوسوم XML. تستطيع استعمالها لهيكلة مدخلاتك والمخرج المتوقّع معًا. XML مفيد خصوصًا حين يحوي مخرجك بنية متداخلة أو حين تحتاج سمات مع القيم.
التّقنيّة الثّالثة: ملء استجابة المساعد مسبقًا
تقنيّة قويّة خاصّة بـ Claude: تبدأ استجابة المساعد نيابةً عنه. هذا يجبر النّموذج على الاستمرار بالشّكل الذي تحدّده ويزيل خطر إضافة مقدّمة قبل الـ JSON.
التّحقّق وأنماط الإعادة
حتّى مع مطالبة مثاليّة، قد يفشل المخرج المنظّم. النّمط الإنتاجي: ولّد، تحقّق، أعد إن لزم.
نقاط مفتاحيّة عن الإعادة:
- إعادة واحدة تكفي عادةً. إن فشل النّموذج مرّتين بنفس المطالبة، المحاولة الثّالثة نادرًا ما تساعد.
- تحقّق بنيويًّا لا نحويًّا فقط. نجاح
JSON.parseلا يكفي. استعمل مدقّق مخطّط مثل Zod أو Pydantic. - احسب الإعادة في ميزانيّة التّأخير. إن كان وعدك ثانيتين والنّموذج يأخذ ثانية ونصفًا، لا تستطيع تحمّل إعادة.
أنماط الفشل الشّائعة
- تغليف بـ Markdown: النّموذج يغلّف JSON بسياج كود. الحلّ: قل "بدون markdown" أو أزل السّياج في المحلّل.
- نصّ زائد: النموذج يضيف مقدّمة قبل الـ JSON. الحلّ: ملء مسبق أو رسالة نظام أكثر صرامة.
- مفاتيح مفقودة: النّموذج يحذف حقلًا يراه غير ذي صلة. الحلّ: اجعل المخطّط صريحًا وأضف "جميع الحقول مطلوبة."
- أنواع خاطئة: السّعر كـ "$29.99" (نصّ) بدل 29.99 (رقم). الحلّ: أظهر الأنواع في المخطّط وأضف مثالًا بأنواع صحيحة.
ما التّالي
الآن تعرف كيف تحصل على أشكال موثوقة من النّموذج. لكن ماذا حين تسوء الأمور على مستوى أعمق — النّموذج يهلوس أو ينحرف عن شخصيّته أو يقع ضحيّة حقن المطالبة؟ الدّرس الأخير، الإخفاقات الواجب معرفتها، يغطّي الإخفاقات الخمس الإنتاجيّة التي يجب أن تعرف كيف تكشفها وتتعافى منها.
جرّب بنفسك
ابنِ مستخرجًا صغيرًا: مدخل = نصّ غير منظّم، مخرج = JSON موافق لمخطّط. أضف تحقّقًا وإعادة محاولة واحدة. شغّل على عشرين عيّنة وقس نسبة الفشل.
تأمّل
ماذا يحصل في نظامك اليوم حين يُرجع النّموذج مخرجًا مشوّهًا؟ هل لديك مسار إعادة محاولة أم يفشل بصمت؟