From dd516f424f1ce059d9aafee7e639fa8daee707cf Mon Sep 17 00:00:00 2001 From: t Date: Tue, 10 Nov 2026 15:11:27 -0400 Subject: [PATCH] tools: hf_tensor.py reads one safetensors tensor with the offset rule I got wrong four times (refs #1934) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A safetensors `data_offsets` entry is measured from the **start of the data section**, i.e. `8 + header_len` bytes into the file -- not from byte 8. Fetch `bytes=8+off` and you get a slice of a *different* tensor, one header-length away; it has a plausible size, it is finite, and a correlation against it is a correlation against noise. That mistake cost two false conclusions about a merged PR tonight, both stated publicly before I caught them: "the 640 B gap does not correlate with the source model's q/k gains at any offset" and "the container still holds the pre-#1938 two-copies signature", the second of which I had to retract on #1976 when the correctly-fetched tensor gave `mean 1.3705, max 1.703125, min 0` — matching the container to three decimals. The tell was in my own output: a norm gain is ~1.0 and my "HF" values were +-0.03. So this tool does the arithmetic once and makes a wrong read *visible* rather than plausible: ``` $ tools/hf_tensor.py --repo tencent/Hunyuan-7B-Instruct \ --tensor model.layers.0.self_attn.query_layernorm.weight model.layers.0.self_attn.query_layernorm.weight BF16 [128] 256 B (model-00001-of-00004.safetensors) mean +1.370461 min -0.000000 max +1.703125 nonfinite 0 a norm gain is ~1.0 and a weight matrix is ~0: check these before trusting a correlation ``` * reads only the index, the shard's 8-byte length + header, and the tensor's own bytes (three range requests); * prints mean/min/max/nonfinite, because that is what separates "the tensor I asked for" from "a slice of its neighbour"; * `--out` writes the raw bytes for a comparison script, `--json` for one; * `--self-test` drives the rule on a **synthetic** shard with no network: a first tensor long enough that the second's offset is past it, then the same offset applied from the data section (returns the tensor) and from byte 8 (does not). Registered as `hf_tensor_self` so the rule is pinned in every configure; `ctest -R 'hf_tensor|tests_referenced'` -> 3/3. Refs #1934. This is the first half of the `diff-hf` instrument I asked for on that issue; the second half -- decode a *container* tensor through the importer's own decoder and print the per-row regression ratio -- is the next step. --- CMakeLists.txt | 5 ++ tools/hf_tensor.py | 213 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100755 tools/hf_tensor.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 79a6b1c44..417ef980b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -331,6 +331,11 @@ add_test(NAME bench_preflight COMMAND bash ${CMAKE_SOURCE_DIR}/tools/tests/test- # engine#1702: builds a per-layer MoE expert placement table from a moe_trace, and refuses a prefill-only trace because # placement is a decode lever (5.4-6.9 % on batched prefill against dedup's 90-94 %). --self-test drives it on synthetic # traces with a known answer; no model, no device. +# engine#1934: reading ONE tensor out of a safetensors shard needs `data_offsets` measured from 8 + header_len, not +# from byte 8. Getting that wrong returns a *different* tensor of the same size that still looks finite, and it cost +# two false conclusions about a pack in one night. `--self-test` drives the rule on a synthetic shard (no network): +# the same offset from the data section returns the tensor, from byte 8 it does not. +add_python_test(hf_tensor_self ${CMAKE_SOURCE_DIR}/tools/hf_tensor.py --self-test) add_python_test(moe_placement ${CMAKE_SOURCE_DIR}/tools/moe_placement.py --self-test) # engine #1279: the version a package is built with (scripts/pack-version.sh) -- a release tag as # it stands, a candidate mapped into the ISO week of its own date with a suffix that sorts below that diff --git a/tools/hf_tensor.py b/tools/hf_tensor.py new file mode 100755 index 000000000..57f9b4b59 --- /dev/null +++ b/tools/hf_tensor.py @@ -0,0 +1,213 @@ +#!/usr/bin/env python3 +# Copyright 2026 bong-water-water-bong +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""hf_tensor.py -- read ONE tensor out of a safetensors shard, over HTTP range requests. + +Written because I got a safetensors offset wrong four times in one night and each time concluded something +false about a pack. The rule that bit me, and the only reason this file exists: + + a safetensors `data_offsets` entry is relative to the START OF THE DATA SECTION, i.e. `8 + header_len` + bytes into the file -- not to byte 8. + +Fetch `bytes=8+off` and you get a slice of whatever tensor is 11,656 B (this shard's header) away from the one +you asked for, which still *looks* like a tensor: it has a plausible size, it is finite, and a correlation +against it is a correlation against noise. Two of those cost me a retraction on a merged PR. + +So this tool does the arithmetic once, prints the tensor's own statistics so a wrong read is visible rather +than plausible (a norm gain is ~1.0, not +-0.03), and can write the raw bytes for a comparison script. + +usage: + tools/hf_tensor.py --repo tencent/Hunyuan-7B-Instruct \ + --tensor model.layers.0.self_attn.query_layernorm.weight [--out q.bin] [--json] + tools/hf_tensor.py --self-test + +Exit: 0 ok, 1 the tensor or shard was not found, 2 cannot tell (no network / not a safetensors repo). +""" + +import argparse +import json +import pathlib +import struct +import sys +import urllib.request + +UA = {"User-Agent": "1bit-aba/hf_tensor"} # HF rejects the default python urllib agent on some endpoints +DTYPE_TABLE = { + "F64": ("