Fix family download metadata and counted download flows

#2
by gump2049 - opened
README.md CHANGED
@@ -143,6 +143,9 @@ The optimization reduces output-head work, not the context-processing backbone.
143
 
144
  ## 5. Minimal Inference
145
 
 
 
 
146
  The repository is a model-family bundle. Choose a subdirectory containing complete BF16 weights and the reference runtime:
147
 
148
  | Variant | Model directory | Suggested use |
@@ -158,7 +161,7 @@ Use a CUDA-capable PyTorch environment. Select the model directory to download:
158
  python -m pip install huggingface_hub
159
  hf auth login
160
  hf download apus-ailab/APUS-OpenJev-v1 \
161
- --include "9B-3000/*" --local-dir ./APUS-OpenJev-v1
162
  cd ./APUS-OpenJev-v1/9B-3000
163
  python -m pip install -r requirements.txt
164
  python examples.py . --device cuda:0 --effort high
 
143
 
144
  ## 5. Minimal Inference
145
 
146
+ The root [meta.yaml](meta.yaml) catalogs model variants and their configuration hashes. Include it when downloading a variant; the repository and existing model paths are unchanged. You can also use [download_model.py](download_model.py) with `--variant 9B-3000 --local-dir ./APUS-OpenJev-v1`; it selects and checks the variant at one fixed Hub revision. Hub download statistics count requests to selected metadata files, not unique users or completed weight transfers. Older subfolder-only clients can bypass this metadata.
147
+
148
+
149
  The repository is a model-family bundle. Choose a subdirectory containing complete BF16 weights and the reference runtime:
150
 
151
  | Variant | Model directory | Suggested use |
 
161
  python -m pip install huggingface_hub
162
  hf auth login
163
  hf download apus-ailab/APUS-OpenJev-v1 \
164
+ --include "meta.yaml" "9B-3000/*" --local-dir ./APUS-OpenJev-v1
165
  cd ./APUS-OpenJev-v1/9B-3000
166
  python -m pip install -r requirements.txt
167
  python examples.py . --device cuda:0 --effort high
README.zh-CN.md CHANGED
@@ -143,6 +143,9 @@ tags:
143
 
144
  ## 5. 最小推理示例
145
 
 
 
 
146
  本仓库集中保存一个模型系列。请选择包含完整BF16权重和参考runtime的具体子目录:
147
 
148
  | 版本 | 模型目录 | 建议用途 |
@@ -158,7 +161,7 @@ tags:
158
  python -m pip install huggingface_hub
159
  hf auth login
160
  hf download apus-ailab/APUS-OpenJev-v1 \
161
- --include "9B-3000/*" --local-dir ./APUS-OpenJev-v1
162
  cd ./APUS-OpenJev-v1/9B-3000
163
  python -m pip install -r requirements.txt
164
  python examples.py . --device cuda:0 --effort high
 
143
 
144
  ## 5. 最小推理示例
145
 
146
+ 根目录 [meta.yaml](meta.yaml) 提供模型版本及配置哈希;下载指定版本时请同时保留它,仓库与原模型路径不变。也可运行 [download_model.py](download_model.py),参数为 `--variant 9B-3000 --local-dir ./APUS-OpenJev-v1`,在同一固定 Hub revision 选择并校验模型。Hub 下载统计按指定元数据文件的请求计数,不等同独立用户或完整权重下载;旧版仅下载子目录的客户端可能绕过此元数据。
147
+
148
+
149
  本仓库集中保存一个模型系列。请选择包含完整BF16权重和参考runtime的具体子目录:
150
 
151
  | 版本 | 模型目录 | 建议用途 |
 
161
  python -m pip install huggingface_hub
162
  hf auth login
163
  hf download apus-ailab/APUS-OpenJev-v1 \
164
+ --include "meta.yaml" "9B-3000/*" --local-dir ./APUS-OpenJev-v1
165
  cd ./APUS-OpenJev-v1/9B-3000
166
  python -m pip install -r requirements.txt
167
  python examples.py . --device cuda:0 --effort high
bundle-manifest.json CHANGED
@@ -28,9 +28,11 @@
28
  "assets/equations/projection-cost.svg",
29
  "assets/latency-vllm.svg",
30
  "deployment/serve_vllm.py",
 
31
  "effort-tradeoff-data.json",
32
  "equations-source.json",
33
- "latency-vllm-data.json"
 
34
  ],
35
  "files": [
36
  {
@@ -590,13 +592,13 @@
590
  },
591
  {
592
  "path": "README.md",
593
- "bytes": 18803,
594
- "sha256": "47b45662d3356a3324062b84cb6bd381621865241744cbe9ff0c0928fb8f948d"
595
  },
596
  {
597
  "path": "README.zh-CN.md",
598
- "bytes": 14045,
599
- "sha256": "0a733d01ed54e3f9dca9210c5384d46a62128a746d5c78b20474f0c7d76e7bfb"
600
  },
601
  {
602
  "path": "TECHNICAL_REPORT.md",
@@ -685,8 +687,13 @@
685
  },
686
  {
687
  "path": "deployment/serve_vllm.py",
688
- "bytes": 3535,
689
- "sha256": "7d8fac3021a9f9949e73364013989d861dcb6fd4c44ee338239822584d32ecf8"
 
 
 
 
 
690
  },
691
  {
692
  "path": "effort-tradeoff-data.json",
@@ -703,6 +710,11 @@
703
  "bytes": 3456,
704
  "sha256": "3165a4510d2d294934b0374d1f6e9a53303f5fa734daf662eb8a3aa69581fab0"
705
  },
 
 
 
 
 
706
  {
707
  "path": "subset-chart-data.json",
708
  "bytes": 58611,
 
28
  "assets/equations/projection-cost.svg",
29
  "assets/latency-vllm.svg",
30
  "deployment/serve_vllm.py",
31
+ "download_model.py",
32
  "effort-tradeoff-data.json",
33
  "equations-source.json",
34
+ "latency-vllm-data.json",
35
+ "meta.yaml"
36
  ],
37
  "files": [
38
  {
 
592
  },
593
  {
594
  "path": "README.md",
595
+ "bytes": 19342,
596
+ "sha256": "93fdbfe97a697fb5576b7e12fd9e2871656a99b5994b56e6eb9e2e2cf77dcbae"
597
  },
598
  {
599
  "path": "README.zh-CN.md",
600
+ "bytes": 14539,
601
+ "sha256": "bdc3560df8a90a75f6ce4cc996aaddae5f9801134760279f2b7efbc05f995448"
602
  },
603
  {
604
  "path": "TECHNICAL_REPORT.md",
 
687
  },
688
  {
689
  "path": "deployment/serve_vllm.py",
690
+ "bytes": 5319,
691
+ "sha256": "2dab173e233c3b96c49a6fc416204a7800e0887aae53bb60e28e9f8ecfa4b777"
692
+ },
693
+ {
694
+ "path": "download_model.py",
695
+ "bytes": 2894,
696
+ "sha256": "3a5abe26075c47d10ee1854c60365b651be5d7caad8523896fd27c1b881a53a2"
697
  },
698
  {
699
  "path": "effort-tradeoff-data.json",
 
710
  "bytes": 3456,
711
  "sha256": "3165a4510d2d294934b0374d1f6e9a53303f5fa734daf662eb8a3aa69581fab0"
712
  },
713
+ {
714
+ "path": "meta.yaml",
715
+ "bytes": 811,
716
+ "sha256": "937aaa3208cf803e03295a64b788e3c4f99299c5d1f5b6341701e90e93250989"
717
+ },
718
  {
719
  "path": "subset-chart-data.json",
720
  "bytes": 58611,
deployment/serve_vllm.py CHANGED
@@ -1,6 +1,7 @@
1
  """Download APUS-OpenJev-v1 merged 9B weights and launch standard vLLM serving."""
2
 
3
  import argparse
 
4
  import json
5
  import os
6
  from pathlib import Path
@@ -48,6 +49,45 @@ def engine_command(model, host, port):
48
  ]
49
 
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  def main():
52
  parser = argparse.ArgumentParser(description=__doc__)
53
  parser.add_argument(
@@ -88,6 +128,7 @@ def main():
88
  revision = HfApi().model_info(MODEL_REPO, revision=args.revision).sha
89
  if not revision or not re.fullmatch(r"[0-9a-f]{40}", revision):
90
  parser.error("The Hub did not return an immutable model commit SHA")
 
91
  snapshot = snapshot_download(
92
  repo_id=MODEL_REPO, revision=revision, allow_patterns=[f"{MODEL_SUBFOLDER}/*"]
93
  )
@@ -96,6 +137,8 @@ def main():
96
  parser.error(
97
  "Downloaded subfolder is missing config.json or merged safetensors weights"
98
  )
 
 
99
  if (model / "adapter_config.json").exists():
100
  parser.error("Expected merged weights, not an adapter-only directory")
101
  print(
 
1
  """Download APUS-OpenJev-v1 merged 9B weights and launch standard vLLM serving."""
2
 
3
  import argparse
4
+ import hashlib
5
  import json
6
  import os
7
  from pathlib import Path
 
49
  ]
50
 
51
 
52
+ def select_catalog_model(repo, revision):
53
+ from huggingface_hub import hf_hub_download
54
+ from huggingface_hub.errors import EntryNotFoundError
55
+
56
+ try:
57
+ path = hf_hub_download(repo_id=repo, filename="meta.yaml", revision=revision)
58
+ except EntryNotFoundError:
59
+ # Preserve explicit older revisions published before the family catalog.
60
+ path = hf_hub_download(
61
+ repo_id=repo, filename="bundle-manifest.json", revision=revision
62
+ )
63
+ manifest = json.loads(Path(path).read_text())
64
+ if manifest.get("repo_id") != repo:
65
+ raise ValueError("Unexpected legacy family manifest")
66
+ matches = [
67
+ item for item in manifest["files"]
68
+ if item.get("path") == MODEL_SUBFOLDER + "/config.json"
69
+ ]
70
+ if len(matches) != 1:
71
+ raise ValueError("Missing or duplicate legacy config identity")
72
+ entry = {
73
+ "subfolder": MODEL_SUBFOLDER,
74
+ "config_sha256": matches[0]["sha256"],
75
+ }
76
+ else:
77
+ catalog = json.loads(Path(path).read_text())
78
+ if (
79
+ catalog.get("schema") != "apus-openjev-family.v1"
80
+ or catalog.get("repo_id") != repo
81
+ ):
82
+ raise ValueError("Unexpected model-family catalog")
83
+ entry = catalog["variants"][MODEL_SUBFOLDER]
84
+ if entry.get("subfolder") != MODEL_SUBFOLDER or not re.fullmatch(
85
+ r"[0-9a-f]{64}", entry.get("config_sha256", "")
86
+ ):
87
+ raise ValueError("Unexpected model variant identity")
88
+ return entry
89
+
90
+
91
  def main():
92
  parser = argparse.ArgumentParser(description=__doc__)
93
  parser.add_argument(
 
128
  revision = HfApi().model_info(MODEL_REPO, revision=args.revision).sha
129
  if not revision or not re.fullmatch(r"[0-9a-f]{40}", revision):
130
  parser.error("The Hub did not return an immutable model commit SHA")
131
+ entry = select_catalog_model(MODEL_REPO, revision)
132
  snapshot = snapshot_download(
133
  repo_id=MODEL_REPO, revision=revision, allow_patterns=[f"{MODEL_SUBFOLDER}/*"]
134
  )
 
137
  parser.error(
138
  "Downloaded subfolder is missing config.json or merged safetensors weights"
139
  )
140
+ if hashlib.sha256((model / "config.json").read_bytes()).hexdigest() != entry["config_sha256"]:
141
+ parser.error("Downloaded model config does not match family catalog")
142
  if (model / "adapter_config.json").exists():
143
  parser.error("Expected merged weights, not an adapter-only directory")
144
  print(
download_model.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Download one APUS-OpenJev variant using its verified family catalog.
2
+
3
+ The Hub's meta.yaml is JSON (a YAML 1.2 subset), so no YAML dependency is needed.
4
+ Only the requested model subdirectory is downloaded. Requires huggingface_hub.
5
+ """
6
+
7
+ import argparse
8
+ import hashlib
9
+ import json
10
+ from pathlib import Path
11
+ import re
12
+
13
+ REPO_ID = "apus-ailab/APUS-OpenJev-v1"
14
+ VARIANTS = ("4B-5949", "9B-3000", "9B-5949")
15
+ SCHEMA = "apus-openjev-family.v1"
16
+
17
+
18
+ def download_variant(*, local_dir, variant="9B-3000", revision="main"):
19
+ """Resolve once, validate the catalog, download and verify the model config."""
20
+ if variant not in VARIANTS:
21
+ raise ValueError("Unknown model variant")
22
+
23
+ from huggingface_hub import HfApi, hf_hub_download, snapshot_download
24
+
25
+ commit = HfApi().model_info(REPO_ID, revision=revision).sha
26
+ if not isinstance(commit, str) or not re.fullmatch(r"[0-9a-f]{40}", commit):
27
+ raise ValueError("Hub did not return an immutable commit SHA")
28
+ catalog_path = hf_hub_download(REPO_ID, "meta.yaml", revision=commit)
29
+ catalog = json.loads(Path(catalog_path).read_text(encoding="utf-8"))
30
+ if (
31
+ not isinstance(catalog, dict)
32
+ or catalog.get("schema") != SCHEMA
33
+ or catalog.get("repo_id") != REPO_ID
34
+ or not isinstance(catalog.get("variants"), dict)
35
+ ):
36
+ raise ValueError("Invalid model family catalog")
37
+ entry = catalog["variants"].get(variant)
38
+ if not isinstance(entry, dict) or entry.get("subfolder") != variant:
39
+ raise ValueError("Catalog subfolder does not match the selected variant")
40
+ expected_sha = entry.get("config_sha256")
41
+ if not isinstance(expected_sha, str) or not re.fullmatch(
42
+ r"[0-9a-f]{64}", expected_sha
43
+ ):
44
+ raise ValueError("Catalog config_sha256 is invalid")
45
+
46
+ snapshot = snapshot_download(
47
+ repo_id=REPO_ID,
48
+ revision=commit,
49
+ allow_patterns=[f"{variant}/*"],
50
+ local_dir=str(local_dir),
51
+ )
52
+ model_path = Path(snapshot) / variant
53
+ actual_sha = hashlib.sha256((model_path / "config.json").read_bytes()).hexdigest()
54
+ if actual_sha != expected_sha:
55
+ raise ValueError("Downloaded config.json does not match the family catalog")
56
+ return {
57
+ "repo_id": REPO_ID,
58
+ "revision": commit,
59
+ "variant": variant,
60
+ "model_path": str(model_path.resolve()),
61
+ "config_sha256": actual_sha,
62
+ }
63
+
64
+
65
+ def main(argv=None):
66
+ parser = argparse.ArgumentParser(description=__doc__)
67
+ parser.add_argument("--variant", choices=VARIANTS, default="9B-3000")
68
+ parser.add_argument("--revision", default="main")
69
+ parser.add_argument("--local-dir", type=Path, required=True)
70
+ args = parser.parse_args(argv)
71
+ result = download_variant(
72
+ local_dir=args.local_dir, variant=args.variant, revision=args.revision
73
+ )
74
+ print(json.dumps(result, indent=2))
75
+
76
+
77
+ if __name__ == "__main__":
78
+ main()
meta.yaml ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "schema": "apus-openjev-family.v1",
3
+ "repo_id": "apus-ailab/APUS-OpenJev-v1",
4
+ "description": "Select a complete model subdirectory; this is family metadata, not a Transformers model config.",
5
+ "variants": {
6
+ "4B-5949": {
7
+ "subfolder": "4B-5949",
8
+ "config_sha256": "4b53bdb886bb68d228841409c2db2f5d7eb670c28ae4376849f58d3bd014968d",
9
+ "checkpoint": 5949,
10
+ "dtype": "bfloat16"
11
+ },
12
+ "9B-3000": {
13
+ "subfolder": "9B-3000",
14
+ "config_sha256": "b1d02fb6b40aeba43105ca558b2532f31d062e0bd95bce564d9996c0a34b4211",
15
+ "checkpoint": 3000,
16
+ "dtype": "bfloat16"
17
+ },
18
+ "9B-5949": {
19
+ "subfolder": "9B-5949",
20
+ "config_sha256": "b1d02fb6b40aeba43105ca558b2532f31d062e0bd95bce564d9996c0a34b4211",
21
+ "checkpoint": 5949,
22
+ "dtype": "bfloat16"
23
+ }
24
+ }
25
+ }