refactor: replace fixed STYLE_user with open-ended style tag system
- STYLE_user renamed to STYLE_H1K0 in VOCAB (author's personal tag) - Style field now accepts any [A-Za-z][A-Za-z0-9_]* identifier in .chord files - Unknown styles fall back to STYLE_other at tokenization time with a log warning - Test fixtures updated to style: other; drop closed _VALID_STYLES frozenset - Spec bumped to v2.1: documents open style field, fallback behaviour, and §5.7 guide on registering a new style token Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+38
-21
@@ -1,7 +1,7 @@
|
||||
# Спецификация формата данных hamori
|
||||
|
||||
**Версия:** 2.0
|
||||
**Дата:** 2026-05-16
|
||||
**Версия:** 2.1
|
||||
**Дата:** 2026-05-20
|
||||
|
||||
---
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
Формат двухуровневый:
|
||||
|
||||
- **Исходный (`.chord`)** — то, что пишется руками. Близок к лид-шиту, человекочитаем, легко правится в любом текстовом редакторе.
|
||||
- **Токенизированный** — то, что подаётся в модель. Факторизованное представление с маленьким словарём (~75 токенов).
|
||||
- **Токенизированный** — то, что подаётся в модель. Факторизованное представление с фиксированным словарём (81 токен).
|
||||
|
||||
Между уровнями стоит детерминированный парсер.
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
# key: D_major
|
||||
# time: 4/4
|
||||
# subdivision: 4
|
||||
# style: user
|
||||
# style: H1K0
|
||||
# function: chorus
|
||||
|
||||
| Gmaj7 . . . | A . . . | F#m7 . . . | Bm7 . . . |
|
||||
@@ -53,14 +53,14 @@
|
||||
|
||||
### 3.3 Поля шапки
|
||||
|
||||
| Поле | Обязательно | Допустимые значения | Назначение |
|
||||
| ------------- | ----------- | -------------------------------------------------------------------------------- | -------------------------------------------- |
|
||||
| `title` | да | свободная строка | идентификация периода |
|
||||
| `key` | да | `<note>_major` или `<note>_minor` | для нормализации в C/Am перед обучением |
|
||||
| `time` | да | `4/4`, `3/4`, `6/8`, `2/4`, `12/8` | тактовый размер |
|
||||
| `subdivision` | да | `4` или `8` | сколько позиций в одном такте |
|
||||
| `style` | да | `user`, `jpop`, `classical`, `jazz`, `other` | стилевой тег периода |
|
||||
| `function` | нет | `verse`, `prechorus`, `chorus`, `bridge`, `intro`, `outro`, `interlude`, `other` | функциональная роль периода в исходной пьесе |
|
||||
| Поле | Обязательно | Допустимые значения | Назначение |
|
||||
| ------------- | ----------- | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `title` | да | свободная строка | идентификация периода |
|
||||
| `key` | да | `<note>_major` или `<note>_minor` | для нормализации в C/Am перед обучением |
|
||||
| `time` | да | `4/4`, `3/4`, `6/8`, `2/4`, `12/8` | тактовый размер |
|
||||
| `subdivision` | да | `4` или `8` | сколько позиций в одном такте |
|
||||
| `style` | да | любой идентификатор `[A-Za-z][A-Za-z0-9_]*` (например: `H1K0`, `jpop`, `other`) | стилевой тег периода; при токенизации тег должен совпасть с токеном `STYLE_<tag>` в словаре, иначе используется `STYLE_other` |
|
||||
| `function` | нет | `verse`, `prechorus`, `chorus`, `bridge`, `intro`, `outro`, `interlude`, `other` | функциональная роль периода в исходной пьесе |
|
||||
|
||||
**Допустимые ноты для `key`:** `C, C#, D, D#, E, F, F#, G, G#, A, A#, B`. Бемольные написания (`Db`, `Eb`, ...) принимаются и нормализуются к диезной форме.
|
||||
|
||||
@@ -110,10 +110,10 @@
|
||||
Примеры:
|
||||
|
||||
- `C` → root=C, quality=maj (по умолчанию), без extension, bass=root
|
||||
- `Am7` → root=A, quality=min7, без extension, bass=root
|
||||
- `Am7` → root=A, quality=m7, без extension, bass=root
|
||||
- `Fmaj9` → root=F, quality=maj7, extension=9, bass=root
|
||||
- `G7/B` → root=G, quality=7, без extension, bass=B
|
||||
- `Dm9/F` → root=D, quality=min7, extension=9, bass=F
|
||||
- `Dm9/F` → root=D, quality=m7, extension=9, bass=F
|
||||
|
||||
### 4.2 Корневой тон
|
||||
|
||||
@@ -228,7 +228,7 @@ D/F# ← D, бас F♯
|
||||
- `MODE_major`, `MODE_minor` — 2 токена (наследие тональности; нужны, потому что мажор и минор остаются разделёнными)
|
||||
- `TIME_4/4`, `TIME_3/4`, `TIME_6/8`, `TIME_2/4`, `TIME_12/8` — 5 токенов
|
||||
- `SUB_4`, `SUB_8` — 2 токена
|
||||
- `STYLE_user`, `STYLE_jpop`, `STYLE_classical`, `STYLE_jazz`, `STYLE_other` — 5 токенов
|
||||
- `STYLE_H1K0`, `STYLE_jpop`, `STYLE_classical`, `STYLE_jazz`, `STYLE_other` — 5 токенов стиля (текущий словарь); неизвестный тег → `STYLE_other`
|
||||
- `FUNC_verse`, `FUNC_prechorus`, `FUNC_chorus`, `FUNC_bridge`, `FUNC_intro`, `FUNC_outro`, `FUNC_interlude`, `FUNC_other`, `FUNC_unspecified` — 9 токенов
|
||||
|
||||
**Аккордовые слоты (новый аккорд = ровно 4 токена в порядке root, quality, extension, bass):**
|
||||
@@ -274,7 +274,7 @@ BAR
|
||||
1. Прочитать шапку.
|
||||
2. Транспонировать все аккорды: если `key = X_major`, транспонировать так, чтобы X стало C; если `key = X_minor` — так, чтобы X стало A.
|
||||
3. Выпустить `<BOS>`.
|
||||
4. Выпустить метатокены: `MODE_<major|minor>`, `TIME_<x>`, `SUB_<x>`, `STYLE_<x>`, `FUNC_<x>` (если `function` не задан — выпустить `FUNC_unspecified`).
|
||||
4. Выпустить метатокены: `MODE_<major|minor>`, `TIME_<x>`, `SUB_<x>`, `STYLE_<x>`, `FUNC_<x>` (если `function` не задан — выпустить `FUNC_unspecified`; если `STYLE_<style>` отсутствует в словаре — выпустить `STYLE_other` с предупреждением в лог).
|
||||
5. Для каждого такта:
|
||||
- Для каждой позиции в такте:
|
||||
- Если новый аккорд: разобрать на (root, quality, extension, bass), выпустить 4 токена в этом порядке.
|
||||
@@ -304,6 +304,18 @@ BAR
|
||||
|
||||
Длинный период (16 тактов с частой сменой): редко превышает 250 токенов. Контекстное окно 512 токенов более чем достаточно.
|
||||
|
||||
### 5.7 Добавление нового стилевого тега
|
||||
|
||||
Поле `style` в `.chord` файле принимает любой идентификатор — дополнительный код менять не нужно. Однако, чтобы модель кондиционировалась на новый стиль отдельным токеном (а не сваливала его в `STYLE_other`), нужно зарегистрировать токен в словаре:
|
||||
|
||||
1. Открыть `src/tokenizer.py`, найти блок `# Style (5)` в списке `VOCAB`.
|
||||
2. Добавить `"STYLE_<tag>"` в этот блок. Пример: `"STYLE_ALICE"`.
|
||||
3. Обновить счётчик в §5.2 этой спецификации и в итоговой строке («**N токенов**»).
|
||||
4. **Переобучить модель с нуля** — изменение размера словаря меняет размер матрицы эмбеддингов и выходного слоя; дообучить существующий чекпоинт не получится.
|
||||
5. Обновить все `.chord` файлы нужного корпуса, выставив новый тег в поле `style`.
|
||||
|
||||
Если токен не зарегистрирован, парсер принимает файл без ошибок, но токенизатор выдаёт `STYLE_other` и пишет предупреждение в лог. Это удобно для экспериментов до переобучения.
|
||||
|
||||
---
|
||||
|
||||
## 6. Полный пример
|
||||
@@ -315,10 +327,10 @@ BAR
|
||||
# key: G_major
|
||||
# time: 4/4
|
||||
# subdivision: 4
|
||||
# style: user
|
||||
# style: H1K0
|
||||
# function: chorus
|
||||
|
||||
| Gmaj7 . . . | Bm7 . . . | Em7 . . . | C . . D . |
|
||||
| Gmaj7 . . . | Bm7 . . . | Em7 . . . | C . D . |
|
||||
| Cmaj7 . . . | G/B . . . | Am7 . D . | G . . . |
|
||||
```
|
||||
|
||||
@@ -327,7 +339,7 @@ BAR
|
||||
Шаг 1: транспонировать из G major в C major (вниз на 7 полутонов или вверх на 5):
|
||||
|
||||
```
|
||||
| Cmaj7 . . . | Em7 . . . | Am7 . . . | F . . G . |
|
||||
| Cmaj7 . . . | Em7 . . . | Am7 . . . | F . G . |
|
||||
| Fmaj7 . . . | C/E . . . | Dm7 . G . | C . . . |
|
||||
```
|
||||
|
||||
@@ -335,7 +347,7 @@ BAR
|
||||
|
||||
```
|
||||
<BOS>
|
||||
MODE_major TIME_4/4 SUB_4 STYLE_user FUNC_chorus
|
||||
MODE_major TIME_4/4 SUB_4 STYLE_H1K0 FUNC_chorus
|
||||
|
||||
ROOT_C QUAL_maj7 EXT_none BASS_root
|
||||
HOLD HOLD HOLD
|
||||
@@ -468,7 +480,12 @@ YYYY_NNN_<short-title>_<function>.chord
|
||||
|
||||
## 11. История изменений
|
||||
|
||||
- **v2.0** (текущая)
|
||||
- **v2.1** (текущая)
|
||||
- Поле `style` теперь принимает любой идентификатор `[A-Za-z][A-Za-z0-9_]*`, а не фиксированный список.
|
||||
- `STYLE_user` заменён на `STYLE_H1K0` (авторский тег) в словаре модели.
|
||||
- Неизвестный стиль при токенизации маппируется на `STYLE_other` с предупреждением в лог.
|
||||
|
||||
- **v2.0**
|
||||
- Единицей датасета стал **гармонический период**, не пьеса целиком.
|
||||
- Введена **нормализация тональности** в C major / A minor. Поле `key` сохраняется в шапке для парсера, но в словаре модели нет — есть только `MODE_major` / `MODE_minor`.
|
||||
- Введён тег `function` (необязательный) как метаданные периода.
|
||||
|
||||
Reference in New Issue
Block a user