How to use from the
Use from the
Transformers library
# 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="ngocdang83/HachimiMT-60-QT")
# Load model directly
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM

tokenizer = AutoTokenizer.from_pretrained("ngocdang83/HachimiMT-60-QT")
model = AutoModelForSeq2SeqLM.from_pretrained("ngocdang83/HachimiMT-60-QT", device_map="auto")
Quick Links

HachimiMT-60-QT: Chinese→Vietnamese translation with a perfectly consistent "convert" voice

🇻🇳 Đọc bản tiếng Việt

The "classical register" edition of HachimiMT-60: it translates Chinese web novels into Vietnamese using the truyện convert pronoun register — ta, ngươi, hắn, nàng, tỷ tỷ, ca ca… (the archaic Sino-Vietnamese address style that Vietnamese web-novel readers know by heart) — and keeps that voice perfectly stable from the first line of a chapter to the last.

What's new in v1.1 (2026-09-12)

Same model, same tokenizer, same files — drop-in. v1.1 was continue-trained for 2,000 steps on 5,380 hand-mined sentences covering "long-tail" phrases the previous version got wrong: verb-object idioms (背黑锅, 敲竹杠, 碰钉子, 钻牛角尖, 狮子大开口, 翻旧账 …), the four-character 宁缺毋滥 (v1.0 turned it into a fake name "Ninh Khuyết"), the literary causative 教 ("khiến", not "dạy"), 莫不 / 讨X / 凛然-type words — each with contrast sentences so the ordinary senses (教 = to teach, names containing 莫/宁) stay intact — plus 30k replay sentences from the original data so nothing else moves.

Real output, CTranslate2 INT8, beam 1 (the settings shipped below):

Source v1.0 v1.1
宁缺毋滥,这才是王者的傲气。 Ninh Khuyết không có lạm dụng, đây mới là ngạo khí của bậc vương giả. Thà thiếu chứ không lấy bừa, đây mới là ngạo khí của bậc vương giả.
老黄满脸不忿地说道:“就不怕他们狮子大开口? Lão Hoàng mặt mũi tràn đầy bất mãn nói: “Không sợ bọn hắn mở miệng sư tử sao? Lão Hoàng mặt đầy không phục nói: "Không sợ bọn hắn hét giá trên trời sao?"
四名顶尖高手,心中凛然,如临大敌。 Bốn cao thủ đỉnh cao, trong lòng nghiêm nghị, như đối mặt với đại địch. Bốn cao thủ đỉnh cao, trong lòng rúng động, như lâm đại địch.
‘轻轻吻着你的脸,教我如何不想她’ 'Nhẹ nhàng hôn lên mặt ngươi, dạy ta làm sao không nhớ nàng' 'nhẹ nhàng hôn lên mặt ngươi, khiến ta làm sao không nghĩ nàng'
之前他有意收买沈薇,却碰了一鼻子灰,…… Trước đó hắn có ý mua chuộc Thẩm Vi, lại bị ăn một phát bụi, … Trước đây hắn cố ý mua chuộc Thẩm Vi, lại chuốc lấy thất vọng, …

Measured, v1.0 → v1.1, identical decoding settings:

  • Blind review by two independent reviewers, 192 new sentences built around these phrases: mean error severity 0.92 → 0.59; v1.1 better on 46 sentences, worse on 14. On the 175-sentence pack from the first round: 1.01 → 0.50 (53 better / 10 worse).
  • Voice consistency (the reason this model exists): still 0 flips in every pronoun class on the 7-chapter test; coverage of the you class 0.92 → 1.00.
  • General quality, 1,392-sentence clean suite: BLEU 51.4 → 52.4; repetition rate 0.79 % unchanged; latency unchanged. Rare-name guard (49 hard sentences): BLEU 56.4 → 57.9, name-anchor pass rate unchanged. Name-calibration gate 223/230 unchanged.

Still weak, so you know: 敲竹杠 in some contexts is still literal ("gõ thanh tre"), 放鸽子 is still literal, 莫不 right after a list of places can come out as a name ("Mạc Bất"), and rare names can still shift a syllable or lose capitalisation ("Tô đạm Nguyệt").

Need the previous weights? Pin the tag: revision="v1.0" (works with from_pretrained and snapshot_download).

What's different from the base model?

Ordinary MT models (including base HachimiMT-60) have a habit that drives novel readers crazy: they switch address style mid-chapter. The same character is "ngươi" (archaic you) in one line and suddenly "cậu" (modern you) in the next; the narrator says "ta" (I, archaic) in one paragraph and "tôi" (I, modern) in another.

This QT edition was trained on data whose entire pronoun system was normalized, so the voice never flips. Real output, same chapter, same interview scene (base HachimiMT-60 vs this model):

Source Base model QT model
你为什么要报考我们的学校? Tại sao ngươi lại muốn thi vào trường của chúng ta? Ngươi vì sao phải thi vào trường của chúng ta?
你成绩没有问题…… (very next line) Thành tích của cậu không thành vấn đề… ← voice flips! Thành tích của ngươi không có vấn đề…
我来给你介绍介绍这里的福利吧 Để tôi giới thiệu … cho cậu nhé, chúng tôi Để ta giới thiệu … cho ngươi nhé, chúng ta
张羽……他感觉…… (narration) Trương Vũ… cậu cảm thấy… ← modern "cậu" in narration Trương Vũ… hắn cảm thấy…

Measured on 7 chapters across 7 genres (538 lines): in the you-register class the base model flips voice at ~24% of line transitions; this model: 0%. The I, we and third-person classes also drop to zero.

Stress tests

Four pronouns in one sentence — nothing gets mixed up:

他说你不懂她的心思,我们都别插手了。 → Hắn nói ngươi không hiểu tâm tư của nàng, chúng ta đều đừng nhúng tay vào nữa. (he→hắn, you→ngươi, she→nàng, we→chúng ta)

A long multi-clause paragraph — where the base model mixes two voices inside a single paragraph:

张羽同学,我们了解到你的家庭情况恐怕不足以负担这边的学费。不过我们为贫困生提供了优惠的贷款服务,只要你愿意抵押一些不重要的器官就行……

Translation
Base Bạn học Trương Vũ, chúng tôi hiểu được tình hình gia đình của bạn… Tuy nhiên, chúng ta đã cung cấp dịch vụ vay… chỉ cần bạn… ← two registers in one paragraph
QT Trương Vũ đồng học, chúng ta biết được tình hình gia đình của ngươi… Nhưng chúng ta đã cung cấp dịch vụ vay vốn ưu đãi… chỉ cần ngươi chịu thế chấp một số nội tạng không quan trọng là được...

When to use it

  • ✅ Xianxia, xuanhuan, historical, danmei — or any genre where you want the convert voice all the way through.
  • ⚠️ Modern-setting stories also come out in the archaic voice ("Sao ngươi chưa nghỉ ngơi?") — that is by design. If you want context-appropriate natural register instead, use the base model.

Deliberate trade-offs (documented so nothing surprises you):

  • 我们/咱们 both become "chúng ta" (the inclusive/exclusive we distinction is dropped).
  • Modern intimate address (anh/em between lovers) mostly becomes ta/ngươi.

Known limitations (real example, not hidden)

Rare proper nouns and coined terms can come out with a shifted syllable, a lower-case syllable or a literal translation — a limitation of every model in this size class, not specific to the QT edition. Examples from v1.1: the spirit-beast name 【异瞳金丝猴】 (reference: Dị Đồng Kim Ty Hầu) comes out as "Kim Ti Hầu"; the character 苏淡月 (Tô Đạm Nguyệt) once came out as "Tô đạm Nguyệt"; the Western name 泰尔齐奇 came out half-transliterated ("Til Tề Kỳ"). If your novel is full of first-time rare names, spot-check them.

Quick start (Python)

from transformers import AutoTokenizer, MarianMTModel
import torch

repo = "ngocdang83/HachimiMT-60-QT"
tokenizer = AutoTokenizer.from_pretrained(repo)
model = MarianMTModel.from_pretrained(repo).eval()

src = "你成绩没有问题,但想要进嵩阳高中,光靠校内考试成绩是远远不够的。"
inp = tokenizer(src, return_tensors="pt", truncation=True, max_length=256)
with torch.inference_mode():
    out = model.generate(**inp, max_new_tokens=300, num_beams=4, early_stopping=True)
print(tokenizer.decode(out[0], skip_special_tokens=True))
# "Thành tích của ngươi không có vấn đề gì, nhưng muốn vào trường trung học
#  Tung Dương, chỉ dựa vào điểm thi trong trường thì còn xa mới đủ."

💡 Decoding tip: do not set no_repeat_ngram_size with this model — it forces the decoder to avoid repeating n-grams and tends to mangle proper names (Lý Giáng Thiên → Lý Giáng Dương). The defaults above are what we ship with.

Fast CPU inference (CTranslate2)

The repo ships an INT8 export under ct2-int8_float32/ — several times faster on machines without a GPU:

import ctranslate2
from pathlib import Path
from huggingface_hub import snapshot_download
from transformers import AutoTokenizer

repo = "ngocdang83/HachimiMT-60-QT"
path = Path(snapshot_download(repo, allow_patterns=[
    "config.json", "source.spm", "target.spm", "vocab.json",
    "tokenizer_config.json", "ct2-int8_float32/*",
]))
tokenizer = AutoTokenizer.from_pretrained(path)
translator = ctranslate2.Translator(str(path / "ct2-int8_float32"),
                                    device="cpu", compute_type="int8_float32")

src = "你放心吧,人家是大公司,不会骗人的。"
toks = tokenizer.convert_ids_to_tokens(tokenizer(src).input_ids)
res = translator.translate_batch([toks], beam_size=1, max_decoding_length=256)
print(tokenizer.decode(tokenizer.convert_tokens_to_ids(res[0].hypotheses[0]),
                       skip_special_tokens=True))
# "Ngươi yên tâm đi, người ta là công ty lớn, sẽ không lừa người đâu."

The Hachimi family

Model Use when
HachimiMT-60-zh-vi Natural, context-dependent register
HachimiMT-60-QT (this) One perfectly stable convert voice
Demo Space Try it in the browser

Technical details (56.96M params, Marian encoder-decoder, runs fine on CPU or GPU) are in config.json. License CC-BY-4.0 — use freely with attribution.

Downloads last month
380
Safetensors
Model size
56.4M params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Datasets used to train ngocdang83/HachimiMT-60-QT

Spaces using ngocdang83/HachimiMT-60-QT 3