如果你只是想尽快把模型跑起来看个效果,照下面三步走:
pip install -r requirements.txt
# 起一个服务,默认 8001 端口
python inference.py --serve
# 另开一个终端,POST 一段序列过去,马上就能拿到预测
curl -X POST http://127.0.0.1:8001/v1/forecast \
-H "Content-Type: application/json" \
-d '{"input":[0.5,0.52,0.51,0.55,0.58,0.6,0.62,0.61,0.64,0.66],"horizon":32}'大概十几毫秒后,接口就会回给你未来 32 个时刻的预测,每个时刻带 99 个分位点。就这么简单。
这个模型是通义实验室开源的 YingLong(应龙)时序基础模型家族里的 110M 版本。它不是那种"你说一句话它回一句话"的大语言模型,而是专门吃连续数值序列、往外预测的模型——比如温度曲线、能耗序列、股票价格这类带时间先后关系的数据。
模型本身约 1.2 亿参数,权重是 BF16 的 safetensors,整套文件加起来大概 240MB。结构上走的是 GPT 那一套:先把序列切块(每 32 个点一块),做一次 Haar 小波变换再映射进向量空间,中间过 12 层自注意力,最后一口气吐出未来若干时刻的分位数分布。输出 99 个分位数意味着它给的不只是一个"点",而是一整条概率带,业务上可以拿来做区间预测。
先说大家最关心的:预测准不准。我在本地用正弦波做了两组外推实验,拿中位数(50% 分位)当点预测去和真实值比:
| 测试 | 输入 | 预测步 | MAE | RMSE |
|---|---|---|---|---|
| 干净正弦 | 512 | 64 | 0.1677 | 0.1953 |
| 带噪声正弦 | 512 | 32 | 0.2949 | 0.3505 |
干净信号下中位数预测能贴着真实曲线走,前几步误差基本在 0.1~0.2 之间;把 5% 的噪声加进去之后误差变大一些,这也符合直觉——输入越脏,越难预测准。另外检查了分位数的自洽性,99 个分位点整体是单调递增的,只有少量边界位置因为 BF16 舍入出现 ±1 个最小单位的抖动,属于正常现象,不影响使用。
我是跑在昇腾 Atlas 800 上的,具体环境如下:
依赖装好之后,一条命令起服务:
python inference.py --model-dir /你的/权重/路径 --serve --port 8001权重目录就是放 config.json 和 model.safetensors 的那个文件夹。--port 可以按需改,但注意别和机器上其他服务撞了。
如果不想起服务,也可以直接命令行跑单次预测:
python inference.py --input "0.5,0.6,0.7,0.8" --horizon 32 --json服务起来之后,两个接口够用了:
GET /health:确认服务还活着。会返回 {"status":"ok","model":"YingLong_110m","device":"npu:1",...}。POST /v1/forecast:真正干活的接口,传 {"input":[序列],"horizon":步数}。我自己验证过一轮:起服务 → curl 健康检查 → 发一次 512 点的请求 → 拿到 64 步 × 99 分位的结果,整个流程没有报错,返回的 JSON 里 steps 和 horizon 对得上,point_forecast 是 64 个数的中位数序列,看着是合理的趋势外推。
实测的数据(输入 512、输出 64 步、单张卡):
npu-smi info 看看哪张卡空闲,用 --device npu:0 或 npu:1 指定,别把别人的进程挤掉。最麻烦的是官方原版代码里引了 xformers、flash-attn、dropout_layer_norm、rotary_emb 这几个东西,全是 CUDA 专用内核,昇腾上根本没有。我把它们逐个改成了纯 PyTorch 写法:SwiGLU 用三个线性层自己拼,RMSNorm 直接手写归一化公式,旋转位置编码也用纯张量运算重写。改完之后的权重和官方参数名一一对应,能原样加载不丢一个张量。整个适配和验证的日志、踩坑记录都整理在 assets/ 目录下。
数据与论文来源:阿里巴巴通义实验室 YingLong(arXiv:2506.11029),权重许可证 CC-BY-4.0。