Add oxidize-c engine with Gemma 4, MoE support, and CUDA optimizations - #37
Jackson57279 wants to merge 307 commits into
Conversation
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 635f2ae231
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (strncmp(req, "GET /v1/realtime", 16) == 0 && | ||
| strcasestr(req, "Upgrade: websocket")) { | ||
| ws_session(fd, req, m, tok, temperature, draft_k); | ||
| continue; |
There was a problem hiding this comment.
Enforce API keys before serving generation routes
When --serve is bound to anything reachable beyond localhost, setting OXIDIZE_API_KEY only gates process startup; this request path never checks the Authorization header before accepting WebSocket sessions or the POST completion routes below. That makes the advertised API-key protection ineffective and allows any client that can reach the port to run inference. Add a header check against OXIDIZE_API_KEY/OXIDIZE_API_KEYS before dispatching /v1/realtime, /v1/chat/completions, and /v1/completions while leaving /health unauthenticated if desired.
Useful? React with 👍 / 👎.
| if (layer.ffn_gate_expert_list.size() != config_.num_experts) { | ||
| throw std::runtime_error("incomplete split-expert tensor set for " + p); |
There was a problem hiding this comment.
Skip split-expert validation for dense MoE blocks
For MoE checkpoints with leading dense layers (the Hunyuan/DeepSeek layouts this change adds support for), config_.num_experts is nonzero but the early blk.* layers legitimately have dense ffn_gate/up/down weights and no _exps or ffn_gate.<i> tensors. This newly added completeness check still runs on those dense layers, the split-expert loop breaks at expert 0, and model construction throws incomplete split-expert tensor set before the dense layer can be used. Only enforce split-expert completeness after detecting a router/expert layer, or skip it for leading_dense_layers.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
24 issues found across 106 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="scripts/prime-gemma4-31b-int4/nginx-dual.conf">
<violation number="1" location="scripts/prime-gemma4-31b-int4/nginx-dual.conf:15">
P0: The ALPHA load balancer will return 502 for every request because 127.0.0.1 in `gemma4-lb` is the Nginx container's loopback, not the host where ports 8000 and 8001 are bound. Align the containers on a shared network (or use host networking for Nginx) before using these upstream addresses.</violation>
</file>
<file name="oxidize-core/src/model/inference.rs">
<violation number="1" location="oxidize-core/src/model/inference.rs:267">
P1: CUDA fused attention ignores YaRN for models configured with `rope.scaling.type = "yarn"`, producing different positional embeddings from the CPU path; extending the CUDA RoPE interface or disabling the fused path when YaRN is active would preserve correctness.</violation>
</file>
<file name="scripts/prime-qwen35-self-train/strip_branding.py">
<violation number="1" location="scripts/prime-qwen35-self-train/strip_branding.py:46">
P1: Rendering `tokenizer_config.json` fails whenever its template uses `qwythos_identity`: this branch deletes the definition but leaves the references undefined. Applying the same `t.replace("qwythos_identity", '""')` transformation used for `chat_template.jinja` keeps both HF template copies executable.</violation>
</file>
<file name="scripts/prime-qwen35-self-train/run-self-train.sh">
<violation number="1" location="scripts/prime-qwen35-self-train/run-self-train.sh:69">
P1: A rerun can upload an incomplete adapter: the watcher sees a previous run's `finished` marker because this command appends to the shared log. Truncating the log for each run or using a run-specific completion marker would keep uploads tied to the current training job.</violation>
</file>
<file name="oxidize-core/src/compute/quantization/quant_simple.rs">
<violation number="1" location="oxidize-core/src/compute/quantization/quant_simple.rs:122">
P1: Q4_0 CUDA/ROCm GEMV now returns incorrect dot products for the newly encoded blocks because the quantizer uses split-half ordering while `gemv_q4_0_kernel` still uses interleaved vector indices. Updating the kernel indexing (including the shared ROCm build) would keep GPU results consistent with `dequantize_q4_0_scalar`.</violation>
</file>
<file name="scripts/gemma4_31b_al_remote.sh">
<violation number="1" location="scripts/gemma4_31b_al_remote.sh:21">
P1: User-controlled path, repository, and quant arguments are interpolated into remote shell command text without serialization, allowing shell-command injection on the target host. Passing a quoted/encoded payload over stdin or shell-escaping every SSH argument would preserve values without interpreting them as commands.</violation>
<violation number="2" location="scripts/gemma4_31b_al_remote.sh:53">
P0: The generated AL files cannot be valid full-model quants because this command feeds only shard 1 to the GGUF writer even though the downloaded model has two shards. The quantizer needs a multi-shard-safe input path/writer before this script can publish usable models.</violation>
</file>
<file name="scripts/prime-qwen35-self-train/setup-node.sh">
<violation number="1" location="scripts/prime-qwen35-self-train/setup-node.sh:54">
P1: Setup currently aborts during the build step because `oxidize-finetuning` is a documented failing crate in this checkout. A working finetuning revision or a fixed crate needs to be used before this one-time setup can complete.</violation>
</file>
<file name="scripts/publish_gguf_remote_hf.sh">
<violation number="1" location="scripts/publish_gguf_remote_hf.sh:12">
P1: The exit trap recursively deletes whatever `STAGING` points at, including pre-existing user data when `STAGING` is supplied or `.hf-staging` already exists. A unique `mktemp` subdirectory should be created and only that run directory cleaned up.</violation>
<violation number="2" location="scripts/publish_gguf_remote_hf.sh:36">
P1: A caller-controlled `HF_REPO` is interpolated into Python source, so a crafted repository argument can execute arbitrary Python locally. Passing the value as a Python argv/environment value with a quoted heredoc avoids code injection.</violation>
<violation number="3" location="scripts/publish_gguf_remote_hf.sh:52">
P1: The final publication step can report success while the README upload failed, because its fallback performs no HF operation and returns zero; it also creates the bogus `null` file on success. A single `--readme-only` call without the no-op fallback would preserve the failure status.</violation>
</file>
<file name="oxidize-cpp/src/tensor_cpu.cpp">
<violation number="1" location="oxidize-cpp/src/tensor_cpu.cpp:694">
P1: Quantized inference can crash on AVX2/F16C CPUs that lack FMA because this gate enables code containing `_mm256_fmadd_ps` without checking FMA support. Include `__builtin_cpu_supports("fma")` in the runtime condition, or provide a non-FMA implementation.</violation>
</file>
<file name="scripts/prime-qwen35-self-train/upload-hf.sh">
<violation number="1" location="scripts/prime-qwen35-self-train/upload-hf.sh:6">
P1: When `OUT_DIR` is customized without an explicitly exported `TRAIN_OUT`, the shell waits on the customized output but Python falls back to `$HOME/models/qwen35-9b-agent/self-train-out`; it can therefore upload an older/default run instead of the current adapter. Exporting the computed `TRAIN_OUT` or passing the shell value directly into Python would preserve the selected output path.</violation>
</file>
<file name="oxidize-c/tokenizer.c">
<violation number="1" location="oxidize-c/tokenizer.c:257">
P1: SentencePiece/Gemma prompts are segmented by local max-score pair merges here, not by the global score-maximizing unigram segmentation. A vocabulary can prefer `a+bc` overall while the heap commits to `ab`, producing different token IDs for the same prompt; the C tokenizer should use unigram/Viterbi segmentation.</violation>
</file>
<file name="notebooks/coding_agent_sft_datasets.ipynb">
<violation number="1" location="notebooks/coding_agent_sft_datasets.ipynb:241">
P1: The Colab workflow cannot clone its checkout because `/content/oxidize` is already non-empty when this command runs, and the ignored clone failure leaves the subsequent build pointed at that incomplete directory. Cloning into a clean path before creating `OUT_DIR` and checking the command status would make the documented Colab flow executable.</violation>
<violation number="2" location="notebooks/coding_agent_sft_datasets.ipynb:315">
P1: With `RUN_TRAIN=True`, the subprocess fails before self-training starts because `self-train` does not support `--max-tokens`; that option exists for `sft`, not `SelfTrainArgs`. Removing this pair or replacing it with a supported self-train option lets the training workflow run.</violation>
</file>
<file name="oxidize-cpp/src/gguf.cpp">
<violation number="1" location="oxidize-cpp/src/gguf.cpp:451">
P1: Recognizing Hunyuan without routing it through the HF decoder mapper leaves every Hunyuan tensor in its raw name; loading then cannot find required tensors such as `tok_embeddings.weight`. Include all Hunyuan aliases in the `map_tensor_name` decoder branch.</violation>
</file>
<file name="modal_oxidize.py">
<violation number="1" location="modal_oxidize.py:58">
P1: The public `serve` endpoint exits on every standard Modal deployment because the function has no `secrets=[...]` binding, so a local `OXIDIZE_API_KEY` is not present remotely; this also downloads the multi-GB model before failing. Inject the key through a Modal Secret and validate it before calling `ensure_model()`.</violation>
</file>
<file name="scripts/prime-gemma4-31b-int4/setup-node.sh">
<violation number="1" location="scripts/prime-gemma4-31b-int4/setup-node.sh:27">
P1: A pod without a preconfigured NVIDIA Docker runtime fails at the first `docker run --gpus all`, so setup never reaches the model download. The setup needs to install/configure and validate the NVIDIA Container Toolkit, or avoid requesting a GPU for the CPU-only download step.</violation>
<violation number="2" location="scripts/prime-gemma4-31b-int4/setup-node.sh:30">
P0: The INT4 checkpoint download never runs: this image's `vllm serve` entrypoint receives `python3 -c ...` as serve arguments, so the container exits or tries to serve a model named `python3`. Overriding the entrypoint to `python3` is needed for this download step.</violation>
</file>
<file name="scripts/hy3_1m_al_remote.sh">
<violation number="1" location="scripts/hy3_1m_al_remote.sh:27">
P1: Running without `HF_TOKEN` fails immediately with an unbound-variable error, even though the script explicitly defaults the token to empty. Expanding the optional positional parameter with an unset-safe form, or passing arguments through a safe serialized channel, preserves anonymous downloads.</violation>
</file>
<file name="oxidize-core/src/compute/tensor/kernels/q_kernels.rs">
<violation number="1" location="oxidize-core/src/compute/tensor/kernels/q_kernels.rs:1757">
P1: IQ4_NL GEMV returns incorrect results for every nontrivial block because the activation indices do not match the format's two-half weight layout. Pair each packed weight byte with Q8 positions `i` and `i + 16` instead of `2*i` and `2*i + 1`.</violation>
</file>
<file name="scripts/bench_iq_remote.sh">
<violation number="1" location="scripts/bench_iq_remote.sh:186">
P1: The Rust leg will not benchmark ordinary IQ GGUF models: `--engine standard` is not a supported normal-model engine and falls through to the DFlash loading path, which can fail before producing throughput. Using the supported `inference` engine would run the intended model benchmark.</violation>
</file>
<file name="scripts/prime-gemma4-31b-int4/llamacpp-unsloth.sh">
<violation number="1" location="scripts/prime-gemma4-31b-int4/llamacpp-unsloth.sh:14">
P1: The fallback exits before starting because both expected filenames are wrong for the files downloaded by the setup recipe: the target is `gemma-4-31B-it-qat-UD-Q4_K_XL.gguf` and the MTP drafter is `mtp-gemma-4-31B-it.gguf`; the latter is also excluded by the setup download pattern. Use the repository filenames consistently and include the `mtp-` file in the download step.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
|
|
||
| upstream gemma4_backends { | ||
| least_conn; | ||
| server 127.0.0.1:8000 max_fails=3 fail_timeout=10s; |
There was a problem hiding this comment.
P0: The ALPHA load balancer will return 502 for every request because 127.0.0.1 in gemma4-lb is the Nginx container's loopback, not the host where ports 8000 and 8001 are bound. Align the containers on a shared network (or use host networking for Nginx) before using these upstream addresses.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/prime-gemma4-31b-int4/nginx-dual.conf, line 15:
<comment>The ALPHA load balancer will return 502 for every request because 127.0.0.1 in `gemma4-lb` is the Nginx container's loopback, not the host where ports 8000 and 8001 are bound. Align the containers on a shared network (or use host networking for Nginx) before using these upstream addresses.</comment>
<file context>
@@ -0,0 +1,33 @@
+
+ upstream gemma4_backends {
+ least_conn;
+ server 127.0.0.1:8000 max_fails=3 fail_timeout=10s;
+ server 127.0.0.1:8001 max_fails=3 fail_timeout=10s;
+ keepalive 64;
</file context>
|
|
||
| echo "==> Pre-downloading INT4 QAT checkpoint (~20GB)" | ||
| docker run --rm \ | ||
| --gpus all \ |
There was a problem hiding this comment.
P1: A pod without a preconfigured NVIDIA Docker runtime fails at the first docker run --gpus all, so setup never reaches the model download. The setup needs to install/configure and validate the NVIDIA Container Toolkit, or avoid requesting a GPU for the CPU-only download step.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/prime-gemma4-31b-int4/setup-node.sh, line 27:
<comment>A pod without a preconfigured NVIDIA Docker runtime fails at the first `docker run --gpus all`, so setup never reaches the model download. The setup needs to install/configure and validate the NVIDIA Container Toolkit, or avoid requesting a GPU for the CPU-only download step.</comment>
<file context>
@@ -0,0 +1,49 @@
+
+echo "==> Pre-downloading INT4 QAT checkpoint (~20GB)"
+docker run --rm \
+ --gpus all \
+ -v "$HF_HOME:/root/.cache/huggingface" \
+ -e HF_TOKEN="${HF_TOKEN:-}" \
</file context>
| theta: f32, | ||
| output: &mut [f32], | ||
| ) -> Result<(), crate::tensor::RopeError> { | ||
| apply_rope_f32_yarn( |
There was a problem hiding this comment.
P1: CUDA fused attention ignores YaRN for models configured with rope.scaling.type = "yarn", producing different positional embeddings from the CPU path; extending the CUDA RoPE interface or disabling the fused path when YaRN is active would preserve correctness.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At oxidize-core/src/model/inference.rs, line 267:
<comment>CUDA fused attention ignores YaRN for models configured with `rope.scaling.type = "yarn"`, producing different positional embeddings from the CPU path; extending the CUDA RoPE interface or disabling the fused path when YaRN is active would preserve correctness.</comment>
<file context>
@@ -232,11 +248,33 @@ impl Default for InferenceConfig {
+ theta: f32,
+ output: &mut [f32],
+ ) -> Result<(), crate::tensor::RopeError> {
+ apply_rope_f32_yarn(
+ input,
+ position,
</file context>
Add Gemma-specific forward path: - GeGLU activation: gelu(gate) * up (erf-based exact GeLU), used by Gemma's FFN instead of SwiGLU. Added oc_geglu_inplace_f32, oc_gelu_exact_f32, oc_gelu_approx_f32 to activation.h/c. - Norm scaling: Gemma multiplies RMSNorm output by sqrt(n_embd). Added norm_scale field to OcLlamaConfig (default 1.0, set to sqrt(n_embd) for Gemma). Applied after each RMSNorm call (attn_norm, ffn_norm, final_norm). - Config detection: uses_geglu and norm_scale set based on arch string starting with gemma. - forward_dense_ffn dispatches between SwiGLU and GeGLU based on config. Mistral/Phi share the Llama SwiGLU path by default. Tests: GeGLU basic (gelu(0)=0, gelu(1)=0.841345), GeGLU vs SwiGLU differ, Gemma config defaults (norm_scale = sqrt(3072)). Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Add CUDA backend (OC_CUDA) for NVIDIA GPU deployment (L40S on Modal): - CUDA kernels: embedding lookup, RMSNorm (shared-mem reduction), matvec (one block per row, tree reduction), RoPE (split-halves), SwiGLU/GeGLU, per-head attention (online softmax), KV cache write, residual add. - oc_cuda_init: uploads + dequantizes all weights to device f32, allocates KV cache + workspace on GPU. - oc_cuda_forward: full layer loop on GPU (RMSNorm → QKV → RoPE → KV cache → attention → output proj → FFN → residual), final norm + lm_head. - Makefile: make cuda compiles .cu with nvcc, .c with gcc, links with -lcudart. CPU build unaffected (no .cu in LIB_SRCS wildcard). - oc_cuda_available() runtime check; falls back to CPU when no GPU. Untested locally (no GPU); designed for Modal L40S deployment. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Add YaRN (Yet another RoPE extensioN) for long-context models: - oc_apply_rope_yarn_f32: smooth ramp interpolation between [0.8, 1.2] × orig_ctx. Beyond orig_ctx × 1.2, positions are scaled by orig_ctx / pos, effectively compressing the rotary frequencies for extended context. - Config: yarn_factor and yarn_orig_ctx fields in OcLlamaConfig. Parsed from GGUF metadata rope.scaling.type="yarn" + rope.scaling.factor. - Forward path dispatches to YaRN RoPE when yarn_factor > 0, normal RoPE otherwise. Applied to both Q and K heads. - Added cfg_str helper for reading string metadata from GGUF. Tests: YaRN identity within ctx, YaRN differs beyond ctx, YaRN no-op when factor=0. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Add chat template rendering for proper message formatting: - ChatML (Qwen/Mistral): <|im_start|>role\ncontent<|im_end|>\n - Llama-3: <|start_header_id|>role<|end_header_id|>\n\ncontent<|eot_id|> - Llama-2: [INST] content [/INST] with <<SYS>> system handling - Gemma: <start_of_turn>role\ncontent<end_of_turn>\n - Plain text fallback oc_chat_render_message renders a single message with is_first/is_last flags for generation prompt injection. oc_chat_render_messages renders a full conversation. oc_chat_detect auto-selects template from arch string. Tests: ChatML user message, ChatML assistant prompt, Llama-3 format, Llama-2 format, Gemma format, multi-message rendering, auto-detect. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
…streaming Add new CLI flags: - --draft-model: path to draft model for speculative decoding - --draft-tokens: K draft tokens per step (default 4) - --quantize: input GGUF path for offline weight quantization - --output: output GGUF path for quantized model - --quant-type: target quantization type (Q4_0, Q4_K_M, etc.) - --stream: enable streaming output mode (SSE) Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- Add --backend cpu|cuda flag to CLI args - Wire oc_cuda_init/forward/free into run_generation - CUDA forward used for prefill + decode when --backend cuda - CPU stub (cuda_stub.c) compiled when OC_CUDA not defined - Fix Makefile: CUDA build excludes cuda_stub.c, compiles .cu with nvcc - Fix OC_ERR_UNSUPPORTED -> OC_ERR_BACKEND (no unsupported error code) - Fix unused parameter warning in chat.c Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
…ld, and tests - arena: overflow guards (round_up_pow2 hang, chunk size wrap, fit check, dup_n n+1), reset now reuses existing chunks - vector: multiplication/count overflow guards, self-append aliasing safe in push and push_n; error: ctx_format returns full chain length - tokenizers: DISALLOW_SPECIAL enforced for all kinds, atomic GPT-2 init, OOM propagation in interning/training/Viterbi, seg_ids leak, NULL role/content validation, strict merge metadata (Rust parity), shared utf8_utils.h with WHATWG-correct lossy decode - gguf/mmap: open_fd validates len vs st_size, aggregate mlock budget for split shards, filename scan UB, name-dup OOM propagation, unified file no longer claims mmap bytes as freeable - build: -Iinclude in CPPFLAGS, lint propagates exit status, cuda target links -L$(CUDA_HOME)/lib64 -lstdc++; criterion alloc.h delete_arr prefix fix + bad_alloc on OOM - tests: hashtable per-insert key storage, log env-filter coverage, mmap oversized-len expectation; cli: declare missing decode_start 307/307 tests passing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d, GPU test, lint, cross-compile - cpu-build-test: Ubuntu + macOS builds with ASan+UBSan test suite - static-lib: verify liboxidize-c.a builds correctly - avx512-build: AVX-512 build for Cascade Lake (matches .121) - cuda-build: CUDA compile-only build with nvcc (no GPU required) - gpu-test: Modal T4 GPU inference test (requires Modal secrets) - lint: clang-tidy, TODO/FIXME check, memory leak pattern check - cross-compile-arm64: aarch64 cross-compile verification Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
…, bench/min-p/mirostat CLI flags Samplers: - Mirostat v2 (surprise-based): oc_mirostat_v2_sample with running mu estimate - Min-p: filter tokens below min_p * max_p ratio - CLI flags: --min-p, --mirostat-tau, --mirostat-eta Vision/multimodal stubs: - OcVisionConfig/Encoder with CLIP-style ViT config - oc_vision_encode (stub: returns zeros) - oc_vision_resize (bilinear), oc_vision_normalize ([-1,1] range) - OcMultimodalPrompt for text+image embedding fusion Mesh/distributed stubs: - OcMesh with peer discovery, broadcast, all-reduce, shard layout - TP degree sharding (oc_mesh_shard_for_layer) CLI: - --bench, --bench-iters flags - --min-p, --mirostat-tau, --mirostat-eta flags Tests: vision init/encode/resize/normalize/multimodal, mesh init/connect/shard/broadcast/allreduce (11 new tests, 324 total). Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- --bench flag: runs N iterations of greedy decode, reports best/avg tok/s with per-iteration timing using clock() - SSE streaming for /v1/completions: detects stream:true in request body, returns text/event-stream with data: JSON chunks + data: [DONE] Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- oc_quantize_model: reads input GGUF, dequantizes weight tensors to f32, re-quantizes to target type, writes output GGUF with patched tensor types - Minimal GGUF v3 writer with metadata copying, tensor info patching, alignment padding - --quantize flag wired in CLI (--quantize INPUT --output OUT --quant-type Q4_K_M) - oc_quantize_parse_type: string→OcGgufQuantizationType via name table - 7 new tests (type parsing, block sizes), 331 total passing. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
MLA (Multi-head Latent Attention): - OcLlamaConfig: uses_mla, mla_q_lora_dim, mla_kv_lora_dim, mla_q_rope_dim, mla_kv_nope_head_dim, mla_v_head_dim fields - OcLlamaLayer: mla_q_a, mla_q_b, mla_kv_a_mqa, mla_k_b, mla_v_b weight views + mla_q_a_norm, mla_kv_a_norm RMSNorm weights - OcLlamaSession: mla_c_q, mla_c_kv, mla_q_full, mla_kv_compressed temporaries - forward_mla_attention: Q down→norm→up, KV down→norm, per-head K/V up-proj, decoupled RoPE on q_pe/k_pe, online-softmax attention per head - Config parsing: deepseek2.attention.key_length_mla + lora_q/lora_kv/key_length_rope - Tensor loading: attn_q_a, attn_q_a_norm, attn_q_b, attn_kv_a_mqa, attn_kv_a_norm, attn_k_b, attn_v_b - MLA KV cache sized n_head*head_dim (per-head, no GQA sharing) Model inspect mode: - --inspect flag: prints GGUF header, metadata, tensor table (first 20), total file size, architecture detection Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- OcBatchSession: processes up to OC_MAX_BATCH_SEQ=16 sequences per forward pass - OcBatchSeq: per-sequence token, position, logits output, active flag - oc_batch_forward: iterates active sequences through shared weight workspace (better cache locality than separate sessions) - KV cache sized per-sequence: [n_layer][n_ctx][kv_row_floats * max_seqs] - Reuses forward_layer for each sequence (MLA excluded in batch for now) Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- OcStreamingDetokenizer: incremental token-by-token decoding with pending byte buffer for partial UTF-8 sequences split across token boundaries - oc_streaming_detok_push: decode one token, emit complete UTF-8 delta, buffer incomplete tail - oc_streaming_detok_flush: emit remaining pending bytes at end of stream - UTF-8 sequence validation (lead byte + continuation byte checking) - Thread-local combined buffer for zero-copy delta emission Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- OC_SAMPLER_TYPICAL_P (6): locally typical sampling - computes entropy H, scores tokens by |surprise - H|, keeps tokens with lowest deviation until cumulative probability reaches typical_p threshold - OC_SAMPLER_TAIL_FREE (7): tail-free sampling - computes second derivative of sorted probabilities |d2(p)|, normalizes, accumulates until z-threshold - OcSamplerConfig: added typical_p and tail_free_z fields Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- OcLlamaSession: kv_quantized flag + kv_k_q8/kv_v_q8 int8 caches + per-block f16 scales (kv_k_scale/kv_v_scale) - kv_quantize_q8: per-block (32-element) asymmetric quantization with f16 scale - kv_dequantize_q8: reverse quantization for attention computation - Q8 KV cache halves memory usage at a small quality cost - Allocated on session init (not yet wired into forward path) Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- OcLlamaConfig: sliding_window (window size) + sliding_window_pattern (1=all global, 2=alternating global/sliding) - Config parsing: reads attention.sliding_window from GGUF metadata for Gemma2 models, sets pattern=2 (alternating) - attention_head: skips tokens outside the sliding window for layers matching the alternating pattern (layer % pattern == 1) Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- OcAttnDumper: env-gated (OXIDIZE_TRACE_VALS / OXIDIZE_TRACE_FWD) per-layer attention weight + logits dump to disk - oc_attn_dump_f32: writes float arrays as .f32 binary files - oc_attn_dump_logits: writes logits per forward step - oc_attn_dump_set_context: sets step/layer for subsequent dumps - 3 new tests (init, dir, context), 334 total passing. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- OcGrammarConstraint: JSON, choice, and regex (stub) constraint types - JSON mode: tracks string/escape state, filters structural chars outside strings, validates escape sequences inside strings - Choice mode: allows tokens matching any of a set of literal strings, tracks match position, marks finished when a choice is completed - oc_grammar_allows_token: simulates token advancement to check validity - oc_grammar_advance: updates state after token acceptance - oc_grammar_is_satisfied: checks if constraint is met (JSON complete, choice done) - 7 new tests (init, JSON structural, string mode, choice, reset, satisfied, token), 341 total passing. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- OcPrefixCache: LRU cache of KV snapshots keyed by FNV-1a token hash - oc_prefix_hash_tokens / oc_prefix_hash_continue: incremental FNV-1a hashing - oc_prefix_cache_lookup/store/evict/clear: standard LRU operations - OcCachedPrefix: hash, n_tokens, opaque kv_data, last_used timestamp - OcPrefixCacheStats: entry count, total KV bytes - 7 new tests (hash, incremental, init, store/lookup, evict, clear, stats), 348 total. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Timing: - Replace clock() (CPU time) with clock_gettime(CLOCK_MONOTONIC) (wall clock) - Benchmark mode: now reports decode tok/s AND prefill tok/s per iteration - Generation mode: wall-clock tok/s reporting Perplexity: - oc_perplexity_evaluate: tokenizes text, runs forward, computes cross-entropy loss at each position, returns perplexity (2^avg_nll) - oc_perplexity_evaluate_file: reads text from file for evaluation - --perplexity / --ppl CLI flag: runs perplexity evaluation on prompt or file - OcPerplexityResult: ppl, avg_nll, total_nll, n_tokens, eval_time, tok/s Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Disable fused multiply-add in CFLAGS, compare OXK results within 1 ULP, and drop calls to missing K-quant multi kernels. Load logs that LongCat n-gram tensors are unused and that MLA/LongCat skip batched prefill. Gemma 4 no longer gets a second RMS scale in the batch path. Remove the committed debug journal. Co-authored-by: Cursor <cursoragent@cursor.com>
CORS is no longer hardcoded to *; extra headers come from middleware. Generation errors return NULL so handlers emit 500 instead of an empty 200, and repeat penalty receives prompt token history. Disable fused multiply-add so OXK results match the scalar reference. Co-authored-by: Cursor <cursoragent@cursor.com>
LongCat/MLA/prefill/TUI land on the oxidize-c v2 branch. Serving-file conflicts keep the longcat-c SSE auth and CORS extra-header path. Co-authored-by: Cursor <cursoragent@cursor.com>
Install CORS and stream auth before workers start, reject oversized header blocks, and clamp completion history to remaining context. Stream rejections now hit metrics/audit. MTP copies prefix state, records last_hidden without logits, uses absolute RoPE, and null-checks the model. Qwen3.6 joins the loader list; AVX-512 Q8_K quant requires DQ/VL; attention ISA detect is pthread_once; CUDA CFLAGS keep -ffp-contract=off. Co-authored-by: Cursor <cursoragent@cursor.com>
GPT-J GGUFs still died in oc_llama_load after parse_config accepted them. The sampler chain still handed Mirostat v1 a NULL RNG after the function gained a caller state. Co-authored-by: Cursor <cursoragent@cursor.com>
A failed pthread_create left workers on stack-owned state. Completions treated a missing model pointer as 500. JSON unquote broke on escaped backslash. Llama GGUFs always used Llama-3 markup. Co-authored-by: Cursor <cursoragent@cursor.com>
CPU ASan tests failed because a missing prompt never reached 400 once a NULL model pointer returned 503. Nested stream-in-text also expected 500 for that same placeholder state. Co-authored-by: Cursor <cursoragent@cursor.com>
Windows CI clippy -D warnings failed on Q4_K/Q8_K block walks after stable 1.98 started treating constant-size chunks_exact as an error. Co-authored-by: Cursor <cursoragent@cursor.com>
Workspace lint on stable 1.98 fails ~90 constant-size chunks_exact sites in oxidize-core. Allow the lint (unknown on 1.97) instead of a mechanical rewrite on this C-port PR. Co-authored-by: Cursor <cursoragent@cursor.com>
Ubuntu lint still failed after the core crate allow: oxidize-merge byte blends, oxidize-quantize imatrix parse, and OXK benches are separate crates. Co-authored-by: Cursor <cursoragent@cursor.com>
Ubuntu lint failed on oxidize-core lib tests: Clippy now denies filling a slice with a for-loop. Allow the lint crate-wide and use fill in the video temporal test. Co-authored-by: Cursor <cursoragent@cursor.com>
CI fmt --check on 1.98 splits the crate-level unknown_lints / chunks_exact / manual_slice_fill allow onto multiple lines. Co-authored-by: Cursor <cursoragent@cursor.com>
cargo-deny on Ubuntu fails advisories: epoch 0.9.18 has an invalid-pointer Display impl. Update to >=0.9.20. Co-authored-by: Cursor <cursoragent@cursor.com>
GPT-J now has an interleaved-RoPE forward path instead of GPT-2 WPE. Chat templates prefer tokenizer.chat_template, JSON unescapes \\r\\b\\f\\uXXXX, Mirostat v2 uses chain RNG, chat 400 precedes 503, and Q4_K/Q8_K walks use chunks_exact so a short tail does not panic. Co-authored-by: Cursor <cursoragent@cursor.com>
CI fmt --check rejected the multi-line iterator chain after switching back from as_chunks. Co-authored-by: Cursor <cursoragent@cursor.com>
Homebrew Criterion ran tests in parallel under ASan and leaked HTTP server threads when stream assertions aborted. Run one job on Darwin, always join the test server, and cap macOS CI tests at 20 minutes. Co-authored-by: Cursor <cursoragent@cursor.com>
The Homebrew Criterion + ASan run does not finish on macos-latest (6h cancel, then a 20m timeout with the runner still inside test_runner). Ubuntu keeps the full sanitizer suite. Co-authored-by: Cursor <cursoragent@cursor.com>
oxidize-c v2: modular C11 port, threaded forward pass, kernel correctness fixes
Cap speculative draft-step and top-k Vec allocations so untrusted config values cannot request unbounded capacity. Stop writing Kubernetes env and SA token material from getenv/secrets onto plaintext sockets; validate API host/port and send Host from getpeername, attaching the bearer token only on loopback. Drop stat-then-unlink in the Qwen 3.5 fixture test in favor of the already-open GGUF backing length. Co-authored-by: Jackson <Jackson57279@users.noreply.github.com>
_POSIX_C_SOURCE 200809L does not expose getnameinfo size macros on this toolchain; provide the POSIX defaults so k8s.c compiles. Co-authored-by: Jackson <Jackson57279@users.noreply.github.com>
A 1024 clamp changed sampling for vocab > 1024. Cap allocation with a 1,048,576 constant bound and return InvalidTopK above that so CodeQL still sees a sanitizer without shrinking normal top_k. Co-authored-by: Jackson <Jackson57279@users.noreply.github.com>
Zero token and request buffers on every oc_k8s_scale exit with a volatile wipe so the bearer string does not linger. Save and restore OC_K8S_API_URL / KUBERNETES_SERVICE_HOST around tests that mutate them. Co-authored-by: Jackson <Jackson57279@users.noreply.github.com>
Keep requested top_k: k<=1024 uses an O(n log k) min-heap so with_capacity stays CodeQL-bounded; larger k sorts the full distribution then truncates instead of O(n*k) min_by scans. Co-authored-by: Jackson <Jackson57279@users.noreply.github.com>
Strip [::1]-style brackets from OC_K8S_API_URL before DNS. HTTP Host still uses getpeername, which already emits RFC 3986 brackets. Co-authored-by: Jackson <Jackson57279@users.noreply.github.com>
…ng-c1df Fix GitHub Code Scanning (CodeQL) allocation, k8s, and TOCTOU alerts
| let mut indexed_probs = if let Some(top_k) = top_k_limit { | ||
| let mut raw_sum = 0.0_f32; | ||
| let mut top_candidates: Vec<(usize, f32)> = Vec::with_capacity(top_k); | ||
| let mut heap: BinaryHeap<Reverse<TopKCandidate>> = BinaryHeap::with_capacity(top_k); |
Review: what this is, how it works, what to stealWhat it is. This PR is inverted. Head is How it works.
The “updated today” activity is CodeQL re-running because Steal. Nothing unique versus current Closing as no merge intent: wrong base/head, superseded, conflicting. |
Summary by cubic
Adds a plain-C
oxidize-cinference engine with Gemma 4 and MoE support, plus CUDA resident-forward optimizations and AL-family quantization across Rust/C++/C for faster, smaller GGUF serving.New Features
oxidize-cC11 runtime: GGUF loader/writer, BPE tokenizer, transformer forward, batched decode, paged KV cache with scheduler, autotune planner, 16 CLI subcommands, and an OpenAI-compatible HTTP/WebSocket server with SSE streaming.oxidize-core,oxidize-cpp, and de/quant pipelines.oxidize-convert/oxidize-quantize, merge strategies, Wanda pruning, SafeTensors→GGUF conversion, HF Hub downloads with resume, model registry, and perplexity evaluation./v1/embeddingsand/v1/responsesroutes, auth/rate-limit/metrics middleware, LoRA adapter inference, and a WebSocket realtime API.oxidize-finetuninggains generation, a self-train loop, and richer LoRA export/CLI wiring.Bug Fixes
oxidize-cppNUMA caps to physical cores; security advisories patched via vendored libp2p crates.Written for commit df9f876. Summary will update on new commits.