Mova0.5 pre-release⌕
☰
home / docs / train / Mova's UD dialect and converters

Mova's UD dialect and converters

Gist

Treebanks disagree. UD versions rename labels: obl:tmod became obl:unmarked in 2.15. Single treebanks keep their own habits. Older conversions (PTB and others) follow other conventions. Mova fixes one internal dialect, mova. Every treebank is converted into it before training, and every target is produced from it. Quality on any treebank is measured by converting back and comparing with that treebank's own gold.

Converters are plain markdown: fenced ```convert blocks inside convert.md files. A small deterministic engine in en/src/convert.rs runs them. The engine reuses the matching language of the grammar-check seeds (en/src/expert.rs) and adds from, to and set.

What mova is

Layout

pathholds
dialects/<name>/README.mdwhat the dialect is and how it differs
dialects/<name>/convert.mdrules between mova and a version dialect (ud-2.14, ud-next)
dialects/<name>/seeds/*.mdone decision or difference per file, often with ```rule counters
treebanks/en/<treebank>/convert.mdrules between mova and one treebank's habits (gum, atis, childes, ewt, ...)
en/src/convert.rsthe engine: parser, application order, tree gate, unit tests

A dialect name is any string without whitespace. The name is just what rules put in from: and to:.

When to use

Rule syntax (exactly as parsed)

A rule is one fenced block tagged convert. The tag must be followed by a space or the end of the line, so ```convert-todo blocks are drafts and are ignored. Inside a block every line is field: value. Split happens at the first :, each field sits on one line, and fields cannot repeat. An unknown field is an error. A line without : is ignored, so don't put prose inside the block.

rule: ud-2.14.obl-unmarked
what: obl:tmod, obl:npmod -> obl:unmarked
from: ud-2.14
to: mova
match: t[rel=obl:tmod|obl:npmod]
set: t[rel=obl:unmarked]
source: UD _en/dep/obl-unmarked.md (History)
fieldrequiredmeaning
ruleyesid, unique across all files loaded together
from, toyesdialect names; must differ; no spaces
matchyesnodes name[cond, cond, ...] separated by ;; each binds a different word
requirenoclauses separated by ;, all must hold; alternatives inside a clause joined by or
unlessnosame form; the binding is skipped if any clause holds
setyesactions name[action, action]; name[action] on match nodes
sourceyeswhere the convention comes from (guideline page, treebank README, issue)
whatnoone-line human description

Conditions on a node (comma-separated; lemma, form and affixes compare lowercase; | means "one of"):

Clauses in require / unless:

Example: require: none c[rel~nsubj, head=v]; none c[rel=expl, head=v].

Actions in set:

actioneffect
rel=nmodset DEPREL (a known relation)
upos=ADVset UPOS
xpos=NN / xpos=_set XPOS (PTB tag or _)
lemma=who / lemma=@formset the lemma / lemma = lowercased form
feats+=Case=Accset one feature (replaces its old value; keys stay sorted)
feats-=Caseremove a feature
feats+=Number=@vcopy a feature from node v (no-op if v lacks it)
head=v / head=@v / head=0head becomes node v / v's head / root
misc+=Key=Val / misc-=Keyset / remove a MISC key

Separate actions with , or ; inside the brackets. A value may contain commas after feats+=, lemma= or misc+= (feats+=PronType=Int,Rel).

How rules run:

Steps: add a rule

  1. Find the difference with a counter: count it in the data before you change anything.
  2. Add a ```convert block to the right file:
    • treebanks/en/<treebank>/convert.md for one treebank's habit;
    • dialects/<name>/convert.md for a UD version. Write both directions when the change is reversible (x -> mova and mova -> x). Give the reverse rules from: mova.
  3. Run the forward conversion and read the summary on stderr: rule count, sentences, words, changed words.
  4. Run the round trip x -> mova -> x with convert-check. Every column should show 0 differences unless the reverse is knowingly lossy. Then explain the remainder in the convert.md prose.
  5. Run the engine's tests. repo_rules_all_parse loads every convert.md under dialects and treebanks and fails on any parse error or duplicate id.
  6. Retrain en on the converted data if the rule changes training input (Retrain the English tagger and parser).

Example

# forward: ud-2.14 -> mova, CoNLL-U on stdout, summary on stderr
cargo run --release --manifest-path en/Cargo.toml -- \
  convert dialects/ud-2.14 ud-2.14 mova data/ud/en_eslspok-ud-train.conllu > eslspok-train.conllu

# round trip report (markdown tables: forward changes, what did not come back, per-rule counts)
cargo run --release --manifest-path en/Cargo.toml -- \
  convert-check dialects/ud-2.14 ud-2.14 data/ud/en_eslspok-ud-train.conllu

# a treebank converter: point at its directory and use its dialect name
cargo run --release --manifest-path en/Cargo.toml -- \
  convert treebanks/en/gum gum mova data/ud/en_gum-ud-train.conllu > gum-train.conllu

# engine tests, including "every convert.md in the repo parses"
cd en && cargo test --release convert

The first argument is a directory, searched recursively for files named convert.md (hidden directories and target are skipped), or a single file. convert-check takes the non-mova dialect and needs rules for at least one direction.

On a one-sentence file with yesterday as obl:tmod, the forward run rewrites it to obl:unmarked. The round trip returns it exactly: 1 of 1 restored, 0 differences in every column.

Related checks:

Pitfalls

This page in Markdown → https://md.mova.elamur.ai/free/en/docs/train/dialects-and-converters/