一、模型介绍
Hunyuan-MT-7B 是腾讯混元团队发布的轻量级翻译模型,参数量仅 70 亿,支持 33 个语种及 5 种民汉语言/方言互译。在国际计算语言学协会(ACL)WMT2025 比赛中拿下 31 个语种比赛中的 30 个第 1 名,表现卓越。模型能精准理解网络用语、古诗、社交对话等,结合语境进行意译,提出了覆盖预训练到集成强化全链条的训练范式。推理速度快,经过腾讯自研 AngelSlim 压缩工具处理后,性能进一步提升 30%。可在多样化硬件环境中部署,成本低。
二、模型部署
快速部署及使用方法,请点击Hunyuan-MT-7B-镜像社区 算家云详细了解
或进入算家云官网,参考 “镜像社区”。
基础环境最低配置推荐
| 环境名称 | 版本信息 |
|---|---|
| Ubuntu | 22.04.4 LTS |
| Python | 3.10 |
| CUDA | 12.1 |
| NVIDIA Corporation | RTX 4090 * |
1.更新基础软件包、配置镜像源
查看系统版本信息
#查看系统的版本信息,包括 ID(如 ubuntu、centos 等)、版本号、名称、版本号 ID 等cat /etc/os-release配置 apt 国内源
#更新软件列表apt-get update这个命令用于更新本地软件包索引。它会从所有配置的源中检索最新的软件包列表信息,但不会安装或升级任何软件包。这是安装新软件包或进行软件包升级之前的推荐步骤,因为它确保了您获取的是最新版本的软件包。
#安装 Vim 编辑器apt-get install -y vim这个命令用于安装 Vim 文本编辑器。-y 选项表示自动回答所有的提示为“是”,这样在安装过程中就不需要手动确认。Vim 是一个非常强大的文本编辑器,广泛用于编程和配置文件的编辑。
为了安全起见,先备份当前的 sources.list 文件之后,再进行修改:
# 备份现有的软件源列表cp /etc/apt/sources.list /etc/apt/sources.list.bak这个命令将当前的 sources.list 文件复制为一个名为 sources.list.bak 的备份文件。这是一个好习惯,因为编辑 sources.list 文件时可能会出错,导致无法安装或更新软件包。有了备份,如果出现问题,您可以轻松地恢复原始的文件。
# 编辑软件源列表文件vim /etc/apt/sources.list这个命令使用 Vim 编辑器打开 sources.list 文件,以便您可以编辑它。这个文件包含了 APT(Advanced Package Tool)用于安装和更新软件包的软件源列表。通过编辑这个文件,您可以添加新的软件源、更改现有软件源的优先级或禁用某些软件源。
在 Vim 中,您可以使用方向键来移动光标,
i 键进入插入模式(可以开始编辑文本), Esc 键退出插入模式,
:wq 命令保存更改并退出 Vim,
或 :q! 命令不保存更改并退出 Vim。
编辑 sources.list 文件时,请确保您了解自己在做什么,特别是如果您正在添加新的软件源。错误的源可能会导致软件包安装失败或系统安全问题。如果您不确定,最好先搜索并找到可靠的源信息,或者咨询有经验的 Linux 用户。
配置国内镜像源(阿里云)
按 “i” 进入编辑模式,将如下内容插入至 sources.list 文件中
deb http://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiversedeb-src http://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiversedeb http://mirrors.aliyun.com/ubuntu/ jammy-security main restricted universe multiversedeb-src http://mirrors.aliyun.com/ubuntu/ jammy-security main restricted universe multiversedeb http://mirrors.aliyun.com/ubuntu/ jammy-updates main restricted universe multiversedeb-src http://mirrors.aliyun.com/ubuntu/ jammy-updates main restricted universe multiversedeb http://mirrors.aliyun.com/ubuntu/ jammy-backports main restricted universe multiversedeb-src http://mirrors.aliyun.com/ubuntu/ jammy-backports main restricted universe multiverse最后,按 "esc" 键退出编辑模式,输入 :wq 命令并按下 “enter” 键便可保存并退出 sources.list 文件
安装常用软件和工具
#更新源列表,输入以下命令:apt-get update#更新系统软件包,输入以下命令:apt-get upgrade#安装常用软件和工具,输入以下命令:apt-get -y install vim wget git git-lfs unzip lsof net-tools gcc cmake build-essential出现以下页面,说明国内 apt 源已替换成功,且能正常安装 apt 软件和工具
2.创建虚拟环境
创建虚拟环境
#创建名为Hunyuan-MT的虚拟环境,python版本:3.10conda create -n Hunyuan-MT python=3.10 -y激活虚拟环境
conda activate Hunyuan-MT3.克隆项目
创建Qwen-Image文件夹
#创建Hunyuan-MT文件夹mkdir Hunyuan-MT#进入Hunyuan-MT目录cd Hunyuan-MT#克隆仓库git clone https://github.com/Tencent-Hunyuan/Hunyuan-MT.git4.下载依赖
pip install -r requirements.txt5.模型下载
转到魔塔社区官网下载模型文件:modelscope.cn/models/Tenc… 模型库。
下载完整模型库
#命令行下载(下载至当前文件夹)modelscope download --model Tencent-Hunyuan/Hunyuan-MT-7B --local_dir /Hunyuan-MT-7B查看
三、web页面启动
采用显卡RTX4090,用如下的app.py文件运行模型。
app.py:
# gradio_demo.pyimport osimport sysimport timeimport signalimport subprocessimport atexitimport psutilimport gradio as grfrom openai import OpenAI# -------------------- 1. vLLM 配置 --------------------MODEL_PATH = "/root/sj-data/LargeModel/Hunyuan-MT-7B"VLLM_PORT = 8021VLLM_CMD = [ sys.executable, "-m", "vllm.entrypoints.openai.api_server", "--host", "0.0.0.0", "--port", str(VLLM_PORT), "--trust-remote-code", "--model", MODEL_PATH, "--gpu_memory_utilization", "0.92", "--tensor-parallel-size", "1", "--dtype", "bfloat16", "--disable-log-stats"]# -------------------- 2. 进程管理 --------------------vllm_proc = Nonedef cleanup(): global vllm_proc if vllm_proc and vllm_proc.poll() is None: print("\n[INFO] 正在关闭 vLLM ...") for child in psutil.Process(vllm_proc.pid).children(recursive=True): child.terminate() vllm_proc.terminate() vllm_proc.wait(timeout=5) vllm_proc.kill()atexit.register(cleanup)signal.signal(signal.SIGINT, lambda *_: cleanup())signal.signal(signal.SIGTERM, lambda *_: cleanup())def wait_port(port, timeout=120): import socket start = time.time() while True: try: with socket.create_connection(("localhost", port), timeout=1): print(f"[INFO] vLLM 端口 {port} 已就绪 ✔") return except Exception: if time.time() - start > timeout: raise RuntimeError("等待 vLLM 超时") time.sleep(1)# -------------------- 3. 启动 vLLM --------------------print("[INFO] 启动 vLLM ...")vllm_proc = subprocess.Popen(VLLM_CMD, stdout=sys.stdout, stderr=sys.stderr)wait_port(VLLM_PORT)# -------------------- 4. Gradio 聊天 --------------------client = OpenAI(api_key="EMPTY", base_url=f"http://localhost:{VLLM_PORT}/v1")SYSTEM_PROMPT = "你是一个乐于助人的中文 AI 助手。"STOP_TOKENS = ["<|im_end|>"]def chat_fn(message, history): msgs = [{"role": "system", "content": SYSTEM_PROMPT}] for h, a in history: msgs += [{"role": "user", "content": h}, {"role": "assistant", "content": a}] msgs.append({"role": "user", "content": message}) stream = client.chat.completions.create( model=MODEL_PATH, messages=msgs, temperature=0.6, top_p=0.9, stream=True, extra_body={"top_k": 20, "repetition_penalty": 1.05, "stop": STOP_TOKENS} ) partial = "" for ch in stream: partial += ch.choices[0].delta.content or "" yield partial# 明亮配色方案的全屏CSS样式custom_css = """/* 全局样式 - 全屏设计 */.gradio-container { max-width: 100% !important; margin: 0 !important; padding: 0 !important; background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%); font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; min-height: 100vh; height: 100vh; overflow: hidden;}/* 标题区域 */.header { text-align: center; padding: 1rem 0; background: rgba(255, 255, 255, 0.9); backdrop-filter: blur(10px); border-bottom: 1px solid rgba(0, 0, 0, 0.1); position: sticky; top: 0; z-index: 100; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);}.header-title { font-size: 1.8rem; font-weight: 700; margin-bottom: 0.25rem; letter-spacing: -0.02em; background: linear-gradient(135deg, #3b82f6 0%, #6366f1 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent;}.header-subtitle { font-size: 1rem; opacity: 0.7; font-weight: 400; color: #64748b;}/* 主容器 */.main-container { height: calc(100vh - 80px) !important; display: flex; flex-direction: column; padding: 0; margin: 0; background: transparent;}/* 聊天容器 - 全屏高度 */.chat-container { background: rgba(255, 255, 255, 0.8); backdrop-filter: blur(12px); border-radius: 0; flex-grow: 1; display: flex; flex-direction: column; height: 100%; border: 1px solid rgba(0, 0, 0, 0.1); margin: 0; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);}/* 聊天历史区域 - 占据大部分空间 */#chatbot { flex-grow: 1; padding: 1.5rem; overflow-y: auto; background: transparent; display: flex; flex-direction: column; gap: 1.25rem; height: calc(100% - 120px) !important; scrollbar-width: thin; scrollbar-color: rgba(59, 130, 246, 0.5) transparent;}/* 自定义滚动条 */#chatbot::-webkit-scrollbar { width: 6px;}#chatbot::-webkit-scrollbar-track { background: transparent;}#chatbot::-webkit-scrollbar-thumb { background-color: rgba(59, 130, 246, 0.5); border-radius: 3px;}#chatbot::-webkit-scrollbar-thumb:hover { background-color: rgba(59, 130, 246, 0.7);}/* 消息气泡样式 */.message { max-width: 75%; padding: 1.25rem 1.5rem; border-radius: 20px; line-height: 1.6; animation: fadeInUp 0.4s ease forwards; position: relative; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08); backdrop-filter: blur(4px);}@keyframes fadeInUp { from { opacity: 0; transform: translateY(20px) scale(0.95); } to { opacity: 1; transform: translateY(0) scale(1); }}/* 用户消息 */.message.user { background: linear-gradient(135deg, rgba(59, 130, 246, 0.9) 0%, rgba(99, 102, 241, 0.9) 100%); color: white; align-self: flex-end; border-bottom-right-radius: 6px; margin-left: auto;}/* AI消息 */.message.bot { background: rgba(255, 255, 255, 0.9); color: #1e293b; align-self: flex-start; border-bottom-left-radius: 6px; border: 1px solid rgba(0, 0, 0, 0.1); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);}/* 消息时间戳 */.message-time { font-size: 0.75rem; opacity: 0.6; margin-top: 0.5rem; display: block;}/* 输入区域 - 固定在底部 */.input-container { padding: 1.5rem; background: rgba(255, 255, 255, 0.9); backdrop-filter: blur(12px); border-top: 1px solid rgba(0, 0, 0, 0.1); display: flex; gap: 1rem; align-items: center; width: 100%; margin: 0; box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);}/* 输入框样式 - 与对话框等宽 */#user_input { flex-grow: 1; border-radius: 24px; padding: 1.25rem 1.5rem; border: 1px solid rgba(0, 0, 0, 0.1); font-size: 1rem; transition: all 0.3s ease; resize: none; background: rgba(255, 255, 255, 0.9); color: #1e293b; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); min-height: 25px;}#user_input::placeholder { color: #94a3b8;}#user_input:focus { border-color: rgba(59, 130, 246, 0.8); outline: none; box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2); background: rgba(255, 255, 255, 1);}/* 按钮样式 */#submit_btn { background: linear-gradient(135deg, #3b82f6 0%, #6366f1 100%); color: white; border-radius: 24px; padding: 1.25rem 2rem; font-weight: 600; transition: all 0.3s ease; border: none; min-width: 100px; box-shadow: 0 4px 15px rgba(59, 130, 246, 0.3); position: relative; overflow: hidden;}#submit_btn::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); transition: all 0.6s ease;}#submit_btn:hover::before { left: 100%;}#submit_btn:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(59, 130, 246, 0.4);}#clear_btn { background: rgba(255, 255, 255, 0.9); color: #64748b; border-radius: 24px; padding: 1.25rem 1.5rem; font-weight: 500; transition: all 0.3s ease; border: 1px solid rgba(0, 0, 0, 0.1); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);}#clear_btn:hover { background: rgba(255, 255, 255, 1); color: #334155; border-color: rgba(0, 0, 0, 0.2);}/* 响应式调整 */@media (max-width: 768px) { .gradio-container { padding: 0; } .message { max-width: 85%; padding: 1rem 1.25rem; } .input-container { padding: 1rem; flex-direction: column; } #user_input { width: 100%; } #submit_btn, #clear_btn { width: 100%; text-align: center; }}/* 加载动画 */.typing-animation { display: inline-flex; align-items: center;}.typing-dot { width: 8px; height: 8px; border-radius: 50%; background-color: #3b82f6; margin: 0 3px; animation: typingAnimation 1.4s infinite ease-in-out;}.typing-dot:nth-child(1) { animation-delay: 0s; }.typing-dot:nth-child(2) { animation-delay: 0.2s; }.typing-dot:nth-child(3) { animation-delay: 0.4s; }@keyframes typingAnimation { 0%, 60%, 100% { transform: translateY(0); opacity: 0.5; } 30% { transform: translateY(-10px); opacity: 1; }}/* 消息状态指示器 */.message-status { font-size: 0.75rem; opacity: 0.6; text-align: right; margin-top: 0.25rem;}"""# 构建高级全屏界面with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo: # 页面标题 with gr.Column(elem_classes="header"): gr.Markdown("### Hunyuan-MT-7B 智能助手", elem_classes="header-title") gr.Markdown("全屏沉浸式对话体验", elem_classes="header-subtitle") # 主容器 with gr.Column(elem_classes="main-container"): # 聊天容器 with gr.Column(elem_classes="chat-container"): # 聊天记录 - 占据大部分空间 chatbot = gr.Chatbot( label="聊天记录", bubble_full_width=False, show_label=False, avatar_images=(None, "https://picsum.photos/id/1005/200/200"), # AI头像 height="100%" ) # 输入区域 - 固定在底部,与对话框等宽 with gr.Row(elem_classes="input-container"): msg = gr.Textbox( placeholder="请输入您的问题...", elem_id="user_input", container=False, scale=8, lines=1, max_lines=5 ) with gr.Column(scale=1, min_width=120): submit_btn = gr.Button("发送", elem_id="submit_btn") with gr.Column(scale=1, min_width=120): clear_btn = gr.Button("清除历史", elem_id="clear_btn") # 提交消息处理函数 def submit_message(message, history): if not message.strip(): # 忽略空消息 return "", history # 添加用户消息到历史记录 history.append((message, "")) yield "", history # 流式获取AI响应 for response in chat_fn(message, history[:-1]): # 排除刚添加的空回复 history[-1] = (message, response) yield "", history # 绑定事件 msg.submit( fn=submit_message, inputs=[msg, chatbot], outputs=[msg, chatbot] ) submit_btn.click( fn=submit_message, inputs=[msg, chatbot], outputs=[msg, chatbot] ) # 清除对话 clear_btn.click( fn=lambda: None, inputs=None, outputs=chatbot, queue=False )if __name__ == "__main__": demo.launch(server_name="0.0.0.0", server_port=8080, share=False)四、页面展示
#激活环境conda activate Hunyuan-MT#进入项目cd Hunyuan-MT/Hunyuan-MT#执行基于gradio+vllm模型部署文件python app.py出现以下 Gradio 页面,即是模型已搭建完成。
