Instructions to use jj90/Kev-0.8B-RKNN3-RK1828 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use jj90/Kev-0.8B-RKNN3-RK1828 with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf jj90/Kev-0.8B-RKNN3-RK1828 # Run inference directly in the terminal: llama cli -hf jj90/Kev-0.8B-RKNN3-RK1828
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf jj90/Kev-0.8B-RKNN3-RK1828 # Run inference directly in the terminal: llama cli -hf jj90/Kev-0.8B-RKNN3-RK1828
Build from source code
git clone https://github.com/ggml-org/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-app # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama serve -hf jj90/Kev-0.8B-RKNN3-RK1828 # Run inference directly in the terminal: ./build/bin/llama cli -hf jj90/Kev-0.8B-RKNN3-RK1828
Use Docker
docker model run hf.co/jj90/Kev-0.8B-RKNN3-RK1828
- Llama new
- LM Studio
- Jan
- Ollama
How to use jj90/Kev-0.8B-RKNN3-RK1828 with Ollama:
ollama run hf.co/jj90/Kev-0.8B-RKNN3-RK1828
- Unsloth Desktop
- Pi
How to use jj90/Kev-0.8B-RKNN3-RK1828 with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf jj90/Kev-0.8B-RKNN3-RK1828
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "jj90/Kev-0.8B-RKNN3-RK1828" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use jj90/Kev-0.8B-RKNN3-RK1828 with Docker Model Runner:
docker model run hf.co/jj90/Kev-0.8B-RKNN3-RK1828
- Lemonade
How to use jj90/Kev-0.8B-RKNN3-RK1828 with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull jj90/Kev-0.8B-RKNN3-RK1828
Run and chat with the model
lemonade run user.Kev-0.8B-RKNN3-RK1828-{{QUANT_TAG}}List all available models
lemonade list
- Hermes Agent
How to use jj90/Kev-0.8B-RKNN3-RK1828 with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf jj90/Kev-0.8B-RKNN3-RK1828
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default jj90/Kev-0.8B-RKNN3-RK1828
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use jj90/Kev-0.8B-RKNN3-RK1828 with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf jj90/Kev-0.8B-RKNN3-RK1828
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "jj90/Kev-0.8B-RKNN3-RK1828" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
Kev-0.8B-RKNN3-RK1828
Kev-0.8B (decision model) converted to RKNN3 and running on the Rockchip RK1828 NPU โ with zero accuracy loss versus the original fp32 model.
Kev is not a chat model. It runs a single prefill and scores options with a pointer head; it never generates tokens.
You can verify this yourself: ask it 1+1, and you get nonsense. That is the model behaving correctly.
This repository contains the converted artifacts plus the minimal host-side code needed to actually
use them, because a plain rkllm3-server deployment cannot run Kev (see Why this needs host code).
| Base model | Qwen/Qwen3.5-0.8B-Base @ dc7cdfe |
| Adapter | jaredpalmer/kev-0.8b (LoRA r16, merged into base) |
| Target hardware | RK1828 NPU (RK1820/RK1828 AI SDK), host = Windows PC / RK3588 / RK3576 |
| Toolchain | RKNN3 v1.1.0 (runtime/rknn3_110), target_platform='rk1820' |
| Quantization | w4a16, quantized_algorithm='normal', quantized_method='group32' (weight-only, no calibration set) |
| NPU footprint | 802 MB (as reported by rknn-smi) |
| Latency |
Files
| File | Size | What it is |
|---|---|---|
rknn/Kev-0.8B.rknn |
20.6 MiB | RKNN3 graph. Output is [1, 1, 248320] fp16 logits |
rknn/Kev-0.8B.weight |
498 MiB | Quantized backbone weights |
rknn/Kev-0.8B.embed.bin |
485 MiB | Token embedding table, 248320 ร 1024 fp16 (also the dequantization matrix W) |
rknn/Kev-0.8B.tokenizer.gguf |
10.4 MiB | Tokenizer. Identical to Qwen3.5-0.8B โ LoRA does not touch the vocab |
rknn/start.cmd |
1.4 KiB | rkllm3-server launch line (for the "text-only" sanity check) |
host/kev_daemon.cpp |
โ | Device-side runner: loads the model once, then takes TOK/R/A commands and dumps logits per request |
host/kev_serve.py |
โ | HTTP service exposing POST /v1/systemone |
host/serve_assets/*.npy |
6.1 MiB | Ginv.npy (1024ร1024), head_q.npy, head_k.npy, temperature.npy โ precomputed, so you do not have to invert a 1024ร1024 normal-equation matrix at startup |
host/e2e_check.py |
โ | End-to-end accuracy check against the decision-v2 labels |
docs/DEPLOY.md |
โ | Step-by-step deployment, including the traps |
Total: ~1.06 GB.
Checksums
776f782272076d2579eb5d5e59aee733ea8c10bd2994013ed791d05c449ff3f0 Kev-0.8B.rknn
0fcc3e04de7a645e166c11b1b98e769df8a145767d1979be54ba34578a0d6dce Kev-0.8B.weight
2146dc176cff21240562283cf0b709a91499917d5b5f2c4fb0b7b41b21d407b0 Kev-0.8B.embed.bin
f2235450332c615492e7cfa13b103090a9adc7a802bef5d425842a87f8b6b03f Kev-0.8B.tokenizer.gguf
sha256sum -c <<'EOF'
776f782272076d2579eb5d5e59aee733ea8c10bd2994013ed791d05c449ff3f0 Kev-0.8B.rknn
0fcc3e04de7a645e166c11b1b98e769df8a145767d1979be54ba34578a0d6dce Kev-0.8B.weight
2146dc176cff21240562283cf0b709a91499917d5b5f2c4fb0b7b41b21d407b0 Kev-0.8B.embed.bin
f2235450332c615492e7cfa13b103090a9adc7a802bef5d425842a87f8b6b03f Kev-0.8B.tokenizer.gguf
EOF
Why this needs host code
Kev's scoring path is:
h_decide = backbone(state + question + "<decide>") # hidden state, 1024-d, *before* lm_head
h_opt_k = backbone(state + question + option_k + "</opt>")
z_k = (k(h_opt_k) ยท q(h_decide)) / sqrt(256)
answer = softmax(z / T) # T = 2.3510958125672174
The runtime exposes vocab logits, not hidden states. The usual conclusion is "blocked, needs retraining".
It is not blocked, because logits = h @ Wแต is an overdetermined system:
W โ R^(248320 ร 1024), unknown h โ R^1024, 248320 equations
h = (WแตW)โปยน Wแต ยท logits
W is the (shared) embedding matrix, so it is already on disk. The per-coordinate quantization noise gets
averaged over ~248k equations, i.e. suppressed by roughly โ248320 โ 500ร. Measured cosine similarity
between device-recovered h and the fp32 reference is 0.96โ0.99, with top-1 agreeing on every sampled position.
So the original pointer head runs unmodified on the host. No retraining, no downgrade to an embedding model.
Ginv.npy is the precomputed (WแตW)โปยนWแต, so recovery is a single 1024ร1024 @ 1024 matmul per position.
Two consequences worth knowing before you deploy:
- The graph only keeps the last position. There is no
num_logits_to_keepin the public API andclear_kvcachehas no truncate. To read the</opt>positions you must re-run a truncated sequence. A request withKoptions therefore costs K+1 prefills โ that is a hard floor, not an implementation choice. - Per-call fixed overhead is ~50 ms, independent of length. Latency scales with number of calls, not token count. Batching long states into one prefix helps a lot; splitting into many short calls does not.
Usage
1. Sanity check (text only)
cd rknn
start.cmd
Then POST /v1/chat/completions. Output will be garbage โ this only proves the weights loaded and the NPU
is running. Do not use this to judge whether the conversion worked.
2. Real usage: decision API
Build host/kev_daemon.cpp against the RKNN3 SDK session demo, run it, then:
python host/kev_serve.py # listens on :17890
curl -X POST http://127.0.0.1:17890/v1/systemone \
-H "Content-Type: application/json" \
-d '{
"state": {"ticket": "Checkout returns 500 for EU customers", "age_hours": 30},
"questions": {
"team": {"type": "choice", "instructions": "Which team should own this?",
"criteria": {"billing": "payment, invoices, refunds",
"platform": "infra, deploys, runtime",
"growth": "onboarding, activation"}},
"urgent": {"type": "noul", "instructions": "Is this urgent?"},
"sev": {"type": "score", "instructions": "Rate the severity",
"criteria": ["cosmetic", "degraded", "broken", "outage"]}
}
}'
{"answers": {
"team": {"type": "choice", "answer": "billing", "confidence": 0.7638, "probabilities": {...}},
"urgent": {"type": "noul", "p_true": 0.912},
"sev": {"type": "score", "score": 2.31, "legend": [...], "score_confidence": 0.54}
}}
Response schema follows the upstream kev/api.py::to_answers conventions:
noulreturnsp_trueonly (the upstream API does not binarize it)choicereturnsconfidence = (p_max โ 1/K) / (1 โ 1/K), soK=2withp=1.0givesconfidence=1.0scorereturns the probability-weighted expected level asscore, plus per-level probabilities
Full commands and the build line: docs/DEPLOY.md.
Performance
Measured on RK1828 (5051.8 MB NPU), Windows host, single model loaded.
| Metric | Value |
|---|---|
| Accuracy, decision-v2 dev 60 (fp32 reference, host) | 49/60 = 0.817 |
Accuracy, decision-v2 dev 60 (device, w4a16 + recovered h) |
49/60 = 0.817 |
| Per-question argmax agreement, device vs fp32 | 58/60 = 96.7% |
| End-to-end HTTP, 26 mixed-type questions | 23/26 = 0.885 |
| Prefill throughput (long sequences) | 1200โ1500 tok/s |
| Single prefill, ~100 tokens | ~75 ms |
| Per-call fixed overhead | ~50 ms |
| One decision (K=5) | ~0.5 s |
| End-to-end HTTP per question | ~0.9 s |
| Model load | ~30 s, once |
| NPU memory | 802 MB |
The two disagreeing questions (q9, q10) cancel out โ one is right on device and wrong on fp32, the other the reverse. That is the signature of the same function being computed, with numerical noise flipping borderline cases.
Coexistence, measured with rknn-smi on the same device:
| Configuration | NPU used | Delta |
|---|---|---|
| baseline (proxy only) | 34 MB | โ |
| Kev-0.8B alone | 802 MB | โ |
| Kev-0.8B + Qwen3-ASR-0.6B | 2848 MB | +2047 MB |
| Kev-0.8B + Qwen3-ASR-1.7B | 2953 MB | +2152 MB |
Kev can share the NPU with an ASR model. Both fit; only ~105 MB separates the two ASR sizes. Measure coexisting configurations, not standalone ones โ a standalone run reports 779 MB for the 0.6B ASR, which will make you over-budget your plan.
Limitations
- Not a chat model. Text generation output is meaningless by design. Any benchmark that prompts it for answers is invalid.
- Numeric noise flips borderline decisions. 96.7% per-question agreement means ~3% of hard cases can differ from the fp32 reference. If you need exact reproducibility, run the fp32 model.
- K+1 prefill calls per request cannot be reduced with this runtime (see above). Very large option lists get slow linearly.
- Single-request serialization. The service holds a global lock around one decision, because
K+1prefills share one KV cache; interleaving concurrent requests corrupts it. Throughput is therefore ~1 request at a time. Concurrency is safe (tested), but it queues. - Host must be Windows / RK3588 / RK3576. The RK1828 is a co-processor; an x86 Linux box can convert and simulate but cannot drive the module.
- Quantization format is fixed to
w4a16 + normal + group32by this toolchain.w8a16andfp16builds are rejected (request_type=float16/Failed to create initializer tensor), so you cannot "build a higher-precision version" to isolate quantization error.
Provenance
- Base:
Qwen/Qwen3.5-0.8B-Base, revisiondc7cdfe2ee4154fa7e30f5b51ca41bfa40174e68 - Adapter:
jaredpalmer/kev-0.8b, LoRA r16 / ฮฑ32, task typeFEATURE_EXTRACTION - Merged via
merge_and_unload(), then exported to ONNX with the officialrknn3-model-zoo/examples/Qwen3_5pipeline h, the pointer head, and the option/decide token ids are all taken from the upstream Kev implementation unchanged
Special token ids used (from upstream kev/model.py::SPECIAL):
<state> 248060 <question> 248061 <opt> 248049 </opt> 248050 <decide> 248062
Artifact sizes match the officially published Qwen3.5-0.8B RKNN3 build file-for-file (20.6 / 498 / 485 / 10.4 MiB), which is the practical proof that the conversion is structurally correct.
License: Apache-2.0, inherited from the base model.
ไธญๆๆ่ฆ
Kev-0.8B ๆฏๅณ็ญๆจกๅ๏ผไธๆฏๅฏน่ฏๆจกๅ๏ผๅฎๅช่ทไธๆฌก prefill๏ผ็จๆ้ๅคด็ปๅ้้กนๆๅ๏ผไธ็ๆ tokenใ ็จ"้ฎๅฎ 1+1"ๆฅ้ชๆถๆฏ้็โโ้ฃๆ ทไธๅฎไผๅพๅฐๆ ๆไน็ๅ็ญใ
RKNN3 ่ฟ่กๆถๅชๆด้ฒ vocab logits๏ผ่ Kev ้่ฆ hidden stateใไฝ logits = h @ Wแต ๆฏ่ถ
ๅฎๆน็จ
๏ผ248320 ไธชๆน็จ่งฃ 1024 ไธชๆช็ฅๆฐ๏ผ๏ผh = (WแตW)โปยนWแตยทlogits ๅฏไปฅ็ฒพ็กฎ่งฃๅๆฅ๏ผ
้ๅๅชๅฃฐ่ขซ็บฆ 500 ๅๅนณๅๆใๅ ๆญคๅ็ๆ้ๅคดๅฏไปฅๅๆ ท่ทๅจ host ไพง๏ผๆ ้้่ฎญใๆ ้ๆน็ปๆใ
| ้กน | ็ปๆ |
|---|---|
| ็ๆบๅ็กฎ็๏ผ60 ้ข๏ผ | 0.817๏ผไธ fp32 ๅฎๅ จไธ่ด |
| ้้ขไธ่ด | 58/60 |
| ็ซฏๅฐ็ซฏ HTTP๏ผ26 ้ขไธ้ขๅ๏ผ | 0.885๏ผ็บฆ 0.9 s/้ข |
| NPU ๅ ็จ | 802 MB |
ๆฌไปๅบๅ
ๅซ่ฝฌๆขไบง็ฉ + ๅฏๅค็ฐ็ host ไพงไปฃ็ ๏ผdaemonใHTTP ๆๅกใๅ่งฃ็ฉ้ตใๅคดๆ้๏ผ๏ผ
ๆฟๅฐๅณๅฏ่ท้ใ้จ็ฝฒๆญฅ้ชค่ง docs/DEPLOY.mdใ
- Downloads last month
- -
We're not able to determine the quantization variants.
Model tree for jj90/Kev-0.8B-RKNN3-RK1828
Base model
Qwen/Qwen3.5-0.8B-BaseEvaluation results
- Accuracy (device) on Kev decision-v2 (60 held-out)self-reported0.817
- Accuracy (HTTP service) on Kev decision-v2 (26 mixed-type, end-to-end HTTP)self-reported0.885