Шаблоны загрузки¶
Шаблон загрузки — таблица XLSX или CSV, в которую человек вносит записи одного вида базы знаний: номенклатуру, лицензии, договоры, активы или собственный вид компании. Шаблоны не пишутся руками: генератор строит их из схемы вида любого включённого пакета онтологии, и тот же код проверяет заполненную таблицу перед планом загрузки. Статья для администраторов базы знаний и авторов пакетов онтологии. Обоснование — TAI-ADR-0056 (решение 2).
Как получить шаблон¶
Скилл knowledge.template@1 (побочных эффектов нет) возвращает файл прямо в
выходе — contentBase64, имя файла и media type:
| Вход | Что значит |
|---|---|
pack |
пакет вида: company@1, procurement@2, tenant:<имя>@<версия> |
kind |
вид |
profile |
значение профиля вида, например sro |
format |
xlsx (по умолчанию) или csv |
packs |
другие включённые пакеты — виды концов связей и профили (default@1…) |
definitions |
описания пакетов, которых нет среди встроенных (пакет арендатора) |
Выход: templateVersion, filename (<вид>.<формат>), mediaType,
contentBase64, columns[] — {field, header, required, type, hint}.
Неизвестный пакет или вид — ошибка kind_not_found.
Из чего строится шаблон¶
Колонки идут в таком порядке:
| Колонки | Откуда | Поле колонки |
|---|---|---|
| ключ | плейсхолдеры шаблона naturalKey вида, которые не являются атрибутами и не <source>: offering:<source>:<id> → колонка «Код» |
key.<часть> |
| атрибуты | JSON Schema атрибутов вида и профилей: заголовок — title, подсказка — description, проверка — type, format, enum, pattern, minimum/maximum, maxLength; обязательность — required |
attributes.<имя> |
| связи | связи пакетов, у которых вид стоит в fromKinds: заголовок — title связи, значение — ключи связанных записей |
links.<связь> |
- Заголовок колонки ключа:
idиslug— «Код»,key— «Ключ», иначе имя плейсхолдера (vehicle:<vin>→ «vin»). - У вида без шаблона ключа ключ — атрибут
inn(так уlegal_entity) или колонка «Ключ». - Профили. Профиль без
whenдобавляет атрибуты ко всем сущностям вида — такcompany@1описываетlegal_entityпакетаdefault. Профиль сwhenвыбирается явно значениемprofile:credentialсprofile: sroполучает колонки членства в СРО изprocurement@2, а атрибут условия (memberOf) — постоянное значение. - Версия шаблона —
<пакет>/<вид>, с профилем —<пакет>/<вид>#<атрибут>=<значение>(напримерcompany@1/offering).
Типы колонок¶
| Тип | Из схемы | Как заполнять |
|---|---|---|
string |
type: string |
текст; проверяются pattern, enum, maxLength |
number, integer |
type: number, integer |
число; пробелы и запятая как десятичный разделитель допустимы |
boolean |
type: boolean |
да/нет, true/false, 1/0, +/- |
date |
type: string, format: date |
ГГГГ-ММ-ДД или ДД.ММ.ГГГГ; дата ячейки Excel тоже принимается |
list |
type: array |
несколько значений через «;» (разделитель меняет уточнение); каждое проверяется items.pattern |
object |
type: object |
имя=значение; имя=значение или JSON-объект |
key |
колонка ключа | уникальный код записи в источнике: по нему повторная загрузка узнаёт запись |
Колонка связи — ключ связанной записи: полный (с префиксом ключа вида конца, например
unit:1c:NORTH или ИНН организации) или короткий, если в ключе вида конца один
плейсхолдер кроме <source>: короткий G-1 в колонке «Группа» дополнится по шаблону
group:<source>:<id> с источником этой таблицы. Ключи записей другого источника
указывайте полностью. У связи cardinality: many — несколько ключей через «;».
Коды из ячеек Excel не портятся: число 62.01 остаётся строкой 62.01, целое
796 — 796.
Файл шаблона¶
| Лист | Что на нём |
|---|---|
| «Данные» | строка заголовков (* у обязательных), строка-пример, выпадающие списки для колонок с enum (если значения короче 250 символов), закреплённая первая строка |
| «Инструкция» | название и описание вида, текст уточнения, правила заполнения, таблица колонок: обязательность, тип, подсказка; версия шаблона |
_meta (скрыт) |
версия шаблона и поля колонок — по ним загрузчик сопоставляет таблицу даже с переименованными заголовками |
UTF-8 с BOM, разделитель «;»: строка заголовков (* у обязательных) и
строка-пример.
Строку-пример удалите
Пример на листе «Данные» — подсказка, а не запись. Удалите его перед загрузкой, иначе он станет записью базы знаний.
Уточнение шаблона пакетом¶
Пакет может уточнить подачу шаблона данными — файл templates/<вид>.yaml в
интеграции пакета, форма — packages/schema/v1/knowledge-template.schema.json.
Уточнение меняет заголовки, порядок, подсказки и примеры; колонок сверх схемы вида
оно не добавляет.
| Поле | Что задаёт |
|---|---|
pack, kind |
к какому виду относится (company@1, offering) |
title |
название шаблона |
instructions |
текст листа «Инструкция» перед описанием колонок (до 4000 символов) |
columns[] |
порядок колонок: field (key, title, attributes.<имя>, links.<связь>), header, hint, example, separator; не перечисленные идут после в порядке схемы |
examples[] |
до пяти строк-примеров: поле → значение |
forbiddenColumns[] |
запрещённые заголовки сверх общего списка персональных данных |
Уточнение номенклатуры, которое поставляется с company@1:
pack: company@1
kind: offering
title: Номенклатура
instructions: >-
Одна строка — одна позиция: товар, работа или услуга. Код — из вашей учётной системы:
по нему повторная загрузка узнаёт позицию. Коды ОКПД2 — через «;».
columns:
- {field: key, header: Код, hint: "Код позиции в учётной системе"}
- {field: attributes.name, header: Наименование}
- {field: attributes.type, header: Тип}
- {field: attributes.okpd2, header: ОКПД2, example: "62.01.11.000"}
- {field: attributes.unit, header: Единица (ОКЕИ), example: "796"}
- {field: attributes.unitName, header: Единица, example: "шт"}
- {field: attributes.description, header: Описание}
- {field: links.item_of, header: Группа}
examples:
- {key: "SKU-001", name: "Разработка программного обеспечения", type: service, okpd2: "62.01.11.000"}
Проверка таблицы¶
Заполненную таблицу проверяет тот же код, что строит план загрузки
(knowledge.import_plan@1), и локальная команда:
{
"status": "invalid",
"pack": "company@1",
"kind": "offering",
"templateVersion": "company@1/offering",
"rows": 120,
"entities": 118,
"relations": 118,
"errors": [
{"row": 14, "code": "enum", "message": "«товар» — допустимо: product, work, service", "column": "Тип"},
{"row": 37, "code": "duplicate_key", "message": "ключ offering:template:offering:SKU-7 уже был в строке 12"}
],
"errorsTotal": 2,
"columns": ["Код", "Наименование", "Тип", "ОКПД2", "…"]
}
status: ok — можно загружать, invalid — есть ошибки, empty — записей нет.
Код выхода команды — 0 только при ok. Показывается до 50 ошибок, всего — в
errorsTotal.
Чтение файла. XLSX — лист «Данные» или первый; CSV — UTF-8 (с BOM или без) или
cp1251, разделитель «;», «,» или табуляция (тот, которого больше в строке
заголовков). Пустые строки пропускаются. Колонки сопоставляются по листу _meta,
иначе по заголовку (без * и без учёта регистра) или по имени поля.
Ошибки — с номером строки листа и заголовком колонки:
code |
Когда |
|---|---|
required |
нет обязательной колонки (строка 1), пусто в обязательной колонке, не из чего собрать ключ |
type |
значение не того типа: не число, не «да/нет», не объект |
format |
не подходит pattern, не дата |
enum |
значение не из списка |
unknown_column |
колонки нет в шаблоне |
duplicate_key |
ключ уже был в другой строке |
personal_data |
запрещённая колонка или значение, похожее на персональные данные |
kind_not_found |
пакета или вида нет |
file_unreadable |
файл не читается как XLSX или CSV |
Строка с ошибкой в снимок не идёт, а план по таблице с ошибками не строится (см. Загрузка таблицы).
Персональные данные¶
Колонки с персональными данными физических лиц запрещены в любом шаблоне.
Заголовок, содержащий одно из слов списка, — ошибка personal_data в строке 1, и
таблица дальше не проверяется:
фио, фамилия, имя сотрудника, отчество, паспорт, снилс,
дата рождения, адрес проживания, домашний адрес, телефон, мобильный,
e-mail, email, электронная почта — плюс forbiddenColumns уточнения.
Каждое строковое значение проверяет страж skill-sdk: значение, похожее на ФИО, СНИЛС,
паспорт, телефон или e-mail, — ошибка строки «похоже на персональные данные». Роли
людей в базе знаний — вид role с атрибутом platformRole, а не ФИО.
Исключение — атрибут, который пакет онтологии явно пометил x-personal-data: allowed:
значения такой колонки страж не проверяет, но ИИ их не заполняет и в промпт не
получает.
Пример: свой вид арендатора¶
Перевозчику нужно вести транспорт со страховкой — такого вида в company@1 нет.
Описание пакета арендатора:
name: acme-logistics
version: 1
scope: tenant
extends: ["company@1"]
description: Транспорт перевозчика
kinds:
- kind: vehicle
title: Транспортное средство
naturalKey: "vehicle:<vin>"
searchable: {fields: [model]}
attributes:
type: object
required: [plate]
properties:
plate: {type: string, title: Госномер}
model: {type: string, title: Модель}
capacityKg: {type: number, title: "Грузоподъёмность, кг"}
insurer: {type: string, title: Страховщик}
validFrom: {type: string, format: date, title: Страховка с}
validUntil: {type: string, format: date, title: Страховка до}
relations:
- {relation: assigned_to, title: Подразделение, fromKinds: [vehicle], toKinds: [org_unit]}
expiry:
- {kind: vehicle, role: fleet-manager, leadDays: 14}
-
Проверка описания — схема, конфликты имён с включёнными пакетами, шаблон по каждому виду:
-
Шаблон — пакет арендатора не встроен, поэтому его описание передаётся
--definition:python3 tools/knowledge.py template --pack tenant:acme-logistics@1 --kind vehicle \ --packs company@1 --definition vehicles.pack.yaml --out vehicles.csvКолонки:
vin *(ключ из плейсхолдера), «Госномер *», «Модель», «Грузоподъёмность, кг», «Страховщик», «Страховка с», «Страховка до», «Подразделение» (связьassigned_to). -
Заполненная таблица:
vin *;Госномер *;Модель;Грузоподъёмность, кг;Страховщик;Страховка с;Страховка до;Подразделение XTA000001;А123ВС77;Газель;1500;Страховщик А;2026-01-01;2026-12-31;unit:1c:NORTH XTA000002;В456ОР77;Валдай;3500;Страховщик Б;04.10.2025;03.10.2026;unit:1c:NORTHДаты в двух форматах принимаются обе; ключ записи —
vehicle:XTA000001. -
Регистрация, включение и загрузка — после согласия человека:
pack-register,pack-enableсо всем набором пакетов дерева, затемimport-startс--definition vehicles.pack.yaml(см. База знаний компании). - Сроки. У вида есть
validUntil, а вexpiry— рольfleet-managerи 14 дней: чтобы правилоknowledge-expiryнапоминало о страховке, пакет добавляется в его входpacks, описание — вdefinitions(см. Истечение сроков).