时间序列预测一直是工业场景里又常见又棘手的问题——电力负荷、设备温度、流量监控,处处需要"看了过去、预判未来"。timer-base-84m 是 thuml 团队开源的时间序列基础模型,走的是"预训练 + 零样本"路线:它在大规模时序语料上练好了"怎么从历史形态推演未来",所以拿来做预测时不需要再针对某个数据集重新训练,直接把历史序列丢给它就能得到未来一段时间的预测值。
84M 参数量在基础模型里属于轻量级,但得益于 decoder-only 的 GPT 式架构,它对"趋势延续、周期往复、噪声扰动"这类序列规律有不错的建模能力。本次我们把它部署到了本地昇腾 Ascend910 上,跑通了从权重下载、模型加载到 HTTP 服务发布的完整链路,并给出了一份可复现的实操文档。
先说结论:这个模型不是大语言模型。它虽然长着一张 GPT-2 的脸(8 层 decoder、8 头注意力、1024 隐藏维),但喂给它的是连续的时间序列数值,吐出来的是未来的连续预测值,全程没有 token、没有词表、没有采样器。这意味着 vLLM 那种"分词 -> 生成 -> 采样"的文本服务管线对它不适用——实测 vllm serve 会直接拒绝这个架构(TimerForPrediction are not supported)。
因此我们的适配路线是:保留 vLLM-Ascend 的昇腾推理栈(CANN + torch_npu 提供 NPU 算子执行),把模型本体用 transformers 的 remote code 机制加载,再包一层 FastAPI 做成服务。另外,模型自带的远程代码是按 transformers==4.40.1 写的,我们环境里是 4.57.6,两者在缓存类接口上有不兼容,这一步我做了三处最小改动(后面"注意事项"里有清单),没有动任何权重,所以推理结果和官方实现是一致的。
本次跑通所用的环境如下,供复现参考:
模型权重为 float32 的 safetensors 单文件,约 321MB(84M 参数)。
目录里直接给出了可运行的 inference.py,建议按下面的步骤操作:
# 安装依赖
pip install -r requirements.txt
# 启动服务(默认 0.0.0.0:8088,NPU 设备 0)
python3 inference.py --port 8088 --device 0服务起来后(首次加载约 1~2 秒),就可以用下面这些请求来调用:
# 看服务是否就绪
curl http://127.0.0.1:8088/health
# 扔一段真实的序列进去,预测后面 96 个点
curl -X POST http://127.0.0.1:8088/infer \
-H 'Content-Type: application/json' \
-d '{"series":[20.0,20.5,21.0,21.5,22.0,22.5,23.0,23.5,24.0,24.5,25.0,24.5,24.0,23.5,23.0,22.5],"prediction_length":96}'
# 不准备数据的话,也可以点一下内置的冒烟接口
curl -X POST http://127.0.0.1:8088/infer_simple如果只是想在脚本里用,也可以不启服务、直接加载模型:
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("本地模型目录", trust_remote_code=True).to("npu:0")
seqs = torch.randn(1, 2880) # 历史序列
pred = model.generate(seqs, max_new_tokens=96) # 未来 96 点部署完先别急着接业务,花十秒钟确认三个接口都通:
GET /health 应返回 {"status":"ok","device":"npu:0","model_loaded":true,...};POST /infer_simple 会用内置的随机序列跑一次前向,返回 shape [1, 96] 的预测;POST /infer 传入真实数据应返回 forecast、shape、elapsed_ms 等字段。三个接口都返回 200,就说明模型加载、前向、序列化三个环节都没问题,可以往下走。
在单张 Ascend910 上、float32 精度下实测:
| 项目 | 结果 |
|---|---|
| 模型加载 | 约 1.92 s |
| 稳态单次推理 | 9~10 ms |
| 首请求(算子预热) | 约 185 ms |
| 持续压测吞吐 | 25 秒约 2770 次,平均约 110 次/秒 |
| 推理时 NPU 显存 | 约 6203 MB / 65536 MB |
| 推理时算力占用 | AICore 18%~20% |
| 服务进程显存 | 约 616 MB |
可以看到 84M 的小模型在这张卡上是非常富余的,单次预测 10ms 级别,即便扛不住高并发,横向加进程或者换 batch 也能轻松应对。对大多数业务来说,这台机器的算力瓶颈基本不在推理侧。
精度这块我们的处理原则是"不引入额外误差":
我们用一段"趋势 + 正弦周期 + 噪声"合成的 2880 点序列做了验证:输入均值约 21.44、标准差约 1.72,输出 96 点预测均值约 22.64、标准差约 0.33,数值上平滑地承接了输入末端的上行趋势,符合零样本预测的预期。生产环境建议再用自己的历史数据做一轮 MAE/MSE 评估,看模型在你的业务序列上的实际贴合度。
inference.py 就是为这个模型定制的服务。DynamicCache 接口报错。本仓库的两个 modeling_timer.py / ts_generation_mixin.py 已修好。--device 指到空闲卡、--port 换到空闲端口。prediction_length,服务会按 96 步滚动拼接。timer-base-84m/
├── inference.py # FastAPI 服务:加载模型 + /health /infer /infer_simple
├── README.md # 本说明
├── requirements.txt # 依赖清单
└── assets/
└── README.md # 部署与调用细节补充