Add create_onboarding_experiments utility#1120
Merged
Merged
Conversation
Parses the onboarding.log from a MT/experiments/_OnboardingRequests folder, selects reference projects that pass parallel-count and alignment-score thresholds, and creates Country/Language/experiment folders containing config.yml and translate_config.yml. Supports single-source and two-source mixed_src experiments, corpus_books derivation from verse_counts.csv (98% completeness rule), and a --dry-run mode. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
After creating experiment folders, print the silnlp.nmt.experiment command for each one and offer to run them (or run directly with --run). Experiments skipped because an identical config.yml already exists are included in the offer, since they may not have been run yet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Enforce distinct src/trg iso codes: when a reference shares the target project's iso, synthesize a non-real, non-NLLB target code (first letter kept, last two letters mutated) and rename the target extract file in MT/scripture (and its MT/terms renderings files) to match. The rename is deferred until an experiment folder is actually created, and the renamed file on disk is reused as the durable record of the code on later runs. - Always exclude --translate-books from corpus_books so no translated text is used for training, warning the user once per distinct set. Explicit book lists are kept verbatim with subtraction selections appended (e.g. NT -> NT;-MAT); complete-mode lists subtract before compaction. - Parse and validate book-list arguments with machine.scripture get_chapters: full silnlp selection syntax is preserved verbatim (ranges, chapter selections, subtractions), comma/space-separated lists are normalised, input is case-insensitive, and invalid book IDs are rejected at the CLI instead of failing at preprocess time. - Add mutually exclusive --no-test (type: train, folder suffix _notest, --test dropped from the run command) and --test100 (test_size: 100, folder suffix _test100) options. - Rename --books to --training-books. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The request argument now also accepts a folder relative to MT/experiments containing a corpus-stats.csv written by silnlp.common.analyze (e.g. an alignment folder like PNG/Taupota/Align), as an alternative to an onboarding request: - The main project is detected as the stem appearing in every row on one side (trg for alignment runs, src for onboarding analyze runs), with reference stems, parallel counts, alignment scores, and scripts taken from the CSV columns. - verse_counts.csv is read from the same folder, so --training-books complete works unchanged. - When the stats folder lies inside the experiments tree, experiments are created next to it (PNG/Taupota/Align -> PNG/Taupota), preserving the existing country/language folder naming; otherwise the location is derived from languageFamilies.json as before. - onboarding.log takes precedence when a folder contains both. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- corpus-stats.csv (probed at the folder top level, then alignments/) is now the preferred input, with onboarding.log kept as the fallback for older request folders. When the log sits next to the CSV, its main-project line orients the CSV direction, so single-reference onboarding CSVs are never misread; without a hint an ambiguous CSV errors and suggests --target. Request folders keep the derived <Country>/<Language> location (the create-next-to-stats rule now explicitly excludes _OnboardingRequests). - New --target argument: an iso code or project name naming the target language regardless of which corpus-stats.csv column it appears in (rows not involving it are ignored; matching two projects that share an iso is an error suggesting the project name). With only a log the value is validated against the log's main project. - Experiment selection: instead of creating all singles automatically and prompting only for >3 mixed pairs, always display one numbered list capped at the top 20 (singles first by alignment, then pairs in best-source-first order) and ask which to create; dry runs list without prompting and report all displayed experiments. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Confirm before renaming: the iso-clash rename of the target extract (and terms renderings) in the shared MT/scripture store now always asks y/N first (defaulting to abort), with a strong warning when --target overrode the analyze run's own target - guarding against renaming a shared reference Bible's extract - and a caution when the target's iso is an NLLB language code. - Soft log hint with a fallback chain: if the log-derived main-project hint does not fit the CSV, warn and fall back to auto-detection, then to parsing the log itself, so a stale or partial corpus-stats.csv never breaks a folder that previously worked. An explicit --target remains authoritative. parse_log_main_name streams the log and tolerates non-UTF-8 bytes. - Skip CSV rows with missing statistics (analyze writes empty counts when original extracts are absent) instead of crashing on NaN. - Location rules: the create-next-to-stats rule no longer applies to folders directly under MT/experiments (was writing to the tree root), to request folders identified by their onboarding.log (not just the _OnboardingRequests name), or when --target flipped the target language (a note is printed and the derived location used). - --target matching: 2- and 3-letter iso forms are equivalent (fra matches fr- stems), and a target matching both sides of a row is an explicit ambiguity error instead of silently picking src. - Selection: duplicate numbers are deduplicated (a repeat was submitted twice), an empty selection prints "No experiments selected.", and a new --top flag (default 20) lifts the hard display ceiling. The tool stays deliberately interactive - no non-interactive escape flags. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- The synthetic-iso handling now copies the target extract file (and its terms renderings) to the new stem, keeping the originals - they may be referenced by other experiments and tools, and clashes are rare enough that the duplicate file is not a concern. The y/N confirmation remains; its warnings are reframed for the copy. The copy on disk stays the durable record of the chosen code, and if the original is re-extracted after the copy was made, a warning says the copy may be outdated (replacing the old both-files-exist error). - --dry-run no longer prints the silnlp.nmt.experiment run commands: nothing will be run, so it only lists the experiments that would be created. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Each chosen source project doubles as the src_project in translate_config.yml, so before the configs are written the tool now verifies that the project folder exists in M/Paratext/projects and that it contains a book file for every book being translated, deriving the file names from the project's Settings.xml naming convention via FileParatextProjectSettingsParser (the same mechanism paratext.py uses). A missing project or missing books produces a warning and an interactive offer to translate from a different project - the replacement is checked the same way - or to keep the original and proceed. The replacement only affects src_project in translate_config.yml; the training config keeps the original extract stems. Dry runs print the warnings without prompting. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
TaperChipmunk32
self-requested a review
July 20, 2026 16:05
TaperChipmunk32
approved these changes
Jul 20, 2026
TaperChipmunk32
left a comment
Collaborator
There was a problem hiding this comment.
This will be a good foundation for me to add automatic model building to the automated onboarding requests sometime later this year.
@TaperChipmunk32 made 1 comment.
Reviewable status: 0 of 3 files reviewed, all discussions resolved.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
silnlp/common/create_onboarding_experiments.py, a utility that turns a production Serval onboarding request into ready-to-run NMT experiment folders.Given a request folder name in
MT/experiments/_OnboardingRequests/, it:onboarding.logfor the main project and every aligned reference project (both the request's onboarded references and the standard alignment set), collecting verse counts, parallel counts, alignment scores, and scripts.assets/languageFamilies.jsonand creates<Country>/<Language>/folders (title case, underscores for spaces/hyphens).--min-parallel, default 2000;--min-alignment, default 0.2) and creates one experiment per passing reference plus two-sourcemixed_srccombinations ordered by alignment score (interactive selection when more than 3 pairs qualify).config.yml(NLLB lang codes, with<iso3>_<script>fallback for languages not in NLLB) andtranslate_config.yml(one translate entry per source project).corpus_bookscomes from--training-books, either a book selection orcomplete, which derives the books fromverse_counts.csvusing a 98% completeness rule.silnlp.nmt.experimentcommand for each experiment and offers to run them (--runskips the prompt). Experiments skipped because an identicalconfig.ymlalready exists are still offered, since they may not have been run yet.--dry-runto report everything without creating files (run commands are not printed — nothing will be run).Distinct src/trg iso codes
The src and trg isos of a corpus pair must differ (silnlp would otherwise collapse both sides into one NLLB language token). When a passing reference shares the main project's iso — e.g. a closely related language whose translation team uses the major language's code — the tool synthesizes a target code that is neither a real iso nor in NLLB (first letter kept, last two letters mutated) and copies the target extract file in
MT/scripture(plus itsMT/termsrenderings files) to the new stem, keeping the originals. The copy is deferred until an experiment folder is actually created, so a run that creates nothing leaves the shared store untouched, and the copied file on disk is the durable record: later runs reuse the same code even if the clash is no longer visible under different thresholds.Translated books are excluded from training
Books in
--translate-booksare always excluded fromcorpus_books, so none of their text is used for training (a config that trains on the books it translates looks invalid even when the target books are empty). Explicit book lists are kept verbatim with subtraction selections appended (NT→NT;-MAT,GEN-DEU→GEN-DEU;-EXO, chapter selections subtract exactly the selected chapters);completemode subtracts before NT/OT compaction. The user is warned with the list of excluded books.Book-list arguments
--training-booksand--translate-booksare parsed and validated withmachine.scripture.get_chapters: the full silnlp selection syntax is preserved verbatim (ranges likeGEN-DEU, chapter selections like"MAT 1-4", subtractions like"NT;-REV"), comma- or space-separated lists are normalised (GEN,RUTworks unquoted), input is case-insensitive, and invalid book IDs are rejected at the CLI instead of failing later at preprocess time.Translation-source checks
Before the configs are written, each chosen source project (the
src_projectin translate_config.yml) is verified: its folder must exist inM/Paratext/projectsand contain a book file for every book being translated, with file names derived from the project's Settings.xml naming convention viaFileParatextProjectSettingsParser. A missing project or book produces a warning and an interactive offer to translate from a different project (checked the same way) or keep the original; the replacement only affects translate_config.yml. Dry runs warn without prompting.Test-set options
--no-testcreates train-only experiments (type: train, folder suffix_notest,--testdropped from the run command);--test100uses a 100-verse test set (test_size: 100, folder suffix_test100). The default remains the standard random 250-verse test set with no suffix.Corpus-stats input (preferred) with log fallback
corpus-stats.csvwritten bysilnlp.common.analyzeis the preferred input — it is the stable machine-readable artifact, whereas the log parser scrapes message wording. The tool probes<folder>/corpus-stats.csvthen<folder>/alignments/corpus-stats.csv, falling back toonboarding.logonly when neither exists (older request folders). Therequestargument therefore also accepts any folder relative toMT/experimentscontaining a stats file — e.g. an alignment folder likePNG/Taupota/Align. The main project is the stem appearing in every row on one side (trg for alignment runs, src for onboarding runs); when a log sits next to the CSV its main-project line orients the direction, so single-reference CSVs are never misread.verse_counts.csvis read from the same folder so--training-books completeworks unchanged. A stats folder inside the experiments tree (but not under_OnboardingRequests) creates its experiments next to itself (PNG/Taupota/Align→PNG/Taupota), preserving the existing country/language folder naming.--target override
--targetnames the target language by iso code or project name, overriding detection: it may match either corpus-stats.csv column (rows not involving it are ignored), iso codes match across their 2/3-letter forms, and matching two projects that share an iso — or both sides of a row — is an error suggesting the project name. With only an onboarding.log the value is validated against the log's main project. When the override flips the direction away from the analyze run's own target, a note is printed and the derived<Country>/<Language>location is used instead of the stats folder's parent.Safeguards
The log-derived main-project hint is soft: if it does not fit the CSV the tool warns and falls back to auto-detection, then to parsing the log itself, so a stale or partial CSV never breaks a previously working folder. CSV rows with missing statistics are skipped with a warning. For a synthetic iso the target extract file (and its terms renderings) is copied to the new stem — the originals are kept, since they may be referenced by other experiments — after a y/N confirmation (default No), with a warning when --target overrode the direction and a caution when the target's iso is an NLLB code. If the original is later re-extracted, a warning flags the copy as possibly outdated. The create-next-to-stats location rule is disabled for request folders, folders directly under MT/experiments, and flipped targets.
Experiment selection
Every run displays one numbered list of possible experiments capped at the top 20 (
--topadjusts the cap) — all single-source experiments first (ranked by alignment), then two-source pairs in best-source-first order — and asks which to create (1,3,all, ornone; duplicates are deduplicated). Nothing is created automatically;--dry-runprints the list without prompting and reports all displayed experiments.Usage
Test plan
tests/test_create_onboarding_experiments.pyusing a real-format fixture log: log parsing, folder naming, NLLB tag resolution, the 98% completeness rule and NT/OT compaction, book-list parsing/validation, translate-book exclusion (plain lists, ranges, chapter selections, complete mode), synthetic iso derivation, deferred extract/terms renames with dry-run and re-run/prior-rename behaviour, test-set variants, index handling and identical-config skipping, corpus-stats parsing (both directions, --target by iso/project/stem, mixed-direction rows, ambiguity detection), CSV-over-log precedence with the log hint, the stats-folder experiment location, the top-20 selection prompt, end-to-end folder/YAML creation, dry-run, and the run-offer behaviour.--dry-runagainst real onboarding request folders (A33_2026_07_02_Request,MKWBe_2026_07_16_Request) and used to create and launch real experiments.🤖 Generated with Claude Code
This change is