Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Следующая версия
Предыдущая версия
tech:toloka [2022/03/22 05:59]
dmitry_kalashnikov создано
tech:toloka [2024/02/10 00:12] (текущий)
anastasia_melnikova [Сохранение артефактов]
Строка 1: Строка 1:
-====== Тестирование диктанта в Яндекс.Толоке ======+====== Яндекс.Задания — тестирование диктанта ======
  
 ===== Вводные ===== ===== Вводные =====
  
  
-**Цель**: получение текстов разнообразных вариантов написания диктанта для построения тепловой карты ошибок с последующим анализом возможных ошибок/вариантов и корректировки разметки.+**Цель**: получение текстов разнообразных вариантов написания диктанта для построения [[dictations/statistics/heatmap|тепловой карты ошибок]] с последующим анализом возможных ошибок/вариантов и корректировки разметки.
  
 **Ограничение**: цельный текст диктанта под секретом, нельзя его полностью показывать отдельному человеку. **Ограничение**: цельный текст диктанта под секретом, нельзя его полностью показывать отдельному человеку.
  
-**Решение**: предлагать пользователям сервиса "Яндекс.Толока" писать отдельные предложения под диктовку, а затем склеивать результаты в единые тексты, затем формировать архив для импорта.+**Решение**: предлагать пользователям сервиса "Яндекс.Заданий" писать отдельные предложения под диктовку, а затем склеивать результаты в единые тексты, затем формировать [[tech/import|архив для импорта]].
  
 ===== Описание решения ===== ===== Описание решения =====
Строка 15: Строка 15:
  
 Зарегистрируйтесь в сервисе  Зарегистрируйтесь в сервисе 
-[[https://toloka.yandex.ru/|Яндекс.Толока]] в качестве заказчика.+[[https://tasks.yandex.ru//|Яндекс.Задания]] в качестве заказчика.
  
 ==== Пополнение баланса ==== ==== Пополнение баланса ====
  
-Пополните баланс на нужную сумму (в долларах). Примерная экономика: 3 цента за предложение. В диктанте в среднем 15-20 предложений, следовательно, одно написание будет стоить от 45 до 60 центов.+Пополните баланс на нужную сумму (в рублях). Примерная экономика: 1,85 ₽ за предложение. В диктанте в среднем 15-20 предложений, следовательно, одно написание будет стоить от 28 до 37 рублей.
  
 Можно пополнить баланс с расчётного счёта юрлица. Можно пополнить баланс с расчётного счёта юрлица.
Строка 25: Строка 25:
 ==== Формирование проекта ==== ==== Формирование проекта ====
  
-Создайте новый проект.+Создайте [[https://tasks.yandex.ru/requester/templates|новый проект]]. Шаблон: "Аудио → Расшифровка аудиозаписей"
  
-**Название**: "Напишите предложение из школьного диктанта".+**Название для исполнителей**: "Напишите предложение из школьного диктанта".
  
 **Описание для исполнителей**: "Нужно послушать и записать предложение со всеми знаками препинания, опираясь на собственную грамотность". **Описание для исполнителей**: "Нужно послушать и записать предложение со всеми знаками препинания, опираясь на собственную грамотность".
  
-**Интерфейс задания**:+**Интерфейс задания** → Конструктор шаблонов → Конфигурациявставить json из поля ниже.
  
 <code javascript json> <code javascript json>
Строка 78: Строка 78:
 **Инструкция для исполнителей** **Инструкция для исполнителей**
  
 +В поле "Инструкция для исполнителей" вставляется инструкция:
 <code> <code>
 Используйте наушники для прослушивания аудиозаписи. Используйте наушники для прослушивания аудиозаписи.
Строка 87: Строка 88:
 * Предложение начинается с заглавной буквы. * Предложение начинается с заглавной буквы.
  
-Задание будет отклонено, если Ваш текст совсем не похож на продиктованный.''+Задание будет отклонено, если Ваш текст совсем не похож на продиктованный.
 </code> </code>
  
 +После заполнения всех полей нажимается **Создать проект**.
 ==== Создание пула ==== ==== Создание пула ====
  
-Создаётся новый пул заданий, для каждого диктанта отдельный. Называние, например, "Диктант 1".+Создаётся новый пул заданий ("Добавить пул"), для каждого диктанта отдельный. Называние пишется в поле "Название пула (доступно только вам)", например, "Диктант 1" (название текущего диктанта). В публичное описание вставляется инструкция для исполнителей задания (например, //Внимательно послушайте и запишите предложение со всеми знаками препинания, опираясь только на собственную грамотность (без словарей, справочников и поисковиков)//).
  
-Выставляется русский язык. Принимаются только исполнители, сдавшие тест на знание языка+На странице пула выставляются следующие параметры: 
-Выбирается, например, топ 50% лучших исполнителей.+  * В поле **"Аудитория"** убирается галочка "В моих заданиях может содержаться шокирующий или порнографический контент", сохраняется опция "Языки" в поле "= Значение" выставляется "Русский". На шкале "Соотношение скорости и качества" выбирается, например, топ 60% лучших исполнителей. 
 +{{:tech:audience.png?600|}}
  
-Цена: $0,02+  * В поле **"Контроль качества"** удаляются поля "Учитывать последних страниц заданий... Минимальное время на страницу заданий", "Мнение большинства". Оставляется правило контроля качества **"Выполненные задания"**, там проставляются значения''Если отправленных страниц = 3то приостановить в пуле навсегда'' — для того, чтобы один человек смог увидеть не более трёх предложений диктанта. В **"Причина"** вписывается "Ответ получен"
 +{{:tech:quality_control.png?600|}}
  
-Контроль качества: перекрытие задания — ставится число написаний диктанта, которое нужно получить. Например100 написаний. +  * В окне **"Цена"** в поле ена за страницу заданий₽" выставляется цена 1,85, в поле ерекрытие" выставляется значение 120.  
-Добавляется правило контроля качества: ''если отправленных страниц заданий = 3, то приостановить в пуле навсегда'' — для того, чтобы один человек смог увидеть не более трёх предложений диктанта.+{{:tech:price.png?400|}}
  
-Тип пулаПул с обычными заданиями.+  * В расширенных настройках → Дополнительные настройки выбирается **"Время на страницу заданий, с"** — 600, **"Тип пула"** — Пул с обычными заданиями. Выбирается опция "Сохранять порядок заданий"
 +{{:tech:task-order.png?600|}}
  
-Поставить галочкусохранять порядок заданий. +==== Клонирование пула ==== 
 +Если в проекте есть пул, удовлетворяющий всем необходимым параметрам, его можно скопировать, чтобы не заполнять заново вручную все поля. Это можно сделать двумя способами: 
 +  - На странице проекта со всеми пулами заданий навести мышь на нужный и выбрать кнопку "Клонировать".// 
 +{{:tech:clone_1.png?800|}}// 
 +  - На странице выбранного пула в дополнительных опциях по кнопке "…" выбрать "Клонировать".// 
 +{{:tech:clone_02.png?800|}}//
  
 ==== Загрузка заданий ==== ==== Загрузка заданий ====
 +
 +Можно взять готовый [[https://docs.google.com/spreadsheets/d/1tVUvaM8ilou-GKqqeMVjZaqM2UWQnSynl0fpYWK9kuk/copy|шаблон]] или создать таблицу с нуля.
  
 Формируется таблица в гугл.документах (https://sheet.new/) с двумя листами: Формируется таблица в гугл.документах (https://sheet.new/) с двумя листами:
Строка 112: Строка 124:
   * OUTPUT   * OUTPUT
  
-На листе //INPUT// добавляется в ячейку A1 строка ''INPUT:audio''. Ниже вставляются ссылки на аудиофайлы предложений в прямом порядке. Ссылки можно получить в Учительской → Диктовка → Предложение → Скачать звуковой файл фрагмента+На листе //INPUT// добавляется в ячейку A1 строка ''INPUT:audio'' 
 + 
 +Ниже вставляются ссылки на аудиофайлы предложений в прямом порядке. Ссылки на предложения можно получить в Учительской: страница диктанта → Страница диктовки → кнопка "Скачать" → "Скачать предложения". 
 Примерно так должен выглядеть лист: Примерно так должен выглядеть лист:
  
 {{:tech:toloka_input.png|}} {{:tech:toloka_input.png|}}
  
-Далеес листа копируется первый столбец и вставляется в текстовый файл. Каждая ссылка разделяется пустой строкой:+Далее с листа копируется первый столбец и вставляется в текстовый файл. Каждая ссылка разделяется пустой строкой:
 <code> <code>
 INPUT:audio INPUT:audio
Строка 127: Строка 142:
 </code> </code>
  
-Файл сохраняется и загружается в текущий пул задач (кнопка "Загрузить"). Количество заданий на странице выбирается как "По пустой строке". +Файл сохраняется с расширением ''.tsv'' и загружается в текущий пул задач (кнопка **"Загрузить задания"**).
 ==== Запуск пула ==== ==== Запуск пула ====
  
-Разметка запускается и можно попить кофепока толокеры выполняют задания.+На странице пула нажимается кнопка **"Запустить разметку"**. 
 +После модерации проект будет запущен и откроется исполнителям. 
 +==== Получение результатов написания ====
  
-==== Получение результатов ====+После выполнения всех заданий можно скачать результаты по кнопке "Скачать результаты" в пуле. В окне скачивания выбираются только статусы "Принятые" и "ID Исполнителя".
  
-По окончании разметки можно скачать результаты по одноимённой кнопке в пуле. В окне скачивания выбирается только статус "Принятые" без полей и разделения ответов пустой строкой.+{{:tech:results.png?400|}}
  
-Данные из скачанного файла импортируются в таблицу, на лист //OUTPUT// так, чтобы в каждой строке была ссылка на аудиофайл и текст результата:+Данные из скачанного файла импортируются в таблицу, на лист //OUTPUT// так, чтобы в каждой строке была ссылка на аудиофайлтекст результата и ID толокера:
  
 {{:tech:toloka_output.png|}} {{:tech:toloka_output.png|}}
  
 +==== Анализ результатов написания ====
 +
 +1. Значения сортируются по столбцу с "ID толокера" (столбец "C").\\ 
 +2. Для всех недобросовестных толокеров, явно не старавшихся написать предложения, в столбце "D" пишется слово "бан" (для последующей фильтрации).\\ 
 +3. С помощью фильтра по значению "бан" (в столбце "D") копируются в новый лист с названием "BAN" все строки.\\ 
 +4. В листе "BAN" по столбцу "C" удаляются все повторы, чтобы в "ID толокеров" не осталось дублей.\\ 
 +{{:tech:doubles.png?600|}}\\ 
 +5. Столбец с "ID толокеров" без первой строки сохраняется в новую таблицу типа ''ban.csv''.\\ 
 +6. На странице [[https://tasks.yandex.ru/requester/workers?ban=REQUESTER_BAN|Пользователи]] через "Загрузить файл" (1) загружается получившаяся csv-таблица. При загрузке списка пользователей нажимается "Добавить". На открывшейся странице с пользователями выбирается кнопка "Заблокировать" (2), место блокировки в открывшемся окне — "У меня".\\ 
 +{{:tech:ban_01.jpg?350|}}\\
 +{{:tech:ban_02.jpg?700|}}\\
 +7. В изначальном листе с помощью фильтра выбираются все строки //без// значения "бан", копируются и вставляются в новый лист с названием "OUTPUT". Старый лист удаляется.\\ 
 +8. Все строки сортируются по столбцу "B" ("Сортировать А > Я"), чтобы было проще убирать лишнее: удаляются пустые строки, обрывочные написания, незаконченные предложения (пропуск двух и более слов).\\ 
 +
 +После анализа таблица готова для работы скрипта по формированию текстов диктанта.
 +==== Подготовка скрипта слияния ====
 +
 +В среде [[https://script.google.com/home|AppsScript]] создаётся новый проект (или можно запросить доступ к [[https://script.google.com/home/projects/1sb3IJs9TO9mGaAsjrr8hkKV1D1c7S8iYRUxDSPDRMJLxOVGQYF8Amlp_/edit|готовому проекту]]). Вставляется следующий код ниже.
 +
 +
 +<code javascript js>
 +//--------------------------------------------------------------------------------------------
 +//                        ---=== основные параметры скрипта ===---
 +//
 +// URL таблицы с данными по диктанту в нужном формате: два листа INPUT, OUTPUT. 
 +// В первом упорядоченные ссылки на звуковые фрагменты по предложениям, во втором результаты из Толоки
 +const sheetName = 'https://docs.google.com/spreadsheets/d/1fbP4rylF5ryZS905D2xlgA9qhRimD6IxpHPR-bbz3tE/edit'; 
 +//
 +// id директории, куда сохранять файлы диктантов (берётся из URL'а https://drive.google.com/drive/folders/%id)
 +const folderSave = '1s9p2RBowh3hou94p_jDdJ1Zv4Ty7fqu-'; 
 +//
 +//id диктанта из Учительской (берётся из URL'а диктанта)
 +const dictId = '61f8e9a6a5fd104693b9646d'; 
 +//--------------------------------------------------------------------------------------------
 +
 +function RunImport() { 
 +  Logger.log("Запуск скрипта формирования текстов диктантов из результатов Яндекс.Толоки...");  //https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app
 +  
 +
 +  var sheetDict = SpreadsheetApp.openByUrl(sheetName); 
 +  Logger.log('Получен доступ к гугл.таблице "%s"', sheetDict.getName());
 +  var dictFolder = DriveApp.getFolderById(folderSave); 
 +  Logger.log('Получен доступ к директории "%s"', dictFolder.getName());
 +
 +  var range = sheetDict.getRange("INPUT!A2:A100");  //задаём название листа и интервал со значениями ссылок на диктовки предложений (задания в Толоке)
 +  var sentencesIds = getSentenceIds(range.getValues());  
 +  var range = sheetDict.getRange("OUTPUT!A2:B"); //задаём название листа и интервал со значениями результатов Толоки  
 +  mergeResults(range.getValues(), sentencesIds, dictFolder);  
 +  Logger.log("Готово!");        
 +};
 +
 +function saveDict(text, dictFolder){  
 +  var fileName = dictId + '_' + createUUID() + '.txt';
 +  dictFolder.createFile(fileName, text);  
 +  Logger.log('диктант "%s" сохранён (размер %d символов)', fileName, text.length);  
 +}
 +
 +function mergeResults(valuesInput, sentencesIds, dictFolder){
 +  var dictText = [];
 +  var link = '';
 +  var text = '';
 +  var idx = -1;
 +
 +  for (var i = 0,countLines = valuesInput.length; i < countLines; i++)   {
 +   link =  valuesInput[i][0].trim();
 +   text = valuesInput[i][1].trim();
 +    
 +   if (link.length > 2 && text.length > 2) {
 +     idx = sentencesIds.indexOf(link);
 +     if (idx == -1) { 
 +       Logger.log('В таблице предложений не найден элемент со ссылкой %s', link) 
 +     } else {
 +       if (dictText[idx] == null) {
 +         dictText[idx] = text;
 +         valuesInput[i][0] = '?';
 +         valuesInput[i][1] = '?';
 +         if (Object.keys(dictText).length == sentencesIds.length) 
 +         {
 +           var fullText = dictText.join(" ");           
 +           saveDict(fullText, dictFolder);
 +           dictText.length = 0;           
 +           i = 0;
 +         }
 +       }
 +     }
 +   }  
 +  }    
 +}
 +
 +// получение массива id предложений по ссылкам на аудиозаписи
 +function getSentenceIds(valuesInput){
 +
 +  var sentencesIds = [];
 +  for (var i = 0,countLines = valuesInput.length; i < countLines; i++)   {
 +   if (valuesInput[i][0].length > 1) {
 +     sentencesIds.push(valuesInput[i][0].trim())
 +   }
 +  }
 +  return (sentencesIds)
 +}
 +
 +function createUUID() {
 +    // http://www.ietf.org/rfc/rfc4122.txt
 +    var s = [];
 +    var hexDigits = "0123456789abcdef";
 +    for (var i = 0; i < 36; i++) {
 +        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
 +    }
 +    s[14] = "4";  
 +    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);  
 +    //s[8] = s[13] = s[18] = s[23] = "-";
 +
 +    var uuid = s.join("");
 +    return uuid;
 +}
 +</code>
 +
 +В начале, в секции "основные параметры скрипта", прописываются нужные значения: ID таблицы с результатами, ID папки для сохранения текстовых файлов, ID диктанта. Подробные пояснения в комментариях скрипта.
 +
 +После заполнения нужных параметров нажимается команда "Выполнить".
 +
 +==== Получение архива с текстами диктантов ====
 +
 +Через некоторое время появляются результаты в указанной папке на Гугл.Диске. Внутри папки выделяются все файлы и через контекстное меню скачивается архив:
 +
 +{{:tech:toloka_download.png?400|}}
 +
 +Архив импортируется в Учительскую в [[tech/import#format_importa_tekstov|формате для импорта]].
 +
 +===== Сохранение артефактов =====
  
 +В комментарии к Редмайн-задаче даётся ссылка на гугл-таблицу, ссылка на "Карту ошибок", прикрепляется zip-архив с текстами из Яндекс.Заданий.
  • /opt/bitnami/dokuwiki/data/attic/tech/toloka.1647928753.txt.gz
  • Последнее изменение: 2022/03/22 05:59
  • dmitry_kalashnikov