> ## Documentation Index
> Fetch the complete documentation index at: https://avala.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Схема метаданных последовательности

> Метка результата каждой последовательности, как сообщается техническая валидность и как читать, записывать и экспортировать и то и другое

Каждая последовательность несёт два отдельных вида метаданных:

* **Техническая валидность.** Пригодна ли запись к использованию? Avala сообщает её на основе критериев приёмки и целевых показателей качества. См. раздел «Техническая валидность» ниже.
* **Поведенческий результат.** Что сделал человек или робот и успешно ли выполнена задача? Avala хранит его как **метку результата** последовательности.

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

## Метка результата

У каждой последовательности не более одной текущей метки результата. Каждая запись создаёт новую версию. Более ранние версии остаются доступными в истории метки.

### Пример

Так выглядит метка демонстрации человеком с соскальзыванием и восстановлением в ответе `GET .../sequences/<sequence-uid>/outcome/`:

```json theme={null}
{
  "uid": "<outcome-uid>",
  "sequence_uid": "<sequence-uid>",
  "version": 2,
  "is_current": true,
  "outcome": "mistake_and_recovery",
  "progress": 1.0,
  "quality": 4,
  "speed": 3,
  "subtasks": [
    { "label": "Load the plate into the lower rack", "start_ts": 0.0, "end_ts": 19.8, "outcome": "mistake_and_recovery" },
    { "label": "Pull out the lower rack", "start_ts": 0.0, "end_ts": 6.2, "outcome": "expert_success" },
    { "label": "Place the wet plate in a free slot", "start_ts": 6.2, "end_ts": 19.8, "outcome": "mistake_and_recovery" }
  ],
  "hand_actions": {
    "left": [
      { "start_ts": 0.0, "end_ts": 6.2, "action": "pulling the lower rack out by its front edge", "object": "dishwasher rack", "verb": "pull", "contact": true },
      { "start_ts": 6.2, "end_ts": 19.8, "action": "holding the rack steady", "object": "dishwasher rack", "verb": "hold", "contact": true }
    ],
    "right": [
      { "start_ts": 6.2, "end_ts": 9.1, "action": "carrying the wet plate to the rack", "object": "plate", "verb": "carry", "contact": true },
      { "start_ts": 9.1, "end_ts": 10.4, "action": "the plate slips out of the grasp", "object": "plate", "verb": null, "contact": false },
      { "start_ts": 10.4, "end_ts": 14.7, "action": "regrasping the plate by its rim", "object": "plate", "verb": "grasp", "contact": true },
      { "start_ts": 14.7, "end_ts": 19.8, "action": "placing the plate in a free slot", "object": "plate", "verb": "place", "contact": true }
    ]
  },
  "mistake_type": "slip_during_place",
  "recovery_type": "regrasp",
  "failure_stage": "place",
  "autonomy_level": "human_demonstration",
  "model_version": "",
  "evaluation_membership": "train",
  "leakage_groups": {
    "location": "loc_8f2a",
    "object": "obj_set_31",
    "mechanism": "dishwasher_pull_rack_v2",
    "operator": "op_5c1e",
    "environment_family": "kitchen_galley"
  },
  "source": "human",
  "source_metadata": {},
  "labeled_by": "<user-uid>",
  "confidence": null,
  "created_at": "2026-09-30T17:42:11.204000Z",
  "updated_at": "2026-09-30T17:42:11.204000Z"
}
```

Значения иллюстрируют структуру метки. Они не описывают реальную поставку.

### Поля

Все временные метки указаны в секундах от начала последовательности.

| Поле | Тип | Значение |
| - | - | - |
| `uid` | string | ID этой версии метки. Только для чтения. |
| `sequence_uid` | string | Последовательность, к которой относится метка. Только для чтения. |
| `version` | integer | Версия метки, начиная с 1. Каждая запись увеличивает её на единицу. Только для чтения. |
| `is_current` | boolean | `true` для текущей версии. Только для чтения. |
| `outcome` | string | Поведенческий результат. Обязательное поле. См. раздел «Значения результата». |
| `progress` | number или null | Прогресс задачи от 0 до 1. |
| `quality` | integer или null | Качество исполнения от 1 до 5. |
| `speed` | integer или null | Скорость исполнения от 1 до 5. |
| `subtasks` | list | Размеченные временные диапазоны. См. раздел «Подзадачи». |
| `hand_actions` | object | Потоки действий для каждой руки, `left` и `right`. См. раздел «Действия рук». |
| `mistake_type` | string | Ваш тег для вида ошибки. До 128 символов. Пустая строка, если не задан. |
| `recovery_type` | string | Ваш тег для вида восстановления. До 128 символов. Пустая строка, если не задан. |
| `failure_stage` | string | Ваш тег для этапа, на котором произошёл сбой. До 128 символов. Пустая строка, если не задан. |
| `autonomy_level` | string | Кто управлял. См. раздел «Уровень автономии». Пустая строка, если не задан. |
| `model_version` | string | Версия политики или модели, которая управляла роботом. До 255 символов. Пустая строка для демонстраций человеком. |
| `evaluation_membership` | string | `train`, `held_out_eval` или `none`. Пустая строка, если не задано. См. раздел «Принадлежность к оценке». |
| `leakage_groups` | object | Идентификаторы групп для чистоты разбиения. См. раздел «Группы утечки». |
| `source` | string | Кто записал метку: `human`, `model` или `imported`. По умолчанию `human`. |
| `source_metadata` | object | Происхождение импорта. См. раздел «Метаданные источника». |
| `labeled_by` | string или null | UID пользователя, записавшего версию. Возвращается только тем, кто может редактировать набор данных. Только для чтения. |
| `confidence` | number или null | Уверенность модели от 0 до 1. Принимается, только когда `source` равен `model`. |
| `created_at`, `updated_at` | string | Временные метки версии. Только для чтения. |

`mistake_type`, `recovery_type` и `failure_stage` задаются свободным текстом. Используйте теги из таксономии сбоев вашей программы, чтобы последовательности чисто группировались.

### Значения результата

| Результат | Значение |
| - | - |
| `expert_success` | Задача выполнена. Исполнение плавное, в экспертном темпе. |
| `slow_success` | Задача выполнена. Исполнение правильное и заметно медленнее экспертного темпа. |
| `partial_success` | Часть задачи выполнена. Конечное целевое состояние не достигнуто. |
| `mistake_and_recovery` | Происходит ошибка, например соскальзывание, промах или неверное размещение. Исполнитель восстанавливается без посторонней помощи и завершает задачу. |
| `intervention` | Человек вмешивается, чтобы исправить или завершить задачу. |
| `unsafe` | Последовательность содержит небезопасное действие или состояние. |
| `aborted` | Попытка прекращается до завершения задачи, без восстановления. |
| `failure` | Попытка заканчивается, а задача не выполнена. |
| `novel_strategy` | Задача решена допустимым способом, который отличается от обычной стратегии. |
| `inefficient_strategy` | Задача решена с лишними движениями, повторными попытками или обходными путями, которых можно было избежать. |

Каждая подзадача может нести собственный результат из того же списка.

### Уровень автономии

| Значение | Смысл |
| - | - |
| `human_demonstration` | Задачу выполняет человек. |
| `teleoperation` | Человек управляет роботом удалённо. |
| `autonomous` | Робот работает на своей политике. |
| `shared_autonomy` | Политика и человек делят управление. |
| `intervention` | Человек перехватывает управление у политики во время последовательности. |

### Подзадачи

Каждая подзадача имеет вид `{label, start_ts, end_ts, outcome}`.

| Поле | Правило |
| - | - |
| `label` | Описание подзадачи на естественном языке. Обязательное. От 1 до 500 символов. |
| `start_ts`, `end_ts` | Конечные числа, 0 или больше. `end_ts` не меньше `start_ts`. |
| `outcome` | Значение результата или `null`. |

Метка содержит не более 256 подзадач. Список должен быть упорядочен по `start_ts`. Любые две подзадачи либо не пересекаются, либо одна полностью содержит другую, как этап и его шаги. Соприкасающиеся концы считаются непересекающимися. Частичное перекрытие отклоняется. Когда две подзадачи начинаются в один момент, первой указывайте охватывающую.

### Действия рук

`hand_actions` содержит два независимых потока, `left` и `right`. Каждый элемент описывает, что делает одна рука на временном диапазоне.

| Поле | Правило |
| - | - |
| `start_ts`, `end_ts` | Конечные числа, 0 или больше. `end_ts` не меньше `start_ts`. |
| `action` | Описание действия на естественном языке. Обязательное. От 1 до 500 символов. |
| `object` | Объект, с которым работает рука. Необязательное. До 255 символов. |
| `verb` | Короткий глагол для действия. Необязательное. До 64 символов. |
| `contact` | `true`, когда рука касается объекта, `false`, когда не касается, `null`, когда это неизвестно. Принимаются только булевы значения JSON. |

* В пределах одной руки элементы упорядочены по `start_ts` и не должны перекрываться. Элемент начинается в момент окончания предыдущего или позже. Соприкосновение допустимо.
* Потоки двух рук могут свободно перекрываться.
* Для каждой руки допускается не более 3600 элементов. Это один час при одной метке в секунду.
* `left` и `right` являются единственными ключами. Любой из них можно опустить. Опущенная рука сохраняется как пустой список.
* Пустые `object` или `verb` сохраняются как `null`. Каждый сохранённый элемент содержит все шесть полей.

### Длительность последовательности

Когда Avala знает длительность последовательности, каждый `end_ts` подзадачи и каждый `end_ts` действия руки должен быть не больше длительности плюс 1 секунда. Дополнительная секунда учитывает метки, записанные раз в секунду. Avala знает длительность, когда у последовательности ровно один извлечённый файл MCAP с записанной длиной. Для остальных последовательностей проверка пропускается.

### Принадлежность к оценке

`evaluation_membership` относит последовательность к одному из разбиений:

| Значение | Смысл |
| - | - |
| `train` | Последовательность можно использовать для обучения. |
| `held_out_eval` | Последовательность входит в отложенный оценочный набор. Не используйте её для обучения. |
| `none` | Последовательность не входит ни в одно из разбиений. |

Avala задаёт `held_out_eval` для последовательностей каждой оценочной когорты. Такие последовательности никогда не попадают в релиз для обучения. См. [Оценка](/docs/ru/fleet-learning/evaluation.md).

### Группы утечки

Группы утечки не дают почти одинаковым последовательностям попасть по обе стороны разбиения на обучение и оценку. `leakage_groups` принимает следующие ключи, каждый с идентификатором группы длиной до 255 символов:

| Ключ | Объединяет последовательности с общим |
| - | - |
| `location` | Домом, площадкой или комнатой. |
| `object` | Набором физических объектов. |
| `mechanism` | Экземпляром прибора или механизма. |
| `operator` | Сборщиком данных или телеоператором. |
| `environment_family` | Типом окружения и планировки, например кухней-коридором. |

Любой другой ключ отклоняется. Каждый ключ необязателен.

Avala формирует оценочные когорты так, чтобы ни одно значение группы из когорты не встречалось ни в одном релизе для обучения. Вы можете разбивать собственные данные тем же способом: откладывайте данные по группам, никогда по случайным последовательностям. Идентификаторы групп Avala псевдонимны, поэтому вы можете группировать и разбивать данные, не узнавая, кто и где записывал.

### Метаданные источника

`source_metadata` фиксирует, откуда пришла импортированная метка, например `{"importer": "...", "run_id": "...", "task": "...", "log_path": "..."}`.

* Это плоский объект, не более 20 ключей.
* Длина каждого ключа от 1 до 64 символов.
* Каждое значение является строкой до 512 символов, конечным числом или булевым значением.
* Вложенные объекты, списки и значения `null` отклоняются.

### Как работает запись

* Запись заменяет текущую метку целиком и создаёт новую версию. Любое необязательное поле, которое вы не передали, сохраняется как незаданное. Оно не копируется из предыдущей версии.
* Для записи нужен доступ на редактирование набора данных. Для чтения нужен тот же доступ, что и для чтения последовательности, в том числе для публичных наборов данных.
* `confidence` отклоняется, если `source` не равен `model`.
* Чтение последовательности без метки возвращает `404`.

## Техническая валидность

Техническая валидность не входит в метку результата. Avala сообщает её на основе механизма приёмки и целевых показателей качества, и собственной JSON-схемы у неё нет.

**Критерии приёмки.** Каждая запись в кампании сбора получает машинный вердикт: `accept`, `quarantine` или `reject`. Вердикт выносится по следующим критериям:

| Критерий | Что проверяет |
| - | - |
| `capture_health` | Файл MCAP проходит валидацию, и все каналы, которые требует кампания, присутствуют. |
| `frame_rate` | Частота кадров камеры держится на протяжении всего клипа, без длительного провала. |
| `completeness` | Длина близка к той, которую запросила кампания. |
| `framing` | Руки видны достаточную часть времени, в течение которого работал детектор. |
| `shake` | Камера не трясётся большую часть клипа. |

Каждый критерий сообщает `pass`, `fail`, `insufficient_evidence` или `skipped`. Непройденный критерий записывает код причины, например `acceptance_frame_rate_drop` или `hands_not_visible`. Затем рецензент подтверждает или переопределяет вердикт. Коды причин перечислены на странице [Принятый час](/docs/ru/fleet-learning/accepted-hour.md).

Читайте результаты приёмки через MCP-инструменты: `get_result_acceptance` для одной записи и `get_campaign_acceptance_summary` для кампании. `list_capture_submissions` включает машинную сводку приёмки для каждой записи.

**Целевые показатели качества.** Проект может задавать пороги для метрик качества, например для доли принятых, доли отклонённых и доли проблем. Avala оповещает, когда метрика пересекает свой порог. Читайте их через MCP-инструмент `list_quality_targets`.

Проверки программы, которые не являются машинными критериями, например калибровка, согласие и синхронизация временных меток, отражаются как причины отклонения в [отчёте о покрытии](/docs/ru/fleet-learning/coverage.md). См. [Принятый час](/docs/ru/fleet-learning/accepted-hour.md).

## Чтение и запись меток результата

REST-эндпоинты расположены под `https://api.avala.ai/api/v1`:

| Метод и путь | Что делает |
| - | - |
| `GET /datasets/{owner}/{slug}/sequences/{sequence_uid}/outcome/` | Текущая метка одной последовательности. `404`, если метки нет. |
| `PUT /datasets/{owner}/{slug}/sequences/{sequence_uid}/outcome/` | Записывает новую текущую метку. |
| `GET /datasets/{owner}/{slug}/sequences/{sequence_uid}/outcome/history/` | Все версии метки, от новых к старым. |
| `GET /datasets/{owner}/{slug}/sequence-outcomes/` | Текущие метки в наборе данных, с пагинацией. |

Список по набору данных принимает фильтры `outcome`, `evaluation_membership`, `source` и `autonomy_level`. Каждый принимает одно значение или список через запятую, и последовательность подходит, если совпадает с любым значением из списка. `model_version` совпадает с одной точной версией. Неизвестное значение фильтра возвращает `400`.

Список последовательностей, `GET /datasets/{owner}/{slug}/sequences/`, принимает `outcome` и `evaluation_membership` в том же виде. Он возвращает последовательности, текущая метка которых подходит под фильтр.

### Запись метки

```bash cURL theme={null}
curl -X PUT \
  "https://api.avala.ai/api/v1/datasets/your-org/kitchen-rollouts/sequences/<sequence-uid>/outcome/" \
  -H "X-Avala-Api-Key: $AVALA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "outcome": "failure",
    "progress": 0.4,
    "subtasks": [
      { "label": "Place the plate in the lower rack", "start_ts": 0.0, "end_ts": 21.5, "outcome": "failure" }
    ],
    "mistake_type": "slip_during_place",
    "failure_stage": "place",
    "autonomy_level": "autonomous",
    "model_version": "your-policy@2026-09-20",
    "evaluation_membership": "held_out_eval",
    "source": "imported",
    "source_metadata": { "importer": "your-eval-harness", "run_id": "r42", "task": "load_dishwasher" }
  }'
```

```python Python theme={null}
from avala import Client

client = Client()  # reads AVALA_API_KEY

label = client.sequence_outcomes.set(
    "your-org",
    "kitchen-rollouts",
    "<sequence-uid>",
    outcome="failure",
    progress=0.4,
    subtasks=[
        {"label": "Place the plate in the lower rack", "start_ts": 0.0, "end_ts": 21.5, "outcome": "failure"},
    ],
    mistake_type="slip_during_place",
    failure_stage="place",
    autonomy_level="autonomous",
    model_version="your-policy@2026-09-20",
    evaluation_membership="held_out_eval",
    source="imported",
    source_metadata={"importer": "your-eval-harness", "run_id": "r42", "task": "load_dishwasher"},
)
print(label.version, label.outcome)
```

```typescript TypeScript theme={null}
import Avala from "@avala-ai/sdk";

const avala = new Avala(); // reads AVALA_API_KEY

const label = await avala.sequenceOutcomes.set("your-org", "kitchen-rollouts", "<sequence-uid>", {
  outcome: "failure",
  progress: 0.4,
  subtasks: [{ label: "Place the plate in the lower rack", startTs: 0.0, endTs: 21.5, outcome: "failure" }],
  mistakeType: "slip_during_place",
  failureStage: "place",
  autonomyLevel: "autonomous",
  modelVersion: "your-policy@2026-09-20",
  evaluationMembership: "held_out_eval",
  source: "imported",
  sourceMetadata: { importer: "your-eval-harness", run_id: "r42", task: "load_dishwasher" },
});
console.log(label.version, label.outcome);
```

```bash CLI theme={null}
avala sequence-outcomes set your-org kitchen-rollouts <sequence-uid> \
  --outcome failure \
  --progress 0.4 \
  --subtasks-file subtasks.json \
  --mistake-type slip_during_place \
  --failure-stage place \
  --autonomy-level autonomous \
  --model-version your-policy@2026-09-20 \
  --evaluation-membership held_out_eval \
  --source imported \
  --source-metadata '{"importer": "your-eval-harness", "run_id": "r42", "task": "load_dishwasher"}'
```

TypeScript SDK принимает имена параметров в camelCase и отправляет поля API в snake\_case. Ключи внутри `sourceMetadata` отправляются в том виде, в каком они записаны. В CLI `--hand-actions-file` принимает JSON-файл с `{"left": [...], "right": [...]}`, а `--leakage-group KEY=ID` можно указывать несколько раз.

### Чтение меток

```bash cURL theme={null}
# Current label of one sequence
curl "https://api.avala.ai/api/v1/datasets/your-org/kitchen-rollouts/sequences/<sequence-uid>/outcome/" \
  -H "X-Avala-Api-Key: $AVALA_API_KEY"

# Every version, newest first
curl "https://api.avala.ai/api/v1/datasets/your-org/kitchen-rollouts/sequences/<sequence-uid>/outcome/history/" \
  -H "X-Avala-Api-Key: $AVALA_API_KEY"

# Failed or aborted held-out sequences
curl "https://api.avala.ai/api/v1/datasets/your-org/kitchen-rollouts/sequence-outcomes/?outcome=failure,aborted&evaluation_membership=held_out_eval" \
  -H "X-Avala-Api-Key: $AVALA_API_KEY"

# The sequences themselves, filtered by their current label
curl "https://api.avala.ai/api/v1/datasets/your-org/kitchen-rollouts/sequences/?outcome=mistake_and_recovery,intervention" \
  -H "X-Avala-Api-Key: $AVALA_API_KEY"
```

```python Python theme={null}
from avala import Client

client = Client()

label = client.sequence_outcomes.get("your-org", "kitchen-rollouts", "<sequence-uid>")
versions = client.sequence_outcomes.history("your-org", "kitchen-rollouts", "<sequence-uid>")

page = client.sequence_outcomes.list(
    "your-org",
    "kitchen-rollouts",
    outcome=["failure", "aborted"],
    evaluation_membership="held_out_eval",
    model_version="your-policy@2026-09-20",
)
for item in page:
    print(item.sequence_uid, item.outcome, item.progress)
```

```typescript TypeScript theme={null}
import Avala from "@avala-ai/sdk";

const avala = new Avala();

const label = await avala.sequenceOutcomes.get("your-org", "kitchen-rollouts", "<sequence-uid>");
const versions = await avala.sequenceOutcomes.history("your-org", "kitchen-rollouts", "<sequence-uid>");

const page = await avala.sequenceOutcomes.list("your-org", "kitchen-rollouts", {
  outcome: ["failure", "aborted"],
  evaluationMembership: "held_out_eval",
  modelVersion: "your-policy@2026-09-20",
});
for (const item of page.items) {
  console.log(item.sequenceUid, item.outcome, item.progress);
}
```

```bash CLI theme={null}
avala sequence-outcomes get your-org kitchen-rollouts <sequence-uid>
avala sequence-outcomes history your-org kitchen-rollouts <sequence-uid>
avala sequence-outcomes list your-org kitchen-rollouts \
  --outcome failure,aborted \
  --evaluation-membership held_out_eval
```

Список по набору данных возвращает до 100 меток на страницу. Чтобы продолжить, передайте `cursor` из предыдущей страницы.

### Чтение меток через MCP-сервер

MCP-сервер читает метки результата. Записывать их он не может.

* `get_sequence_outcome` принимает `owner`, `slug` и `sequenceUid`. Он возвращает текущую метку.
* `list_sequence_outcomes` принимает `owner` и `slug`, фильтры `outcome`, `evaluationMembership`, `source`, `autonomyLevel` и `modelVersion`, а также `limit` и `cursor`.

Оба инструмента по умолчанию возвращают краткую форму. Передайте `detail: "full"`, чтобы включить подзадачи, действия рук, теги ошибки и восстановления, группы утечки, метаданные источника и автора метки. См. [Использование Avala с ИИ](/docs/ru/getting-started/mcp.md), чтобы подключиться.

## Экспорт меток результата вместе с LeRobot

Экспортёр LeRobot может записать текущую метку результата каждой последовательности рядом с набором данных. Одна последовательность Avala становится одним эпизодом LeRobot.

```bash CLI theme={null}
avala lerobot export your-org/kitchen-rollouts \
  --repo-id your-hf-user/kitchen-rollouts \
  --output ./lerobot-out \
  --include-outcomes
```

```python Python theme={null}
from avala import Client
from avala.lerobot import export_dataset

export_dataset(
    Client(),
    "your-org",
    "kitchen-rollouts",
    repo_id="your-hf-user/kitchen-rollouts",
    output_dir="./lerobot-out",
    include_outcomes=True,
)
```

Метки записываются в `meta/avala_sequence_outcomes.jsonl`: один JSON-объект на строку и одна строка на каждый сохранённый эпизод LeRobot. В собственной таблице эпизодов LeRobot нет места для этих метаданных, поэтому они вынесены в отдельный файл. Каждая строка содержит следующие ключи:

| Ключ | Значение |
| - | - |
| `episode_index` | Индекс эпизода LeRobot. |
| `avala_sequence_uid` | Последовательность Avala, из которой получен эпизод. |
| `outcome` | Значение результата или `null`, если у последовательности нет метки. |
| `outcome_version` | Экспортированная версия метки. |
| `progress`, `quality`, `speed` | Как в метке. |
| `subtasks`, `hand_actions` | Как в метке. Временные метки указаны в секундах от начала эпизода. |
| `mistake_type`, `recovery_type`, `failure_stage`, `autonomy_level`, `model_version`, `evaluation_membership` | Как в метке, с `null` вместо пустого значения. |
| `leakage_groups` | Как в метке. |
| `outcome_source`, `outcome_source_metadata`, `outcome_confidence` | Поля `source`, `source_metadata` и `confidence` метки. |

Последовательность без метки получает строку только с `episode_index`, `avala_sequence_uid` и `"outcome": null`.

## Линия сбоев и восстановления

Сбои с восстановлением поставляются отдельной линией: это последовательности с результатом `mistake_and_recovery` или `intervention`. Подзадачи и действия рук каждой последовательности отмечают, где происходят сбой и восстановление.

Линия поставляется в релизе отдельным срезом. Вы можете обучать на ней модель, задавать ей вес или исключить её. Вы также можете сами собрать такой же набор с помощью `?outcome=mistake_and_recovery,intervention`. Небезопасные последовательности в линию не входят.
