atlasleong/peek-npu
模型介绍
文件和版本
Pull Requests
讨论
分析

momentslab/peek(PEEK)昇腾 NPU 推理适配

任务: video-understanding(视频理解 —— 逐帧相关性评分与关键帧选择) 目标设备: npu:4(Ascend 910B4) · 推理引擎: torch_npu 模型: momentslab/peek · HF 源修订: b3ef71b21223fd36cc415698690e3bc3b3251b48

本目录是一个自包含的 PEEK 昇腾 NPU 推理交付物。它从本地检查点 peek_base.safetensors 加载真实的 PeekScorer 权重(30 张张量 / 1,712,129 参数, 严格加载,无缺失/多余键),在 npu:4 上以确定性 eval / torch.inference_mode 前向推理,对一帧集输出逐帧相关性分数,并按 stratified_argmax 策略选出 k 个关键帧, 同时写入 logs/npu_inference.log 与 logs/npu_result.json。

图片说明
agent_workflow本次 ModelAgent 适配工作流(真实命令)
modelagent_live_sessionModelAgent 实况会话(真实脱敏 transcript)
npu_device_callnpu:4 设备调用与进程证据(真实日志渲染)
model_result最终 NPU 推理结果(logs/npu_result.json 渲染)

模型简介

momentslab/peek(PEEK = Peek Explores Everything Key)是一个 查询无关的视频帧相关性评分模型:给定一段视频的逐帧嵌入,PeekScorer 直接为每帧打 一个相关性分数(不需要文本查询),再通过 stratified_argmax 选出最值得保留的关键帧, 广泛用于视频摘要、帧检索与视频问答的预筛。

  • 推理目标:对一帧集(每帧 512 维 MobileCLIP2-S0 嵌入)输出逐帧分数,并选择 k 个关键帧 —— 即 video-understanding(视频理解)。
  • 本交付使用真实完整权重 peek_base.safetensors(30 张张量,约 1.71M 参数), 不使用 ONNX、随机权重或配置占位。

模型架构(与上游模型卡 / config.json / 权重键完全一致)

超参数值
architecturePeekScorer(查询无关帧相关性评分器)
embedding_dim512(每帧 MobileCLIP2-S0 嵌入维度)
hidden_dim256
num_heads / num_layers4 / 2
ffn_dim / dropout1024 / 0.15
output_activationidentity
encoderapple/MobileCLIP2-S0(冻结图像编码器,训练/推理前置)
selection_modestratified_argmax
参数量1,712,129(float32)

网络结构:LayerNorm(512) → Linear(512→256) → 2× Pre-LN Transformer 层 (nn.MultiheadAttention256/4 heads batch_first + GELU FFN 256→1024→256) →score_head Linear(256→1)`,identity 激活。

关于图像编码器:apple/MobileCLIP2-S0 是一个独立的、冻结的编码器,它不包含在 发布检查点内,且本离线环境无法联网下载(GitHub / HuggingFace 被阻断)。本交付因此 运行的是完整的发布评分器(真实权重 + 真实架构);评分器输入即 512 维帧嵌入(与模型卡 描述一致)。在线场景下可用 --input 传入任意 MobileCLIP2-S0 兼容编码器产出的真实嵌入 文件(.npy / .pt)。离线验证使用确定性 CC0 合成嵌入(见“完整测试用例”)。

版本与哈希(已核对)

文件SHA256字节数
peek_base.safetensors(本交付使用的真实全量模型)941b985bc9e6bc55331270faaa40071fe9fc763bebebbf61f99c74a131fe30bb6,851,668
  • 模型源:https://huggingface.co/momentslab/peek @ revision b3ef71b21223fd36cc415698690e3bc3b3251b48
  • 源码仓库:https://github.com/momentslab/peek(代码 Apache-2.0)
  • 权重许可:CC-BY-NC-SA-4.0;权重在本地 /work/pipeline/models/other40/peek/, 运行时绝不联网下载。

环境依赖清单

运行环境(实测)

组件版本
OS / 架构Linux aarch64
NPUAscend 910B4-1(npu-smi 25.5.1,8 卡,本任务使用 npu:4)
CANN8.5.1(/usr/local/Ascend/cann-8.5.1,driver 25.5.1)
Python3.11.14
torch2.9.0+cpu(镜像内置,与 torch_npu 配套,不得用普通 PyPI wheel 替换)
torch_npu2.9.0(镜像内置)
numpy1.26.4
safetensors0.8.0

依赖安装

# 配置阿里云镜像(本环境已预设)
export PIP_INDEX_URL=https://mirrors.aliyun.com/pypi/simple/
export PIP_TRUSTED_HOST=mirrors.aliyun.com

# 只安装非 torch 的应用依赖(torch / torch_npu 使用镜像自带版本)
pip install -r requirements.txt

requirements.txt 仅包含 numpy==1.26.4、safetensors==0.8.0(纯应用依赖,阿里云镜像可用)。 不要安装或替换 torch / torch_npu。


分步推理操作流程

0) 进入交付目录

cd /work/pipeline/jobs/other40/peek/peek-npu

1) 确认 NPU 环境(可选)

npu-smi info          # 应看到 8 张 910B4,目标卡 npu:4 状态 OK
python3 -c "import torch, torch_npu; print(torch.npu.is_available(), torch.npu.device_count())"
# True 8

2) 语法自检

python3 -m py_compile inference.py   # 应无输出、退出码 0

3) 运行端到端 NPU 推理

python3 inference.py \
  --device npu:4 \
  --model-dir /work/pipeline/models/other40/peek \
  --k 4 \
  --num-frames 32 \
  --hold-seconds 6 \
  --log logs/npu_inference.log \
  --json logs/npu_result.json

一键运行(含并发 npu-smi 进程证据采集):

bash scripts/run_npu_inference.sh 6

可选参数:

  • --input <file.npy|.pt>:传入真实的帧嵌入文件([N,512] 或 [B,N,512]);省略时使用 确定性 CC0 合成测试夹具。
  • --k N:要选择的关键帧数量(预算)。
  • --hold-seconds N:在模型就位后保持 NPU 显存 N 秒,便于并发的 npu-smi 抓取进程 PID 证据。

4) 结果文件

文件内容
logs/npu_inference.log原始推理日志(设备/版本/放置/输出/耗时/退出码)
logs/npu_result.json机器可读结果(结构化,含 checks)
logs/npu_device_call.log并发 npu-smi 进程证据(PID 在 NPU 4 上)

完整测试用例

测试输入:CC0 合成帧嵌入(inference.py 内部确定性生成,无 RNG、无外部数据)。 每帧 512 维、L2 归一化,公式为 emb[t, d] = sin(phi(t, d)) + 0.5*cos(0.5*phi(t, d)) + 0.1*t/N, 其中 phi(t, d) = d*1.618 + t*freq(d)*2*pi/N、freq(d) = 0.5 + 0.25*sin(0.137*d) + 0.05*(d % 7); 相邻帧时间相关,类似真实视频帧嵌入。license 为 CC0。

执行命令(本次最终验收运行):

bash scripts/run_npu_inference.sh 6

实际输出(来自 logs/npu_inference.log / logs/npu_result.json,真实 NPU 运行):

[2026-08-21 15:16:42] === momentslab/peek / PeekScorer Ascend NPU inference ===
[2026-08-21 15:16:44] NPU available=True count=8 device=npu:4 current=4 name=Ascend910B4-1
[2026-08-21 15:16:44] hardware=Ascend910B4-1 soc=225
[2026-08-21 15:16:44] versions: python=3.11.14 torch=2.9.0+cpu torch_npu=2.9.0 CANN=8.5.1
[2026-08-21 15:16:44] weights=.../peek_base.safetensors size_bytes=6851668 sha256=941b985bc9e6bc55331270faaa40071fe9fc763bebebbf61f99c74a131fe30bb
[2026-08-21 15:16:44] model loaded (strict, 30 tensors) params=1712129 param_dtype=torch.float32 all_params_on_npu:4=True
[2026-08-21 15:16:50] input: kind=cc0-synthetic num_frames=32 embedding_dim=512 source=CC0 synthetic (self-generated, deterministic analytic formula, no RNG) license=CC0 / public domain
[2026-08-21 15:16:50] input placement asserted: device=npu:4 dtype=torch.float32 shape=(32, 512)
[2026-08-21 15:16:50] scores shape=(32,) device=npu:4
[2026-08-21 15:16:50] scores checksum: sum=-30.421921 abs_sum=30.421921
[2026-08-21 15:16:50] max score frame=29 value=-0.175279
[2026-08-21 15:16:50] forward elapsed=586.99 ms
[2026-08-21 15:16:50] selected frames (k=4, stratified_argmax): [7, 12, 23, 29]
[2026-08-21 15:16:50] selected scores: [-1.330377, -0.809006, -0.73901, -0.175279]
[2026-08-21 15:16:50] peak_memory_mb=22.89404296875 allocated_mb=6.609375
[2026-08-21 15:16:50] check input_on_npu4=True
[2026-08-21 15:16:50] check model_on_npu4=True
[2026-08-21 15:16:50] check output_on_npu4=True
[2026-08-21 15:16:50] check current_device_is_4=True
[2026-08-21 15:16:50] check scores_shape_ok=True
[2026-08-21 15:16:50] check output_meaningful=True
[2026-08-21 15:16:50] check hash_match=True
[2026-08-21 15:16:50] === done: exit_code=0 ===

并发 npu-smi 进程证据(PID 在 NPU 4 上,见 logs/npu_device_call.log):

| 4       0                 | 537229        | python3                  | 138                     |
| 4       0                 | 537229        | python3                  | 168                     |

输出结果

关键帧选择(stratified_argmax,k=4)

关键帧 index对应时间戳 (s)相关性分数
73.5-1.330377
126.0-0.809006
2311.5-0.739010
2914.5-0.175279
  • 全帧集前向 scores 形状:(32,),device=npu:4
  • scores 校验和:sum=-30.421921,abs_sum=30.421921
  • 最高分帧:29(-0.175279)
  • 前向耗时:586.99 ms;峰值显存:22.89 MB;已分配:6.61 MB
  • 放置断言:input_on_npu4=True,model_on_npu4=True,output_on_npu4=True, current_device_is_4=True
  • 退出码:0;all_checks_passed=True

交付物清单

inference.py               # 自包含 NPU 推理脚本(fail-closed,无 CPU 回退)
readme.md / README.md      # 本文档(字节相同)
requirements.txt           # 非 torch 应用依赖(numpy==1.26.4, safetensors==0.8.0)
.gitignore                 # 忽略字节码/缓存/权重/密钥/临时文件
assets/agent_workflow.png  # 工作流图(1440x1800)
assets/modelagent_live_session.png  # 实况会话图(真实脱敏 transcript)
assets/npu_device_call.png # NPU 设备调用证据(1440x900)
assets/model_result.png    # 模型结果图(1440x900)
logs/npu_inference.log     # 原始推理日志
logs/npu_result.json       # 结构化结果
logs/npu_device_call.log   # 并发 npu-smi 进程证据

故障排查与限制

  • torch_npu 导入失败 / torch.npu.is_available()==False:请 source /usr/local/Ascend/ascend-toolkit/latest/set_env.sh 并确认 CANN 8.5.x 与 torch_npu 2.9.0 配套;脚本此时会以非零码失败(fail-closed),不会回退 CPU。
  • 设备不在 npu:4:脚本断言 torch.npu.current_device()==4;如目标卡不同,请用 --device 指定并确认该卡空闲(npu-smi info)。
  • 权重哈希不匹配:请核对 sha256sum peek_base.safetensors 是否等于 941b985bc9e6bc55331270faaa40071fe9fc763bebebbf61f99c74a131fe30bb;脚本以退出码 7 失败。
  • 图像编码器不可用:apple/MobileCLIP2-S0 不在发布检查点内,本离线环境无法下载。 本交付运行完整的发布评分器(真实权重);在线场景请用 --input 传入 MobileCLIP2-S0 兼容 编码器产出的真实帧嵌入。
  • 精度说明:本交付为确定性帧评分与 stratified_argmax 选择;合成测试夹具为 CC0, 不含任何外部训练数据。
  • 镜像:仅使用阿里云镜像安装非 torch 依赖;不要用普通 PyPI 轮子替换镜像自带的 torch / torch_npu 配套。

License

  • 模型权重:CC-BY-NC-SA-4.0(momentslab/peek)
  • 代码:Apache-2.0(momentslab/peek 源码仓库)
  • 测试输入:CC0 合成数据(inference.py 自生成,无外部数据)

适配交付补充

环境依赖:torch、torch_npu 与 CANN,详见 requirements.txt。

推理步骤:执行 inference.py 并确认目标设备为 Ascend NPU。

完整测试用例:使用仓库固定测试输入执行一次端到端推理。

输出结果:真实 NPU 结果保存在 logs/npu_result.json。