ADM云GPU私有化部署MOSS-TTS+远程API访问

发布时间:2026/7/1 7:44:27

ADM云GPU私有化部署MOSS-TTS+远程API访问 ​ 上篇我们介绍了在云切片上私有部署 Z-Image 开源大模型然后通过 ComfyUI 远程访问云切片上的 Z-Image 的方法这一篇我们用 MOSS-TTS 开源大模型演示以下如何用 FastAPI 封装大模型的推理 API以及远程访问封装的推理 API。关于如何获取免费 GPU 算力的方法之前的文章也给出了注册链接本篇的结尾也附上了链接。1 准备环境1.1 软件环境​ 之前的篇章里介绍了基本环境的创建这里假设你已经创建了 Template。我们仍然以基础容器切片为例启动切片后打开一个终端 CLI 界面准备下来 MOSS-TTS。MOSS-TTS 基础模型参数大小是 8B切片上的 GPU 显存是 48G跑这个模型够用了如果你打算同时部署 MOSS-TTS 和其他大模型可以考虑使用 MOSS-TTS-nano 版本这个版本的参数小但是性能接近 MOSS-TTS。​ 因为是在 AMD 的 GPU 上部署大模型所以环境变量要设置好这是通知 pyTorch 底层 API 调用的方式export PYTORCH_ROCM_ARCHgfx1100 export HSA_OVERRIDE_GFX_VERSION11.0.0然后从 git 上下载 MOSS-TTS 项目代码git clone https://github.com/OpenMOSS/MOSS-TTS.git代码下载之后就可以安装依赖软件包。这一步需要注意MOSS-TTS 的版本部署说明是要用 conda 创建一个隔离的 python 环境但是在这个隔离环境上安装 ROCm 环境会遇到很多问题比如软件包的版本兼容问题非常耗时且容易出错。所以我的建议是在云切片环境上直接安装因为这个环境上的pyTorch 都已经安装好了所以直接安装 MOSS-TTS 的依赖软件即可。云切片环境的好处就是每次云切片 destroy所有的环境都会初始化为最初的状态所以也就没必要再单独弄一个隔离的 python 环境。可以用以下命令安装依赖软件包cd MOSS-TTS pip install --extra-index-url https://download.pytorch.org/whl/rocm7.2 -e .这一步安装需要注意 huggingface-hub 的版本要求的版本号在 0.34.0 和 1.0.0 之间我最初就是因为 huggingface-hub 版本号太高后面写 python api 封装的时候遇到很多错误。另一个需要说明的是 MOSS-TTS 推理支持 FlashAttention 2 加速使用该组件可以降低显存占用加速推理速度。我最开始测试因为不知道云切片上的 GPU 是否支持 FlashAttention 2 组件所以没有安装这个组件因为显存够大所以速度也能接收。后来查了一些资料说是 AMD 的 GPU 支持 FlashAttention 2 组件所以你可以用下面的命令安装依赖软件包pip install --extra-index-url https://download.pytorch.org/whl/rocm7.2 -e .[flash-attn]1.2 模型下载​ 第一次使用 MOSS-TTS 的 API 的时候会自动下载模型权重文件因为默认是从 huggingface 下载所以非常慢且容易失败。如果遇到这类问题可以选择手工下载模型权重文件。目前 MOSS-TTS 的版本是 1.5国内可选择从 modelscope 上下载关于 modelscope 的安装之前的文章介绍过这里直接给出下载模型权重文件的命令modelscope download --model openmoss/MOSS-TTS-v1.5 --local_dir /workspace/models/moss2 部署与验证2.1 本地环境验证​ 上一节的准备工作完成后就可以在本地验证模型是否可以工作了。打开一个 python 环境输入下面的代码加载模型from transformers import AutoModel, AutoProcessor pretrained_model_name_or_path OpenMOSS-Team/MOSS-TTS-v1.5 processor AutoProcessor.from_pretrained(pretrained_model_name_or_path) model AutoModel.from_pretrained( pretrained_model_name_or_path, device_mapcuda ) model.eval() # 设置为推理模式如果是本地下载了 MOSS 模型可以将 pretrained_model_name_or_path 赋值为本地模型的位置。如果准备使用 FlashAttention 2则加载模型时要添加 attn_implementation 参数model AutoModel.from_pretrained( pretrained_model_name_or_path, device_mapcuda;, attn_implementationflash_attention_2 )上述代码执行没有问题就可以尝试推理一段文本试试text 欢迎使用MOSS-TTS-v1.5这是一个开源的文本转语音模型。 inputs processor(texttext, return_tensorpt).to(cuda) with torch.no_grad(): outputs model.generate(**inputs) audio outputs.audio[0].cpu().numpy() torchaudio.save(/workspace/output.wav, audio.unsqueeze(0), processor.model_config.sampling_rate)如果软件环境不出问题就可以在等待一段时间后得到 output.wav 文件可以下载到本地听听。2.2 远程访问 MOSS-TTS​ 本地测试没有问题接下来就是如何打通网络让其他电脑能远程访问服务器上部署的 MOSS-TTS 大模型。一般的思路是将 MOSS-TTS 大模型推理封装成可远程访问的 API此类工具可选 FastAPI 或 Flask。FastAPI 功能比较丰富并且文档也很丰富遇到问题容易获得帮助所以我选择用 FastAPI 做 web api 的封装。因为 云切片实际上是一个私网环境需要打通内网穿透我们选择 ngrok 做内网端口映射。2.2.1 ngrok​ 关于 ngrok 的安装和用户注册上一篇已经介绍过了这里就不啰嗦了直接启动 ngrok 服务注意端口号要与下一节的 fastAPI 的封装一致这里使用 8000ngrok http 8000这条命令执行成功会看到几条转换信息记住其中最重要的一条https://****.ngrok-free.dev - http://localhost:8000这是个转换规则。记住这里的 ****.ngrok-free.dev 和端口号 8000下一节启动 FastAPI 服务时需要这两个信息。2.2.2 FastAPI 封装​ 因为切片环境上已经安装了 FastAPI所以也不需要额外动手安装。关于 FastAPI 的使用也不是本篇的重点直接新建一个 python 文件 svr_api.py输入以下代码创建 API 封装并启动服务import os import uuid from fastapi import FastAPI, HTTPException from pydantic import BaseModel import uvicorn from moss_tts import synthesize app FastAPI(titleMOSS-TTS API, description一个用于远程语音合成的API服务) class TTSRequest(BaseModel): text: str speaker_wav: str None language: str zh # 定义响应体格式 class TTSResponse(BaseModel): audio_url: str # 用于保存生成音频的目录 AUDIO_OUTPUT_DIR ./workspace/output_audio os.makedirs(AUDIO_OUTPUT_DIR, exist_okTrue) app.post(/synthesize, response_modelTTSResponse) async def synthesize_speech(request: TTSRequest): if not request.text: raise HTTPException(status_code400, detail文本内容不能为空) try: audio_data synthesize(textrequest.text, speaker_wavrequest.speaker_wav, languagerequest.language) # 生成一个音频文件用 uuid 命名避免名字冲突 audio_filename f{uuid.uuid4()}.wav audio_path os.path.join(AUDIO_OUTPUT_DIR, audio_filename) with open(audio_path, wb) as f: f.write(audio_data) # 返回音频文件的访问URL我们在 Web 服务器在 / 路径下提供音频服务 audio_url f****.ngrok-free.dev/static/{audio_filename} return TTSResponse(audio_urlaudio_url) except Exception as e: print(f语音合成失败: {e}) raise HTTPException(status_code500, detailf语音合成失败: {str(e)}) # 挂载一个静态文件目录用于 web url 访问 from fastapi.staticfiles import StaticFiles app.mount(/static, StaticFiles(directoryAUDIO_OUTPUT_DIR), namestatic) if __name__ __main__: # 启动服务监听所有地址 uvicorn.run(app, host0.0.0.0, port8000)TTSRequest 中的 speaker_wav 参数用于指定一个音色文件需要是 48000 Hz 采样率如果不指定则使用默认音色输出语音。language 指定输出语言一般输入是中文输出自动适配为中文如果是其他语言可以用这个参数指定。synthesize_speech() 函数的作用是从 TTSRequest 请求中接收参数调用 MOSS-TTS 生成语音输出并返回音频文件的 URL。​ 返回的 URL 需要根据实际情况修改这里的 ****.ngrok-free.dev 就是启动 ngrok 时得到的映射地址端口号也要与 ngrok 启动时使用的端口号一致。接下来就是把 API 服务跑起来python svr_api.py2.2.3 远程 API 调用​ 客户端的代码很简单就是生成一个 http 请求获得一个 json 格式的应答从中解析出 audio_url 参数。audio_url 是一个完整的音频文件链接下载这个文件得到音频文件。以下是完整的客户端代码import requests import json import os SERVER_URL ****.ngrok-free.dev SYNTHESIZE_ENDPOINT f{SERVER_URL}/synthesize # 保存音频文件的本地路径 (Windows) OUTPUT_DIR E:/workspace/tts/downloaded_audio os.makedirs(OUTPUT_DIR, exist_okTrue) def synthesize_and_download(text: str, speaker_wav: str None, language: str zh): # 构造请求体与服务端的 TTSRequest 模型对应 payload { text: text, speaker_wav: speaker_wav, language: language } # 发送 POST 请求 print(f正在合成语音: {text[:30]}...) try: response requests.post( SYNTHESIZE_ENDPOINT, jsonpayload, timeout120 # 语音合成可能耗时较长 ) response.raise_for_status() # 检查 HTTP 状态码 except requests.exceptions.RequestException as e: print(f请求失败: {e}) return None # 解析响应获取音频文件 URL result response.json() audio_url result.get(audio_url) if not audio_url: print(服务端返回的响应中没有 audio_url) print(f响应内容: {result}) return None print(f音频文件 URL: {audio_url}) # 下载音频文件 try: audio_response requests.get(audio_url, timeout60) audio_response.raise_for_status() except requests.exceptions.RequestException as e: print(f下载音频失败: {e}) return None # 保存到本地 filename audio_url.split(/)[-1] if not filename: filename output.wav local_path os.path.join(OUTPUT_DIR, filename) with open(local_path, wb) as f: f.write(audio_response.content) print(f音频已保存至: {local_path}) return local_path if __name__ __main__: text_to_synthesize 欢迎使用MOSS-TTS-v1.5这是一个开源的文本转语音模型。 saved_path synthesize_and_download( texttext_to_synthesize, languagezh ) if saved_path: print(f语音合成完成文件保存在: {saved_path}) else: print(语音合成失败)这段代码的主体就是 synthesize_and_download() 函数这个函数的作用就是发送文本到 MOSS-TTS FastAPI 服务合成语音并下载音频文件。返回的字符串就是本地保存的音频文件路径。​ 和大多数 TTS 模型一样MOSS-TTS 在遇到长文本的时候会出现不稳定的情况比如因为延迟导致出现长时间的静音或者短句不自然音色不能保持等现象。一般 TTS 聚合工具都会提供分句分段的功能我也简单从某开源工具代码中抄了一个函数对于长文本可以拆成一组 chunks逐次调用 synthesize_and_download 函数然后将返回的音频文件合并成一个完整的音频文件。def split_text(text, max_chars180): marks 。\n chunks [] buf for ch in text: buf ch if ch in marks or len(buf) max_chars: chunks.append(buf.strip()) buf if buf.strip(): chunks.append(buf.strip()) return chunks合并 wav 文件的方法很多可以使用 pydub也可以用 wave NumPy 组合这不是本篇的重点这里就不罗嗦了。3 总结​ 本篇给出了一个在 AMD 云切片上部署 MOSS-TTS 大模型并结合了使用 ngrok 做内网穿透实现了远程 API 访问大模型的操作和部署完整过程。关于如何注册用户获取免费 GPU 算力的过程可以从下面的链接开始注册入口点击这里…

相关新闻