{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# JMangaTranslator-Fast v1\n", "\n", "Japanese → Simplified Chinese translation of manga speech bubbles, one bubble at a time.\n", "日译简中漫画对话框翻译,一次翻译一个框。\n", "\n", "- **Colab**: Runtime → Change runtime type → **T4 GPU**.\n", "- **Kaggle**: Settings → Accelerator → **GPU T4**, and turn **Internet** on.\n", "- Without a GPU the notebook runs on the CPU with ONNX Runtime (slower). 没有 GPU 时改用 CPU 上的 ONNX Runtime(较慢)。\n", "\n", "Model card: https://huggingface.co/muscgab/JMangaTranslator-Fast" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "# 1. Install dependencies (PyTorch is preinstalled on Colab and Kaggle)\n", "import subprocess, sys\n", "import torch\n", "\n", "GPU = torch.cuda.is_available()\n", "pkgs = [\"transformers>=5.14\", \"safetensors\", \"sentencepiece\", \"tokenizers\", \"huggingface_hub\"]\n", "if not GPU:\n", " pkgs.append(\"onnxruntime\")\n", "subprocess.run([sys.executable, \"-m\", \"pip\", \"install\", \"-q\", *pkgs], check=True)\n", "print(\"GPU:\", torch.cuda.get_device_name(0) if GPU else \"none, using the CPU (ONNX Runtime)\")" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "# 2. Download only the files this runtime needs (about 1.5 GB)\n", "from huggingface_hub import snapshot_download\n", "\n", "files = [\"config.json\", \"vocab.json\", \"joint.model\", \"tokenizer/*\", \"jmt_fast/*\", \"translate.py\"]\n", "files += [\"model.safetensors\", \"norm_scales.json\"] if GPU else [\"onnx/*\"]\n", "path = snapshot_download(\"muscgab/JMangaTranslator-Fast\", allow_patterns=files)\n", "print(path)" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "# 3. Load the model once (CUDA Graphs fp16 on a GPU, ONNX Runtime on the CPU)\n", "import time\n", "sys.path.insert(0, path)\n", "from jmt_fast import load, pick\n", "\n", "t = time.perf_counter()\n", "tr = load(path)\n", "tr.translate(\"こんにちは\") # warm-up: the first call is slower\n", "print(f\"backend: {pick()}, loaded in {time.perf_counter() - t:.1f} s\")" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "# 4. Translate. Each call is one speech bubble; remove line breaks inside a bubble first.\n", "bubbles = [\n", " \"堪忍袋の緒が切れた!\",\n", " \"お前、まだそんなこと言ってるのか?\",\n", " \"今日こそ決着をつけてやる!\",\n", " \"べ、別にあんたのためじゃないんだからね!\",\n", " \"腹減ったなあ……\",\n", "]\n", "for b in bubbles:\n", " t = time.perf_counter()\n", " out = tr.translate(b)\n", " print(f\"{1000 * (time.perf_counter() - t):6.1f} ms {b} → {out}\")" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "# 5. Your own text\n", "print(tr.translate(\"ここに日本語のセリフを入力してください\"))" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "# 6. A file with one bubble per line: input.txt → output.txt\n", "from pathlib import Path\n", "\n", "src = Path(\"input.txt\")\n", "if src.exists():\n", " lines = src.read_text(encoding=\"utf-8\").splitlines()\n", " Path(\"output.txt\").write_text(\"\\n\".join(tr.translate(x) if x.strip() else \"\" for x in lines) + \"\\n\", encoding=\"utf-8\")\n", " print(f\"translated {len(lines)} lines → output.txt\")\n", "else:\n", " print(\"Upload input.txt (one bubble per line) and run this cell again.\")" ] } ], "metadata": { "accelerator": "GPU", "colab": { "gpuType": "T4", "provenance": [] }, "kernelspec": { "display_name": "Python 3", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 0 }