Hy-MT2+OllamaをREST API化し、DeepL代替の翻訳・用語辞書・Markdown保護をコピペ実装。月額コスト比較も掲載。
関連記事としては
Blogローカル翻訳AIHy-MT2とDeepL無料版を5テストで比較した結果Hy-MT2をOllamaで実機検証。DeepL無料版との5テスト比較、1.8Bが7Bに勝った理由、onseバグ修正、スペック別推奨までまとめます。→ もあわせて読むと、今回の論点とのつながりを把握しやすくなります。
TL;DR: この記事の手順どおりに進めれば、設定と導入までひと通り完了できます。詰まりやすい箇所は、その都度補足しています。
この記事では、Hy-MT2 + Ollama の REST API を自前の翻訳APIとして呼び出し、DeepL代替として使う最小構成をそのまま作れます。あわせて、用語辞書ありの翻訳とMarkdownを壊しにくい保護付き翻訳まで、コピペで動く形で載せます。
先に関連回も置いておきます。実際の比較結果は、前回の検証記事
Blogローカル翻訳AIHy-MT2とDeepL無料版を5テストで比較した結果Hy-MT2をOllamaで実機検証。DeepL無料版との5テスト比較、1.8Bが7Bに勝った理由、onseバグ修正、スペック別推奨までまとめます。→ を見てもらうと話が早いです。RTX 4070 Ti 12GB周りの構成感は
BlogGemma 4 MTP drafter を今すぐ入れるべきか? RTX 4070 Ti 12GB でつまずいた3つのポイントと結論RTX 4070 Ti 12GBでGemma 4 MTP drafterを実測。ドラフター0.14GB、ただし最速はvLLMの162.7 tok/s。導入判断を正直にまとめます。→ も参考になります。
DeepL APIは便利ですが、月額固定費と従量課金がじわじわ効きます。しかも、専門用語のブレ、Markdownの崩れ、社外秘文書を外部に出したくない問題は、有料版でもきれいに消えません。ここが現場の悩ましいところです。
この記事の狙いはシンプルです。Hy-MT2 + Ollama で、翻訳・用語辞書・Markdown保護をローカル完結させる。理屈より先に、まず動くものを置きます。
所要時間は、Ollamaの導入済みなら15〜30分です。初回のモデル取得があるなら、もう少しかかります。
環境によってモデル名は変わることがあります。ここは一度、足元を見ておきます。Ollama 側で Hy-MT2 系の取得ができる前提で進めます。
ollama pull hy-mt2
確認します。
ollama list
hy-mt2 が見えればOKです。
Ollama は標準でローカルAPIを持っています。確認はこれで十分です。
curl http://localhost:11434/api/tags
JSONが返れば、APIは動いています。
curl http://localhost:11434/api/generate \
-d '{
"model": "hy-mt2",
"prompt": "Translate to Japanese: The voltage rail is unstable.",
"stream": false
}'
ここで翻訳文が返れば、APIとして使える状態です。
まずは最小構成です。scripts/hy-mt2-translate.py に置く想定で書きます。
# scripts/hy-mt2-translate.py
import sys, requests
MODEL = "hy-mt2"
OLLAMA_URL = "http://localhost:11434/api/generate"
text = " ".join(sys.argv[1:]).strip()
if not text:
print("Usage: python scripts/hy-mt2-translate.py <text>")
raise SystemExit(1)
prompt = f"Translate to Japanese. Keep meaning accurate:
{text}"
r = requests.post(
OLLAMA_URL,
json={"model": MODEL, "prompt": prompt, "stream": False},
timeout=300,
)
r.raise_for_status()
print(r.json()["response"].strip())
python scripts/hy-mt2-translate.py "The voltage rail is unstable."
電圧レールが不安定です。
この1本で、DeepL API の代わりにローカル翻訳の入口ができます。もちろん、これだけだと用語が揺れます。そこで次です。
専門用語がブレる問題は、現場ではかなり地味に効きます。翻訳品質が良くても、rail が「レール」になったり「電源ライン」になったりすると、文書としては使いづらいです。
scripts/hy-mt2-glossary-sample.json の内容です。
{
"glossary": [
{"src": "voltage rail", "dst": "電源レール"},
{"src": "firmware", "dst": "ファームウェア"},
{"src": "throughput", "dst": "スループット"},
{"src": "latency", "dst": "レイテンシ"},
{"src": "fail-safe", "dst": "フェイルセーフ"}
]
}
scripts/hy-mt2-translate.py を少しだけ拡張します。
# scripts/hy-mt2-translate.py
import sys, json, requests, pathlib
MODEL = "hy-mt2"
OLLAMA_URL = "http://localhost:11434/api/generate"
GLOSSARY_PATH = pathlib.Path("scripts/hy-mt2-glossary-sample.json")
text = " ".join(sys.argv[1:]).strip()
if not text:
print("Usage: python scripts/hy-mt2-translate.py <text>")
raise SystemExit(1)
glossary = []
if GLOSSARY_PATH.exists():
data = json.loads(GLOSSARY_PATH.read_text(encoding="utf-8"))
glossary = data.get("glossary", [])
glossary_text = "
".join([f'- {g["src"]} => {g["dst"]}' for g in glossary])
prompt = f"""Translate to Japanese.
Use the following glossary strictly when matching terms:
{glossary_text}
Text:
{text}
"""
r = requests.post(
OLLAMA_URL,
json={"model": MODEL, "prompt": prompt, "stream": False},
timeout=300,
)
r.raise_for_status()
print(r.json()["response"].strip())
python scripts/hy-mt2-translate.py "The voltage rail and firmware affect throughput and latency."
電源レールとファームウェアはスループットとレイテンシに影響します。
この手の辞書は、DeepLの用語集機能に慣れている人ほど価値が分かります。完全に同じではありませんが、ローカルで固定語彙を持てるのは大きいです。
ここが実務で一番面倒です。Markdownはそのまま翻訳すると、リンク、コード、見出し、箇条書きが崩れやすいです。APIを変えても、ここは勝手に綺麗にはなりません。
やり方は単純で、コードブロックやインラインコード、リンクをいったんプレースホルダに退避してから翻訳し、最後に戻します。
# scripts/hy-mt2-translate-md.py
import re, sys, requests
MODEL = "hy-mt2"
URL = "http://localhost:11434/api/generate"
text = " ".join(sys.argv[1:]).strip()
if not text:
print("Usage: python scripts/hy-mt2-translate-md.py <markdown>")
raise SystemExit(1)
store = []
def hold(pattern, src):
def repl(m):
store.append(m.group(0))
return f"__PH_{len(store)-1}__"
return re.sub(pattern, repl, src, flags=re.M)
text = hold(r"```[\s\S]*?```", text)
text = hold(r"`[^`]+`", text)
text = hold(r"\[[^\]]+\]\([^\)]+\)", text)
prompt = f"Translate to Japanese while keeping placeholders unchanged.
{text}"
r = requests.post(URL, json={"model": MODEL, "prompt": prompt, "stream": False}, timeout=300)
r.raise_for_status()
out = r.json()["response"].strip()
for i, item in enumerate(store):
out = out.replace(f"__PH_{i}__", item)
print(out)
python scripts/hy-mt2-translate-md.py "# Title
Use `ollama` and see [docs](https://example.com).
```bash
curl localhost:11434
```"
# タイトル
`ollama` を使い、[docs](https://example.com) を参照してください。
```bash
curl localhost:11434
正直、ここは少し迷いました。完全自動で何でも守るより、**壊れて困る要素だけ守る**ほうが実運用では強いです。
## 実測コスト比較: DeepL API Pro vs ¥0
ここは感情より数字です。DeepLは便利ですが、月間文字数が増えると固定費が効いてきます。Hy-MT2 + Ollama は、少なくともAPI課金はありません。電気代だけです。
※ DeepL API Pro の金額は、ここでは**月額固定費を含む概算**として扱います。契約条件や時期で変わるので、最終確認は自分の契約画面でお願いします。
### 月間文字数別の試算
| 月間文字数 | DeepL API Pro概算 | Hy-MT2 + Ollama | 差分 |
|---:|---:|---:|---:|
| 10万文字 | 約1,200円 | 約0円 | 約1,200円安い |
| 30万文字 | 約1,200円〜+従量分 | 約0円 | さらに差が広がる |
| 100万文字 | 約1,200円〜+従量分 | 約0円 | かなり差が出る |
| 300万文字 | 約1,200円〜+従量分 | 約0円 | 固定費が重い |
### ざっくり判断
- **月10万文字程度**なら、DeepLの固定費はまだ見えます
- **定常的に大量翻訳する**なら、ローカル翻訳の価値が出ます
- **社外秘を外に出せない**なら、コスト以前にローカル一択です
電気代は環境差が大きいので、この記事では「¥0」と表記しました。厳密には0ではありませんが、API課金の議論をするうえでは十分に小さいです。
## どこで詰まりやすいか
### 1. `Connection refused` が出る
Ollama が起動していません。
確認:
```bash
curl http://localhost:11434/api/tags
stream: false を入れているか確認します。長文ならタイムアウトも見ます。
辞書は「入れた」だけでは効きません。プロンプトで強制する必要があります。曖昧な書き方だと、モデルは平気で流します。そこは人間より図太いです。
保護対象を増やしすぎると、今度は文脈が悪くなります。まずは コード・リンク・インラインコード から始めるのが現実的です。
この順で足していくのが無難です。最初から全部盛りにすると、たいていどこかでつまずきます。
ollama list で hy-mt2 を確認curl http://localhost:11434/api/tags でAPI確認python scripts/hy-mt2-translate.py "The voltage rail is unstable." を実行Hy-MT2 + Ollama をREST APIとして使うと、DeepL APIの代替をローカルで組めます。この記事の範囲では、少なくとも次の3つはコピペで動く形にしました。
そして、判断材料として大事なのはここです。
一方で、無条件に置き換わるわけではありません。翻訳品質の細かな好み、運用時のマシンスペック、辞書の手入れは必要です。そこを含めて、「自社の文書パイプラインに入れる価値があるか」を見てください。
次にやることは、この記事の3本をそのまま自分のリポジトリへ置いて、1件だけ実文書で試すことです。そこで崩れるか、辞書が効くか、速度が足りるか。机上で悩むより、その1回のほうが判断は早いです。
エラーメッセージをそのままコピーして検索すると解決策が見つかることが多いです。バージョン違いが原因のケースも多いため、前提条件を再確認してください。
記事内に記載の環境で確認しています。他のOSでの差異は適宜読み替えてください。
HW系エンジニアとして20年以上、10,000件を超える顧客訪問と2,000件を超える単独ソリューション実績。AIツールを使った個人開発やIoT農園など、Raspberry Piを使ったオートメーション化なども実践中です。エンジニア専門結婚相談所も運営中です。
META-MARK × AI
ローカルAIを動かすGPU、ちゃんと選べていますか?
VRAM・性能・コスパをMetaScoreで数値化。AIアプリ別の推奨ハードウェア要件も確認できます。