Структурированные форматы данных, такие как JSON и YAML, необходимы для создания приложений, которые программно обрабатывают выходные данные ИИ. В этой главе рассматриваются техники для надёжной генерации структурированного вывода.

<Callout type="info" title="От текста к данным">
JSON и YAML преобразуют выходные данные ИИ из произвольного текста в структурированные, типобезопасные данные, которые код может напрямую использовать.
</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

Начните со схемы, показывающей ожидаемую структуру. Модель заполнит значения на основе входного текста.

```
Extract the following information as 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

Данные реального мира часто имеют вложенные связи. Чётко определите каждый уровень вашей схемы, особенно для массивов объектов.

```
Parse this order into 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>

Добавьте явные инструкции:

```
CRITICAL: Return ONLY valid JSON. No markdown, no explanation, 
no additional text before or after the JSON object.

If a field cannot be determined, use null.
Ensure all strings are properly quoted and escaped.
Numbers should not be quoted.
```

## Основы промптинга с YAML

YAML более читаем для человека, чем JSON, и поддерживает комментарии. Это стандарт для конфигурационных файлов, особенно в DevOps (Docker, Kubernetes, GitHub Actions).

### Простой вывод YAML

YAML использует отступы вместо фигурных скобок. Предоставьте шаблон, показывающий ожидаемую структуру.

```
Generate a configuration file in YAML format:

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

Requirements: Production server on port 443 with SSL, PostgreSQL database
```

Вывод:
```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.

```
Generate a GitHub Actions workflow in YAML:

Requirements:
- Trigger on push to main and pull requests
- Run on Ubuntu latest
- Steps: checkout, setup Node 18, install dependencies, run tests
- Cache npm dependencies
```

## Определения типов в промптах

Определения типов дают модели точный контракт для структуры вывода. Они более явные, чем примеры, и их легче валидировать программно.

### Использование типов в стиле TypeScript

Интерфейсы TypeScript знакомы разработчикам и точно описывают опциональные поля, объединённые типы и массивы. Платформа 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 предоставляет ограничения, такие как минимальные/максимальные значения, обязательные поля и регулярные выражения:

```
Extract data according to this 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 элементов, укажите это явно. Модель обеспечит правильную длину массива.

```
Extract exactly 3 key points as JSON:

{
  "key_points": [
    "string (first point)",
    "string (second point)", 
    "string (third point)"
  ]
}

Article: [article text]
```

### Массивы переменной длины

Для массивов переменной длины укажите, что делать при нулевом количестве элементов. Включение поля count помогает проверить полноту извлечения.

```
Extract all mentioned people as JSON:

{
  "people": [
    {
      "name": "string",
      "role": "string or null if not mentioned"
    }
  ],
  "count": number
}

If no people are mentioned, return empty array.

Text: [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

Перечислите допустимые значения явно. Используйте формулировку «ДОЛЖЕН быть одним из» для обеспечения строгого соответствия.

```
Classify this text. The category MUST be one of these exact values:
- "technical"
- "business" 
- "creative"
- "personal"

Return JSON:
{
  "text": "original text (truncated to 50 chars)",
  "category": "one of the enum values above",
  "confidence": number between 0 and 1
}

Text: [text to classify]
```

### Валидация чисел

Числовые ограничения предотвращают выход значений за пределы диапазона. Укажите тип (целое число или число с плавающей точкой) и допустимый диапазон.

```
Rate these aspects. Each score MUST be an integer from 1 to 5.

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

Review: [review text]
```

## Обработка отсутствующих данных

В текстах реального мира часто отсутствует какая-то информация. Определите, как модель должна обрабатывать отсутствующие данные, чтобы избежать выдуманных значений.

### Что делать и чего избегать: отсутствующая информация

<Compare 
  before={{ label: "❌ Не делайте: позволяйте ИИ угадывать", content: "Извлеки все данные о компании как JSON:\n{\n  \"revenue\": number,\n  \"employees\": number\n}" }}
  after={{ label: "✓ Делайте: явно разрешите null", content: "Извлеки данные о компании. Используй null для любого поля, которое НЕ упомянуто явно. НЕ выдумывай и не оценивай значения.\n\n{\n  \"revenue\": \"number or null\",\n  \"employees\": \"number or null\"\n}" }}
/>

### Значения Null

Явно разрешите null и проинструктируйте модель не выдумывать информацию. Это безопаснее, чем позволять модели угадывать.

```
Extract information. Use null for any field that cannot be 
determined from the text. Do NOT invent information.

{
  "company": "string or null",
  "revenue": "number or null",
  "employees": "number or null",
  "founded": "number (year) or null",
  "headquarters": "string or null"
}

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

Вывод:
```json
{
  "company": "Apple",
  "revenue": null,
  "employees": null,
  "founded": 1976,
  "headquarters": "Cupertino"
}
```

### Значения по умолчанию

Когда значения по умолчанию имеют смысл, укажите их в схеме. Это обычная практика для извлечения конфигураций.

```
Extract settings with these defaults if not specified:

{
  "theme": "light" (default) | "dark",
  "language": "en" (default) | other ISO code,
  "notifications": true (default) | false,
  "fontSize": 14 (default) | number
}

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

## Ответы с множественными объектами

Часто вам нужно извлечь несколько элементов из одного входа. Определите структуру массива и любые требования к сортировке/группировке.

### Массив объектов

Для списков однотипных элементов определите схему объекта один раз и укажите, что это массив.

```
Parse this list into JSON array:

[
  {
    "task": "string",
    "priority": "high" | "medium" | "low",
    "due": "ISO date string or null"
  }
]

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

### Сгруппированные объекты

Задачи группировки требуют логики категоризации. Модель распределит элементы по определённым вами категориям.

```
Categorize these items into JSON:

{
  "fruits": ["string array"],
  "vegetables": ["string array"],
  "other": ["string array"]
}

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Включи: проверки работоспособности, persistence томов, переменные окружения из .env файла" }}
/>

### Docker Compose

Укажите необходимые сервисы и любые особые требования. Модель позаботится о синтаксисе YAML и лучших практиках.

```
Generate a docker-compose.yml for:
- Node.js app on port 3000
- PostgreSQL database
- Redis cache
- Nginx reverse proxy

Include:
- Health checks
- Volume persistence
- Environment variables from .env file
- Network isolation
```

### Манифесты Kubernetes

Манифесты Kubernetes многословны, но следуют предсказуемым паттернам. Предоставьте ключевые параметры, и модель сгенерирует соответствующий YAML.

```
Generate Kubernetes deployment YAML:

Deployment:
- Name: api-server
- Image: myapp:v1.2.3
- Replicas: 3
- Resources: 256Mi memory, 250m CPU (requests)
- Health checks: /health endpoint
- Environment from ConfigMap: api-config

Also generate matching Service (ClusterIP, port 8080)
```

## Валидация и обработка ошибок

Для продакшн-систем встраивайте валидацию в ваши промпты. Это позволяет отлавливать ошибки до того, как они распространятся по вашему пайплайну.

### Промпт с самовалидацией

Попросите модель валидировать собственный вывод по указанным вами правилам. Это позволяет отловить ошибки формата и недопустимые значения.

```
Extract data as JSON, then validate your output.

Schema:
{
  "email": "valid email format",
  "phone": "E.164 format (+1234567890)",
  "date": "ISO 8601 format (YYYY-MM-DD)"
}

After generating JSON, check:
1. Email contains @ and valid domain
2. Phone starts with + and contains only digits
3. Date is valid and parseable

If validation fails, fix the issues before responding.

Text: [contact information]
```

### Формат ответа при ошибке

Определите отдельные форматы для успеха и ошибки. Это значительно упрощает программную обработку.

```
Attempt to extract data. If extraction fails, return error format:

Success format:
{
  "success": true,
  "data": { ... extracted data ... }
}

Error format:
{
  "success": false,
  "error": "description of what went wrong",
  "partial_data": { ... any data that could be extracted ... }
}
```

## JSON vs 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 вы можете создавать промпты со структурированными форматами вывода:

```
When creating a prompt on prompts.chat, you can specify:

Type: STRUCTURED
Format: JSON or YAML

The platform will:
- Validate outputs against your schema
- Provide syntax highlighting
- Enable easy copying of structured output
- Support template variables in your schema
```

## Распространённые ошибки

<Callout type="warning" title="Сначала проверьте это">
Эти три проблемы вызывают большинство ошибок парсинга JSON. Проверяйте их, когда ваш код не может распарсить вывод ИИ.
</Callout>

### 1. Блоки кода Markdown

**Проблема:** Модель оборачивает JSON в блоки ```json

**Решение:** 
```
Return ONLY the JSON object. Do not wrap in markdown code blocks.
Do not include ```json or ``` markers.
```

### 2. Висячие запятые

**Проблема:** Невалидный JSON из-за висячих запятых

**Решение:**
```
Ensure valid JSON syntax. No trailing commas after the last 
element in arrays or objects.
```

### 3. Неэкранированные строки

**Проблема:** Кавычки или специальные символы ломают JSON

**Решение:**
```
Properly escape special characters in strings:
- \" for quotes
- \\ for backslashes
- \n for newlines
```

## Резюме

<Callout type="tip" title="Ключевые техники">
Определяйте схемы явно с помощью интерфейсов TypeScript или JSON Schema. Указывайте типы и ограничения, обрабатывайте null и значения по умолчанию, запрашивайте самовалидацию и выбирайте правильный формат для вашего случая использования.
</Callout>

<Quiz 
  question="Когда следует предпочесть YAML вместо JSON для выходных данных ИИ?"
  options={[
    "При создании REST API",
    "Когда вывод должен быть читаемым для человека и может включать комментарии",
    "При работе с JavaScript-приложениями",
    "Когда нужно максимально компактное представление"
  ]}
  correctIndex={1}
  explanation="YAML предпочтителен, когда важна читаемость для человека, например в конфигурационных файлах, DevOps-манифестах и документации. Он также поддерживает комментарии, в отличие от JSON."
/>

На этом завершается Часть II о техниках. В Части III мы рассмотрим практические применения в различных областях.
