Instructions to use DanVP/MoxhiMT-30-Tag with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use DanVP/MoxhiMT-30-Tag with Transformers:
# Use a pipeline as a high-level helper # Warning: Pipeline type "translation" is no longer supported in transformers v5. # You must load the model directly (see below) or downgrade to v4.x with: # pip install "transformers<5.0.0" from transformers import pipeline pipe = pipeline("translation", model="DanVP/MoxhiMT-30-Tag")# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForSeq2SeqLM tokenizer = AutoTokenizer.from_pretrained("DanVP/MoxhiMT-30-Tag") model = AutoModelForSeq2SeqLM.from_pretrained("DanVP/MoxhiMT-30-Tag", device_map="auto") - Notebooks
- Google Colab
- Kaggle
MoxhiMT-30-Tag (zh→vi translation with entity tags)
A Chinese → Vietnamese translation model (37M parameters) that marks proper names in its own output. One model and one decoding pass give the translation and the names. You do not need a second NER model.
苏夜祭出赤霄剑,剑光一闪,将对面那面玄冥盾劈成两半。
<PER>Tô Dạ</PER> tế ra <ITEM>Xích Tiêu Kiếm</ITEM>, kiếm quang lóe lên, chém tấm <ITEM>Huyền Minh Thuẫn</ITEM> đối diện thành hai nửa.
| Tag | Meaning | Examples |
|---|---|---|
PER |
person | Hàn Lập, Mộ Vân Yên |
LOC |
place | Thiên Nam Thành, Hoàng Phong Cốc |
ORG |
organization: sect, clan, guild, country | Lạc Vân Tông, Thiên Cơ Các |
ITEM |
named item: treasure, weapon, pill, technique, formation, scripture | Xích Tiêu Kiếm, Cửu Chuyển Hoàn Hồn Đan |
Generic words ("kiếm", "đan dược") do not get an ITEM tag; only names do.
Status: experimental. This is a variant of MoxhiMT-30
v4.0. It is not a drop-in replacement: the vocabulary has 24,008 entries (24,000 + 8 tag
tokens), and the raw output contains tags that you must post-process (see below). ITEM is
the newest and weakest type. Nobody has done a blind human review of this model yet.
Quick start
# pip install transformers sentencepiece torch huggingface_hub
import sys
from pathlib import Path
from huggingface_hub import hf_hub_download
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
repo = "DanVP/MoxhiMT-30-Tag"
tok = AutoTokenizer.from_pretrained(repo)
model = AutoModelForSeq2SeqLM.from_pretrained(repo)
# moxhi_tag.py: plain-Python tag post-processing (about 200 lines, no dependencies).
sys.path.insert(0, str(Path(hf_hub_download(repo, "moxhi_tag.py")).parent))
import moxhi_tag as mt
tagged, plain, names = mt.translate(model, tok, "慕云烟是落云宗的长老,她来自天南城。")
print(tagged) # <PER>Mộ Vân Yên</PER> là trưởng lão của <ORG>Lạc Vân Tông</ORG>, nàng đến từ <LOC>Thiên Nam Thành</LOC>.
print(plain) # Mộ Vân Yên là trưởng lão của Lạc Vân Tông, nàng đến từ Thiên Nam Thành.
print(names) # [('PER', 'Mộ Vân Yên'), ('ORG', 'Lạc Vân Tông'), ('LOC', 'Thiên Nam Thành')]
mt.translate uses beam search with 4 beams and max_length=512, the setting of all scores
below. Translate long text one sentence or one short paragraph at a time.
Post-processing
The tags are 8 special tokens (ids 24000–24007). Remove the <pad> and </s> ids, then decode
with skip_special_tokens=False (mt.translate also removes <s> and <unk>). The raw string
has extra spaces around the tags:
text = "韩立呈上青冥剑和一枚记载着《太玄丹经》的玉简,殿中众人无不动容。"
out = model.generate(**tok(text, return_tensors="pt"), num_beams=4, max_length=512)
ids = [i for i in out[0].tolist() if i not in {tok.pad_token_id, tok.eos_token_id}]
raw = tok.decode(ids, skip_special_tokens=False)
# '<PER> Hàn Lập</PER> dâng lên<ITEM> Thanh Minh kiếm</ITEM> cùng một ngọc giản ghi chép "<ITEM> Thái Huyền Đan Kinh</ITEM> " , ...'
tagged = mt.postprocess(raw)
# '<PER>Hàn Lập</PER> dâng lên <ITEM>Thanh Minh kiếm</ITEM> cùng một ngọc giản ghi chép “<ITEM>Thái Huyền Đan Kinh</ITEM>”, ...'
mt.postprocess runs three deterministic steps:
normalize_tags: one space before an opening tag, no space inside the tags, no space before closing punctuation.repair_tags: about 2 % of lines have broken tags, for example<LOC>…</ORG>. A closing tag takes the type of the open tag. A closing tag with no open tag is removed. When two tags open in a row, the first opening tag is removed. An opening tag that never closes is removed. The step never changes the text and never creates a new name.tidy_punct: after a closing tag the model writes punctuation as a separate word (</ITEM> "). This step removes the spaces inside《 》and turns an even number of straight quotes into “…” pairs.
Then mt.strip_tags(tagged) gives the plain translation and mt.entities(tagged) gives the
list of (type, name) pairs.
Decoding notes:
- Do not set
no_repeat_ngram_size. It blocks repeated pairs such as</PER> ,and breaks the tags. - Greedy decoding with
repetition_penalty=1.05(the setting of the web demo) also works. The tag scores below were measured with beam 4 only. - Output is about 5 % longer in tokens than MoxhiMT-30 output because of the tags.
Names in the Chinese source (optional)
ner_head/ner_head_l6_linear.json is a small linear classifier (9 BIO labels, 4,041
weights) that reads the encoder state after 6 of the 8 encoder layers and finds the names in
the Chinese source. The encoder runs anyway during translation, so this costs almost nothing.
import json
head = json.load(open(hf_hub_download(repo, "ner_head/ner_head_l6_linear.json"), encoding="utf-8"))
ner = mt.SourceNER(model, tok, head, hf_hub_download(repo, "source.spm"))
print(ner(text)) # [(0, 2, 'PER', '韩立'), (4, 7, 'ITEM', '青冥剑'), (14, 18, 'ITEM', '太玄丹经')]
Offsets are character offsets into the source text. The web demo uses these spans to link each Vietnamese name to its Chinese name (by Sino-Vietnamese reading first, then by order).
Evaluation
Tags in the translation (beam 4, after repair_tags):
| Type | F1 | Precision | Recall | Test set |
|---|---|---|---|---|
| PER | 0.88 | 0.88 | 0.89 | 500 Chinese sentences from 11 novels, 607 gold names |
| LOC | 0.54 | 0.53 | 0.54 | same |
| ORG | 0.68 | 0.70 | 0.67 | same |
| ITEM | 0.68 | 0.69 | 0.67 | 300 other sentences, 250 gold items (95 % CI of F1: 0.62–0.74) |
A tag counts as correct when its type is correct and its Vietnamese text matches the gold name, checked against the Sino-Vietnamese reading of the Chinese name or against a reference rendering (for names that are not read in Sino-Vietnamese).
Names in the source (SourceNER, same test sets): F1 0.84 for PER/LOC/ORG together
(PER 0.90, LOC 0.54, ORG 0.67) and 0.77 for ITEM (precision 0.75, recall 0.80).
Other measurements:
- Well-formed tags before repair: 98.1 % of lines (1,392-line clean test suite). After repair: 100 %.
- Over-tagging: on the 179 test sentences that have no gold PER/LOC/ORG name, 11.7 % get a tag
(some of these are names that the gold labels missed). On item-free sentences, 6.8 % get an
ITEMtag. - Translation (tags removed) against MoxhiMT-30 v4.0 on the 1,392-line clean suite: BLEU −0.13, repetition rate 1.36 % (v4.0: 1.51 %). Only 22 % of lines are word-for-word the same as v4.0; most other lines use different wording.
Caveats:
- The 500-sentence set was also used to choose between training variants, so the PER/LOC/ORG numbers are slightly optimistic. Some of its source sentences are in the training data of the base translation model (without tags).
- The
ITEMgold labels come from a majority vote of three LLMs, followed by a review pass. A human annotator did not label them. - LOC and ORG are much weaker than PER. The same name can get two different readings in two sentences (for example "Mặc Thái Hoàn" and "Mặc Thải Hoàn").
Training
- Start: MoxhiMT-30 v4.0 (Marian, 8 encoder + 2 decoder layers, d_model 448) with tokenizer
v4.0.3, plus 8 new special tokens. The new embedding rows start from the
【/】pieces. - Data: 86,573 different Chinese web-novel sentences, with all test sentences removed. The target of each sentence is the base model's own translation; tags were added from labels on the source side. PER/LOC/ORG labels come from a fine-tuned Chinese NER model. ITEM labels come from two LLMs that had to agree; a third LLM decided the cases where they did not. 28,599 sentences have no name and stay unchanged. In the training file, sentences with LOC/ORG appear 4 times and sentences with ITEM get one more copy (128,467 lines in total).
- 1,000 updates, batch 128, learning rate 3e-5 (linear decay, 50 warm-up steps), label smoothing 0.1, bf16, one RTX 4090, about 2 minutes.
Files
| File | Content |
|---|---|
model.safetensors, config.json, generation_config.json |
Model weights (fp32) and config |
source.spm, target.spm, vocab.json, tokenizer_config.json, added_tokens.json, special_tokens_map.json |
Tokenizer (MoxhiMT-30 v4.0.3 + 8 tag tokens); loads with transformers 4.57 and 5.x |
moxhi_tag.py |
Tag post-processing and the SourceNER helper |
ner_head/ner_head_l6_linear.json |
Linear head for names in the source (layer 6) |
Tag token ids: <PER> 24000, <LOC> 24001, <ORG> 24002, <ITEM> 24003, </PER> 24004,
</LOC> 24005, </ORG> 24006, </ITEM> 24007.
Web demo
moxhi-tag.pages.dev (mirror: Space) runs this model in the browser with WebGPU, with 8-bit weights (37 MB). Text does not leave your computer. It needs Chrome or Edge 113+ on a computer, or Chrome on Android 12+. With 8-bit weights, about 83 % of sentences are word-for-word the same as the fp32 model output.
License
CC-BY-NC-4.0 (research / non-commercial use), the same as MoxhiMT-30.
- Downloads last month
- -
Model tree for DanVP/MoxhiMT-30-Tag
Base model
DanVP/MoxhiMT-30