7 октября 2019

Стандарт электронного обучения xAPI (Tin Can API)

Что это, для чего нужен и в чем преимущество, принцип работы LRS, структура стейтментов
Олег Буйлов
Разработчик LEVEL
Более пяти лет занимается сборкой электронных курсов, настройкой систем дистанционного обучения (LMS) и учебной аналитикой.
Электронные курсы и системы дистанционного обучения (далее СДО) обычно взаимодействуют по стандарту SCORM. Однако
за 20 лет существования этот формат технически устарел. В последние годы компании могут выбирать в качестве альтернативы новый стандарт — xAPI, который позволяет собрать больше данных по обучению.

Что такое xAPI

xAPI (сокращенно от Experience API, ранее Tin Can API) — это открытая спецификация, которая описывает формат передачи статистики между курсом / сайтом / приложением / любым другим провайдером учебной активности и базой данных — LRS (Learning Record Store, хранилище учебных активностей).

Разработка спецификации началась в 2009 году после прекращения работы над SCORM, первая версия вышла
в 2013 году. Формат SCORM был признан устаревшим по двум причинам:

  • Технические возможности. Проблемы с безопасностью; использование XML, а не JSON; лимиты в сохранении прогресса по курсу; ограничения в использовании SCORM-пакетов за пределами текущего домена; неудобство использования контента только в виде iframe.

  • Учебная концепция. SCORM предполагает обучение только через загружаемые электронные курсы в LMS. Это все еще распространенный и понятный способ организации электронного обучения, но он не позволяет фиксировать учебный опыт в мобильных приложениях, AR/VR, чат-ботах, соцсетях и даже внутри курсов, разработанных в самой СДО. Часто у компании есть несколько LMS в разных подразделениях или обучение происходит за пределами своей LMS — на площадках провайдеров, MOOC-платформах. Это приводит к отсутствию комплексной учебной аналитики: могут быть отдельные отчеты по SCORM-пакетам, отдельная админ-панель для чат-бота, отдельный кабинет руководителя на платформе с онлайн-курсами и т. п.

Для чего нужен xAPI

Использование xAPI позволяет фиксировать в одном месте и одной структуре данных любой учебный опыт.

Это стало возможным благодаря использованию REST API вместо устаревшего подхода «открыли в LMS окно с курсом > SCORM-сессия поднялась, данные записываются > закрыли окно > SCORM-сессия прекратилась». REST API лежит в основе работы большинства сайтов и мобильных приложений, он позволяет пользоваться функциями веб-сервисов откуда угодно, например, получить прогноз погоды не только на сайте (как было на заре интернета), но и на экране умных часов.

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

С точки зрения разработчиков электронных курсов, xAPI — более простая и современная спецификация, чем SCORM. Добавить поддержку xAPI в курс легче, чем поддержку SCORM. При использовании инструментов быстрой разработки (Articulate, iSpring) почти нет разницы, в каком формате публиковать курс, но ситуация обстоит иначе с разработчиками нестандартного контента — учебных симуляций, приложений и т. п. Они изначально не могли использовать SCORM из-за его ограниченных возможностей и поэтому вели разработку, самостоятельно определяя технологии, структуру данных, делали собственные форматы отчетов для заказчиков. Для таких разработчиков xAPI скорее является ограничением: они и так могут написать свое API без использования постороннего.

Но рассматривать xAPI нужно не как технологию, а как договоренность между основными представителями e-learning рынка.

Если заказчик заинтересован в развитии экосистемы, он будет отдавать преимущество провайдерам, которые ей соответствуют. Например, компания WebSoft добавила в наиболее распространенную российскую LMS — WebTutor — функциональность LRS и рекомендует интегрироваться с внешними провайдерами посредством xAPI.

Плюс xAPI

Это универсальный стандарт, который позволяет построить учебную экосистему. Его поддерживают многие поставщики программного обеспечения для разработки электронных курсов, СДО, аналитических инструментов. Компании могут приобрести xAPI-совместимую платформу обучения и сотрудничать с теми провайдерами учебного контента, которые тоже используют xAPI.

Минус xAPI

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

Как работает LRS

LRS может быть отдельным модулем внутри LMS или автономной системой ー это непринципиальная разница. Есть LRS, написанные на NodeJS и MongoDB, на PHP и MySQL, на Java. Наиболее распространенная open sourse LRS ー Learning Locker, ее используют в Сбербанке, Газпроме, Ростелекоме. Есть другие, например, Veracity.

Все LRS работают примерно одинаково: они принимают и передают по API запросы и следят за их корректностью. Если запросы содержат ошибку или неправильно сформированы, то будут отклонены. Но это уже немало: существует специальный инструмент LRS Conformance Test Suite, который проверяет LRS более чем по 1300 параметрам. В отличие от LMS, нет большого смысла в разнообразии LRS и нет необходимости каждому провайдеру разрабатывать «свою». Во-первых, это сложно, во-вторых, она все равно обычно является невидимым для пользователей звеном.

Любая LRS должна иметь несколько определенных endpoint ー url-адресов для отправки запросов. Основной endpoint обычно такого вида: https://learninglocker.ru/data/xAPI/statements. По подобному адресу провайдеры активности (электронный курс, игра, приложение и т. д.) отправляют GET-запросы с логами изучения контента (statements). Стейтменты имеют обязательную, но в то же время гибкую структуру. Один стейтмент равен одному действию. Стейтмент должен содержать информацию о пользователе (actor), его действии (verb) и объекте (object), условно: «Иван Иванов запустил курс», «Иван Иванов изучил слайд 1». В формате JSON это выглядит так:

{
   "actor": {
      "name": "Иван Иванов",
      "mbox": "mailto:ivanov@mail.ru"
   },
   "verb": {
      "id": "http://adlnet.gov/expapi/verbs/attempted",
      "display": {
         "en-US": "attempted"
      }
   },
   "object": {
      "id": "http://mylms.com/activities/course1",
      "definition": {
         "name": {
            "en-US": "Курс 1"
         }
      }
   }
}

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

{
   "actor": {
      "mbox": "mailto:develop@develop.com",
      "name": "Develop",
      "objectType": "Agent"
   },
   "verb": {
      "id": "http://adlnet.gov/expapi/verbs/answered",
      "display": {
         "en-US": "answered"
      }
   },
   "result": {
      "response": "0-var",
      "success": true,
      "score": {
         "min": 0,
         "max": 2,
         "raw": 2,
         "scaled": 1
      }
   },
   "object": {
      "id": "http://bot.cyb.openstart.ru/quizzes/test-2/&id=4",
      "definition": {
         "name": {
            "en-US": "Содержание вопроса 1"
         },
         "description": {
            "en-US": "Содержание вопроса 1"
         },
         "type": "http://adlnet.gov/expapi/activities/cmi.interactio…",
         "interactionType": "choice",
         "correctResponsesPattern": [
            "0-var"
         ],
         "choices": [
            {
               "id": "0-var",
               "description": {
                  "en-US": "Вариант ответа 1"
               }
            },
            {
               "id": "1-var",
               "description": {
                  "en-US": "Вариант ответа 2"
               }
            }
         ]
      },
      "objectType": "Activity"
   },
   "context": {
      "contextActivities": {
         "parent": {
            "id": "http://bot.cyb.openstart.ru/quizzes/test-2/",
            "definition": {
               "name": {
                  "en-US": "Тест 2"
               },
               "description": {
                  "en-US": "Тест 2"
               },
               "type": "http://adlnet.gov/expapi/activities/assessment"
            },
            "objectType": "Activity"
         },
         "grouping": {
            "id": false,
            "definition": {
               "name": "en-US"
            },
            "description": "en-US"
         },
         "type": "http://adlnet.gov/expapi/activities/course"
      },
      "objectType": "Activity"
   },
   "id": "ca4d5fa3−4c17−4047−8804−29f605e0d192",
   "stored": "2017−12−16T17:18:16.429Z",
   "timestamp": "2017−12−16T17:18:16.429Z",
   "authority": {
      "account": {
         "homePage": "https://grassblade.ru/xAPI/",
         "name": "17−31023ca8243b9fc"
      },
      "objectType": "Agent"
   }
}
Такие логи создаются на каждое действие пользователя: за время прохождения среднего курса из 40−50 слайдов и теста может быть сгенерировано до нескольких сотен стейтментов. При большом количестве учащихся за несколько лет могут быть накоплены миллиарды стейтментов — те самые большие данные об обучении.

Структура стейтментов

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

Actor
Это идентификатор пользователя. В нем может быть указан email или логин пользователя в какой-то системе, например, в СДО.

«actor»:{  
   «mbox»:«mailto:develop@develop.com»,
   «name»:«Develop»,
   «objectType»:«Agent»
},
Verb
Это тип действия пользователя: начал, закончил, прошел, ответил и т. д. Можно указать любой, но рекомендуется использовать существующие термины из специального реестра.

Например, в большинстве электронных курсов используется глагол passed, когда пользователь сдал тест.

«verb»:{  
   «id»:«http://adlnet.gov/expapi/verbs/answered»,
   «display»:{  
      «en-US»:«answered»
   }
Подпишитесь на нашу рассылку и получайте свежие новости два раза в месяц

Если вы нажали на кнопку, вы согласны с политикой конфиденциальности.
Object
Это идентификатор учебной активности. Причем имеется в виду не весь курс, а отдельный элемент — блок, слайд, страница, хоть даже отдельная картинка. Обычно уровень дробления прослеживается с помощью слеша.

Например:
http://bot.cyb.openstart.ru — курс,
http://bot.cyb.openstart.ru/quizzes — тестирование в рамках курса,
http://bot.cyb.openstart.ru/quizzes/test-2 — конкретный банк вопросов,
http://bot.cyb.openstart.ru/quizzes/test-2/id-4#nb.....— конкретный вопрос в банке.

Object также включает читаемое название, описание, тип, а если этот тип — вопрос, то еще и варианты ответа с идентификаторами и описаниями. Такая структуризация очень удобна при анализе данных.

"object":{  
   "id":"http://bot.cyb.openstart.ru/quizzes/test-2/&id=4",
   "definition":{  
      "name":{  
         "en-US":"Содержание вопроса 1"
      },
      "description":{  
         "en-US":"Содержание вопроса 1"
      },
      "type":"http://adlnet.gov/expapi/activities/cmi.interaction",
      "interactionType":"choice",
      "correctResponsesPattern":[  
         "0-var"
      ],
      "choices":[  
         {  
            "id":"0-var",
            "description":{  
               "en-US":"Вариант ответа 1"
            }
         },
         {  
            "id":"1-var",
            "description":{  
               "en-US":"Вариант ответа 2"
            }
         }
      ]
   },
   "objectType":"Activity"
},
A
Context
Тут описываются условия, при которых произошла учебная активность. В данном примере указаны только два условия: родительская активность и группировка. Они позволяют фильтровать стейтменты согласно структуре дробления контента. Помимо этого, в контексте можно указывать:



  • Регистрацию (идентификатор учебной сессии, чтобы фиксировать отдельные попытки прохождения);
  • Категорию (тип контента — аудио, видео, книга, тренажер и т. п.);
  • Руководителя и участников группы (для офлайн обучения, прохождения вебинара);
  • Платформу, где проходит обучение.

"context":{  
   "contextActivities":{  
      "parent":{  
         "id":"http://bot.cyb.openstart.ru/quizzes/test-2/",
         "definition":{  
            "name":{  
               "en-US":"Тест 2"
            },
            "description":{  
               "en-US":"Тест 2"
            },
            "type":"http://adlnet.gov/expapi/activities/assessment"
         },
         "objectType":"Activity"
      },
      "grouping":{  
         "id":false,
         "definition":{  
            "name":"en-US"
         },
         "description":"en-US"
      },
      "type":"http://adlnet.gov/expapi/activities/course"
   },
   "objectType":"Activity"
},
Также есть возможность указать произвольные поля (Extensions), не определенные стандартом: геопозицию пользователя, используемый девайс, скорость интернета, объем изучаемого блока и т. п. Например, для аналитики по просмотру видео в extensions добавляют такие поля:

"contextExt:viewId":"id1",
"contextExt:videoDuration":"PT108.483S",
"contextExt:speed":1.0,
"contextExt:volume":100,
"contextExt:fullScreen":true,
"contextExt:quality":720,
"contextExt:screenSize":"1080x960",
"contextExt:focus":true,
Result
Это результат выполнения учебной активности, который может включать набранный балл, пользовательский ответ, продолжительность и дополнительные произвольные поля (если пользователь выполнил некое нестандартное действие в учебном контенте).

"result":{  
   "score":{  
      "scaled":1,
      "min":0,
      "max":100,
      "raw":100
   },
   "success":true,
   "completion":true,
   "response":"Example string",
   "duration":"P1DT12H",
   "extensions":{  
      "http://www.example.com/ext”:true"
   }
}
}
Attachments
Это поле позволяет вставлять ссылки на определенные файлы или встраивать их внутри стейтмента в закодированном формате.

Например, фотографии выполнения упражнения пользователем или PDF-сертификат.

{  
   "attachments":[  
      {  
         "contentType":"application/pdf",
         "usageType":"http://id.tincanapi.com/attachment/certificate-of-completion",
         "display":{  
            "en-US":"Completion of Experience API 101"
         },
         "description":{  
            "en-US":"Certificate provided as proof of completion of Experience API 101 course."
         },
         "length":63878,
         "sha2":"c2a36cbc4db66444d05e134b85a89681f65263cacd93eb4a544f0bef058a5649"
      }
   ]
}

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

"id":"ca4d5fa3-4c17-4047-8804-29f605e0d192",
"stored":"2017-12-16T17:18:16.429Z",
"timestamp":"2017-12-16T17:18:16.429Z",
"authority":{  
   "account":{  
      "homePage":"https://grassblade.ru/xAPI/",
      "name":"17-31023ca8243b9fc"
   },
Структура стейтментов дает много свободы для разработчиков в описании учебных событий. Чтобы была обеспечена максимальная совместимость между поставщиками учебного контента, существуют специальные профили данных (для просмотра видео, тренажеров VR, игр из Unity, выдачи бейджей). Самый крупный из таких профилей называется CMI5: он подходит для традиционных электронных курсов, которые раньше поддерживали SCORM.

Некоторые компании (например, Корпоративный институт Сбербанка) могут разработать необходимую им модель данных и указать провайдерам ее придерживаться. Пример модели данных, которую использует Articulate, описан на официальном сайте.

Еще нужно отметить, что LRS хранит не только стейтменты, но и учебный прогресс (State API). Курсы могут сохранять пользовательские переменные, закладки, как это реализовано в SCORM при помощи переменной suspend_data.
Это была первая часть статьи о xAPI. Во второй части расскажем об использовании данных из LRS, роли LMS и проблемах при построении xAPI экосистемы.
Дополнительно (на английском):

Спецификация xAPI на GitHub: https://github.com/adlnet/xAPI-Spec/blob/master/xAPI.md

Руководство по xAPI для менеджеров по дистанционному обучению: The_Learning_Technology_Managers_Guide_to_xAPI.pdf
Автор: олег буйлов
Поделиться