Skip to content

feat(tts): add checked Japanese dictionary and default-off reading experiment - #237

Merged
Lucas1479 merged 12 commits into
mainfrom
codex/japanese-pronunciation-dictionary
Oct 20, 2026
Merged

Lucas1479 merged 12 commits into
mainfrom
codex/japanese-pronunciation-dictionary

Conversation

@Lucas1479

@Lucas1479 Lucas1479 commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

What and why

The imported English-to-kana CSV contains shifted neighboring-word readings that automatic final-phone screening misses. This change provides a much smaller checked lexical candidate subset, through the existing optional resource installer. The separate Japanese context-reading integration is an explicit default-off experiment because broader testing found real regressions.

Linked public-contract Issue: Refs #244. The separate aiohttp/yarl security PR #243 is merged into main at 79ef387a7e4848046595ddabba0890c9c74c964b. This branch is synchronized with that main commit. The merge changes no committed file content relative to the preceding copy revision.

Change class and ownership

Lexical admission belongs to offline data preparation; contextual reading belongs to the upstream native selector; resource transport remains with the existing installer. Both resources are separately installed, independently switchable and never downloaded at startup. Original Japanese text reaches native reading/prosody planning; character weights, references and checkpoint symbol IDs are unchanged. Restart the backend after resource/setting changes.

Dictionary candidate 2026.10.20.3

The user chose only individually checked word/reading pairs, accepting smaller coverage. japanese_dictionary_reviewed_readings.json is a model-assisted lexical candidate ledger against CMU phones/Japanese usage, not independent human/native-speaker sign-off. Maintainer lexical review, accent and listening acceptance remain pending.

  • 129 rows / 127 distinct words, from 129 ledger words after base ownership and conservative quarantine. Every stored reading/pronunciation field must match an exact allowed pair; another variant of a checked word is not automatically allowed.
  • Known whole words remain owned by the independent pinned base dictionary. Old full-data candidates lacking the ledger are rejected. Personal/legacy CSVs remain separate explicit local inputs.
  • CMU quarantine still reproduces 1,557 direct flags plus 112 variants, including known false positives. It is secondary screening, not a correctness oracle. Unreviewed source/correction rows are research inputs and cannot enter the official CSV.
  • Preserve source costs and the existing complete-token boundary contract; no runtime per-word reading exceptions. Only exact registered official tokens are bounded, preventing mode/model and con/icon intrusion.
  • Provenance retains source/CMU/base/ledger hashes, allowed pairs, aggregate exclusions and an excluded-row-set hash. Rejected source readings are not copied into the resource metadata. Complete MIT/BSD/AGPL notices remain.

The English gate independently reads the source ledger and checks every released word in three production clean_text contexts (381 checks), all 129 row memberships and 127 frontend/prosody comparisons. 303 common-word controls include 190 unlisted words required to preserve baseline phones. Also: 52 baseline controls, 32 additional units, 814 base-owned surfaces × 3 contexts, and 26 externally reported sentence contexts. The gate passes with no unit-prosody changes.

Help/learn/Two/with/Production retain correct base readings; let’s uses レッツ. Unreviewed model/welcome/directly/reset/deadline and the new interior-shift examples fall back to the base, sometimes letter spelling. Coverage is deliberately smaller. The former “290 common words passed” wording was incorrect: most were coverage records, not correctness assertions. That claim and the old 125,306-row release candidate are retired.

Context-reading quality remains blocked

Use the existing pyopenjtalk-plus 0.4.1.post9 API and unchanged tsqyomi v5 weights, pinned to model revision 81add61ddba9669d328e307c883d05d77d60f5f4. CPU/local-only loading, three fixed model-file hashes, upstream Aivis MIT attribution, shared plain/prosody selection and native audio-cache identity remain.

ENABLE_JAPANESE_CONTEXT_READING now defaults false, including with the model installed. Settings/docs identify known regressions and hundreds of MiB of additional process memory, varying with runtime/workload. The external audit confirmed a different measurement baseline; its earlier range is not directly comparable.

The original 88 curated cases did not generalize. Four complete source sentences now extend the strict gate to 92 targets: base 72/92, model 89/92, three failures and two lost base-correct readings. The native quality command exits nonzero; no failure allowlist or runtime four-word blacklist is added.

  • 査読を通った: トオッ → カヨッ (regression).
  • 中立派: base チュウリッパ, model ナカリッパ; both fail whole-compound チュウリツハ. Certifying just 中 would hide the base segmentation defect.
  • 玉は5個: intact production sentence reads タマ correctly. Removing the number in a masked corpus changes the input and produced the reported ギョク result.
  • 仕事だけ止める: トメル → ヤメル for the “stop running Work task” acceptance context. ヤメル is valid in other senses.

The model is not fixed by changing the default. Independent lexical/listening acceptance remains blocked. Model-free CI tests do not certify these weights.

Validation on this revision

The audited code/data head 6e7c9f8af5497f2a342405a4f356b84354d1775b passed all 18 CI checks. Accepted head: de2b5f4a8bbc3b5ee1ff15e7724cca79300dd6d1; all 18 CI checks passed before normal squash merge. Its committed file tree is identical to documentation/settings-copy revision 0d223162b0476b9c455ead69b9058310133f9dc8. The following code/data checks were run on the audited code/data revision; the copy follow-up additionally passed 19 configuration tests, 9 Electron settings tests and the full Electron build.

  • 198 related Python tests passed, plus 124 speech frontend/reference/device tests passed, 1 skipped; 9 Electron settings tests and full npm run build passed.
  • Ruff passes for the PR source. A workspace-wide run also encounters seven errors solely in an unrelated, untracked local benchmark; that file is excluded from this commit. Seven architecture views, README overview and third-party provenance checks pass. Source selection has no scan errors; the local workspace remains intentionally dirty with unrelated work.
  • Build/verify/install with the committed installer into a fresh Japanese path containing spaces: six members, idempotent second install, dictionary production gate passes. Local official dictionary updated; personal/legacy CSVs, .env and unrelated edits preserved by hash checks.
  • A reproducible fresh-process benchmark over the supplied 12,027 local sentences records RSS and Windows private memory separately. Model load added about 312 MiB RSS / 314 MiB private; final increments were about 323 / 318 MiB over warmed base. Absolute final process memory: ~544 MiB RSS / 897 MiB private. No memory reduction or upper bound is claimed. Base/model median ~0.595/1.125 ms, p95 ~1.23/8.91 ms; load ~0.82 s. The 203 changed phone sequences are observations, not correctness labels.
  • The previous 160-Kurisu phone/prosody comparison and six local same-voice V3 waveform integrity checks remain historical evidence only; they did not establish general accuracy or human listening acceptance.

Offline reproduction:

python tools/prepare_japanese_dictionary.py --source GPT_SoVITS/text/ja_userdic/userdict.csv
python tools/validate_japanese_dictionary.py --output output/japanese_dictionary_validation.json
python tools/prepare_japanese_reading.py --source path/to/pinned/v5
# Expected to fail on the three documented targets with the current weights:
python tools/validate_japanese_reading.py --output output/japanese_reading_validation.json
$env:ENABLE_JAPANESE_CONTEXT_READING='false'
python tools/benchmark_japanese_reading.py --corpus path/to/sentences.json --output output/reading_benchmark.json

Local unpublished dictionary ZIP: amadeus-japanese-pronunciation-2026.10.20.3.zip, 94,135 bytes, SHA-256 eb347fa68545056eac8ab9ff7473bfd11c4d1e02e673e64dc5663e574e53ed8c; CSV SHA-256 1becb4959ecaba39ed3886b2bdefb1805cd89210d6c38617de0f0b6b3096571d.
Unchanged local model ZIP: amadeus-japanese-context-reading-2026.10.20.1.zip, SHA-256 d7dc9a0145b99918bb247fe7f73e2c9646e11d48027843d06f5cb376597f2395.

Follow-up external audit

A further model-based external audit on 6e7c9f8 found no additional code or dictionary-data defect, independently checked all 129 row readings and production-context selection, and confirmed installed context weights remain disabled by default. This is additional model evidence, not human/native-speaker sign-off. It corrected the earlier 玉は5個 probe and recognized that 中立派 is already wrong in the base frontend. Two actual model regressions remain.

The copy follow-up removes the incomparable memory range from the settings card and explicitly documents that an existing legacy CSV is loaded as supplied when the official pack is absent; the official checked-reading ledger does not filter that local source. Installing the official pack replaces its role; disabling the dictionary switch uses the base dictionary. Historical source-recipe JSON remains research evidence for future checked-ledger expansion. Runtime behavior, dictionary data and local resource archives are unchanged.

Code acceptance and resource limitations

The maintainer/user has delegated final technical acceptance and authorized normal merge after checks. Technical acceptance found no new code or lexical-data blocker on the exact head de2b5f4a8bbc3b5ee1ff15e7724cca79300dd6d1. The integration is accepted within its documented optional-install/default-off boundaries. Human lexical/accent/perceptual listening sign-off (including provisional proposer accent) has not been performed; the context weights still fail their documented quality targets. These remain explicit resource-quality limitations, not claimed passing results. The author has chosen to retain the documented default-off context-reading experiment in this PR. The maintainer/user explicitly retained this scope and authorized technical acceptance/merge. GitHub merge policy remains in force; no self-approval is represented as independent review. Its known quality failures stay visible; model-free CI does not certify the weights, and accepting the integration does not authorize model-resource publication. A local upstream report draft was expanded with directly verified shifted rows; a separate model regression draft has a clean native reproduction. Neither was posted. No model weights, voice/recordings, resource ZIPs or unrelated working-tree changes are committed. No dictionary/model resource archive has been published. The code PR was normally squash-merged after all 18 exact-head CI checks passed, at commit 02f485ab7ea4119beac19241831356912d709287.

Final delegated technical acceptance, 2026-10-20

Exact head: de2b5f4a8bbc3b5ee1ff15e7724cca79300dd6d1, synchronized with merged #243. Reused a clean attached worktree at this exact commit to exclude unrelated working-tree changes.

  • Reviewed all 129 stored pronunciations against the checked lexical ledger and pinned CMU evidence; no newly confirmed lexical error. Accents remain source annotations, not native-speaker certification.
  • Clean-worktree relevant dictionary/installation/settings/cache/TTS tests: 269 passed, 4 skipped. Clean Ruff and third-party provenance checks pass. The source boundary check is run on the clean tracked checkout too.
  • Used that commit's installer to verify and install both local six-member ZIPs into a fresh Japanese path with spaces. Second install writes zero files. The production dictionary gate passes all 381 retained-word contexts, 303 common controls and the existing base/unit/report controls. Installed model remains disabled without explicit opt-in.
  • The explicitly enabled model still produces 89/92, with three failing targets / two lost base-correct readings. That report is retained unchanged as a known experiment-quality limitation.
  • Generated 12 new same-character/reference/seed dictionary-off/on waveforms covering follower/learner, mode/icon/application, proposer/request, Help/model, ordinary Japanese and numeric units. All are finite, nonempty 24 kHz WAVs with zero clipped samples. This is waveform/integration evidence; no perceptual listening or emotional-naturalness claim is made. Private voice/reference/audio stays local.
  • Inspected actual main and PR voice settings through an isolated local browser preview, saved before/after screenshots locally, and verified the context setting visibly defaults off with the memory/known-regression/restart text. Browser preview does not claim Electron bridge persistence; the settings tests/build cover that contract.

Acceptance decision: suitable for code integration under the documented optional boundaries, after all 18 exact-head CI checks passed and the normal repository merge endpoint accepted the request. This decision does not approve or publish dictionary/model resource releases, remove the known model failures, or fabricate independent human listening sign-off.

Final result: normally squash-merged into main as 02f485ab7ea4119beac19241831356912d709287 on 2026-10-20. The clean source boundary check passed with 4,152 selected / 127 excluded paths and zero errors or warnings. Repository protection settings were unchanged. No independent reviewer approval or human listening sign-off is fabricated.

The proposer English phonemes were additionally checked against Cambridge pronunciation; this supports the lexical review only, not a Japanese pitch-accent certification.

@Lucas1479 Lucas1479 changed the title feat(tts): add optional Japanese pronunciation dictionary pack feat(tts): add optional Japanese dictionary and contextual readings Oct 19, 2026
@Lucas1479 Lucas1479 changed the title feat(tts): add optional Japanese dictionary and contextual readings feat(tts): add checked Japanese dictionary and default-off reading experiment Oct 20, 2026
Lucas1479 added a commit that referenced this pull request Oct 20, 2026
…es (#243)

## What and why

The required dependency audit now rejects main's aiohttp 3.14.3 pin
following
the published advisories. Update aiohttp to 3.14.4 and its minimum
required yarl
to 1.25.1. These are the only two changed package versions in the lock.

This extracts the dependency-only patch from draft #237 so security
maintenance
does not depend on the Japanese pronunciation resource review.

Upstream: [advisory](GHSA-2g87-pp6c-29x5),
[3.14.4
release](https://github.com/aio-libs/aiohttp/releases/tag/v3.14.4).

## Change class

- [x] Routine dependency maintenance

Owning layer: dependency pins and generated lock.

User-visible effect: patched HTTP dependencies; no feature/configuration
change.

Compatibility: yarl's required minimum follows aiohttp. Speech/GPU pins
and
optional profile selections are unchanged.

## Evidence

- Clean main-based branch: 98 profile/environment, loopback HTTP and
gateway
  lifecycle tests passed.
- `uv lock --check --offline` passes; inspected lock changes show only
aiohttp
  3.14.3 → 3.14.4 and yarl 1.24.5 → 1.25.1.
- Exported locked core/dev requirements pass pip-audit with the existing
pytest
  exception unchanged; no new vulnerability suppression.
- The same dependency patch also passed all 18 checks on #237's e59c6fc
head.
  This PR's fresh CI is tracked independently.

## Final check

- [x] One coherent maintenance change, two source files only
- [x] No runtime fallback, feature, model, voice material or local state
included
@Lucas1479
Lucas1479 marked this pull request as ready for review October 20, 2026 07:08
@Lucas1479
Lucas1479 merged commit 02f485a into main Oct 20, 2026
18 checks passed
@Lucas1479
Lucas1479 deleted the codex/japanese-pronunciation-dictionary branch October 20, 2026 07:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant