All news
ASCodeworksReleases

SYNX 3.7: SYNXL приносит типизированные потоки записей в датасеты для ИИ

by APERTURESyndicate · 1 августа 2026 г.

SYNX 3.7: SYNXL приносит типизированные потоки записей в датасеты для ИИ

Вышел SYNX 3.7. В язык добавлен ровно один оператор, а рядом появился целый новый формат файлов — SYNXL: формат потока записей для датасетов, сделанный под две задачи, в которые обычно втискивают JSONL и CSV и с которыми они справляются плохо.

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

Чем JSONL и CSV мешают на датасетах

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

С многострочным текстом ещё хуже. Промпт, кусок кода, ответ модели — всё схлопывается в шум из экранированных \n, который никто не читает и который калечит любой diff.

CSV избегает повторов, но отдаёт почти всё остальное: ни типов, ни вложенности — и тот самый нерешённый вопрос, к которому рано или поздно приходит любой CSV-конвейер: пустая ячейка — это пустая строка или отсутствующее значение? Добавьте в поле запятую, и вы уже в правилах экранирования, которые в каждом диалекте свои.

SYNXL на одном экране

!synxl 1
!fields id[type:int] ; score[type:float] ; messages[block]

1 ; 0.91
  messages
    - role system
      content You are a helpful assistant.
    - role user
      content |+
          def f(x):
              return x + 1

2 ; 0.74
  messages
    - role user
      content Привет

Список полей объявляется один раз. Записи начинаются с нулевой колонки, скалярные поля разделяются символом ;, а любое поле, помеченное как [block], раскрывается под записью в полном SYNX — списки, вложенные объекты, многострочный текст. Именно это позволяет выражать данные в форме диалога напрямую, а не сплющивать их в экранированную строку.

Этот пример проецируется в обычный JSON:

[{"id":1,"messages":[{"content":"You are a helpful assistant.","role":"system"},
  {"content":"def f(x):\n    return x + 1","role":"user"}],"score":0.91}, …]

Что формат действительно гарантирует

  • Типы там, где им место. [type:int], [required], [enum:a|b|c] живут в заголовке, а не в отдельном файле схемы, и не выводятся заново для каждой строки.

  • Пусто — это не ничто. Пустое поле — это null; пустая строка записывается как "". Двусмысленности CSV здесь нет по построению.

  • Ничего не теряется молча. SYNX тихо пропускает битую структуру. SYNXL о ней сообщает — пропущенные поля, лишние поля, неудавшиеся приведения типов, неизвестные ключи блока — каждый раз с номером записи и номером строки. Датасет, который теряет колонку и не говорит об этом, хуже того, который падает громко.

  • Записи независимы. Границу записи видно по одному байту, поэтому формат безопасно дописывается, аккуратно шардируется и разбирается параллельно.

  • Схема может меняться прямо в файле. Появилась новая колонка? Напишите новую строку !fields и продолжайте дописывать. Ранние записи остаются валидными и сохраняют исходную форму.

Сделано для файлов, которые не влезают в память

Ограничение входа в 16 МиБ, которое SYNX применяет к документу, в SYNXL действует на каждую запись: датасеты спокойно занимают гигабайты, а записи независимы, поэтому ограничение на весь файл не защищает ничего сверх того, что защищает ограничение на запись.

Потоковый ридер держит в памяти ровно одну запись. Замер через CLI на файле в 142 МБ с 2,4 миллиона записей: пиковая память остаётся ровной, около 10 МБ, на validate, parse и split — а чтение того же файла целиком в память стоило бы как минимум его собственного размера.

Вторая половина 3.7: |+

Сам язык получил ровно одно новшество: |+ — открыватель многострочного значения, сохраняющий отступы. Обычный | обрезает каждую строку продолжения: для прозы это нормально, для всего, где пробелы значимы, — разрушительно. |+ фиксирует базовый отступ по первой содержательной строке и сохраняет всё, что правее, — поэтому код, ASCII-схемы и каркасы промптов остаются внутри значения целыми.

SYNX 3.6 остаётся замороженной базой совместимости. 3.7 только добавляет: парсер 3.6 остаётся соответствующим стандарту для любого документа, где нет конструкций только из 3.7.

Как читать из кода

Сегодня SYNXL существует в четырёх реализациях, и за каждой стоит одинаковая семантика:

// Rust
let doc = synx_core::synxl::parse_lines(&text)?;
for record in &doc.records { /* … */ }

// TypeScript
import { parseSynxl, streamSynxlFile } from '@aperturesyndicate/synx-format'
for (const record of streamSynxlFile('dataset.synxl')) { /* … */ }

# Python
import synx_native as synx
for record in synx.synxl_stream_file("dataset.synxl"):
    train(record["messages"])

И из командной строки, включая конвертеры в обе стороны:

synx synxl parse dataset.synxl --format ndjson
synx synxl validate dataset.synxl --constraints
synx synxl convert corpus.jsonl          # jsonl → synxl
synx synxl split dataset.synxl -n 500000 # shards that are valid on their own

Где доступно

3.7.1 опубликована на crates.io, npm, PyPI и NuGet.

Сам SYNXL реализован на Rust, TypeScript, Python и в CLI. Нативные парсеры C++, Dart, .NET, Go, Java и Swift поддерживают SYNX 3.7, включая |+, но пока не читают .synxl — до тех пор конвертируйте через CLI или читайте одной из четырёх реализаций.

Спецификация и соответствие

У SYNXL собственная ось версий — версия формата 1, независимая от версии языка, — потому что документ SYNXL не является документом SYNX: на верхнем уровне у него последовательность записей, а не объект.

Нормативный текст — SYNXL-1-NORMATIVE.md, а за ним стоит набор из 67 тестов соответствия, выведенных из этого текста независимо от какой-либо реализации. Раннер на Rust вдобавок перечитывает каждый принятый случай всеми тремя своими ридерами и падает, если они расходятся.

Полная документация и живая песочница: synx.aperturesyndicate.com

Что дальше

Поддержка SYNXL в остальных парсерах, начиная с Go и .NET. Спецификация стабильна, набор тестов соответствия написан, поэтому вторая волна — механическая работа, а не разведка. Ровно ради этого тесты и пишутся раньше реализаций.

Other stories

All stories
SYNX 3.7: SYNXL приносит типизированные потоки записей в датасеты для ИИ | APERTURESyndicate