فرمت‌های داده ساختاریافته مانند JSON و YAML برای ساخت برنامه‌هایی که خروجی‌های هوش مصنوعی را به صورت برنامه‌ای مصرف می‌کنند ضروری هستند. این فصل تکنیک‌هایی برای تولید قابل اعتماد خروجی ساختاریافته را پوشش می‌دهد.

<Callout type="info" title="از متن به داده">
JSON و YAML خروجی‌های هوش مصنوعی را از متن آزاد به داده‌های ساختاریافته و type-safe تبدیل می‌کنند که کد می‌تواند مستقیماً مصرف کند.
</Callout>

## چرا فرمت‌های ساختاریافته؟

<JsonYamlDemo />

## مبانی پرامپت‌نویسی JSON

JSON (JavaScript Object Notation) رایج‌ترین فرمت برای خروجی‌های برنامه‌ای هوش مصنوعی است. سینتکس دقیق آن تجزیه را آسان می‌کند، اما همچنین به این معنی است که خطاهای کوچک می‌توانند کل خط لوله شما را خراب کنند.

### بایدها و نبایدها: درخواست JSON

<Compare 
  before={{ label: "❌ نکنید: درخواست مبهم", content: "اطلاعات کاربر را به صورت JSON به من بده." }}
  after={{ label: "✓ بکنید: اسکیما را نشان دهید", content: "اطلاعات کاربر را به صورت JSON مطابق این اسکیما استخراج کن:\n\n{\n  \"name\": \"string\",\n  \"age\": number,\n  \"email\": \"string\"\n}\n\nفقط JSON معتبر برگردان، بدون markdown." }}
/>

### خروجی ساده JSON

با یک اسکیما شروع کنید که ساختار مورد انتظار را نشان می‌دهد. مدل مقادیر را بر اساس متن ورودی پر می‌کند.

```
اطلاعات زیر را به صورت JSON استخراج کن:

{
  "name": "string",
  "age": number,
  "email": "string"
}

Text: "Contact John Smith, 34 years old, at john@example.com"
```

خروجی:
```json
{
  "name": "John Smith",
  "age": 34,
  "email": "john@example.com"
}
```

### ساختارهای تودرتوی JSON

داده‌های دنیای واقعی اغلب روابط تودرتو دارند. هر سطح از اسکیمای خود را به وضوح تعریف کنید، به خصوص برای آرایه‌های اشیاء.

```
این سفارش را به JSON تبدیل کن:

{
  "order_id": "string",
  "customer": {
    "name": "string",
    "email": "string"
  },
  "items": [
    {
      "product": "string",
      "quantity": number,
      "price": number
    }
  ],
  "total": number
}

Order: "Order #12345 for Jane Doe (jane@email.com): 2x Widget ($10 each), 
1x Gadget ($25). Total: $45"
```

### اطمینان از JSON معتبر

<Callout type="warning" title="نقطه شکست رایج">
مدل‌ها اغلب JSON را در بلوک‌های کد markdown قرار می‌دهند یا متن توضیحی اضافه می‌کنند. صریحاً بگویید که فقط JSON خام می‌خواهید.
</Callout>

دستورالعمل‌های صریح اضافه کنید:

```
مهم: فقط JSON معتبر برگردان. بدون markdown، بدون توضیح،
بدون متن اضافی قبل یا بعد از شیء JSON.

اگر یک فیلد قابل تعیین نیست، از null استفاده کن.
اطمینان حاصل کن که همه رشته‌ها به درستی نقل‌قول و escape شده‌اند.
اعداد نباید نقل‌قول شوند.
```

## مبانی پرامپت‌نویسی YAML

YAML نسبت به JSON برای انسان خواناتر است و از نظرات پشتیبانی می‌کند. این استاندارد برای فایل‌های پیکربندی است، به خصوص در DevOps (Docker، Kubernetes، GitHub Actions).

### خروجی ساده YAML

YAML به جای آکولاد از تورفتگی استفاده می‌کند. یک قالب ارائه دهید که ساختار مورد انتظار را نشان دهد.

```
یک فایل پیکربندی در فرمت YAML تولید کن:

server:
  host: string
  port: number
  ssl: boolean
database:
  type: string
  connection_string: string

الزامات: سرور Production روی پورت 443 با SSL، پایگاه داده PostgreSQL
```

خروجی:
```yaml
server:
  host: "0.0.0.0"
  port: 443
  ssl: true
database:
  type: "postgresql"
  connection_string: "postgresql://user:pass@localhost:5432/prod"
```

### ساختارهای پیچیده YAML

برای پیکربندی‌های پیچیده، در مورد الزامات دقیق باشید. مدل الگوهای رایج برای ابزارهایی مانند GitHub Actions، Docker Compose و Kubernetes را می‌شناسد.

```
یک GitHub Actions workflow در YAML تولید کن:

الزامات:
- راه‌اندازی با push به main و pull request‌ها
- اجرا روی Ubuntu latest
- مراحل: checkout، راه‌اندازی Node 18، نصب وابستگی‌ها، اجرای تست‌ها
- کش کردن وابستگی‌های npm
```

## تعریف تایپ در پرامپت‌ها

تعریف‌های تایپ یک قرارداد دقیق برای ساختار خروجی به مدل می‌دهند. آن‌ها نسبت به مثال‌ها صریح‌تر هستند و اعتبارسنجی برنامه‌ای آن‌ها آسان‌تر است.

### استفاده از تایپ‌های شبیه TypeScript

رابط‌های TypeScript برای توسعه‌دهندگان آشنا هستند و فیلدهای اختیاری، تایپ‌های union و آرایه‌ها را دقیقاً توصیف می‌کنند. پلتفرم prompts.chat از این رویکرد برای پرامپت‌های ساختاریافته استفاده می‌کند.

<TryIt 
  title="استخراج رابط TypeScript"
  description="از یک رابط TypeScript برای استخراج داده‌های ساختاریافته استفاده کنید."
  prompt={`Extract data according to this type definition:

interface ChatPersona {
    name?: string;
    role?: string;
    tone?: "professional" | "casual" | "friendly" | "technical";
    expertise?: string[];
    personality?: string[];
    background?: string;
}

Return as JSON matching this interface.

Description: "A senior software engineer named Alex who reviews code. They're analytical and thorough, with expertise in backend systems and databases. Professional but approachable tone."`}
/>

### تعریف JSON Schema

<Callout type="info" title="استاندارد صنعتی">
JSON Schema یک مشخصات رسمی برای توصیف ساختار JSON است. توسط بسیاری از کتابخانه‌های اعتبارسنجی و ابزارهای API پشتیبانی می‌شود.
</Callout>

JSON Schema محدودیت‌هایی مانند مقادیر حداقل/حداکثر، فیلدهای الزامی و الگوهای regex ارائه می‌دهد:

```
داده‌ها را طبق این JSON Schema استخراج کن:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["title", "author", "year"],
  "properties": {
    "title": { "type": "string" },
    "author": { "type": "string" },
    "year": { "type": "integer", "minimum": 1000, "maximum": 2100 },
    "genres": { 
      "type": "array", 
      "items": { "type": "string" }
    },
    "rating": { 
      "type": "number", 
      "minimum": 0, 
      "maximum": 5 
    }
  }
}

Book: "1984 by George Orwell (1949) - A dystopian masterpiece. 
Genres: Science Fiction, Political Fiction. Rated 4.8/5"
```

## کار با آرایه‌ها

آرایه‌ها نیاز به توجه ویژه دارند. مشخص کنید که آیا به تعداد ثابتی از آیتم‌ها نیاز دارید یا یک لیست با طول متغیر، و چگونه موارد خالی را مدیریت کنید.

### آرایه‌های با طول ثابت

وقتی دقیقاً به N آیتم نیاز دارید، صریحاً بگویید. مدل اطمینان حاصل می‌کند که آرایه طول صحیح دارد.

```
دقیقاً 3 نکته کلیدی را به صورت JSON استخراج کن:

{
  "key_points": [
    "string (نکته اول)",
    "string (نکته دوم)", 
    "string (نکته سوم)"
  ]
}

Article: [متن مقاله]
```

### آرایه‌های با طول متغیر

برای آرایه‌های با طول متغیر، مشخص کنید که وقتی صفر آیتم وجود دارد چه کاری انجام شود. شامل کردن یک فیلد شمارش به تأیید کامل بودن استخراج کمک می‌کند.

```
همه افراد ذکر شده را به صورت JSON استخراج کن:

{
  "people": [
    {
      "name": "string",
      "role": "string یا null اگر ذکر نشده"
    }
  ],
  "count": number
}

اگر هیچ فردی ذکر نشده، آرایه خالی برگردان.

Text: [متن]
```

## مقادیر Enum و محدودیت‌ها

Enum‌ها مقادیر را به یک مجموعه از پیش تعریف شده محدود می‌کنند. این برای وظایف طبقه‌بندی و هر جایی که به خروجی‌های سازگار و قابل پیش‌بینی نیاز دارید حیاتی است.

### بایدها و نبایدها: مقادیر Enum

<Compare 
  before={{ label: "❌ نکنید: دسته‌های باز", content: "این متن را در یک دسته‌بندی طبقه‌بندی کن.\n\n{\n  \"category\": \"string\"\n}" }}
  after={{ label: "✓ بکنید: به مقادیر معتبر محدود کن", content: "این متن را طبقه‌بندی کن. دسته‌بندی باید دقیقاً یکی از این‌ها باشد:\n- \"technical\"\n- \"business\"\n- \"creative\"\n- \"personal\"\n\n{\n  \"category\": \"یکی از مقادیر بالا\"\n}" }}
/>

### Enum‌های رشته‌ای

مقادیر مجاز را صریحاً لیست کنید. از زبان "باید یکی از این‌ها باشد" برای اجرای تطابق دقیق استفاده کنید.

```
این متن را طبقه‌بندی کن. دسته‌بندی باید یکی از این مقادیر دقیق باشد:
- "technical"
- "business" 
- "creative"
- "personal"

JSON برگردان:
{
  "text": "متن اصلی (کوتاه شده به 50 کاراکتر)",
  "category": "یکی از مقادیر enum بالا",
  "confidence": عدد بین 0 و 1
}

Text: [متن برای طبقه‌بندی]
```

### اعداد اعتبارسنجی شده

محدودیت‌های عددی از مقادیر خارج از محدوده جلوگیری می‌کنند. تایپ (integer در مقابل float) و محدوده معتبر را مشخص کنید.

```
این جنبه‌ها را امتیاز بده. هر امتیاز باید یک عدد صحیح از 1 تا 5 باشد.

{
  "quality": 1-5,
  "value": 1-5,
  "service": 1-5,
  "overall": 1-5
}

Review: [متن بازخورد]
```

## مدیریت داده‌های گمشده

متن دنیای واقعی اغلب برخی اطلاعات را ندارد. تعریف کنید که مدل چگونه باید داده‌های گمشده را مدیریت کند تا از مقادیر ساختگی جلوگیری شود.

### بایدها و نبایدها: اطلاعات گمشده

<Compare 
  before={{ label: "❌ نکنید: بگذار AI حدس بزند", content: "همه جزئیات شرکت را به صورت JSON استخراج کن:\n{\n  \"revenue\": number,\n  \"employees\": number\n}" }}
  after={{ label: "✓ بکنید: صریحاً null را مجاز کن", content: "جزئیات شرکت را استخراج کن. برای هر فیلدی که صریحاً ذکر نشده از null استفاده کن. مقادیر را اختراع نکن یا تخمین نزن.\n\n{\n  \"revenue\": \"number یا null\",\n  \"employees\": \"number یا null\"\n}" }}
/>

### مقادیر Null

صریحاً null را مجاز کنید و به مدل دستور دهید که اطلاعات اختراع نکند. این امن‌تر از حدس زدن مدل است.

```
اطلاعات را استخراج کن. برای هر فیلدی که نمی‌توان از متن تعیین کرد
از null استفاده کن. اطلاعات اختراع نکن.

{
  "company": "string یا null",
  "revenue": "number یا null",
  "employees": "number یا null",
  "founded": "number (سال) یا null",
  "headquarters": "string یا null"
}

Text: "Apple, headquartered in Cupertino, was founded in 1976."
```

خروجی:
```json
{
  "company": "Apple",
  "revenue": null,
  "employees": null,
  "founded": 1976,
  "headquarters": "Cupertino"
}
```

### مقادیر پیش‌فرض

وقتی مقادیر پیش‌فرض منطقی هستند، آن‌ها را در اسکیما مشخص کنید. این برای استخراج پیکربندی رایج است.

```
تنظیمات را با این پیش‌فرض‌ها استخراج کن اگر مشخص نشده:

{
  "theme": "light" (پیش‌فرض) | "dark",
  "language": "en" (پیش‌فرض) | کد ISO دیگر,
  "notifications": true (پیش‌فرض) | false,
  "fontSize": 14 (پیش‌فرض) | number
}

User preferences: "I want dark mode and larger text (18px)"
```

## پاسخ‌های چند شیئی

اغلب نیاز دارید چندین آیتم را از یک ورودی واحد استخراج کنید. ساختار آرایه و هرگونه الزامات مرتب‌سازی/گروه‌بندی را تعریف کنید.

### آرایه‌ای از اشیاء

برای لیست‌هایی از آیتم‌های مشابه، اسکیمای شیء را یک بار تعریف کنید و مشخص کنید که یک آرایه است.

```
این لیست را به آرایه JSON تبدیل کن:

[
  {
    "task": "string",
    "priority": "high" | "medium" | "low",
    "due": "رشته تاریخ ISO یا null"
  }
]

Todo list:
- Finish report (urgent, due tomorrow)
- Call dentist (low priority)
- Review PR #123 (medium, due Friday)
```

### اشیاء گروه‌بندی شده

وظایف گروه‌بندی نیاز به منطق دسته‌بندی دارند. مدل آیتم‌ها را در دسته‌هایی که تعریف می‌کنید مرتب می‌کند.

```
این آیتم‌ها را به JSON دسته‌بندی کن:

{
  "fruits": ["آرایه رشته‌ای"],
  "vegetables": ["آرایه رشته‌ای"],
  "other": ["آرایه رشته‌ای"]
}

Items: apple, carrot, bread, banana, broccoli, milk, orange, spinach
```

## YAML برای تولید پیکربندی

YAML برای پیکربندی‌های DevOps می‌درخشد. مدل الگوهای استاندارد برای ابزارهای رایج را می‌شناسد و می‌تواند پیکربندی‌های آماده تولید تولید کند.

### بایدها و نبایدها: پیکربندی‌های YAML

<Compare 
  before={{ label: "❌ نکنید: الزامات مبهم", content: "یک فایل docker-compose برای برنامه‌ام تولید کن." }}
  after={{ label: "✓ بکنید: اجزا و نیازها را مشخص کن", content: "docker-compose.yml تولید کن برای:\n- برنامه Node.js (پورت 3000)\n- پایگاه داده PostgreSQL\n- کش Redis\n\nشامل: health check‌ها، ذخیره‌سازی volume، محیط از فایل .env" }}
/>

### Docker Compose

سرویس‌هایی که نیاز دارید و هرگونه الزامات خاص را مشخص کنید. مدل سینتکس YAML و بهترین شیوه‌ها را مدیریت می‌کند.

```
docker-compose.yml تولید کن برای:
- برنامه Node.js روی پورت 3000
- پایگاه داده PostgreSQL
- کش Redis
- پروکسی معکوس Nginx

شامل:
- Health check‌ها
- ذخیره‌سازی Volume
- متغیرهای محیطی از فایل .env
- جداسازی شبکه
```

### Manifest‌های Kubernetes

Manifest‌های Kubernetes طولانی هستند اما از الگوهای قابل پیش‌بینی پیروی می‌کنند. پارامترهای کلیدی را ارائه دهید و مدل YAML سازگار تولید می‌کند.

```
YAML deployment برای Kubernetes تولید کن:

Deployment:
- Name: api-server
- Image: myapp:v1.2.3
- Replicas: 3
- Resources: 256Mi حافظه، 250m CPU (درخواست‌ها)
- Health check‌ها: endpoint /health
- Environment از ConfigMap: api-config

همچنین Service متناظر تولید کن (ClusterIP، پورت 8080)
```

## اعتبارسنجی و مدیریت خطا

برای سیستم‌های تولیدی، اعتبارسنجی را در پرامپت‌های خود بسازید. این خطاها را قبل از انتشار در خط لوله شما می‌گیرد.

### پرامپت خود-اعتبارسنجی

از مدل بخواهید خروجی خود را در برابر قوانینی که مشخص می‌کنید اعتبارسنجی کند. این خطاهای فرمت و مقادیر نامعتبر را می‌گیرد.

```
داده‌ها را به صورت JSON استخراج کن، سپس خروجی خود را اعتبارسنجی کن.

Schema:
{
  "email": "فرمت ایمیل معتبر",
  "phone": "فرمت E.164 (+1234567890)",
  "date": "فرمت ISO 8601 (YYYY-MM-DD)"
}

بعد از تولید JSON، بررسی کن:
1. ایمیل شامل @ و دامنه معتبر باشد
2. تلفن با + شروع شود و فقط ارقام داشته باشد
3. تاریخ معتبر و قابل تجزیه باشد

اگر اعتبارسنجی شکست خورد، مشکلات را قبل از پاسخ دادن رفع کن.

Text: [اطلاعات تماس]
```

### فرمت پاسخ خطا

فرمت‌های موفقیت و خطای جداگانه تعریف کنید. این مدیریت برنامه‌ای را بسیار آسان‌تر می‌کند.

```
سعی کن داده‌ها را استخراج کنی. اگر استخراج شکست خورد، فرمت خطا برگردان:

فرمت موفقیت:
{
  "success": true,
  "data": { ... داده‌های استخراج شده ... }
}

فرمت خطا:
{
  "success": false,
  "error": "توضیح اینکه چه مشکلی پیش آمد",
  "partial_data": { ... هر داده‌ای که می‌توان استخراج کرد ... }
}
```

## JSON در مقابل YAML: چه زمانی از کدام استفاده کنیم

<div className="my-4 grid md:grid-cols-2 gap-4">
  <div className="p-4 bg-amber-50 dark:bg-amber-950/30 rounded-lg border border-amber-200 dark:border-amber-800">
    <div className="font-semibold text-amber-700 dark:text-amber-300 mb-2">از JSON استفاده کنید وقتی</div>
    <div className="text-sm space-y-1">
      <p className="m-0!">تجزیه برنامه‌ای لازم است</p>
      <p className="m-0!">پاسخ‌های API</p>
      <p className="m-0!">الزامات تایپ دقیق</p>
      <p className="m-0!">یکپارچه‌سازی JavaScript/Web</p>
      <p className="m-0!">نمایش فشرده</p>
    </div>
  </div>
  <div className="p-4 bg-purple-50 dark:bg-purple-950/30 rounded-lg border border-purple-200 dark:border-purple-800">
    <div className="font-semibold text-purple-700 dark:text-purple-300 mb-2">از YAML استفاده کنید وقتی</div>
    <div className="text-sm space-y-1">
      <p className="m-0!">خوانایی انسانی مهم است</p>
      <p className="m-0!">فایل‌های پیکربندی</p>
      <p className="m-0!">نظرات مورد نیاز است</p>
      <p className="m-0!">DevOps/زیرساخت</p>
      <p className="m-0!">ساختارهای تودرتوی عمیق</p>
    </div>
  </div>
</div>

## پرامپت‌های ساختاریافته prompts.chat

در prompts.chat، می‌توانید پرامپت‌هایی با فرمت‌های خروجی ساختاریافته ایجاد کنید:

```
هنگام ایجاد پرامپت در prompts.chat، می‌توانید مشخص کنید:

Type: STRUCTURED
Format: JSON یا YAML

پلتفرم:
- خروجی‌ها را در برابر اسکیمای شما اعتبارسنجی می‌کند
- برجسته‌سازی سینتکس ارائه می‌دهد
- کپی آسان خروجی ساختاریافته را فعال می‌کند
- از متغیرهای قالب در اسکیمای شما پشتیبانی می‌کند
```

## دام‌های رایج

<Callout type="warning" title="این‌ها را اول اشکال‌زدایی کنید">
این سه مشکل بیشتر خطاهای تجزیه JSON را ایجاد می‌کنند. وقتی کد شما نمی‌تواند خروجی هوش مصنوعی را تجزیه کند، این‌ها را بررسی کنید.
</Callout>

### 1. بلوک‌های کد Markdown

**مشکل:** مدل JSON را در بلوک‌های ```json قرار می‌دهد

**راه‌حل:** 
```
فقط شیء JSON را برگردان. در بلوک‌های کد markdown قرار نده.
نشانگرهای ```json یا ``` را شامل نکن.
```

### 2. کاماهای انتهایی

**مشکل:** JSON نامعتبر به دلیل کاماهای انتهایی

**راه‌حل:**
```
سینتکس JSON معتبر را تضمین کن. کامای انتهایی بعد از آخرین
عنصر در آرایه‌ها یا اشیاء نباشد.
```

### 3. رشته‌های Escape نشده

**مشکل:** نقل‌قول‌ها یا کاراکترهای خاص JSON را خراب می‌کنند

**راه‌حل:**
```
کاراکترهای خاص در رشته‌ها را به درستی escape کن:
- \" برای نقل‌قول‌ها
- \\ برای بک‌اسلش‌ها
- \n برای خطوط جدید
```

## خلاصه

<Callout type="tip" title="تکنیک‌های کلیدی">
اسکیماها را صریحاً با استفاده از رابط‌های TypeScript یا JSON Schema تعریف کنید. تایپ‌ها و محدودیت‌ها را مشخص کنید، null‌ها و پیش‌فرض‌ها را مدیریت کنید، خود-اعتبارسنجی درخواست کنید، و فرمت مناسب برای مورد استفاده خود را انتخاب کنید.
</Callout>

<Quiz 
  question="چه زمانی باید YAML را به JSON ترجیح دهید برای خروجی‌های هوش مصنوعی؟"
  options={[
    "هنگام ساخت REST API‌ها",
    "وقتی خروجی باید برای انسان خوانا باشد و ممکن است شامل نظرات باشد",
    "هنگام کار با برنامه‌های JavaScript",
    "وقتی به فشرده‌ترین نمایش نیاز دارید"
  ]}
  correctIndex={1}
  explanation="YAML زمانی ترجیح داده می‌شود که خوانایی انسانی مهم باشد، مانند فایل‌های پیکربندی، manifest‌های DevOps و مستندات. همچنین برخلاف JSON از نظرات پشتیبانی می‌کند."
/>

این بخش دوم درباره تکنیک‌ها را تکمیل می‌کند. در بخش سوم، کاربردهای عملی در حوزه‌های مختلف را بررسی خواهیم کرد.
