@luwuer/translator
v1.1.1
Published
Run Tencent Hy-MT2 locally and expose an OpenAI-compatible translation API
Readme
@luwuer/translator
在本机运行翻译模型,默认是腾讯 Hy-MT2 1.8B 的 Q4_K_M 量化(约 1.06 GiB),另有两个更小的可选模型(约 0.67 GiB / 0.45 GiB);三个模型都可在内置 Web 页面里选择、下载并热切换。服务对外提供本地 HTTP 翻译接口:既提供 /translate 简单接口,也提供兼容 OpenAI 的 Chat Completions API,可被本地编辑器扩展或其他工具调用。
模型与推理完全在本机执行,下载完成后无需任何在线推理服务,数据不出本机。npm 包本身不含模型文件:首次运行 translator init 或 translator serve 时会从 Hugging Face 下载权重并校验。
特性
- 本地推理,数据不出本机:模型下载后翻译完全离线,不依赖网络。
- 双接口:
POST /translate,以及兼容 OpenAI Chat Completions 的POST /v1/chat/completions(支持 SSE 流式输出)。 - 模型可切换:内置 Web 页面列出全部模型,可就地初始化下载、热切换;下载支持 HTTP Range 断点续传,并按固定 revision 校验 SHA-256。
- 默认安全:默认只监听回环地址,绑定非回环地址时必须配置 API key;页面经同源
/api代理访问,浏览器里不存 key。
环境要求
- Node.js
^20.19.0 || >=22.12.0;需平台提供node-llama-cpp预编译运行时(若本机没有对应预编译二进制,其依赖可能尝试从源码构建 llama.cpp)。 - 首次下载模型需要网络,以及至少约 1.1 GiB 磁盘空间;运行时还需要额外的内存。
快速开始
从 npm 安装:
npm install -g @luwuer/translator
translator serve在仓库目录开发 / 试用(serve 需要先构建出页面产物):
npm install
npm run build
node src/cli.js init
node src/cli.js serve首次启动时,serve 会先展示模型来源、许可证和文件大小,经确认后下载并校验模型,再加载模型并启动服务;已有模型则直接启动。也可先用 translator init 单独下载。非交互终端在已阅读并接受模型许可证后,可运行 translator serve --yes 或 translator init --yes。
服务默认监听 127.0.0.1:8787,并额外启动内置 Web 页面(默认 127.0.0.1:8788);终端打印的 Web UI: http://127.0.0.1:8788/ 点开即可使用,也可先自测 API:
curl http://127.0.0.1:8787/v1/models
curl http://127.0.0.1:8787/translate \
-H 'content-type: application/json' \
-d '{"text":"Keep the cache entry until the request completes."}'若 --port 指定的端口已被占用,服务会依次尝试后续端口(最多 --port-attempts 个,默认 10)并打印实际使用的端口;顺延后的 API 端口与 web 端口冲突时,web 端口同样自行顺延。只有 EADDRINUSE 会触发顺延,权限不足(EACCES)等错误会直接失败,不会静默换端口。
CLI
| 命令 / 选项 | 说明 |
| --- | --- |
| init | 仅下载并校验模型,不启动服务 |
| serve | 启动 API 服务(模型缺失时先确认许可证并自动下载、校验) |
| --host HOST | 监听地址,默认 127.0.0.1 |
| --port PORT | 监听端口,默认 8787;被占用时自动顺延 |
| --port-attempts N | 端口顺延的最大尝试次数(含首个端口),默认 10 |
| --context-size TOKENS | 上下文长度,默认 4096(最小 512) |
| --api-key KEY | 启用 Bearer Token 鉴权;绑定非回环地址时必填 |
| --model ID | 启动时使用的模型:hy-mt2-1.8b-q4_k_m(默认)/ hy-mt2-1.8b-ud-iq2_m / lmt-60-0.6b-q4_k_m;与 --model-path 互斥 |
| --model-path PATH | 自定义模型文件路径,默认 ~/.cache/translator/models/;指定后禁用模型切换 |
| --web-port PORT | 内置 Web 页面端口,默认取 API 实际端口 + 1 |
| --no-web | 关闭内置 Web 翻译页面,只保留 API |
| --yes | 跳过模型下载确认(须已阅读并接受模型许可证) |
仅在明确需要局域网访问、且已配置网络防火墙或处于可信网络时,用 HY_MT_API_KEY='replace-with-a-long-random-token' node src/cli.js serve --host 0.0.0.0 --port 8787 启动。
环境变量
所有可通过 CLI 配置的项都支持环境变量;同名时以 CLI 参数为准。
| 变量 | 说明 | 默认值 |
| --- | --- | --- |
| HY_MT_HOST | 监听地址 | 127.0.0.1 |
| HY_MT_PORT | 监听端口 | 8787 |
| HY_MT_CONTEXT_SIZE | 上下文长度 | 4096 |
| HY_MT_API_KEY | Bearer Token 鉴权密钥 | 空(回环地址不启用鉴权) |
| HY_MT_MODEL | 启动时使用的模型 id(同 --model,CLI 优先;页面热切换不改变此默认值) | hy-mt2-1.8b-q4_k_m |
| HY_MT_MODEL_PATH | 模型文件路径 | ~/.cache/translator/models/ |
| HY_MT_PORT_ATTEMPTS | 端口顺延最大尝试次数 | 10 |
| HY_MT_WEB_PORT | Web 页面端口 | API 实际端口 + 1 |
| HY_MT_WEB | 设为 0/false/no/off 时关闭 Web 页面 | 启用 |
| HY_MT_CORS_ORIGINS | 逗号分隔的精确 Origin 白名单 | 空(不开放跨域) |
API
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| GET / POST | /health、/v1/models、/translate、/v1/chat/completions | 健康检查、模型列表与翻译接口,详见下文小节 |
| GET | /models | 模型管理快照:全部模型、已安装状态、进行中的下载、是否锁定(页面用 /api/models) |
| GET | /models/events | 模型与下载事件的 SSE 流(首帧全量快照,进度 ≤5 次/秒,15s 心跳) |
| POST | /models/{id}/download | 初始化(下载)指定模型,需 JSON 请求体;同一模型重复调用返回同一个任务 |
| POST | /models/{id}/cancel | 取消该模型进行中的下载(幂等) |
| POST | /models/{id}/activate | 热切换为指定模型;等旧模型在途请求结束后返回 |
写端点(download / cancel / activate)在 --model-path 启动时返回 403 model_switch_locked;启用 --api-key 时需 Authorization: Bearer(页面经反代注入,无需手填)。GET /v1/models 与 /health 语义未变(前者仍只返回当前生效的 1 个模型),管理能力只走 /models*。
POST /translate
{"text": "// Returns the current user's display name", "source_lang": "English", "target_lang": "Chinese"}返回 translatedText。source_lang / target_lang 均使用完整语言名称,默认 English → Chinese。
POST /v1/chat/completions
兼容 OpenAI Chat Completions 的基础结构:
curl http://127.0.0.1:8787/v1/chat/completions \
-H 'content-type: application/json' \
-d '{"model":"hy-mt2-1.8b-q4_k_m","messages":[{"role":"user","content":"// Retry the request after a short delay"}]}'支持 stream: true 的 SSE 输出;支持 max_tokens(默认 1024,最大钳制为 4096);请求中的历史上下文不参与翻译,只取最后一条 user 消息。所有输入都会做长度、JSON body 和排队数量限制;同一时刻只加载一个生效模型,推理串行执行,避免并发创建多个上下文造成资源压力,队列已满时返回 503(server_busy)。
Web 页面
翻译界面:serve 启动后终端打印的 Web UI: http://127.0.0.1:8788/ 就是页面地址,提供源/目标语言下拉与互换、输入框、一键翻译、结果复制,支持 Ctrl/Cmd + Enter 提交,并跟随系统浅色/深色主题。往输入框粘贴内容会自动开始翻译(延迟 300ms 触发,顺带把连续多次粘贴合并成一次请求;若上一次翻译还在进行,用新内容取代它),可用输入框上方的开关关闭,开关状态记在 localStorage。
模型管理(点页面顶部当前模型条的「切换模型」打开弹窗):
- 模型列表:列出注册表中的全部模型,显示体积、许可证、来源标注与状态(未安装 / 排队中 / 下载中 / 已安装 / 当前使用 / 切换中 / 失败)。
- 初始化下载与热切换:未安装的模型可就地下载,行内显示百分比进度;下载期间仍可继续翻译,译文由当前模型生成,可随时取消、已下载部分保留以便续传。点「使用」切换当前模型,页面进入「切换中」,旧模型继续服务在途请求,切换完成后自动生效。
- 只读情形:以
--model-path启动时页面禁用全部写操作,只列出可选模型;失败原因按服务端原文显示,便于判断该换多小的模型。
页面实现与行为:
- 只托管构建产物:页面源码在
src/web/,用 Vue 3 + Element Plus 编写,发布前由npm run build编译成自包含的dist/web/随包分发;运行时不启动 Vite 开发服务器,只托管dist/web/,vue/element-plus/vite/unplugin-*全是构建期devDependencies,npm install -g不会把它们装进用户环境。 - 同源代理:页面经
/api反向代理访问翻译接口(/api/translate→/translate),因此无需配置 CORS,也不会把 API 直接暴露给浏览器跨域请求。 - 端口与容错:默认 API 实际端口 + 1(可用
--web-port覆盖);页面资源全部打进产物、不走任何 CDN;--no-web或HY_MT_WEB=0可完全关闭,启动失败只记日志、不影响 API;产物缺失(未构建就跑)会提示先执行npm run build。
模型
| id | 量化 | 体积 | 来源 | 许可证 |
| --- | --- | --- | --- | --- |
| hy-mt2-1.8b-q4_k_m(默认) | Q4_K_M | 约 1.06 GiB | 腾讯官方 tencent/Hy-MT2-1.8B-GGUF | Apache-2.0 |
| hy-mt2-1.8b-ud-iq2_m | UD-IQ2_M | 约 0.67 GiB | 社区 requant:unsloth/Hy-MT2-1.8B-GGUF(非腾讯官方产出) | Apache-2.0(继承自 base model tencent/Hy-MT2-1.8B) |
| lmt-60-0.6b-q4_k_m | Q4_K_M | 约 0.45 GiB | 社区 requant:mradermacher/LMT-60-0.6B-GGUF(base NiuTrans/LMT-60-0.6B,非 NiuTrans 官方产出) | Apache-2.0 |
来源说明:
hy-mt2-1.8b-ud-iq2_m由社区项目 unsloth 基于腾讯官方权重重新量化得到,并非腾讯官方发布的模型,许可证继承自 base model;lmt-60-0.6b-q4_k_m由社区项目 mradermacher 基于NiuTrans/LMT-60-0.6B(小牛翻译官方权重)重新量化得到,并非 NiuTrans 官方发布的模型。使用前请自行阅读并遵守对应仓库随附的许可证。
lmt-60-0.6b-q4_k_m的 prompt 依赖:该模型严重依赖其模型专属的 prompt 文案格式,用错会大量回吐原文。本服务已为其自动套用专属 prompt 格式(无需任何额外配置);请勿在未回归验证的情况下改它的 prompt 文案。
取舍提示:更小的量化以质量换体积;本服务不保证各模型在具体语料上的翻译质量,请自行评估,不要默认「体积更小 = 更好」。三个模型共存约需
1.06 + 0.67 + 0.45 ≈ 2.18 GiB磁盘(仅默认 Q4_K_M 时无变化)。
选择与切换:默认使用腾讯官方的 Q4_K_M 量化(质量优先)。如需更小的内存/显存占用,有三个入口:启动参数 --model <id>、环境变量 HY_MT_MODEL,以及内置 Web 页面(列出全部已注册模型、可就地初始化未下载的模型、可热切换)。
node src/cli.js serve --model hy-mt2-1.8b-ud-iq2_m
HY_MT_MODEL=hy-mt2-1.8b-ud-iq2_m node src/cli.js serve
node src/cli.js serve --model lmt-60-0.6b-q4_k_m--model 与 --model-path 互斥,不能同时使用。
热切换的代价:切换期间旧模型继续服务(翻译不中断),但新旧权重会短暂并存(默认 1.06 GiB + 目标模型体积),低内存机器有 OOM 风险;切换失败时旧模型保持可用,翻译不受影响。
切换不持久化:只对本次运行有效,重启后回到启动参数指定的模型。以 --model-path 启动时页面的模型写操作一律被禁用(接口返回 403 model_switch_locked),换模型只能改启动参数后重启。
运行时与许可:
| 项 | 说明 |
| --- | --- |
| 模型仓库 | tencent/Hy-MT2-1.8B-GGUF |
| 默认量化文件 | Hy-MT2-1.8B-Q4_K_M.gguf,固定 Hugging Face revision 并校验 SHA-256 |
| 模型许可证 | 仓库标注 Apache-2.0;使用者需自行阅读并遵守模型随附的许可证 |
| 推理运行时 | node-llama-cpp 独立 Node 服务,原生运行时绑定,平台 / Node ABI 兼容性需在目标设备验证;目前尚未承诺所有平台都可开箱运行 |
安全说明
- API key 仅做请求鉴权,不提供 TLS。不要将无 TLS 的服务直接暴露到公网。
- 远程使用时请通过可信 VPN 或带 TLS 的反向代理,并自行设置速率限制与访问控制。
- 绑定到非回环地址(如
0.0.0.0)时,必须配置--api-key或HY_MT_API_KEY,否则服务拒绝启动。 - 启用
--api-key时,页面的/api请求由本地反代注入凭据,浏览器里不存 key;模型写操作要求 JSON 请求体,并拒绝带sec-fetch-site: cross-site的跨站请求。
开发与验证
npm test # 会先构建再跑完整测试
npm run dev # 可选:Vite 开发服务器(HMR),配合 node src/cli.js serve --no-web 使用dist/ 是构建产物、不入库,但会随 npm 包分发(prepack 保证发布前一定重新构建);改动 src/web/ 后必须重新 npm run build,否则运行时托管的仍是旧产物。
测试覆盖 CLI 配置、回环 / 远程鉴权边界、端口占用自动顺延、模型下载校验与断点续传、队列限制、HTTP API 与 SSE,以及 Web 页面(静态产物托管、路径穿越防护、/api 反代、发布产物与运行时依赖边界);模型管理覆盖列表快照、初始化下载与取消、热切换与切换期请求的模型一致性、SSE 进度帧,以及 /api 反代的凭据注入与跨站守卫。推理调用使用 mock,不会下载真实权重,热切换用假 llama 运行时,web 测试用 stub 服务代替真实推理。
许可证
本 npm 包按 MIT 许可证发布;模型权重依其自身许可证单独授权,不随 npm 包分发。
