dsh-context-compression-improved 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +1 -0
- package/.github/workflows/ci.yml +39 -0
- package/CHANGELOG.ja.md +39 -0
- package/CHANGELOG.ko.md +39 -0
- package/CHANGELOG.md +135 -0
- package/CHANGELOG.zh.md +39 -0
- package/CONTRIBUTING.md +22 -0
- package/README.ja.md +104 -0
- package/README.ko.md +103 -0
- package/README.md +89 -12
- package/README.zh.md +87 -12
- package/SECURITY.md +18 -0
- package/THIRD_PARTY_NOTICES.md +7 -31
- package/docs/installation.ja.md +76 -0
- package/docs/installation.ko.md +76 -0
- package/docs/installation.md +76 -0
- package/docs/installation.zh.md +76 -0
- package/docs/repair-log.md +582 -0
- package/eslint.config.js +30 -0
- package/package.json +84 -81
- package/packages/selector/LICENSE +21 -0
- package/packages/selector/README.md +26 -0
- package/packages/selector/README.zh.md +26 -0
- package/packages/selector/THIRD_PARTY_NOTICES.md +38 -0
- package/packages/selector/docs/history-tool-call-working-set-spec.md +112 -0
- package/packages/selector/docs/native-tool-result-selector-spec.md +34 -0
- package/packages/selector/docs/subagent-cache-reuse-spec.md +46 -0
- package/packages/selector/lib/style.css +308 -0
- package/packages/selector/package.json +115 -0
- package/{screenshots.json → packages/selector/screenshots.json} +6 -6
- package/packages/selector/src/client/CompressionProfileControls.tsx +229 -0
- package/packages/selector/src/client/CompressionProfileSelector.module.css +170 -0
- package/packages/selector/src/client/CompressionProfileSelector.tsx +79 -0
- package/packages/selector/src/client/CustomPolicyEditor.tsx +216 -0
- package/packages/selector/src/client/EstimatorControls.tsx +281 -0
- package/packages/selector/src/client/decode.ts +49 -0
- package/packages/selector/src/client/index.ts +111 -0
- package/packages/selector/src/client/locales.ts +198 -0
- package/packages/selector/src/client/preset-options.ts +70 -0
- package/packages/selector/src/client/settings-section.tsx +126 -0
- package/packages/selector/src/css-modules.d.ts +6 -0
- package/packages/selector/src/deepseek-v4-tokenizer.ts +210 -0
- package/packages/selector/src/estimator-catalog.ts +104 -0
- package/packages/selector/src/index.ts +327 -0
- package/packages/selector/src/invariant.ts +113 -0
- package/packages/selector/src/preset-overlay.ts +567 -0
- package/packages/selector/src/profiles.ts +342 -0
- package/packages/selector/src/pruner/content.ts +188 -0
- package/packages/selector/src/pruner/session.ts +94 -0
- package/packages/selector/src/pruner/state.ts +43 -0
- package/packages/selector/src/pruner/tuning.ts +23 -0
- package/packages/selector/src/pruner/types.ts +60 -0
- package/packages/selector/src/pruner.ts +2144 -0
- package/packages/selector/src/runtime/adaptive-cost.ts +194 -0
- package/packages/selector/src/runtime/audit.ts +215 -0
- package/packages/selector/src/runtime/config.ts +613 -0
- package/packages/selector/src/runtime/custom-policy.ts +278 -0
- package/packages/selector/src/runtime/deepseek-official-pricing.ts +298 -0
- package/packages/selector/src/runtime/deepseek-v4-vision-tokens.ts +254 -0
- package/packages/selector/src/runtime/measurement.ts +403 -0
- package/packages/selector/src/runtime/reducers.ts +656 -0
- package/packages/selector/src/runtime/retrieve.ts +457 -0
- package/packages/selector/src/runtime/session-events.ts +17 -0
- package/packages/selector/src/runtime/tail-trim.ts +166 -0
- package/packages/selector/src/runtime/token-count.ts +72 -0
- package/packages/selector/src/runtime/tokenpilot/dedup.ts +81 -0
- package/packages/selector/src/runtime/tokenpilot/estimator.ts +183 -0
- package/packages/selector/src/runtime/tokenpilot/locator.ts +128 -0
- package/packages/selector/src/runtime/tokenpilot/read-state.ts +77 -0
- package/packages/selector/src/runtime/types.ts +309 -0
- package/packages/selector/src/runtime/value.ts +48 -0
- package/packages/selector/tests/auto-compact.client.spec.tsx +226 -0
- package/packages/selector/tests/built/client-artifact.spec.ts +51 -0
- package/packages/selector/tests/cache-prefix-audit.spec.ts +123 -0
- package/packages/selector/tests/code-skeleton.client.spec.ts +88 -0
- package/packages/selector/tests/custom-contract.client.spec.ts +202 -0
- package/packages/selector/tests/estimator-catalog.spec.ts +70 -0
- package/packages/selector/tests/estimator-channel.client.spec.tsx +247 -0
- package/packages/selector/tests/estimator-route-registration.host.spec.ts +176 -0
- package/packages/selector/tests/host-preset-overlay.host.spec.ts +204 -0
- package/packages/selector/tests/preset-options-write.client.spec.ts +181 -0
- package/packages/selector/tests/preset-overlay-loader.e2e.host.spec.ts +196 -0
- package/packages/selector/tests/preset-overlay.host.spec.ts +243 -0
- package/packages/selector/tests/profiles.client.spec.tsx +434 -0
- package/packages/selector/tests/public/package-contract.client.spec.ts +33 -0
- package/packages/selector/tests/runtime/adaptive-cost.spec.ts +167 -0
- package/packages/selector/tests/runtime/audit.spec.ts +129 -0
- package/packages/selector/tests/runtime/auto-compact-config.spec.ts +523 -0
- package/packages/selector/tests/runtime/code-skeleton.spec.ts +141 -0
- package/packages/selector/tests/runtime/deepseek-official-pricing.spec.ts +186 -0
- package/packages/selector/tests/runtime/deepseek-v4-tokenizer.spec.ts +122 -0
- package/packages/selector/tests/runtime/deepseek-v4-vision-tokens.spec.ts +122 -0
- package/packages/selector/tests/runtime/fixtures/profile-baseline.json +273 -0
- package/packages/selector/tests/runtime/fixtures/tokenizer-golden.json +106 -0
- package/packages/selector/tests/runtime/fixtures/vision-golden.json +459 -0
- package/packages/selector/tests/runtime/public/public-runtime.spec.ts +2531 -0
- package/packages/selector/tests/runtime/session-events.spec.ts +27 -0
- package/packages/selector/tests/runtime/tokenizer-golden.spec.ts +53 -0
- package/packages/selector/tests/runtime/tokenpilot/dedup.spec.ts +52 -0
- package/packages/selector/tests/runtime/tokenpilot/estimator.spec.ts +56 -0
- package/packages/selector/tests/runtime/tokenpilot/locator.spec.ts +76 -0
- package/packages/selector/tests/runtime/tokenpilot/profile-baseline.spec.ts +100 -0
- package/packages/selector/tests/runtime/tokenpilot/read-state.spec.ts +58 -0
- package/packages/selector/tests/runtime/value.spec.ts +23 -0
- package/packages/selector/tests/standing-generation.host.spec.ts +631 -0
- package/packages/selector/tests/subagent-cache-reuse.host.spec.ts +250 -0
- package/packages/selector/tests/support/cache-prefix-audit.ts +105 -0
- package/packages/selector/tests/support/mock-adapter.ts +37 -0
- package/packages/selector/tests/support/ui-primitives.tsx +34 -0
- package/packages/selector/tsconfig.json +11 -0
- package/packages/selector/tsdown.client.config.ts +102 -0
- package/packages/selector/tsdown.config.ts +20 -0
- package/pnpm-workspace.yaml +19 -0
- package/scripts/capture-profile-baseline.ts +80 -0
- package/scripts/generate-tokenizer-fixtures.py +81 -0
- package/scripts/generate-vision-fixtures.py +208 -0
- package/scripts/packed-components-smoke.ts +713 -0
- package/scripts/packed-install-e2e.ts +1072 -0
- package/scripts/verify-release.ts +300 -0
- package/tests/TEST_INVENTORY.md +42 -0
- package/tsconfig.base.json +18 -0
- package/tsconfig.json +7 -0
- package/tsconfig.scripts.json +13 -0
- package/tsconfig.tests.json +15 -0
- package/vitest.built.config.ts +9 -0
- package/vitest.config.ts +43 -0
- /package/{assets → packages/selector/assets}/deepseek-v4/LICENSE.DeepSeek-V4-Pro.txt +0 -0
- /package/{assets → packages/selector/assets}/deepseek-v4/manifest.json +0 -0
- /package/{assets → packages/selector/assets}/deepseek-v4/tokenizer.json +0 -0
- /package/{assets → packages/selector/assets}/deepseek-v4/tokenizer_config.json +0 -0
- /package/{assets → packages/selector/assets}/deepseek-v4-vision-exp/LICENSE.DeepSeek-V4-Flash-Vision-Exp.txt +0 -0
- /package/{assets → packages/selector/assets}/deepseek-v4-vision-exp/manifest.json +0 -0
- /package/{assets → packages/selector/assets}/deepseek-v4-vision-exp/tokenizer.json +0 -0
- /package/{assets → packages/selector/assets}/deepseek-v4-vision-exp/tokenizer_config.json +0 -0
- /package/{assets → packages/selector/assets}/screenshots/context-compression-selector-profiles.jpg +0 -0
- /package/{assets → packages/selector/assets}/screenshots/context-compression-selector-settings.png +0 -0
- /package/{cordis.patch.yml → packages/selector/cordis.patch.yml} +0 -0
- /package/{dsh.plugin.json → packages/selector/dsh.plugin.json} +0 -0
- /package/{lib → packages/selector/lib}/client.d.ts +0 -0
- /package/{lib → packages/selector/lib}/client.js +0 -0
- /package/{lib → packages/selector/lib}/config.js +0 -0
- /package/{lib → packages/selector/lib}/index.d.ts +0 -0
- /package/{lib → packages/selector/lib}/index.js +0 -0
- /package/{lib → packages/selector/lib}/invariant.d.ts +0 -0
- /package/{lib → packages/selector/lib}/invariant.js +0 -0
- /package/{lib → packages/selector/lib}/pruner.d.ts +0 -0
- /package/{lib → packages/selector/lib}/pruner.js +0 -0
- /package/{lib → packages/selector/lib}/tail-trim.js +0 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Regenerate the tokenizer golden fixture for the Node loader equivalence tests.
|
|
3
|
+
|
|
4
|
+
Loads each pinned ``tokenizer.json`` shipped in ``packages/selector/assets`` with
|
|
5
|
+
the official Hugging Face ``tokenizers`` Python library (the same Rust core the
|
|
6
|
+
``transformers`` tokenizer for these repositories uses) and records the token
|
|
7
|
+
counts the Node runtime must reproduce exactly.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
python3 scripts/generate-tokenizer-fixtures.py
|
|
11
|
+
|
|
12
|
+
Requires: pip install tokenizers
|
|
13
|
+
Output: packages/selector/tests/runtime/fixtures/tokenizer-golden.json
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import json
|
|
17
|
+
import pathlib
|
|
18
|
+
import platform
|
|
19
|
+
|
|
20
|
+
REPO_ROOT = pathlib.Path(__file__).resolve().parent.parent
|
|
21
|
+
ASSETS = {
|
|
22
|
+
"deepseek-ai/DeepSeek-V4-Pro": REPO_ROOT / "packages/selector/assets/deepseek-v4",
|
|
23
|
+
"deepseek-ai/DeepSeek-V4-Flash-Vision-Exp": REPO_ROOT
|
|
24
|
+
/ "packages/selector/assets/deepseek-v4-vision-exp",
|
|
25
|
+
}
|
|
26
|
+
OUTPUT = REPO_ROOT / "packages/selector/tests/runtime/fixtures/tokenizer-golden.json"
|
|
27
|
+
|
|
28
|
+
CASES = [
|
|
29
|
+
("english prose", "The quick brown fox jumps over the lazy dog."),
|
|
30
|
+
("simplified chinese", "上下文压缩选择器在长任务中回收工具结果 token。"),
|
|
31
|
+
("mixed zh-en", "DeepSeek Harness 的 tool result 压缩,Fresh/Aggregate/History 三个阶段。"),
|
|
32
|
+
("json tool output", '{"status":"ok","items":[{"id":1,"path":"/tmp/a.txt"}],"count":1}'),
|
|
33
|
+
("python code", "def solve(width: int, height: int) -> int:\n return width * height // 2\n"),
|
|
34
|
+
("shell transcript", "$ pnpm run test\n> vitest run\n\n Test Files 12 passed (12)\n"),
|
|
35
|
+
("unicode whitespace", "line1\nline2\r\nline3\tline4 double spaces"),
|
|
36
|
+
("deepseek chat special tokens", "<|begin▁of▁sentence|><|User|>hello<|Assistant|><think>\n"),
|
|
37
|
+
("vision image placeholder", "before<|deepseek_image|>after"),
|
|
38
|
+
("empty string", ""),
|
|
39
|
+
("single ascii char", "a"),
|
|
40
|
+
("emoji", "compression 🧠✅ done"),
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
MANIFEST_REVISIONS = {}
|
|
44
|
+
for repository, asset_dir in ASSETS.items():
|
|
45
|
+
manifest = json.loads((asset_dir / "manifest.json").read_text(encoding="utf-8"))
|
|
46
|
+
MANIFEST_REVISIONS[repository] = manifest["revision"]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def main() -> None:
|
|
50
|
+
from tokenizers import Tokenizer
|
|
51
|
+
|
|
52
|
+
tokenizers = {}
|
|
53
|
+
for repository, asset_dir in ASSETS.items():
|
|
54
|
+
# Python `tokenizers` loads the fast-tokenizer definition directly from
|
|
55
|
+
# tokenizer.json; tokenizer_config.json only governs transformers-level
|
|
56
|
+
# special-token insertion, which these counts deliberately disable.
|
|
57
|
+
tokenizers[repository] = Tokenizer.from_file(str(asset_dir / "tokenizer.json"))
|
|
58
|
+
|
|
59
|
+
cases = []
|
|
60
|
+
for label, text in CASES:
|
|
61
|
+
counts = {}
|
|
62
|
+
for repository, tokenizer in tokenizers.items():
|
|
63
|
+
encoding = tokenizer.encode(text, add_special_tokens=False)
|
|
64
|
+
counts[repository] = len(encoding.ids)
|
|
65
|
+
cases.append({"label": label, "text": text, "counts": counts})
|
|
66
|
+
|
|
67
|
+
import tokenizers
|
|
68
|
+
|
|
69
|
+
fixture = {
|
|
70
|
+
"generator": f"tokenizers {tokenizers.__version__} on {platform.system()}",
|
|
71
|
+
"revision": "1",
|
|
72
|
+
"tokenizers": {repository: MANIFEST_REVISIONS[repository] for repository in sorted(ASSETS)},
|
|
73
|
+
"cases": cases,
|
|
74
|
+
}
|
|
75
|
+
OUTPUT.parent.mkdir(parents=True, exist_ok=True)
|
|
76
|
+
OUTPUT.write_text(json.dumps(fixture, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
|
77
|
+
print(f"wrote {OUTPUT} with {len(cases)} cases")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
if __name__ == "__main__":
|
|
81
|
+
main()
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Regenerate the DeepSeek V4 Flash Vision image-token golden fixture.
|
|
3
|
+
|
|
4
|
+
Downloads the official ``inference/image_processor.py`` and ``config.json`` from
|
|
5
|
+
the pinned immutable revision of ``deepseek-ai/DeepSeek-V4-Flash-Vision-Exp``,
|
|
6
|
+
runs the official pipeline over synthetic images of many sizes and aspect
|
|
7
|
+
ratios, and records the token counts the Node runtime must reproduce exactly.
|
|
8
|
+
|
|
9
|
+
Every number in the fixture is produced by the official implementation; this
|
|
10
|
+
script never re-implements the arithmetic.
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
python3 scripts/generate-vision-fixtures.py [--workdir DIR]
|
|
14
|
+
|
|
15
|
+
Requires: pip install torch pillow
|
|
16
|
+
Output: packages/selector/tests/runtime/fixtures/vision-golden.json
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
import io
|
|
21
|
+
import json
|
|
22
|
+
import math
|
|
23
|
+
import pathlib
|
|
24
|
+
import sys
|
|
25
|
+
import types
|
|
26
|
+
import urllib.request
|
|
27
|
+
|
|
28
|
+
REPO_ROOT = pathlib.Path(__file__).resolve().parent.parent
|
|
29
|
+
OUTPUT = REPO_ROOT / "packages/selector/tests/runtime/fixtures/vision-golden.json"
|
|
30
|
+
REVISION = "6821d6ad3681a4b137b066b76094fa82ebd0a380"
|
|
31
|
+
BASE = f"https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash-Vision-Exp/resolve/{REVISION}"
|
|
32
|
+
|
|
33
|
+
# (width, height) cases: squares, portrait/landscape, min-pixel upscale,
|
|
34
|
+
# the 8:1 aspect clamp in both orientations, the 384-token cap, and sizes
|
|
35
|
+
# around the patch grid boundaries.
|
|
36
|
+
SINGLE_SIZES = [
|
|
37
|
+
(14, 14),
|
|
38
|
+
(28, 14),
|
|
39
|
+
(56, 56),
|
|
40
|
+
(100, 100),
|
|
41
|
+
(224, 224),
|
|
42
|
+
(240, 180),
|
|
43
|
+
(180, 240),
|
|
44
|
+
(384, 384),
|
|
45
|
+
(512, 384),
|
|
46
|
+
(640, 480),
|
|
47
|
+
(800, 600),
|
|
48
|
+
(1024, 768),
|
|
49
|
+
(768, 1024),
|
|
50
|
+
(1280, 960),
|
|
51
|
+
(1600, 1200),
|
|
52
|
+
(2048, 1536),
|
|
53
|
+
(2000, 2000),
|
|
54
|
+
(4096, 4096),
|
|
55
|
+
(8, 8),
|
|
56
|
+
(4, 400),
|
|
57
|
+
(400, 4),
|
|
58
|
+
(64, 512),
|
|
59
|
+
(1152, 128),
|
|
60
|
+
(1024, 119),
|
|
61
|
+
(4200, 100),
|
|
62
|
+
(100, 4200),
|
|
63
|
+
(147, 147),
|
|
64
|
+
(1414, 1414),
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
# start positions exercising every compress-pad alignment and several
|
|
68
|
+
# multi-image accumulated offsets.
|
|
69
|
+
START_POSITIONS = [0, 1, 2, 3, 4, 5, 7, 8, 17, 64, 101, 383, 384, 766, 767]
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def png_bytes(width: int, height: int) -> bytes:
|
|
73
|
+
from PIL import Image
|
|
74
|
+
|
|
75
|
+
image = Image.new("RGB", (width, height), (127, 127, 127))
|
|
76
|
+
buffer = io.BytesIO()
|
|
77
|
+
image.save(buffer, format="PNG")
|
|
78
|
+
return buffer.getvalue()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def official_module(workdir: pathlib.Path) -> types.ModuleType:
|
|
82
|
+
source_path = workdir / "image_processor.py"
|
|
83
|
+
urllib.request.urlretrieve(f"{BASE}/inference/image_processor.py", source_path)
|
|
84
|
+
config_path = workdir / "config.json"
|
|
85
|
+
urllib.request.urlretrieve(f"{BASE}/config.json", config_path)
|
|
86
|
+
config = json.loads(config_path.read_text(encoding="utf-8"))
|
|
87
|
+
|
|
88
|
+
sys.path.insert(0, str(workdir))
|
|
89
|
+
import image_processor # noqa: PLC0415 (official module, downloaded on demand)
|
|
90
|
+
|
|
91
|
+
args = types.SimpleNamespace(
|
|
92
|
+
vision_patch_size=config["vision_patch_size"],
|
|
93
|
+
vision_downsample_ratio=config["vision_downsample_ratio"],
|
|
94
|
+
vision_max_n_token=config["vision_max_n_token"],
|
|
95
|
+
vision_min_pixels=config["vision_min_pixels"],
|
|
96
|
+
vision_max_wh_ratio=config["vision_max_wh_ratio"],
|
|
97
|
+
vocab_size=0,
|
|
98
|
+
)
|
|
99
|
+
return image_processor, args
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def main() -> None:
|
|
103
|
+
parser = argparse.ArgumentParser()
|
|
104
|
+
parser.add_argument("--workdir", default="/tmp/dsvision-fixture-work")
|
|
105
|
+
options = parser.parse_args()
|
|
106
|
+
workdir = pathlib.Path(options.workdir)
|
|
107
|
+
workdir.mkdir(parents=True, exist_ok=True)
|
|
108
|
+
|
|
109
|
+
official, args = official_module(workdir)
|
|
110
|
+
|
|
111
|
+
single = []
|
|
112
|
+
for width, height in SINGLE_SIZES:
|
|
113
|
+
patches, n_vit_h, n_vit_w, n_llm_h, n_llm_w = official.load_image(
|
|
114
|
+
{"data": png_bytes(width, height)}, args
|
|
115
|
+
)
|
|
116
|
+
assert tuple(patches.shape) == (n_vit_h * n_vit_w, 3, args.vision_patch_size, args.vision_patch_size)
|
|
117
|
+
single.append(
|
|
118
|
+
{
|
|
119
|
+
"width": width,
|
|
120
|
+
"height": height,
|
|
121
|
+
"startTokenPos": 0,
|
|
122
|
+
"nLlmH": n_llm_h,
|
|
123
|
+
"nLlmW": n_llm_w,
|
|
124
|
+
"tokensAtStart0": 0,
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# Official token totals depend on the running position; use one canonical
|
|
129
|
+
# size and sweep start positions through build_image_block directly.
|
|
130
|
+
canonical_width, canonical_height = 640, 480
|
|
131
|
+
_, _, _, n_llm_h, n_llm_w = official.load_image(
|
|
132
|
+
{"data": png_bytes(canonical_width, canonical_height)}, args
|
|
133
|
+
)
|
|
134
|
+
positions = []
|
|
135
|
+
for start in START_POSITIONS:
|
|
136
|
+
types_tensor, _perm = official.build_image_block(n_llm_h, n_llm_w, start)
|
|
137
|
+
positions.append(
|
|
138
|
+
{
|
|
139
|
+
"width": canonical_width,
|
|
140
|
+
"height": canonical_height,
|
|
141
|
+
"startTokenPos": start,
|
|
142
|
+
"nLlmH": n_llm_h,
|
|
143
|
+
"nLlmW": n_llm_w,
|
|
144
|
+
"tokens": int(types_tensor.numel()),
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# Multi-image sequences mirror prepare_vl_inputs: each image starts at the
|
|
149
|
+
# running position accumulated from every earlier image's expanded block.
|
|
150
|
+
sequences = []
|
|
151
|
+
for sizes in [
|
|
152
|
+
[(640, 480), (800, 600), (1024, 768)],
|
|
153
|
+
[(2048, 1536), (147, 147), (4096, 4096)],
|
|
154
|
+
[(64, 512), (1152, 128), (4200, 100), (100, 4200)],
|
|
155
|
+
]:
|
|
156
|
+
position = 3 # a small text prefix keeps this off the trivial 0 case
|
|
157
|
+
entries = []
|
|
158
|
+
for width, height in sizes:
|
|
159
|
+
_, _, _, grid_h, grid_w = official.load_image({"data": png_bytes(width, height)}, args)
|
|
160
|
+
types_tensor, _perm = official.build_image_block(grid_h, grid_w, position)
|
|
161
|
+
tokens = int(types_tensor.numel())
|
|
162
|
+
entries.append(
|
|
163
|
+
{
|
|
164
|
+
"width": width,
|
|
165
|
+
"height": height,
|
|
166
|
+
"startTokenPos": position,
|
|
167
|
+
"nLlmH": grid_h,
|
|
168
|
+
"nLlmW": grid_w,
|
|
169
|
+
"tokens": tokens,
|
|
170
|
+
}
|
|
171
|
+
)
|
|
172
|
+
position += tokens
|
|
173
|
+
sequences.append({"entries": entries})
|
|
174
|
+
|
|
175
|
+
# Token totals for every single size, each measured at its own start
|
|
176
|
+
# position sweep? Keep single sizes at a representative position instead:
|
|
177
|
+
# recompute each at a fixed non-zero start for a second data point.
|
|
178
|
+
for entry, (width, height) in zip(single, SINGLE_SIZES):
|
|
179
|
+
types_tensor, _perm = official.build_image_block(entry["nLlmH"], entry["nLlmW"], 0)
|
|
180
|
+
entry["tokensAtStart0"] = int(types_tensor.numel())
|
|
181
|
+
|
|
182
|
+
fixture = {
|
|
183
|
+
"source": {
|
|
184
|
+
"repository": "deepseek-ai/DeepSeek-V4-Flash-Vision-Exp",
|
|
185
|
+
"revision": REVISION,
|
|
186
|
+
"files": ["inference/image_processor.py", "config.json"],
|
|
187
|
+
},
|
|
188
|
+
"parameters": {
|
|
189
|
+
"visionPatchSize": args.vision_patch_size,
|
|
190
|
+
"visionDownsampleRatio": args.vision_downsample_ratio,
|
|
191
|
+
"visionMaxNTokens": args.vision_max_n_token,
|
|
192
|
+
"visionMinPixels": args.vision_min_pixels,
|
|
193
|
+
"visionMaxWhRatio": args.vision_max_wh_ratio,
|
|
194
|
+
},
|
|
195
|
+
"singleImages": single,
|
|
196
|
+
"startPositions": positions,
|
|
197
|
+
"sequences": sequences,
|
|
198
|
+
}
|
|
199
|
+
OUTPUT.parent.mkdir(parents=True, exist_ok=True)
|
|
200
|
+
OUTPUT.write_text(json.dumps(fixture, indent=2) + "\n", encoding="utf-8")
|
|
201
|
+
print(
|
|
202
|
+
f"wrote {OUTPUT}: {len(single)} sizes, {len(positions)} start positions, "
|
|
203
|
+
f"{len(sequences)} multi-image sequences"
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
if __name__ == "__main__":
|
|
208
|
+
main()
|