Когда вы разрабатываете новый продукт, приложение или функцию, то тестировать ее необходимо на реалистичных данных. Сначала данные создаются вручную, но если нужно протестировать аналитические интерфейсы или большие объемы данных, то ручной подход окажется уже малоэффективным.
Мы сотрудничаем с глобальным сообществом Salesfore.org, которое помогает в решении крупнейших гуманитарных, образовательных проблем, а также проблем окружающей среды. Точно также, как и коммерческие клиенты Salesfore, наши глобальные партнеры ожидают, что предлагаемые нами продукты смогут масштабироваться до десятков миллионов записей. Поэтому перед выпуском нам необходимо тестировать их на реалистичных обширных наборах данных.
Команда Salesforce разработала открытый инструмент под названием Snowfakery, который подобен фабрике по производству крупномасштабных фиктивных данных, содержащих связи между сущностями. Особенность Snowfakery в генерации уникального содержимого датасетов. Каждая строка представляет фиктивные данные, но при этом они уникальны и случайны, наподобие снежинок.
Архитекторы могут использовать этот инструмент для создания CSV, SQL, bulk insert или JSON-файлов, которые затем можно загружать с помощью различных средств, но при этом Snowfakery уже интегрирован с инфраструктурой объемной загрузки CumulusCI и работает с ней очень слаженно.
Что такое Snowfakery?
В связи с доступностью многих систем генерации синтетических данных поначалу мы сомневались, а стоит ли создавать еще одну. Но, несмотря на свое удобство и понятность в использовании, всем этим системам недостает емкости для создания глубоко связанных данных: где Contacts соотносятся с Accounts, Opportunities с обеими этими категориями, Custom Objects связываются в сложных графах и т.д.
Нас интересовала система со следующими характеристиками:
- масштабируемость до сотен миллионов строк;
- реалистичные данные;
- автоматическое управление связями между объектами (Master/Detail, Lookup или Junction);
- интуитивный и понятный синтаксис для “инструкций”;
- возможность по умолчанию использовать его в сочетании с Salesforce;
- открытый исходный код и бесплатность (как и у других наших инструментов: CumulusCI, MetsCI, Metecho и MetaDeploy).
Найти подобный инструмент мы не смогли, поэтому и решили создать его сами.
Snowfakery для простых данных
Инструкции Snowfakery определяются в YAML, который является относительно простым и понятным для человека форматом, знакомым многим разработчикам и проектировщикам. Далее принцип работы инструкций будет расписан подробнее.
В YAML для определения связанных друг с другом частей файла используются отступы. Начнем с простого жестко закодированного примера инструкции:
- object: Contact
fields:
name: Buster Bluth
phone: 555-582-4553 # Comment: same as 555-LUC-ILLE
Через Snowflakery мы прогоняем этот пример так:
$ snowfakery docs/examples/simple_static.yml
В результате генерируется:
Contact(id=1, name=Buster Bluth, phone=555-582-4553)
Как видите, была создана одна запись контакта с тремя полями:
| | Id | Name | Phone |
| ----------- | ----------- | ----------- | ----------- |
| 1 | 1 | Buster Bluth | 555-582-4553 |
Два поля содержат данные из инструкции YAML, а ID генерируется отдельно. Эти данные также можно использовать в CSV, SQL, bulk insert или JSON-формате, а также в качестве диаграммы. Кроме того, после некоторых настроек, Snowfakery может делать запись напрямую в различные базы данных.
Но я обещал вам уникальные данные, подобные прекрасным неповторимым снежинкам. Так что продолжим:
- object: Account
count: 8
fields:
FirstName:
fake: first_name
LastName:
fake: last_name
PhoneNumber:
fake: phone_number
С помощью этого инструкции Snowfakery сгенерирует восемь Account, представляющих ценные и уникальные личности, которые никогда не существовали (точно не с этими номерами телефонов):
Account(id=1, FirstName=Dana, LastName=Ewing, PhoneNumber=7636043937)
Account(id=2, FirstName=Jennifer, LastName=Brown, PhoneNumber=036.920.1773x9467)
Account(id=3, FirstName=Nathan, LastName=Porter, PhoneNumber=(351)905-4880x24018)
Account(id=4, FirstName=Makayla, LastName=Warner, PhoneNumber=981-314-3601)
Account(id=5, FirstName=Marc, LastName=Benioff, PhoneNumber=+1-211-499-3398x412)
Account(id=6, FirstName=Rebecca, LastName=Chavez, PhoneNumber=001-595-256-8369x4195)
Account(id=7, FirstName=Monica, LastName=Jones, PhoneNumber=001-451-980-9489x155)
Account(id=8, FirstName=Justin, LastName=Clark, PhoneNumber=001-526-356-3339)
Есть старая шутка, что ученые по данным считают так: 0, 1, бесконечность. Конечно же, мы можем создать больше, чем эти восемь записей. На деле без изменения инструкции можно попросить Snowfakery выполнить его многократно вплоть до генерации даже миллиона строк.
Следующая инструкция даст Snowfakery команду выполнять инструкцию, пока не будет сгенерирован 1 000 000 аккаунтов, для чего придется выполнить ее 125 000 раз:
$ snowfakery examples/bluth.yml--target-number 1000000 Account--output-format csv
Этот инструмент не потребляет много памяти, поэтому для генерации 1 000 000 строк ее потребуется столько же, сколько для 10. Память из-под более ненужных результатов будет освобождаться сразу после их записи в базу данных или файловую систему.
На моем двухлетнем ноутбуке при выполнении этой простой инструкции Snowfakery генерирует более 3 000 строк в секунду.
Связывание объектов
Я упоминал, что особенным свойством нашей разработки является управление связями. Далее мы поговорим об Accounts (учетные записи), Opportunities (возможности) и Contacts (контакты). Вы уже знаете, что связываются эти объекты между собой так:
Создадим все это в Snowfakery, начав с Contact. Рассматривая этот раздел, мы попутно затронем еще одно новое понятие: взвешенный случайный выбор.
- object: Contact
fields:
FirstName:
fake: first_name
LastName:
fake: last_name
Salutation:
random_choice:
Mr.: 40%
Ms.: 40%
Dr.: 10%
Prof.: 10%
Далее мы перейдем к Contact и Opportunity. Opportunity связывается с Contact, поэтому самым простым способом сделать это будет вложить Contact в Opportunity. Удалим Salutation, чтобы сократить пример.
- object: Opportunity
fields:
ContactId:
- object: Contact
fields:
FirstName:
fake: first_name
LastName:
fake: last_name
Name: The ${{ContactId.LastName}} Opportunity
Здесь у нас три новых принципа:
- Contact можно вложить в Opportunity.
- Opportunity можно связать с Contact через одно из его полей.
- Opportunity можно назвать по имени поля из Contact, используя язык формул Snowfakery.
Единственная сложность при этом заключается в том, что вам зачастую понадобится привязывать к Contact множество Opportunity. Для этого нужно обратить вложение и поместить Count в Opportunity. Проблема в том, что Contact не связываются непосредственно с Opportunity ссылкой. Так куда же их вкладывать?
В этом нам помогает еще одна возможность Snowfakery, а именно friends
. Объявление friends
позволяет связывать объекты в файле при отсутствии их прямой связи в Salesforce или схеме базы данных.
Теперь развернем инструкцию:
- object: Contact
fields:
FirstName:
fake: first_name
LastName:
fake: last_name
friends:
- object: Opportunity
count:
random_number:
min: 5
max: 20
fields:
StageName:
random_choice:
Prospecting: 50%
Qualification: 50%
CloseDate: 2022-01-01
ContactId:
reference: Contact
Name: The ${{Contact.LastName}} Opportunity
Да, я тайком протащил сюда еще одну фишку: random_number
.
Эта команда генерирует для каждого Contact случайное количество Opportunity, именуя их согласно этому контакту. Обратите внимание, что мы обращаемся из Opportunity к содержащему ее Contact с помощью reference
.
Snowfakery может даже генерировать картинки небольших датасетов. Например:
Продолжим проделывать тот же трюк с вложением, чтобы объединить Account и OpportunityContactRole:
- object: Account
fields:
name:
fake: company
friends:
- object: Contact
count: 2
fields:
.... elided for space ....
friends:
- object: Opportunity
count:
random_number:
min: 1
max: 3
fields:
StageName:
random_choice:
Prospecting: 50%
Qualification: 50%
CloseDate: 2022-01-01
ContactId:
reference: Contact
AccountId:
reference: Account
Name: The ${{Contact.LastName}} Opportunity
friends:
- object: OpportunityContactRole
fields:
OpportunityId:
reference: Opportunity
ContactId:
reference: Contact
Role:
random_choice:
Business User: 20%
Decision Maker: 20%
Economic Buyer: 20%
Economic Decision Maker: 20%
Evaluator: 20%
Можно даже вложить еще одну Opportunity во вторую OpportunityContactRole, но так наш пример станет уже слишком длинным.
Вот наглядное представление OpportunityContactRole:
Импорт в Salesforce
Несмотря на то, что Snowfakery можно установить и использовать отдельно от CumulusCI, его также можно установить как часть этого инструмента. В таком случае он просто окажется еще одной из множества его возможностей.
Я могу загрузить приблизительно 10 000 Opportunity вместе со всеми связанными с ними записями так:
$ cci task run generate_and_load_from_yaml --num_records 10000 --num_records_tablename Opportunity --generator_yaml AccountContactOpportunity.recipe.yml --org qa
Эта команда выполнит инструкцию необходимое количество раз, сгенерировав не менее 10 000 возможностей, и автоматически создаст подходящее число соответствующих Account (~2 500), Contact (~5 000) и OpportunityContactRoles(~10 000).
Эта же команда автоматически загружает данные в организацию, подключенную к CumulusCI с псевдонимом “qa”.
Выглядит это так:
В самой организации отобразятся эти данные так:
Дополнительные возможности
В Snowfakery есть и многие другие возможности, включая:
- Удобный механизм встраивания для написанных на Python плагинов.
- Сотни видов фиктивных данных среди десятков языков и регионов, например корпоративные слоганы, адреса в десятках стран, имена людей из многих культур, компьютерные коды, включая hex-цвета, IP-адреса и другие.
- Макрос для поддержки повторного использования кода и реорганизации файлов инструкций.
- Инструкции, включающие другие инструкции в качестве модулей.
- Богатый язык формул с функциями для управления строками и математическими операциями.
- Инструменты для объединения данных CSV и Salesforce.
CumulusCI, в свою очередь, обладает еще более обширным списком возможностей, чем Snowfakery, что делает его чрезвычайно эффективным.
Опенсорс в Salesforce.org
В рамках Salesforce.org мы используем Snowfakery и CumulusCI для тестирования собственных продуктов в масштабе. Открытость этих инструментов также делает их доступными для наших клиентов и партнеров. Помимо этого, мы делаем доступным исходный код наших моделей данных и некоторых продуктов. Вокруг Snowfakery сформировалось открытое сообщество, и некоторые из его участников уже создали красивые Web-интерфейсы для редактирования файлов Snowfakery. Будьте в теме!
Также приглашаем вас в группу Trailblazer для обсуждения любых возникающих вопросов.
Читайте также:
- Обработка естественного языка
- 5 минут на машинное обучение
- За гранью HCD: нужен ли новый подход в дизайне для ИИ?
Читайте нас в Telegram, VK и Яндекс.Дзен
Перевод статьи Paul Prescod: Generate Realistic Datasets with Snowfakery