Перейти к содержимому

Общий кодбук для качественного кодирования

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

Кодбук в Potato — это список кодов, которые применяют кодировщики проекта. Potato хранит кодбук в базе данных проекта, а не в YAML-конфигурации. Схема подключается к кодбуку через codebook: true, и после этого варианты схемы берутся из кодбука. Кодировщик может добавить код посреди сессии, и никому не нужно править конфигурацию или перезапускать сервер. Коды могут располагаться под родительским кодом, а запись каждого кода состоит из типизированных полей, среди которых определение, правила включения и исключения и примеры. Potato помечает каждую сохранённую разметку номером ревизии кодбука, действовавшей в момент сохранения. Кодбук появился вместе с QDA Mode в Potato 2.6.0 и работает в обычной разметке, в Solo Mode и в QDA Mode.

Кодбук в качественном исследовании перечисляет коды, которые применяет команда, и указывает, когда применяется каждый код. MacQueen и соавторы (1998) утверждают, что кодбук с одной и той же фиксированной структурой для каждого кода даёт команде кодировщиков устойчивую рамку и повышает согласованность между кодировщиками. Potato даёт каждому коду один и тот же набор типизированных полей, от краткого определения до контрпримеров. Руководство по разработке кодбука описывает, как команда пишет и пересматривает эти записи.

Хранение и начальное заполнение кодбука

  • Хранение. Коды хранятся в <task_dir>/project.sqlite. Заметки и кейсы используют ту же базу данных проекта. YAML содержит только начальные метки.
  • Начальное заполнение. При первом запуске сервера Potato копирует labels каждой схемы с пометкой codebook: true в пустой кодбук. С этого момента источником истины служит база данных, и сервер игнорирует последующие правки меток в YAML.
  • Один кодбук на проект. Каждая схема с пометкой codebook: true показывает одни и те же коды. В проекте со схемой themes и схемой quotes обе схемы берут коды из одного списка.
  • Типы схем. radio, multiselect, select и span принимают codebook: true.
  • Ревизии. Добавление, переименование, смена цвета, перемещение, удаление, объединение или разделение кода увеличивает номер ревизии кодбука проекта на единицу. Potato записывает ревизию в каждую разметку, сохранённую после этого.
  • Где кодировщики видят кодбук. Переключатель Codebook у правого края страницы разметки открывает боковую панель со списком кодов и кратким определением каждого кода. Страница /codebook показывает полный кодбук со всеми полями всех кодов.

Конфигурация

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

yaml
annotation_task_name: Clinic Access Interviews
task_dir: .
output_annotation_dir: annotation_output/
data_files:
- data/interviews.json
item_properties:
  id_key: id
  text_key: text
user_config:
  allow_all_users: true
 
codebook_mode: extensible
 
annotation_schemes:
- annotation_type: span
  name: codes
  description: Highlight a passage and apply a code
  codebook: true
  labels:
  - name: access barriers
    color: "#4682b4"
    description: Anything the speaker names as standing between them and care they wanted.
  - name: cost concerns
    color: "#b44682"
    description: Money, insurance, or the fear of a bill.
ПараметрПо умолчаниюОписание
annotation_schemes[].codebookfalseБерёт варианты схемы из кодбука проекта.
annotation_schemes[].labels(нет)Заполняет пустой кодбук при первом запуске. Метка может быть строкой или объектом с name, color и description (или tooltip). Описание становится кратким определением кода.
codebook_modeopen, если qda_mode.enabled или solo_mode.enabled равно true, иначе fixedКто может менять коды: fixed, extensible или open. Имеет приоритет над codebook.mode, если заданы оба. Любое другое значение не проходит валидацию.
codebook.modeкак у codebook_modeВложенная запись codebook_mode.
codebook.enabledне заданоВключает или выключает боковую панель, страницу /codebook и API кодбука. Если параметр не задан, кодбук включается, когда какая-либо схема задаёт codebook: true, а также в QDA Mode или Solo Mode. В конфигурации, где задан codebook_mode, кодбук включён независимо от значения codebook.enabled.
codebook.distiller.include (или include_types)short_def, definition, use_when, avoid_when, example, counter_exampleКакие поля каждого кода попадают в текст, который Potato добавляет в промпты разметки с ICL.
codebook.distiller.include_doc_sectionspreamble, general_instructionsКакие разделы уровня всего кодбука попадают в тот же текст промпта.
codebook.distiller.scopeper_codeper_code добавляет поля каждого кода. whole_doc добавляет только разделы уровня всего кодбука.
codebook.distiller.procedureconcatКак собирается текст промпта. llm_summarize и select_icl_examples принимаются, но в 2.13.1 дают тот же результат, что и concat.
codebook.distiller.max_charsбез ограниченияОбрезает текст промпта до заданного числа символов.
codebook_invivo_keyiКлавиша, которая открывает окно кодирования in vivo, пока в схеме span на основе кодбука выделен текст. Учитывается только первый символ.

qda_mode.codebook.mode проходит валидацию. Potato 2.13.1 не читает этот ключ, когда решает, кто может редактировать коды. В QDA Mode задайте codebook_mode, чтобы изменить значение по умолчанию open.

Кто может менять коды

Что может делать вошедший в систему кодировщик, зависит от режима. Арбитр может вносить любые структурные изменения в режимах extensible и open. В режиме fixed ни кодировщики, ни арбитры не могут добавлять, переименовывать, перекрашивать, перемещать или удалять коды. Администраторы и арбитры по-прежнему могут объединять и разделять коды в разделе Curate боковой панели.

РежимКодировщики могутТипичное применение
fixedтолько применять кодыраунд проверки надёжности, краудсорсинг, кодбук, согласованный до начала кодирования
extensibleдобавлять кодыкомандное кодирование с согласованным ядром и местом для новых кодов
openдобавлять, переименовывать, перекрашивать, перемещать и удалять коды, а также править определенияодин аналитик или небольшая команда, которая разрабатывает кодбук вместе

Для любой краудсорсинговой конфигурации Potato фиксирует режим fixed и записывает предупреждение в журнал, если конфигурация запрашивала больше. Potato вводит эту блокировку, чтобы набранные разметчики не перекраивали общий кодбук. Блокировка действует при crowdsourcing.provider с любым значением, кроме expert, при верхнеуровневом блоке prolific: или mturk: и при login.type: prolific или mturk. Нераспознанное имя провайдера и пустое значение провайдера тоже блокируют режим.

crowdsourcing.provider: expert сохраняет запрошенный режим, потому что экспертов приглашают поимённо. login.type: url_direct сам по себе сохраняет запрошенный режим и записывает предупреждение. Любой, у кого есть ссылка на такое исследование, может зарегистрироваться и затем редактировать открытый кодбук.

В 2.13.1 у каждого вида изменений свой путь:

ИзменениеВ браузереЧерез APIКто
Добавить кодполе "Add a code" в боковой панели или клавиша in vivoPOST /api/codebookextensible или open
Переименовать, перекрасить или переместить под родителяв 2.13.1 элемента управления нетPATCH /api/codebook/<id>open или арбитр в extensible
Удалить кодв 2.13.1 элемента управления нетDELETE /api/codebook/<id>open или арбитр в extensible
Объединить один код с другимраздел Curate боковой панелиPOST /api/codebook/admin/mergeадминистратор или арбитр, в любом режиме
Разделить код по кодировщикураздел Curate боковой панелиPOST /api/codebook/admin/splitадминистратор или арбитр, в любом режиме
Изменить определение или добавить примеркарандаш у кода в боковой панели или /codebookPUT /api/codebook/blocksopen или арбитр в extensible. Правка любого другого пользователя встаёт в очередь на подтверждение администратором или арбитром.

Поле добавления в боковой панели создаёт код верхнего уровня. Код помещается под родителя через поле parent_id запроса POST или PATCH.

Кодирование in vivo по выделенному тексту

В схеме span с пометкой codebook: true кодировщик выделяет фрагмент и нажимает клавишу in vivo. Открывается небольшое окно с названием, взятым из выделенных слов (до 60 символов), и кнопка "Create & code" за один шаг добавляет код и выделяет фрагмент новым кодом. Пока кодировщик вводит название, существующие коды с похожими названиями появляются в виде плашек. Кодировщик, который выбирает плашку, применяет существующий код вместо того, чтобы создавать почти дубликат, например cost рядом с cost concerns.

Изменения, предложенные моделью

Модель никогда не меняет общий кодбук напрямую. Агент или модель в Solo Mode ставит изменение в очередь через POST /api/codebook/proposals с actor_kind: "model". Изменение ждёт в разделе Curate в виде фразы, например "Merge «cost» into «cost concerns»". Администратор или арбитр подтверждает или отклоняет предложение. Подтверждённое предложение проходит тот же путь, что и правка человека, и помечается в журнале изменений как исходящее от модели.

Вложенность кодов

Код с parent_id располагается под этим родителем, а родитель может располагаться под другим родителем. Перемещение, которое поместило бы код под одного из потомков этого же кода, завершается ошибкой. Добавление второго кода с тем же названием под одним родителем завершается такой же ошибкой. Удаление родителя удаляет все коды под этим родителем.

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

В 2.13.1 CSV-экспорт codebook и экспорт .qdpx записывают коды схемы на основе кодбука плоским списком. Столбцы parent и color в CSV для этих кодов пусты. Иерархию кодов, нужную в другой программе, придётся восстановить в той программе или записать в названиях кодов.

Как изменения кодов влияют на сохранённое кодирование

Potato сохраняет каждое применение кода с названием кода в качестве метки в файле user_state.json кодировщика. Объединение или разделение никогда не удаляет строки из базы данных. Potato применяет каждое изменение кодбука только к самому кодбуку и никогда не переписывает сохранённую разметку:

  • Добавление кода не меняет сохранённое кодирование.
  • Переименование кода меняет форму с этого момента. Применения, сохранённые под старым названием, сохраняют старое название, и экспорт и статистика согласованности учитывают эти применения под старым названием. Переименовывайте код до начала раунда кодирования или перекодируйте затронутые фрагменты.
  • Удаление кода убирает из формы этот код и все коды под ним. Сохранённые применения сохраняют название, и журнал изменений сохраняет название удалённого кода.
  • Объединение архивирует исходный код. Архивированный код исчезает из формы, а строка кода и его история остаются в базе данных. Применения, сохранённые с исходным кодом, сохраняют название исходного кода.
  • Разделение по кодировщику указывает одного кодировщика и новый или существующий целевой код. Разделение предназначено для случая, когда два кодировщика использовали одно название кода для разных вещей, и задумано так, чтобы переносить только применения указанного кодировщика. В 2.13.1 форма разметки не записывает связи по кодировщикам, которые переносит разделение. Поэтому разделение создаёт целевой код и архивирует исходный код для всех кодировщиков всякий раз, когда у исходного кода нет дочерних кодов. Сохранённые применения сохраняют название, выбранное каждым кодировщиком.

Potato сообщает кодировщикам об изменениях двумя способами. Во-первых, на фрагменте, сохранённом до добавления новых кодов, появляется баннер с названиями новых кодов. Во-вторых, список Review в боковой панели содержит каждый фрагмент, который кодировщик сохранил до последнего изменения любого рода. У каждого фрагмента в списке есть кнопка Go. Оба сигнала можно закрыть, и Potato никогда не заставляет перекодировать. Администратор или арбитр видит тот же список для всего проекта по адресу GET /api/codebook/admin/stale.

У правок определений отдельный счётчик. Правка краткого определения, определения, поля "Use when" или "Avoid when" кода повышает семантическую ревизию, и Potato записывает семантическую ревизию в каждую разметку, сохранённую после этого. Аналитик затем может разделить применения кодов, сделанные до и после изменения определения. Отметка Minor edit (no re-review) в редакторе /codebook сохраняет формулировку без повышения семантической ревизии. В 2.13.1 список Review отслеживает только структурные изменения.

Для раунда проверки надёжности задайте codebook_mode: fixed, потому что Potato вычисляет согласованность по сохранённым названиям кодов, и код, переименованный посреди раунда, превращается в два кода. Коэффициенты описаны на странице Согласованность разметчиков. Временная шкала согласованности на /admin/iaa отмечает каждую ревизию кодбука на графике согласованности во времени. Страница Дрейф согласованности объясняет, как читать эту шкалу.

Типизированные поля в записи каждого кода

Запись каждого кода — это список типизированных полей. /codebook — полностраничный редактор с историей версий для каждого кода, сравнением версий и восстановлением, которое сохраняет старую версию как новую версию. Кнопка "Paste markdown" превращает вставленный текст кодбука в поля по заголовкам и просит пользователя выбрать тип для любого раздела, который парсер не распознал. Два человека, одновременно сохраняющие один и тот же код, не перезаписывают правки друг друга. Второе сохранение завершается ошибкой и возвращает текущий текст для сверки.

ПолеЗаголовок в редактореСемантическое
short_defShort definitionда
definitionDefinitionда
use_whenUse whenда
avoid_whenAvoid whenда
exampleExamplesнет
counter_exampleCounter-examplesнет
rationaleRationaleнет
backgroundBackgroundнет
downstream_usageDownstream usageнет
keywordsKeywordsнет
notesNotesнет
customсобственный заголовок пользователянет

У кодбука в целом есть четыре раздела вне кодов, с заголовками Preamble, General instructions, Background и How codes are used downstream. Боковая панель показывает краткое определение каждого кода, урезанное до двух строк. Если у кода нет краткого определения, боковая панель показывает полное определение.

Дистиллятор (distiller) превращает выбранные поля в текст, который Potato добавляет в промпты разметки с ICL, и пересобирает этот текст после каждого изменения кодбука. GET /api/codebook/distilled возвращает текст, который модель получает сейчас. Чтобы выбрать поля, добавьте блок codebook.distiller в конфигурацию выше:

yaml
codebook:
  distiller:
    include: [definition, use_when, avoid_when, example]
    procedure: concat

Заполнение и перенос через CLI

potato codebook добавляет код для каждой метки каждой схемы codebook: true, которой ещё нет в кодбуке, и не трогает существующие коды:

bash
potato codebook config.yaml

Команда печатает, сколько кодов создано и сколько уже было. Коды, созданные через CLI, получают одинаковый ID на любой машине, потому что CLI вычисляет каждый ID из названия проекта, родителя и названия кода. Запускайте CLI до первого запуска сервера, если ID должны совпадать между копиями проекта, потому что коды, созданные сервером при начальном заполнении, получают случайные ID. CLI копирует только названия. Цвета и определения из меток в объектной форме попадают в кодбук только при начальном заполнении сервером при первом запуске.

Поскольку сервер заполняет только пустой кодбук, добавить новые метки из YAML в кодбук, где уже есть коды, можно через CLI. Чтобы посмотреть результат без записи, запустите модуль напрямую. В 2.13.1 potato codebook --dry-run отбрасывает флаг и записывает коды.

bash
python -m potato.codebook_cli config.yaml --dry-run

API

Все маршруты находятся под /api/codebook и требуют сессии вошедшего пользователя. Административные маршруты принимают администратора или арбитра.

МетодПутьНазначение
GET/api/codebookдерево, плоский список меток, ревизия, схемы на основе кодбука и значения can_add и can_edit вызывающего
GET/api/codebook/versionструктурная ревизия и ревизия содержимого для дешёвого опроса
GET/api/codebook/similar?name=существующие коды с названиями, близкими к name
GET/api/codebook/provenance?instance_id=предшествует ли кодирование одного объекта вызывающим текущей ревизии и какие коды добавлены с тех пор
GET/api/codebook/staleсписок Review вызывающего
POST/api/codebookдобавить код (name, необязательные color и parent_id)
PATCH/api/codebook/<id>переименовать (name), перекрасить (color) или переместить (parent_id)
DELETE/api/codebook/<id>удалить код и все коды под ним
POST/api/codebook/proposalsпоставить изменение в очередь (op, payload, actor_kind)
GET/api/codebook/admin/staleсписок Review для каждого кодировщика (администратор)
POST/api/codebook/admin/mergeобъединить src_id с dst_id (администратор)
POST/api/codebook/admin/splitперенести связи annotator с src_id на target_id или на новый код с названием new_name (администратор)
GET/api/codebook/admin/changesжурнал изменений (администратор)
GET/api/codebook/admin/proposalsожидающие предложения (администратор)
POST/api/codebook/admin/proposals/<id>/confirmвыполнить предложение (администратор)
POST/api/codebook/admin/proposals/<id>/rejectотклонить предложение (администратор)

Редактор определений использует GET /api/codebook/document, GET и PUT /api/codebook/blocks, POST /api/codebook/parse, GET /api/codebook/history, GET /api/codebook/history/<id>, POST /api/codebook/restore и GET /api/codebook/distilled. В QDA Mode /qda/codebook возвращает кодбук в режиме только для чтения.

Экспорт кодбука и история изменений

Экспорт codebook записывает codebook.csv, по одной строке на код для каждой схемы на основе кодбука, со столбцами schema, annotation_type, code, parent, description, color и n_uses. Экспорт читает базу данных кодбука. Коды, добавленные во время кодирования, включаются, а объединённые коды не включаются. description содержит краткое определение кода или полное определение, если у кода нет краткого. n_uses подсчитывает сохранённые применения по названию. Применение, сохранённое под названием, которого в кодбуке больше нет, не учитывается ни в одной строке.

bash
python -m potato.export -c config.yaml --format codebook -o ./export/

Экспорт quotation_report перечисляет каждый закодированный фрагмент вместе с кодом фрагмента. Экспорт qdpx передаёт коды и кодирование в другую программу QDA. Оба экспорта описаны на странице QDA Mode, а столбцы перечислены на странице Форматы экспорта.

История хранится в project.sqlite. Таблица codebook_change записывает каждое переименование, смену цвета, перемещение, удаление, объединение, разделение и подтверждённое или отклонённое предложение со старым и новым значениями, исполнителем, признаком того, был ли исполнитель человеком или моделью, и ревизией. В 2.13.1 переименование, смена цвета, перемещение или удаление через PATCH или DELETE записывается с исполнителем system, а добавленные коды появляются не в журнале, а в таблице codes с именем пользователя-создателя. GET /api/codebook/admin/changes возвращает журнал изменений в формате JSON.

codebook_snapshot хранит каждую сохранённую версию каждого определения, а codebook_revision_history записывает, когда произошла каждая ревизия. И снимок проекта, и архив из potato deploy pull включают project.sqlite. Любой из этих архивов служит журналом аудита кодбука для раздела о методах.

Запустите прилагаемый пример из checkout-копии Potato:

bash
python potato/flask_server.py start examples/advanced/codebook-example/config.yaml -p 8000

Пример кодирует пять комментариев пациентов о доступе к клинике с помощью открытого кодбука с множественным выбором из четырёх тем. examples/advanced/codebook-document-example/ добавляет блок дистиллятора. Откройте /codebook в этом примере, чтобы увидеть редактор определений.

Дополнительные материалы

Литература

MacQueen, K. M., McLellan, E., Kay, K., & Milstein, B. (1998). Codebook Development for Team-Based Qualitative Analysis. CAM Journal, 10(2), 31-36. https://doi.org/10.1177/1525822X980100020301

Подробности реализации см. в исходной документации.