open-jet 0.4.32__py3-none-win_amd64.whl

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.
Files changed (135) hide show
  1. open_jet-0.4.32.data/purelib/megakernel/Makefile +28 -0
  2. open_jet-0.4.32.data/purelib/megakernel/README.md +203 -0
  3. open_jet-0.4.32.data/purelib/megakernel/capi.cpp +140 -0
  4. open_jet-0.4.32.data/purelib/megakernel/draft_vocab_32k.bin +0 -0
  5. open_jet-0.4.32.data/purelib/megakernel/gguf.h +129 -0
  6. open_jet-0.4.32.data/purelib/megakernel/main.cu +192 -0
  7. open_jet-0.4.32.data/purelib/megakernel/prefill.cuh +742 -0
  8. open_jet-0.4.32.data/purelib/megakernel/prefill_gemm.cuh +429 -0
  9. open_jet-0.4.32.data/purelib/megakernel/qwen38_mk.cu +2858 -0
  10. open_jet-0.4.32.data/purelib/megakernel/qwen38_mk.h +60 -0
  11. open_jet-0.4.32.data/purelib/megakernel/server/mk_server.py +544 -0
  12. open_jet-0.4.32.data/purelib/megakernel/tools/vocab_freq.cpp +87 -0
  13. open_jet-0.4.32.data/purelib/open_jet/__init__.py +19 -0
  14. open_jet-0.4.32.data/purelib/openjet/__init__.py +27 -0
  15. open_jet-0.4.32.data/purelib/openjet/sdk/__init__.py +71 -0
  16. open_jet-0.4.32.data/purelib/src/__init__.py +19 -0
  17. open_jet-0.4.32.data/purelib/src/agent.py +949 -0
  18. open_jet-0.4.32.data/purelib/src/airgap.py +172 -0
  19. open_jet-0.4.32.data/purelib/src/api_auth.py +168 -0
  20. open_jet-0.4.32.data/purelib/src/app.py +4177 -0
  21. open_jet-0.4.32.data/purelib/src/app_paths.py +39 -0
  22. open_jet-0.4.32.data/purelib/src/app_rendering.py +326 -0
  23. open_jet-0.4.32.data/purelib/src/app_telemetry.py +151 -0
  24. open_jet-0.4.32.data/purelib/src/benchmark.py +527 -0
  25. open_jet-0.4.32.data/purelib/src/cli.py +717 -0
  26. open_jet-0.4.32.data/purelib/src/codex_auth.py +362 -0
  27. open_jet-0.4.32.data/purelib/src/commands.py +1850 -0
  28. open_jet-0.4.32.data/purelib/src/completion.py +202 -0
  29. open_jet-0.4.32.data/purelib/src/config.py +562 -0
  30. open_jet-0.4.32.data/purelib/src/context/__init__.py +88 -0
  31. open_jet-0.4.32.data/purelib/src/context_index.py +199 -0
  32. open_jet-0.4.32.data/purelib/src/data/token_estimator_hardware.json +138 -0
  33. open_jet-0.4.32.data/purelib/src/data/token_estimator_models.json +118 -0
  34. open_jet-0.4.32.data/purelib/src/device_sources.py +551 -0
  35. open_jet-0.4.32.data/purelib/src/embed_catalog.py +245 -0
  36. open_jet-0.4.32.data/purelib/src/executor.py +854 -0
  37. open_jet-0.4.32.data/purelib/src/hardware.py +456 -0
  38. open_jet-0.4.32.data/purelib/src/harness.py +1414 -0
  39. open_jet-0.4.32.data/purelib/src/harness_debug.py +64 -0
  40. open_jet-0.4.32.data/purelib/src/hybrid.py +209 -0
  41. open_jet-0.4.32.data/purelib/src/litellm_client.py +219 -0
  42. open_jet-0.4.32.data/purelib/src/llama_server.py +908 -0
  43. open_jet-0.4.32.data/purelib/src/mcp_support/__init__.py +8 -0
  44. open_jet-0.4.32.data/purelib/src/mcp_support/cli.py +74 -0
  45. open_jet-0.4.32.data/purelib/src/mcp_support/config.py +372 -0
  46. open_jet-0.4.32.data/purelib/src/mcp_support/manager.py +500 -0
  47. open_jet-0.4.32.data/purelib/src/mcp_support/redaction.py +51 -0
  48. open_jet-0.4.32.data/purelib/src/mcp_support/results.py +121 -0
  49. open_jet-0.4.32.data/purelib/src/mcp_support/schema.py +104 -0
  50. open_jet-0.4.32.data/purelib/src/megakernel_build.py +112 -0
  51. open_jet-0.4.32.data/purelib/src/memory_reflection.py +259 -0
  52. open_jet-0.4.32.data/purelib/src/model_profiles.py +170 -0
  53. open_jet-0.4.32.data/purelib/src/multimodal.py +197 -0
  54. open_jet-0.4.32.data/purelib/src/observation/__init__.py +30 -0
  55. open_jet-0.4.32.data/purelib/src/observation/bridge.py +67 -0
  56. open_jet-0.4.32.data/purelib/src/observation/processors.py +517 -0
  57. open_jet-0.4.32.data/purelib/src/observation/store.py +86 -0
  58. open_jet-0.4.32.data/purelib/src/openai_codex_client.py +173 -0
  59. open_jet-0.4.32.data/purelib/src/openrouter_catalog.py +225 -0
  60. open_jet-0.4.32.data/purelib/src/peripherals/__init__.py +45 -0
  61. open_jet-0.4.32.data/purelib/src/peripherals/audio.py +178 -0
  62. open_jet-0.4.32.data/purelib/src/peripherals/camera.py +65 -0
  63. open_jet-0.4.32.data/purelib/src/peripherals/discovery.py +237 -0
  64. open_jet-0.4.32.data/purelib/src/peripherals/sensors.py +70 -0
  65. open_jet-0.4.32.data/purelib/src/peripherals/system.py +43 -0
  66. open_jet-0.4.32.data/purelib/src/peripherals/types.py +118 -0
  67. open_jet-0.4.32.data/purelib/src/persistent_memory.py +391 -0
  68. open_jet-0.4.32.data/purelib/src/project_setup.py +226 -0
  69. open_jet-0.4.32.data/purelib/src/provisioning.py +1559 -0
  70. open_jet-0.4.32.data/purelib/src/runtime/__init__.py +33 -0
  71. open_jet-0.4.32.data/purelib/src/runtime_client.py +30 -0
  72. open_jet-0.4.32.data/purelib/src/runtime_limits.py +292 -0
  73. open_jet-0.4.32.data/purelib/src/runtime_protocol.py +635 -0
  74. open_jet-0.4.32.data/purelib/src/runtime_registry.py +117 -0
  75. open_jet-0.4.32.data/purelib/src/sdk/__init__.py +81 -0
  76. open_jet-0.4.32.data/purelib/src/sdk/fix.py +1359 -0
  77. open_jet-0.4.32.data/purelib/src/sdk/recommendations.py +171 -0
  78. open_jet-0.4.32.data/purelib/src/sdk/session.py +1061 -0
  79. open_jet-0.4.32.data/purelib/src/sdk/tok_s.py +464 -0
  80. open_jet-0.4.32.data/purelib/src/self_update.py +221 -0
  81. open_jet-0.4.32.data/purelib/src/service_controller.py +1001 -0
  82. open_jet-0.4.32.data/purelib/src/session_logging.py +1163 -0
  83. open_jet-0.4.32.data/purelib/src/session_state.py +239 -0
  84. open_jet-0.4.32.data/purelib/src/setup.py +928 -0
  85. open_jet-0.4.32.data/purelib/src/setup_memory.py +420 -0
  86. open_jet-0.4.32.data/purelib/src/shell_targets.py +175 -0
  87. open_jet-0.4.32.data/purelib/src/skills/__init__.py +16 -0
  88. open_jet-0.4.32.data/purelib/src/skills/discovery.py +118 -0
  89. open_jet-0.4.32.data/purelib/src/skills/model.py +134 -0
  90. open_jet-0.4.32.data/purelib/src/skills/parser.py +193 -0
  91. open_jet-0.4.32.data/purelib/src/skills/registry.py +79 -0
  92. open_jet-0.4.32.data/purelib/src/skills/tools.py +68 -0
  93. open_jet-0.4.32.data/purelib/src/skills/validate.py +104 -0
  94. open_jet-0.4.32.data/purelib/src/skills_hub/__init__.py +17 -0
  95. open_jet-0.4.32.data/purelib/src/skills_hub/installer.py +106 -0
  96. open_jet-0.4.32.data/purelib/src/skills_hub/lockfile.py +48 -0
  97. open_jet-0.4.32.data/purelib/src/skills_hub/model.py +123 -0
  98. open_jet-0.4.32.data/purelib/src/skills_hub/scanner.py +84 -0
  99. open_jet-0.4.32.data/purelib/src/skills_hub/sources/__init__.py +5 -0
  100. open_jet-0.4.32.data/purelib/src/skills_hub/sources/base.py +12 -0
  101. open_jet-0.4.32.data/purelib/src/skills_hub/sources/github.py +7 -0
  102. open_jet-0.4.32.data/purelib/src/skills_hub/sources/official.py +7 -0
  103. open_jet-0.4.32.data/purelib/src/skills_hub/sources/url.py +7 -0
  104. open_jet-0.4.32.data/purelib/src/skills_hub/taps.py +27 -0
  105. open_jet-0.4.32.data/purelib/src/skills_registry.py +216 -0
  106. open_jet-0.4.32.data/purelib/src/surfaces/__init__.py +5 -0
  107. open_jet-0.4.32.data/purelib/src/surfaces/command_specs.py +85 -0
  108. open_jet-0.4.32.data/purelib/src/surfaces/tui.py +14 -0
  109. open_jet-0.4.32.data/purelib/src/swap_llama.py +121 -0
  110. open_jet-0.4.32.data/purelib/src/swap_manager.py +185 -0
  111. open_jet-0.4.32.data/purelib/src/system_metrics.py +328 -0
  112. open_jet-0.4.32.data/purelib/src/theme.py +93 -0
  113. open_jet-0.4.32.data/purelib/src/tool_executor.py +762 -0
  114. open_jet-0.4.32.data/purelib/src/tools/__init__.py +53 -0
  115. open_jet-0.4.32.data/purelib/src/tools/registry.py +472 -0
  116. open_jet-0.4.32.data/purelib/src/tui_bin/windows-x64/SHA256 +1 -0
  117. open_jet-0.4.32.data/purelib/src/tui_bin/windows-x64/openjet-tui.exe +4 -0
  118. open_jet-0.4.32.data/purelib/src/tui_bin/windows-x64/theme/dark.json +90 -0
  119. open_jet-0.4.32.data/purelib/src/tui_bin/windows-x64/theme/light.json +89 -0
  120. open_jet-0.4.32.data/purelib/src/tui_launcher.py +133 -0
  121. open_jet-0.4.32.data/purelib/src/tui_server.py +153 -0
  122. open_jet-0.4.32.data/purelib/src/voice_input.py +294 -0
  123. open_jet-0.4.32.data/purelib/src/workflows/__init__.py +36 -0
  124. open_jet-0.4.32.data/purelib/src/workflows/bindings.py +83 -0
  125. open_jet-0.4.32.data/purelib/src/workflows/daemon.py +239 -0
  126. open_jet-0.4.32.data/purelib/src/workflows/reports.py +76 -0
  127. open_jet-0.4.32.data/purelib/src/workflows/runner.py +295 -0
  128. open_jet-0.4.32.data/purelib/src/workflows/specs.py +165 -0
  129. open_jet-0.4.32.data/purelib/src/workflows/state.py +262 -0
  130. open_jet-0.4.32.dist-info/METADATA +289 -0
  131. open_jet-0.4.32.dist-info/RECORD +135 -0
  132. open_jet-0.4.32.dist-info/WHEEL +5 -0
  133. open_jet-0.4.32.dist-info/entry_points.txt +3 -0
  134. open_jet-0.4.32.dist-info/licenses/LICENSE +235 -0
  135. open_jet-0.4.32.dist-info/top_level.txt +4 -0
@@ -0,0 +1,28 @@
1
+ LLAMA ?= ../llama.cpp
2
+ NVCC ?= /usr/local/cuda/bin/nvcc
3
+ # the first GPU's architecture (sm_86 RTX 30, sm_89 RTX 40, sm_120 RTX 50); sm_86 if nvidia-smi is missing
4
+ ARCH ?= $(or $(shell nvidia-smi --query-gpu=compute_cap --format=csv,noheader 2>/dev/null | head -n1 | tr -d '. '),86)
5
+ ARCH := sm_$(patsubst sm_%,%,$(ARCH))
6
+ NVFLAGS = -O3 -std=c++17 -arch=$(ARCH) -lineinfo -Xptxas -dlcm=cg -Xptxas -v -Xcompiler -fPIC
7
+
8
+ all: qwen38_mk libqwen38mk.so tools/vocab_freq
9
+
10
+ # ptxas register / spill report for every phase function goes to ptxas.log
11
+ qwen38_mk.o: qwen38_mk.cu qwen38_mk.h gguf.h prefill.cuh prefill_gemm.cuh
12
+ $(NVCC) $(NVFLAGS) -c qwen38_mk.cu -o $@ 2> ptxas.log || (cat ptxas.log; false)
13
+
14
+ qwen38_mk: qwen38_mk.o main.cu
15
+ $(NVCC) -O3 -std=c++17 -arch=$(ARCH) -I$(LLAMA)/include -I$(LLAMA)/ggml/include main.cu qwen38_mk.o \
16
+ -L$(LLAMA)/build/bin -lllama -Xlinker -rpath -Xlinker $(abspath $(LLAMA)/build/bin) -o $@
17
+
18
+ # engine + tokenizer as a shared library with a C API (capi.cpp), used by server/mk_server.py
19
+ libqwen38mk.so: qwen38_mk.o capi.cpp qwen38_mk.h
20
+ $(NVCC) -O3 -std=c++17 -arch=$(ARCH) -shared -Xcompiler -fPIC -I$(LLAMA)/include -I$(LLAMA)/ggml/include capi.cpp qwen38_mk.o \
21
+ -L$(LLAMA)/build/bin -lllama -Xlinker -rpath -Xlinker $(abspath $(LLAMA)/build/bin) -o $@
22
+
23
+ tools/vocab_freq: tools/vocab_freq.cpp
24
+ g++ -O2 -std=c++17 -I$(LLAMA)/include -I$(LLAMA)/ggml/include $< -L$(LLAMA)/build/bin -lllama \
25
+ -Wl,-rpath,$(abspath $(LLAMA)/build/bin) -o $@
26
+
27
+ clean:
28
+ rm -f qwen38_mk libqwen38mk.so qwen38_mk.o ptxas.log tools/vocab_freq
@@ -0,0 +1,203 @@
1
+ # Qwen3.8-27B megakernel (RTX 30/40/50 series)
2
+
3
+ A specialised CUDA inference engine for `Qwen3.8-27B-Q4_K_M.gguf` (llama.cpp arch `qwen35`:
4
+ 48 Gated-DeltaNet + 16 gated-attention layers, one MTP block) on RTX 30, 40 and 50-series GPUs
5
+ with 24 GB+ (sm_86, sm_89, sm_120; tuned and benchmarked on an RTX 3090), with an OpenAI-compatible server that open-jet uses in place of `llama-server`
6
+ (`llama_backend: auto`, see [docs/runtimes/llama-cpp.md](../docs/runtimes/llama-cpp.md)).
7
+
8
+ Decoding runs an entire speculative cycle in one persistent cooperative kernel launch:
9
+
10
+ ```
11
+ main model over T = 1 + n_draft tokens -> lm_head + verification on device (greedy, or exact
12
+ speculative sampling) -> MTP catch-up rows for the accepted tokens -> n_draft MTP draft steps
13
+ ```
14
+
15
+ The ~340 phases of a cycle (projections, DeltaNet core, attention, FFN, lm_head, MTP) are separated
16
+ by a software grid barrier; the host only reads back the accepted tokens. Prompts go through
17
+ batched tensor-core kernels instead (see Prefill).
18
+
19
+ ## Results
20
+
21
+ RTX 3090, against `llama-server` with open-jet's flags (`--spec-type draft-mtp --spec-draft-n-max 2
22
+ -fa on -ctk q8_0 -ctv q8_0`). Back-to-back on an otherwise idle GPU; numbers vary with prompt
23
+ predictability (draft acceptance) and other GPU load.
24
+
25
+ **Reasoning mode as open-jet runs it** (thinking on, xhigh effort, temperature 1.0, top_p 0.95,
26
+ top_k 20; 5 coding prompts x 2 seeds, up to 1024 tokens each):
27
+
28
+ | | llama.cpp | megakernel | |
29
+ |---|---|---|---|
30
+ | decode through the HTTP servers (`/v1/chat/completions`) | 50.9 tok/s | **78.0 tok/s** | **1.53x** |
31
+ | decode, CLI (`bench/think_bench.py`, `-d 4`) | 50.7 tok/s | 77.4 tok/s | 1.53x |
32
+
33
+ **Greedy decode, 4 chat prompts x 512 tokens** (`bench/code_bench.py`):
34
+
35
+ | prompt | llama.cpp | megakernel `-d 3` | megakernel `-d 4` |
36
+ |---|---|---|---|
37
+ | Python function (code) | 72.5 | 126.3 | **139.7** (1.93x) |
38
+ | hash map explanation | 64.1 | 107.4 | 106.5 |
39
+ | short story | 52.8 | 66.8 | 70.7 |
40
+ | Flask to FastAPI plan | 63.2 | 102.6 | 109.8 |
41
+ | **mean** | 63.1 | 100.8 | **106.7** (1.69x) |
42
+
43
+ Without speculation: llama.cpp 40.4 tok/s, megakernel 42.9 (`-d 0`): the decode itself is close to
44
+ the memory-bandwidth limit for both; the lead comes from verifying 4-5 drafted tokens per pass at
45
+ almost no extra cost.
46
+
47
+ **A source file in the prompt, then a coding task** (greedy, 256 tokens; prompt = batched prefill of
48
+ the whole prompt incl. the first token):
49
+
50
+ | context | decode llama.cpp | decode megakernel | prompt llama.cpp | prompt megakernel |
51
+ |---|---|---|---|---|
52
+ | 1.8K | 57.4 | 84.8 | 1050 | 1595 |
53
+ | 3.6K | 56.3 | 95.3 | 1124 | 1595 |
54
+ | 7.8K | 54.8 | 85.8 | 1140 | 1533 |
55
+ | 15.9K | 55.7 | 86.5 | 1126 | 1466 |
56
+ | 29.5K | 52.3 | 72.7 | 1062 | 1236 |
57
+
58
+ (tok/s; measured before the sequence-token draft vocabulary and double-buffered attention below,
59
+ which add 1-8% to the megakernel's decode here.)
60
+
61
+ **Pasting a file into the next turn of a conversation** (prompt processing time):
62
+
63
+ | new tokens | llama.cpp (prompt cache) | megakernel |
64
+ |---|---|---|
65
+ | 2.7K | 2.41 s | 1.68 s |
66
+ | 12K | 10.45 s | 8.10 s |
67
+
68
+ With the q8_0 KV cache (chosen automatically for contexts above ~80K tokens, e.g. open-jet's 100K)
69
+ decode is ~1-2% and prefill 2-7% slower than with fp16.
70
+
71
+ **Correctness.** Teacher-forced on llama.cpp's own outputs, the megakernel's greedy prediction
72
+ agrees at 99.3-100% of positions (`--score`: 99.6-100%); the few disagreements are near-ties from
73
+ different float rounding. Speculative verification is exact: greedy output is the main model's
74
+ greedy choice, and with sampling the token distribution is the same as without drafts (2000-sample
75
+ test per position). Verifying 1 vs 4 tokens per pass rounds slightly differently, so on near-ties
76
+ the output can differ between `-d` settings.
77
+
78
+ ## Build / run
79
+
80
+ Requires CUDA 12+ (12.8+ for RTX 50 series; built with 13.2), an sm_86, sm_89 or sm_120 GPU with 24 GB, and the repo's llama.cpp build (only
81
+ `libllama`, for tokenization, loaded vocab-only). `openjet setup` builds `libqwen38mk.so` automatically
82
+ (this source ships in the open-jet wheel); building by hand:
83
+
84
+ ```sh
85
+ cd megakernel
86
+ make # qwen38_mk (CLI), libqwen38mk.so (server library), tools/vocab_freq; ~2 min
87
+ ./qwen38_mk -m ../models/Qwen3.8-27B-Q4_K_M.gguf -p "Write quicksort in C" -n 512 \
88
+ -d 4 --draft-vocab draft_vocab_32k.bin --think --temp 1.0 --top-p 0.95 --top-k 20
89
+ ```
90
+
91
+ CLI flags: `-d` drafts per cycle (0-4; with 4 the depth drops to 3 for a cycle after a rejected
92
+ draft), `-c` KV capacity, `--kv f16|q8|auto` (KV cache format), `--think [xhigh|medium|low]`
93
+ (reasoning mode; the chat template's default effort is xhigh), `--temp` / `--top-p` / `--top-k` /
94
+ `--min-p` / `--seed` (sampling; default greedy), `--raw` (no chat template), `--ids`,
95
+ `--prompt-ids f` (prompt as token ids), `--turn2 text` / `--turn2-file f` (a second user turn
96
+ appended to the conversation), `--score ids.txt` (teacher-forced agreement), `MK_PROFILE=1`
97
+ (per-phase timing, including a "min-composed" estimate that filters out time-slicing by other GPU
98
+ users), `MK_PF_PROFILE=1` (per-kernel prefill timing), `MK_PREFILL=mk` (prefill through the decode
99
+ megakernel instead).
100
+
101
+ Benchmarks: `bench/think_bench.py` (reasoning mode, both engines), `bench/code_bench.py` (greedy
102
+ decode, context sweep, second turn), `bench/bench.py` (decode on the 4 chat prompts);
103
+ `bench/*_bench.cu` are GEMV / GEMM microbenchmarks.
104
+
105
+ ## Server
106
+
107
+ `server/mk_server.py` serves the engine (through `libqwen38mk.so`, the C API in `capi.cpp`) with an
108
+ OpenAI-compatible `/v1/chat/completions`, streaming or not, plus `/health` and `/v1/models`.
109
+ open-jet starts it itself; standalone:
110
+
111
+ ```sh
112
+ python3 server/mk_server.py -m ../models/Qwen3.8-27B-Q4_K_M.gguf --port 18080 -c 100000
113
+ ```
114
+
115
+ - Prompts are rendered with the chat template stored in the GGUF (jinja2): `chat_template_kwargs`
116
+ `enable_thinking` / `preserve_thinking` / `reasoning_effort`, OpenAI `tools`. Reasoning is streamed
117
+ as `reasoning_content`, Qwen's XML tool calls are returned as structured `tool_calls`.
118
+ - Successive requests of a conversation only prefill what is new: the prompt is matched against the
119
+ engine's sequence (prompts + emitted tokens), and when the re-rendered history diverges after the
120
+ end of the previous prompt (e.g. a reformatted tool call) the engine rewinds to a checkpoint
121
+ saved there. Anything else starts over (batched prefill, ~1500 tok/s).
122
+ - Sampling: temperature, top_p, top_k (<= 32), min_p, seed; presence / repetition penalties are
123
+ ignored (with a warning). One request at a time.
124
+ - KV cache: fp16, or q8_0 when fp16 does not fit the requested context (`--kv auto|f16|q8`).
125
+
126
+ ## How it gets its speed
127
+
128
+ - **Weights stay in their GGUF k-quant encoding** (Q4_K / Q5_K / Q6_K / Q8_0), read once per
129
+ cycle regardless of T. Q6_K and Q8_0 are re-laid-out at load time (values unchanged) so every
130
+ lane does aligned 16/8-byte loads; Q6_K blocks carry their scales and `d` in one 8-byte word.
131
+ - **dp4a GEMV with shared activations**: activations are int8 (per-16/32 scales, as llama.cpp's
132
+ q8_1), each warp streams 2-4 weight rows at once and reuses every shared-memory activation
133
+ load across them, so T = 4 costs almost the same memory time as T = 1. Weight loads bypass L1
134
+ and are marked L2 evict-first.
135
+ - **No launches, few round trips**: activations are re-quantised by the producing phase
136
+ (including the next RMS norm's weight), so consumers only async-copy (`cp.async`) them.
137
+ - **Gated-DeltaNet rollback by lazy replay**: the recurrent state is committed only through the
138
+ surely-accepted token; accepted drafts are replayed from a small (k, v, g, beta) ring at the
139
+ start of the next cycle, so rejected drafts cost no state snapshots or extra state traffic.
140
+ - **Attention**: split-K flash decoding with tensor-core MMAs (Q.K^T and P.V in fp16 with fp32
141
+ accumulation, online softmax), double-buffered 32-position K/V tiles in shared memory (the next
142
+ tile streams in while the current one is processed: ~5% faster cycles at 30K context).
143
+ - **MTP drafting on device**, with the draft lm_head restricted to the 32,768 most frequent
144
+ tokens (`draft_vocab_32k.bin`, built by `tools/vocab_freq` from local code + docs; covers
145
+ ~99.4% of tokens), plus the tokens of the current sequence that are missing from it, added on the
146
+ fly (identifiers of pasted code: +3-8% decode speed with code in context). Verification always
147
+ uses the full vocabulary, so this affects only the acceptance rate, never the output.
148
+ - **Sampling** keeps the 32 best logits of each verified row; a draft is accepted with probability
149
+ p(draft) and a rejected one is resampled from the rest of the distribution, which keeps the
150
+ sampled distribution exact.
151
+ - **L2 warm-up**: before each barrier, blocks prefetch (evict-last) what their next latency-bound
152
+ phase reads first (DeltaNet state, conv weights, norm weights, RoPE rows, first K/V tile).
153
+
154
+ ## Prefill
155
+
156
+ A prompt (all but its last token) is processed in chunks of up to 2048 tokens by ordinary kernel
157
+ launches (`prefill.cuh`), which leave exactly the state the megakernel expects (trunk and MTP K/V
158
+ caches, committed DeltaNet state, conv ring, hidden-state history); the last prompt token then goes
159
+ through the megakernel, which produces the first token and the first MTP drafts. The same path
160
+ appends to a running conversation (`MKEngine::prefill` on a non-empty sequence, e.g. the next user
161
+ turn): it starts at the committed DeltaNet position and also re-feeds the last emitted token and any
162
+ accepted drafts not yet folded into the recurrent state; the output is token-identical to
163
+ processing the whole conversation as one fresh prompt.
164
+
165
+ - **GEMMs on fp16 tensor cores straight from the k-quants** (`prefill_gemm.cuh`, ~85% of prefill
166
+ time): 128 x 128 tiles, weights stay in their GGUF blocks and are dequantised to fp16 in
167
+ registers (exact small integers via the `0x6400` trick, then one fp16 scale and min per
168
+ sub-block); activations are fp16 with the elements of each 16-group permuted so that a 4-byte
169
+ weight word is directly an MMA A fragment. Products accumulate in fp16 over k = 128, then in fp32.
170
+ ~100-108 TFLOPS on all four quant types (`bench/mmq_bench.cu`). FFN gate and up share one GEMM
171
+ whose epilogue writes `silu(gate) * up` as the down projection's fp16 input.
172
+ - **DeltaNet in chunked (WY) form on tensor cores**: per 32-token chunk, `A = tril(beta K K^T)`
173
+ with the gate decays, `T = (I + A)^-1` (one warp, forward substitution), then
174
+ `U = T beta V - T beta gamma (K S)`, `O = gamma Q S + P U` and `S <- gamma_last S + K^T (decay U)`.
175
+ Value columns are independent, so a block owns (head, 64 columns) and each warp keeps its 128 x 8
176
+ slice of the state in fp32 MMA accumulators, turning it (and K S, U) into fp16 MMA operands
177
+ in registers with `movmatrix`; gates are carried as log g, so tiny or zero gates are exact.
178
+ ~2% of prefill time; 3.5e-4 relative error against a float64 reference of the recurrence.
179
+ - **Attention**: causal flash attention over the KV cache on tensor cores.
180
+
181
+ ## Limitations
182
+
183
+ - Specialised to this model's shapes and quant mix (27B, Q4_K_M as published by unsloth); the loader
184
+ rejects any other model. Tuned on sm_86 (RTX 3090); open-jet enables it on sm_86, sm_89 and sm_120
185
+ GPUs with 24 GB or more. `make` builds for the installed GPU (`make ARCH=sm_89` to override).
186
+ - Sampling supports temperature, top-k (<= 32), top-p and min-p (llama.cpp's order); no presence /
187
+ repetition penalties yet (open-jet's non-thinking preset uses a presence penalty of 1.5).
188
+ - Text only; one sequence and one checkpoint: a conversation is reused while it grows (or diverges
189
+ only after the end of the previous prompt); editing an earlier part, e.g. context compaction,
190
+ re-prefills it. No slot save / restore (open-jet's low-memory shell swap falls back to
191
+ re-prompting).
192
+
193
+ ## Files
194
+
195
+ - `qwen38_mk.cu` / `qwen38_mk.h` - loader, repacking, the megakernel and the `MKEngine` API
196
+ - `prefill.cuh` / `prefill_gemm.cuh` - batched prefill kernels and their quantised fp16 GEMM
197
+ - `capi.cpp` - C API (engine + libllama tokenizer) for `libqwen38mk.so`
198
+ - `server/mk_server.py` - OpenAI-compatible HTTP server
199
+ - `main.cu` - CLI (tokenization via libllama)
200
+ - `gguf.h` - minimal mmap GGUF reader
201
+ - `draft_vocab_32k.bin` - MTP draft-head token subset (int32 ids)
202
+ - `tools/vocab_freq.cpp` - builds a draft vocabulary from a list of text files
203
+ - `bench/` - benchmarks (see Build / run)
@@ -0,0 +1,140 @@
1
+ // C API over MKEngine plus libllama's tokenizer (vocab only), for the HTTP server (server/mk_server.py).
2
+ #include <algorithm>
3
+ #include <cstring>
4
+ #include <exception>
5
+ #include <stdexcept>
6
+ #include <string>
7
+ #include <vector>
8
+
9
+ #include "llama.h"
10
+ #include "qwen38_mk.h"
11
+
12
+ namespace {
13
+ struct Handle {
14
+ MKEngine * eng = nullptr;
15
+ llama_model * lm = nullptr;
16
+ const llama_vocab * vocab = nullptr;
17
+ std::string err;
18
+ };
19
+ thread_local std::string g_err;
20
+ }
21
+
22
+ extern "C" {
23
+
24
+ const char * mk_last_error() { return g_err.c_str(); }
25
+
26
+ void * mk_new(const char * model, int ctx, int n_draft, const char * draft_vocab, int kv_mode) {
27
+ try {
28
+ llama_backend_init();
29
+ llama_model_params mp = llama_model_default_params();
30
+ mp.vocab_only = true;
31
+ auto * h = new Handle;
32
+ h->lm = llama_model_load_from_file(model, mp);
33
+ if (!h->lm) throw std::runtime_error("failed to load the vocabulary");
34
+ h->vocab = llama_model_get_vocab(h->lm);
35
+ h->eng = new MKEngine(model, ctx, n_draft, draft_vocab ? draft_vocab : "", kv_mode);
36
+ return h;
37
+ } catch (const std::exception & e) {
38
+ g_err = e.what();
39
+ return nullptr;
40
+ }
41
+ }
42
+
43
+ void mk_free(void * hp) {
44
+ auto * h = static_cast<Handle *>(hp);
45
+ delete h->eng;
46
+ llama_model_free(h->lm);
47
+ delete h;
48
+ }
49
+
50
+ // chat template stored in the GGUF (tokenizer.chat_template); returns its length, copies up to cap
51
+ int mk_chat_template(void * hp, char * buf, int cap) {
52
+ auto * h = static_cast<Handle *>(hp);
53
+ const char * t = llama_model_chat_template(h->lm, nullptr);
54
+ if (!t) return -1;
55
+ const int n = (int) strlen(t);
56
+ if (buf && cap > 0) memcpy(buf, t, std::min(n, cap));
57
+ return n;
58
+ }
59
+
60
+ // text -> token ids (special tokens such as <|im_start|> parsed); returns the count (negative: -needed)
61
+ int mk_tokenize(void * hp, const char * text, int len, int * out, int cap) {
62
+ auto * h = static_cast<Handle *>(hp);
63
+ return llama_tokenize(h->vocab, text, len, out, cap, false, true);
64
+ }
65
+
66
+ // token -> its bytes (special tokens rendered as text); returns the byte count
67
+ int mk_piece(void * hp, int tok, char * buf, int cap) {
68
+ auto * h = static_cast<Handle *>(hp);
69
+ return llama_token_to_piece(h->vocab, tok, buf, cap, 0, true);
70
+ }
71
+
72
+ int mk_is_eog(void * hp, int tok) { return llama_vocab_is_eog(static_cast<Handle *>(hp)->vocab, tok) ? 1 : 0; }
73
+
74
+ int mk_set_sampling(void * hp, float temp, float top_p, int top_k, float min_p, unsigned long long seed) {
75
+ try {
76
+ static_cast<Handle *>(hp)->eng->set_sampling(temp, top_p, top_k, min_p, seed);
77
+ return 0;
78
+ } catch (const std::exception & e) {
79
+ g_err = e.what();
80
+ return -1;
81
+ }
82
+ }
83
+
84
+ // appends tokens to the sequence; returns the first generated token (negative on error)
85
+ int mk_prefill(void * hp, const int * toks, int n) {
86
+ try {
87
+ return static_cast<Handle *>(hp)->eng->prefill(std::vector<int>(toks, toks + n));
88
+ } catch (const std::exception & e) {
89
+ g_err = e.what();
90
+ return -1;
91
+ }
92
+ }
93
+
94
+ // one decode cycle; writes 1..n_draft+1 tokens; returns the count (negative on error)
95
+ int mk_step(void * hp, int * out, int cap) {
96
+ try {
97
+ std::vector<int> v;
98
+ static_cast<Handle *>(hp)->eng->step(v);
99
+ const int n = std::min((int) v.size(), cap);
100
+ for (int i = 0; i < n; i++) out[i] = v[i];
101
+ return n;
102
+ } catch (const std::exception & e) {
103
+ g_err = e.what();
104
+ return -1;
105
+ }
106
+ }
107
+
108
+ void mk_reset(void * hp) { static_cast<Handle *>(hp)->eng->reset(); }
109
+
110
+ int mk_truncate(void * hp, int len) {
111
+ try {
112
+ static_cast<Handle *>(hp)->eng->truncate(len);
113
+ return 0;
114
+ } catch (const std::exception & e) {
115
+ g_err = e.what();
116
+ return -1;
117
+ }
118
+ }
119
+
120
+ // copies the sequence so far (up to cap tokens); returns its length
121
+ int mk_sequence(void * hp, int * out, int cap) {
122
+ const auto & s = static_cast<Handle *>(hp)->eng->sequence();
123
+ const int n = (int) s.size();
124
+ if (out)
125
+ for (int i = 0; i < std::min(n, cap); i++) out[i] = s[i];
126
+ return n;
127
+ }
128
+
129
+ int mk_committed(void * hp) { return static_cast<Handle *>(hp)->eng->committed(); }
130
+ int mk_checkpoint_pos(void * hp) { return static_cast<Handle *>(hp)->eng->checkpoint_pos(); }
131
+ int mk_rewind_to_checkpoint(void * hp) { return static_cast<Handle *>(hp)->eng->rewind_to_checkpoint() ? 0 : -1; }
132
+
133
+ void mk_stats(void * hp, long * cycles, long * drafted, long * accepted) {
134
+ const auto & s = static_cast<Handle *>(hp)->eng->stats;
135
+ *cycles = s.cycles;
136
+ *drafted = s.drafted;
137
+ *accepted = s.accepted;
138
+ }
139
+
140
+ } // extern "C"
@@ -0,0 +1,129 @@
1
+ // Minimal read-only GGUF parser (mmap based). Only what the megakernel loader needs.
2
+ #pragma once
3
+
4
+ #include <cstdint>
5
+ #include <cstdio>
6
+ #include <cstdlib>
7
+ #include <cstring>
8
+ #include <map>
9
+ #include <stdexcept>
10
+ #include <string>
11
+ #include <vector>
12
+
13
+ #include <fcntl.h>
14
+ #include <sys/mman.h>
15
+ #include <sys/stat.h>
16
+ #include <unistd.h>
17
+
18
+ namespace gguf {
19
+
20
+ enum GType : uint32_t { F32 = 0, F16 = 1, Q8_0 = 8, Q4_K = 12, Q5_K = 13, Q6_K = 14 };
21
+
22
+ struct Tensor {
23
+ std::string name;
24
+ uint32_t type = 0;
25
+ std::vector<uint64_t> ne;
26
+ uint64_t offset = 0;
27
+ const uint8_t * data = nullptr;
28
+ uint64_t nbytes = 0;
29
+ };
30
+
31
+ inline uint64_t type_row_bytes(uint32_t type, uint64_t n) {
32
+ switch (type) {
33
+ case F32: return n * 4;
34
+ case F16: return n * 2;
35
+ case Q8_0: return n / 32 * 34;
36
+ case Q4_K: return n / 256 * 144;
37
+ case Q5_K: return n / 256 * 176;
38
+ case Q6_K: return n / 256 * 210;
39
+ default: throw std::runtime_error("unsupported ggml type " + std::to_string(type));
40
+ }
41
+ }
42
+
43
+ struct File {
44
+ const uint8_t * base = nullptr;
45
+ size_t size = 0;
46
+ std::map<std::string, Tensor> tensors;
47
+ std::map<std::string, uint64_t> ints;
48
+ std::map<std::string, std::string> strs;
49
+
50
+ explicit File(const std::string & path) {
51
+ int fd = open(path.c_str(), O_RDONLY);
52
+ if (fd < 0) throw std::runtime_error("cannot open " + path);
53
+ struct stat st;
54
+ fstat(fd, &st);
55
+ size = (size_t) st.st_size;
56
+ void * p = mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0);
57
+ close(fd);
58
+ if (p == MAP_FAILED) throw std::runtime_error("mmap failed");
59
+ base = (const uint8_t *) p;
60
+ parse();
61
+ }
62
+ ~File() { if (base) munmap((void *) base, size); }
63
+
64
+ const Tensor & get(const std::string & name) const {
65
+ auto it = tensors.find(name);
66
+ if (it == tensors.end()) throw std::runtime_error("missing tensor " + name);
67
+ return it->second;
68
+ }
69
+
70
+ private:
71
+ size_t pos = 0;
72
+ template <class T> T rd() { T v; memcpy(&v, base + pos, sizeof(T)); pos += sizeof(T); return v; }
73
+ std::string rds() { uint64_t n = rd<uint64_t>(); std::string s((const char *) base + pos, n); pos += n; return s; }
74
+
75
+ void skip_val(uint32_t t, const std::string & key, bool top) {
76
+ switch (t) {
77
+ case 0: case 1: case 7: { uint8_t v = rd<uint8_t>(); if (top) ints[key] = v; break; }
78
+ case 2: case 3: pos += 2; break;
79
+ case 4: { uint32_t v = rd<uint32_t>(); if (top) ints[key] = v; break; }
80
+ case 5: { int32_t v = rd<int32_t>(); if (top) ints[key] = (uint64_t) v; break; }
81
+ case 6: pos += 4; break;
82
+ case 8: { std::string s = rds(); if (top) strs[key] = s; break; }
83
+ case 9: {
84
+ uint32_t et = rd<uint32_t>();
85
+ uint64_t n = rd<uint64_t>();
86
+ for (uint64_t i = 0; i < n; i++) skip_val(et, key, false);
87
+ break;
88
+ }
89
+ case 10: { uint64_t v = rd<uint64_t>(); if (top) ints[key] = v; break; }
90
+ case 11: { int64_t v = rd<int64_t>(); if (top) ints[key] = (uint64_t) v; break; }
91
+ case 12: pos += 8; break;
92
+ default: throw std::runtime_error("bad gguf kv type");
93
+ }
94
+ }
95
+
96
+ void parse() {
97
+ if (memcmp(base, "GGUF", 4) != 0) throw std::runtime_error("not a gguf file");
98
+ pos = 4;
99
+ rd<uint32_t>();
100
+ uint64_t n_tensors = rd<uint64_t>();
101
+ uint64_t n_kv = rd<uint64_t>();
102
+ for (uint64_t i = 0; i < n_kv; i++) {
103
+ std::string key = rds();
104
+ uint32_t t = rd<uint32_t>();
105
+ skip_val(t, key, true);
106
+ }
107
+ std::vector<Tensor> infos;
108
+ for (uint64_t i = 0; i < n_tensors; i++) {
109
+ Tensor t;
110
+ t.name = rds();
111
+ uint32_t nd = rd<uint32_t>();
112
+ for (uint32_t d = 0; d < nd; d++) t.ne.push_back(rd<uint64_t>());
113
+ t.type = rd<uint32_t>();
114
+ t.offset = rd<uint64_t>();
115
+ infos.push_back(t);
116
+ }
117
+ uint64_t align = ints.count("general.alignment") ? ints["general.alignment"] : 32;
118
+ size_t data_start = (pos + align - 1) / align * align;
119
+ for (auto & t : infos) {
120
+ t.data = base + data_start + t.offset;
121
+ uint64_t rows = 1;
122
+ for (size_t d = 1; d < t.ne.size(); d++) rows *= t.ne[d];
123
+ t.nbytes = type_row_bytes(t.type, t.ne[0]) * rows;
124
+ tensors[t.name] = t;
125
+ }
126
+ }
127
+ };
128
+
129
+ } // namespace gguf