文生图已经不新鲜了,但把一句描述直接变成一个能拿去渲染、打印的 3D 模型,仍然是很多人感兴趣的方向。OpenAI 开源的 Shap-E 模型就是做这件事的:你输入一段文字,它输出一个隐式函数表示,再解码成带颜色的网格模型,最终得到一个 GLB 格式的文件,可以直接拖进 Blender、Windows 3D 查看器或者 Unity 里使用。这篇文章完整走一遍用 Python 实现"文字到 3D 模型"的流程,包括环境搭建、代码编写、结果保存与下载,以及一些实际使用中的注意事项。

Shap-E 是什么,它和传统建模方式的区别
Shap-E 是 OpenAI 在 2023 年开源的一个生成式 3D 模型,它的思路和 Stable Diffusion 生成图片有点像,只不过输出的不是像素,而是 3D 隐式场。模型分为两步:第一步是 text2shape 的扩散模型,把文字编码后逐步去噪,得到一个 latent 表示;第二步是解码器,把 latent 转成显式的网格(mesh)和纹理(texture)。官方同时发布了模型权重和推理代码,仓库地址是 github.com/openai/shap-e,基于 MIT 协议,可以自由商用和二次开发。
和传统建模相比,这种方式的最大价值在于速度。人工在 Blender 里捏一把椅子可能要几个小时,而 Shap-E 在一块普通显卡上几十秒就能出一个带颜色的粗模。当然代价是精度:生成的模型结构比较简单,适合做原型验证、游戏素材占位、概念展示,如果需要工业级的精细模型,目前这个技术路线还达不到要求。理解这个定位很重要,可以避免对生成效果抱不切实际的期待。
需要说明的一点是,OpenAI 并没有在官方 API 平台提供名为 Shap-E 的公开付费接口,它的使用方式主要是本地推理,或者部署到自己的服务器上再封装成 API。所以下文会先讲本地运行的完整流程,再给出一个用 FastAPI 把它封装成 HTTP 接口的方案,这样团队里的其他人就可以直接通过 HTTP 调用来生成和下载模型。
环境准备与依赖安装
Shap-E 推荐 Python 3.8 以上版本,依赖 PyTorch。如果你有 NVIDIA 显卡,建议先装好 CUDA 版的 PyTorch,纯 CPU 也能跑,但一次生成可能要几分钟,体验差很多。显卡方面,官方示例在 6GB 显存的消费级显卡上可以运行,16GB 以上会更从容,因为生成 3D 的隐式场解码阶段比较吃显存。
安装步骤很简单,先克隆仓库再安装依赖:
git clone https://github.com/openai/shap-e cd shap-e pip install -e .
如果你的网络环境访问 PyPI 比较慢,可以加上国内镜像源。另外注意 pytorch3d 这个依赖在 Windows 上安装经常出问题,它需要先装好 CUDA Toolkit 并且匹配编译版本。一个省事的办法是直接用官方提供的 conda 环境文件,或者干脆在 Linux/WSL2 环境里跑,能避开绝大多数编译报错。装好之后建议先跑一次官方示例,确认环境没问题再写自己的代码。
编写生成代码并保存 GLB 文件
核心代码其实很短。思路是加载 shapE 和 decoder 两个模型,把提示词传给 sample_model,拿到 latent 后用 decode_latent_mesh 解码,最后写出 GLB 文件。下面是完整可运行的示例:
import torch
from shap_e.diffusion.sample import sample_latents
from shap_e.diffusion.gaussian_diffusion import diffusion_from_config
from shap_e.models.download import load_model, load_config
from shap_e.util.notebooks import create_latent_images, decode_latent_images
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# 加载生成模型和解码器,首次运行会自动下载权重
xm = load_model('transmitter', device=device)
model = load_model('text300M', device=device)
diffusion = diffusion_from_config(load_config('diffusion'))
prompt = "a chair that looks like a tree" # 提示词:一把像树的椅子
latents = sample_latents(
batch_size=1,
model=model,
diffusion=diffusion,
guidance_scale=15.0, # 引导系数,越大越贴合文字描述
model_kwargs=dict(texts=[prompt] * 1),
progress=True,
)
# 解码为网格并导出 GLB
latent = latents[0]
mesh = xm.decode_latent_mesh(latent).tri_mesh()
with open('output/chair.glb', 'wb') as f:
mesh.write_glb(f)
print('模型已保存到 output/chair.glb')
几个参数值得注意。guidance_scale 控制生成结果和文字描述的贴合程度,取 15 左右是官方推荐值,调太高会导致几何结构扭曲。batch_size 决定一次生成几个模型,显存不够就保持为 1。如果想批量生成,可以循环调用,每次换一个提示词,把文件名用序号命名,方便后续统一下载。
保存时目录要提前创建,否则 open 会抛出文件不存在异常。GLB 是二进制格式的 glTF,包含了网格、材质和顶点色,单文件就能携带全部资源,是目前 3D 交付里通用性最好的格式之一。如果需要 OBJ 格式,可以改用 write_obj 方法,但它会额外生成贴图文件,传输和归档稍麻烦一些。
封装成 HTTP 接口实现远程下载
本地脚本能跑通之后,更实用的做法是把它包装成服务,让前端或者其他后端通过 HTTP 请求触发生成,然后下载生成的 GLB 文件。用 FastAPI 实现非常简洁:
import os, uuid
from fastapi import FastAPI
from fastapi.responses import FileResponse
from shap_e_service import generate_glb # 上面封装好的生成函数
app = FastAPI()
OUTPUT_DIR = 'outputs'
os.makedirs(OUTPUT_DIR, exist_ok=True)
@app.get('/generate')
def generate(prompt: str):
task_id = str(uuid.uuid4())[:8]
file_path = os.path.join(OUTPUT_DIR, f'{task_id}.glb')
generate_glb(prompt, file_path) # 阻塞式生成,生产环境建议改用任务队列
return FileResponse(
path=file_path,
filename=f'{task_id}.glb',
media_type='model/gltf-binary',
)
客户端下载就更简单了,用 requests 把响应内容写进本地文件即可。注意 GLB 是二进制文件,必须用二进制模式打开文件句柄,用文本模式会直接把文件写坏:
import requests
resp = requests.get(
'http://192.168.0.10:8000/generate',
params={'prompt': 'a red sports car'},
timeout=600,
)
with open('car.glb', 'wb') as f: # 必须是 'wb' 二进制写模式
f.write(resp.content)
print('下载完成,文件大小:', len(resp.content), '字节')
这套方案跑起来之后,一次生成的完整链路是:客户端提交提示词,服务端排队执行扩散采样和网格解码,生成 GLB 后直接以文件流返回,客户端落盘保存。如果是并发场景,建议把生成任务扔进队列异步处理,客户端先拿到任务 ID 再轮询下载地址,避免多个请求同时占满显存把服务打挂。
常见问题与调优建议
实际使用中最常见的报错是显存不足,表现为 CUDA out of memory。除了降低 batch_size,还可以在解码阶段结束后立即 torch.cuda.empty_cache(),或者在服务端限制同时只有一个生成任务。另外首次运行会从网络下载几百 MB 的权重文件,服务器环境最好提前下载好并缓存,避免每次部署都重复拉取。
生成质量方面,提示词用英文效果明显好于中文,因为训练数据以英文 3D 文本对为主。描述时尽量写清主体、形态和风格,比如 a pineapple shaped house 就比简单的 a house 更容易得到符合预期的结果。如果对某个结果不满意,可以固定随机种子批量生成多个,再人工挑选,这是目前文生 3D 工作流里普遍采用的做法。
最后提醒一下部署成本。如果只是个人实验,一块 8GB 显存的显卡足够;如果要对外提供服务,建议按任务队列加弹性伸缩的思路设计,生成类任务对 GPU 的占用是脉冲式的,合理调度能显著降低成本。Shap-E 之后社区还出现了更多改进方案,比如基于多视图重建的细化管线,可以把粗模再精修一轮,有更高精度需求的读者可以顺着这个方向继续探索。
Shap-E APIPython 3D模型生成OpenAI修改时间:2026-09-06 14:14:44