Instructions to use alfaplus/tegami-27B-qw38 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use alfaplus/tegami-27B-qw38 with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
Tegami-27B ยท Japanese Business-Email LoRA
ๆ็ด (tegami) โ a letter. A QLoRA adapter for Qwen/Qwen3.8-27B that writes
Japanese business email the way a Japanese office actually writes it: correct keigo
(ๆฌ่ช), a proper address block (ๅฎๅ), the internal-vs-external register split, ~30-full-width-character
line wrapping, and a real signature (็ฝฒๅ) โ and it does not turn into a keigo firehose
when you only wanted a casual message.
You can prompt it in English or Japanese; the output is Japanese business correspondence.
What makes this release different: it ships with the mechanical evaluation harness that produced every number below โ no LLM judge, no vibes. Three axes, one script, regex/parse-level 0/1 checks (double-keigo, address form, register mismatch, line width, markdown contamination). Point it at the base model and reproduce the delta yourself.
TL;DR
Two held-out test sets, greedy decoding, scored by eval/jp_bizmail_check.py.
| Axis | What it checks | Base Qwen3.8-27B | + Tegami LoRA |
|---|---|---|---|
| Positive โ in-distribution | keigo + email format correct | 0.0% | 95.3% |
| Positive โ novel scenarios | same, on held-out scenes it never saw | 0.0% | 88.2% |
| Negative (veto) | a casual message is not over-formalized | 80โ100% | 100% |
| Preservation | general Q&A / reasoning still works | 100% | 100% |
In-distribution = eval_probes (70), eval_disjoint: scenes and identity pools disjoint from
training. Novel scenarios = wild2_probes (24), a second held-out set disjoint from training,
eval, and the first held-out set. The base model writes fluent Japanese โ it just doesn't
write it as email (markdown, preamble, missing ไปถๅ/ๅฎๅ/็ฝฒๅ, mixed register), which is exactly
the gap this adapter closes. Proofreading (M-rev), the hardest sub-task, goes from 0/8 to 8/8
in-distribution.
Why the "Negative" axis is the headline
Most style LoRAs quietly fail here. If you train a model to love keigo, it starts sprinkling ใใไธ่ฉฑใซใชใฃใฆใใใพใใ onto a text to your friend. Tegami is trained against that with a dedicated negative axis โ a casual message that comes back over-formalized is a failure, not a success โ and it holds at 100%. Measuring this at all is the differentiator.
English-prompt demos (base vs. + LoRA)
Same English instruction, same greedy decoding. Left is the raw base; right is with the adapter.
Prompt (English): Write a business email in Japanese. We delivered sensor units to a client but shipped the wrong quantity. Apologize, explain the correct shipment will arrive on October 15th, and ask for their understanding.
| Base Qwen3.8-27B | + Tegami LoRA |
|---|---|
ไปถๅ๏ผใ้่ฆใใปใณใตใผใฆใใใใฎ็ดๅๆฐ้ใซ้ขใใใ่ฉซใณใจไฟฎๆญฃๅบ่ทใฎใ้ฃ็ตก | ไปถๅ๏ผใปใณใตใผ้จๅ ็ดๅๆฐ้่ชคใใฎใ่ฉซใณใจใๅฏพๅฟใซใคใใฆ |
Prompt (English): Write a Japanese internal email to my manager reporting that a client requested moving up a delivery deadline, and asking for a decision.
| Base Qwen3.8-27B | + Tegami LoRA |
|---|---|
ไปถๅ๏ผใใ็ธ่ซใโโๆงๅใ็ดๆๅๅใใฎๅฏๅฆใซใคใใฆ | ไปถๅ๏ผใใ็ธ่ซใๆ ชๅผไผ็คพใตใณใฉใคใบ้ฃๅใใใฎ็ดๆๅๅใใฎ่ฆ่ซใซใคใใฆ |
Prompt (English): The following Japanese email to a client has keigo mistakes. Point them out and give a corrected version.
ใใคใใไธ่ฉฑใซใชใฃใฆใใใพใใ ใ้ไปใใใ ใใ่ณๆใๆ่ฆใใใฆใใใ ใใพใใใ ใไผบใใใใฆใใใ ใใใใใจใใใใใพใใ
โ ๏ธ Read this before downloading a GGUF
The adapter's delta is small (r=16). Baking it into bf16 weights and then quantizing to 4-bit washes out the most memory-intensive formats first. Measured honestly on the sibling v1 adapter (identical r=16 and pipeline; the effect is general and applies to this release too):
| Serving path | Positive | M-rev (proofreading โ the hardest task) |
|---|---|---|
| transformers (NF4 + adapter) | 91.9% | 6 / 7 |
| merged โ bf16 โ transformers | 91.9% | 4 / 7 |
| merged โ GGUF IQ4_XS | 81.1% | 1 / 7 |
| merged โ GGUF Q4_K_M | 64.9% | 0 / 7 |
The merge step is lossless; the 4-bit GGUF quantization is what costs you. If you serve via
llama.cpp, use a higher-bit quant (Q6_K / Q8_0) or an imatrix quant calibrated on
business-mail text โ the calibration corpus and the build script are in quant/. Do not judge
the adapter by a Q4_K_M GGUF; that is the worst-case path.
Usage
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
base = "Qwen/Qwen3.8-27B"
tok = AutoTokenizer.from_pretrained(base)
model = AutoModelForCausalLM.from_pretrained(base, torch_dtype=torch.bfloat16, device_map="auto")
model = PeftModel.from_pretrained(model, "<this-repo>")
msg = [{"role": "user", "content":
"Write a Japanese business email to Mr. Tanaka at Aoki Trading, "
"proposing three candidate dates for a meeting about the new inventory system."}]
ids = tok.apply_chat_template(msg, add_generation_prompt=True, return_tensors="pt").to(model.device)
out = model.generate(ids, max_new_tokens=700, do_sample=False)
print(tok.decode(out[0, ids.shape[1]:], skip_special_tokens=True))
Loading note: the base is a multimodal-capable architecture. Loading it with plain
AutoModelForCausalLMcan silently drop the text decoder on some builds; verify the adapter actually changes logits (max|ฮlogit| > 0) before trusting an evaluation. The eval script ineval/does this check for you.
What it handles
- ๅฐๆฌ่ช / ่ฌ่ญฒ่ช / ไธๅฏง่ช distinctions; detects and avoids double keigo (ไบ้ๆฌ่ช, e.g. ใใไผบใใใใฆใใใ ใใ).
- Internal (ใ็ฒใๆงใงใ) vs. external (ใไธ่ฉฑใซใชใฃใฆใใใพใ) greeting register.
- Address forms: ใๆงใ for individuals, ใๅพกไธญใ for organizations, ใๅไฝใ for groups, and a job title as its own honorific (ใ็ฐไธญ้จ้ทใ, not ใ็ฐไธญ้จ้ทๆงใ).
- Structure: ไปถๅ โ ๅฎๅ โ greeting โ body โ closing โ signature; ~30-zenkaku line wrap; no markdown in the mail body.
- Proofreading (ๆทปๅ): quotes the wrong form, explains why, gives the corrected version.
Fixed in this release: when the prompt does not supply the recipient's name, the v1 adapter
dropped the address line instead of falling back to ใใๆ
ๅฝ่
ๆงใ/ใๅไฝใ. Adding seeds for exactly
that case raised the held-out positive score from 58.8% โ 88.2% (see notes/ for the full
before/after). The residual failures are a handful of missing address lines in the hardest
name-absent cases โ the direction is right, the coverage isn't yet complete.
How it was built, and why it's synthetic
There is no license-clean corpus of real Japanese business email, and structurally there never will be โ real business mail is confidential. So the data is generated from a spec:
- Hand-written seeds carry the pragmatics (่ช็จ).
- A generator separates the reusable skeleton from surface identity โ companies, names, dates are placeholders drawn from disjoint pools for train vs. eval.
- A curated phrasebook supplies idiomatic set-phrases.
- A mechanical checker gates every generated sample.
No machine-translated Japanese โ translationese is the exact failure mode this project avoids.
The seeds, generator, phrasebook, and checker are all in this repo (corpus/, eval/), so you
can inspect, audit, and extend the data โ not just consume it.
| Method | QLoRA (4-bit NF4), loss masked to assistant turns only |
| Rank | r = 16 / alpha = 32 โ deliberately small; style/format transfer is low-complexity, and low-data + high-rank memorizes templates |
| Targets | all attention + MLP linears (auto), verified no adapter on vision/audio towers |
| Selection | by the mechanical gate, not eval_loss (eval_loss rose while the gate stayed high) |
| Hardware | single RTX 3090 Ti (24 GB) |
Reproduce it
# Self-check the seed corpus (expect 0 high-severity findings)
python eval/jp_bizmail_check.py --ds-dir corpus
# Base vs. adapter, one base load, adapters swapped on top
python eval/eval_jpmail_hf.py --base Qwen/Qwen3.8-27B \
--adapters base=NONE tegami=<this-repo> \
--probes corpus/wild2_probes.jsonl --max-new-tokens 700
Repository layout
adapter_config.json, adapter_model.safetensors the LoRA
corpus/ seeds, generator, phrasebook, keigo-NG table, held-out probes
eval/ jp_bizmail_check.py (the checker) + eval / rescore / compare scripts
quant/ imatrix calibration corpus + build script for domain-calibrated GGUF
notes/ design note + full run log (the numbers, and how they were isolated)
demos/ showcase.html โ visual before/after
License
Apache-2.0, matching the base Qwen/Qwen3.8-27B. The adapter, corpus, generator, and evaluation
harness are released together.
Not affiliated with the Qwen team; "Tegami" is a nickname for this adapter, not a product of the base-model authors.
- Downloads last month
- -
Model tree for alfaplus/tegami-27B-qw38
Base model
Qwen/Qwen3.8-27B