Instructions to use XHToken/Spark-X2.5-4B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use XHToken/Spark-X2.5-4B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="XHToken/Spark-X2.5-4B", trust_remote_code=True) messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("XHToken/Spark-X2.5-4B", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use XHToken/Spark-X2.5-4B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "XHToken/Spark-X2.5-4B" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "XHToken/Spark-X2.5-4B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/XHToken/Spark-X2.5-4B
- SGLang
How to use XHToken/Spark-X2.5-4B with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "XHToken/Spark-X2.5-4B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "XHToken/Spark-X2.5-4B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "XHToken/Spark-X2.5-4B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "XHToken/Spark-X2.5-4B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use XHToken/Spark-X2.5-4B with Docker Model Runner:
docker model run hf.co/XHToken/Spark-X2.5-4B
[HER Hack-Astron #5] Spark-X2.5-4B Q4_K_M 在无独显 Linux CPU(8核/16G)上的真实编码、吞吐与 OOM 边界
把 Spark-X2.5-4B 放到一台 没有 NVIDIA、15GiB 内存被其他进程挤占 的 Linux 上,用官方 Spark 架构的 llama.cpp 跑通 Q4_K_M。结论很短:中文事实问答能对;默认 thinking 会把生成预算吃光;关掉 thinking 能吐代码,但正则分组写错,实测 FAIL;滑动窗口会掩盖长上下文的 KV 成本,--swa-full -c 131072 会把 16G 机器打进内核 OOM。
官方 BF16 GGUF(约 8.23GB)没有加载。本案例只用社区 Q4_K_M。
1. 真实使用:revision 与产物
| 项 | 值 |
|---|---|
| 实际加载 | abenzerps/Spark-X2.5-4B-GGUF / Spark-X2.5-4B-Q4_K_M.gguf |
| Hub commit | c3235f9779664f2a78c209d077dcab6f9bd6ff61 |
| 文件大小 | 2,600,223,552 bytes |
| SHA256 | 7934660bfc5b9bf04be0a0ac6179a1d16e1d4331b448857c86b8b2801b3ef72c |
| GGUF arch | spark2_5 |
| 未加载 | XHToken/Spark-X2.5-4B-GGUF BF16 80e7e595857290d80f93fd1c85e5bebfed02dc45(Hub 记录 8,229,920,352 bytes) |
| runtime | XHToken/llama.cpp a698f1cc3252597a541bc1fdd2a9975184ae1684(llama-cli 0.1.2-dev b1-a698f1c) |
| 构建 | cmake -S . -B build -DGGML_CUDA=OFF |
| 精度/量化 | Q4_K_M,mmap,无 mlock,-ngl 0 |
下载:
hf download abenzerps/Spark-X2.5-4B-GGUF Spark-X2.5-4B-Q4_K_M.gguf \
--local-dir ./models
未上传任何 safetensors / GGUF 权重。
2. 环境
- Linux 6.12.94+ x86_64,8× Intel Xeon(1 thread/core),无 NVIDIA
- RAM 15GiB + swap 15GiB,实验时已被其他进程占用一部分(共享机器,计费:免费)
- cmake 3.31.6,g++ 14.2.0
- llama-cli 提示:
no usable GPU found, --gpu-layers option will be ignored
必须 --fit off 并显式 -c。模型原生 ctx 是 1,048,576,默认 --fit on 会把上下文撑爆。
采样按模型卡:temperature=1.0, top_p=0.95。卡上 top_k=-1,本 CLI 合法值是 --top-k 0(disable),不能传 -1。
TTFT: llama-cli 不打印首 token 毫秒。下面速度一律是 UI 行 [ Prompt: X t/s | Generation: Y t/s ] + 墙钟。峰值 RSS 来自 /proc/<pid>/status 的 VmRSS;mmap 下 RSS 含文件页,不是稳定的“权重大小”。
3. 实验 1:官方示例句(真实运行)
输入:
安徽的省会在哪里?
公共命令:
llama-cli -m Spark-X2.5-4B-Q4_K_M.gguf \
-p '安徽的省会在哪里?' \
-c 512 -b 128 -ub 64 \
--temp 1.0 --top-p 0.95 --top-k 0 \
--jinja -cnv --single-turn --reasoning on \
--perf --no-display-prompt --color off \
-ngl 0 --load-mode mmap --threads 4 --threads-batch 4 \
--fit off --no-warmup
| 次数 | n_predict | thinking | 墙钟 s | Prompt t/s | Gen t/s | 峰值 RSS | 结果 |
|---|---|---|---|---|---|---|---|
| warmup | 32 | off | 7.17 | 30.0 | 6.9 | 未采样 | 合肥(被 n=32 截断) |
| m1 | 128 | on | 21.67 | 29.7 | 6.7 | ~4.98 GiB | thinking 吃光预算,终答只剩「安徽省」 |
| m2 | 256 | on | 38.51 | 36.3 | 6.5 | ~4.93 GiB | 合肥市 |
| m3 | 256 | on | 34.54 | 33.4 | 5.8 | ~4.94 GiB | 合肥市 |
样本量:1 次 warmup + 3 次测量。Q4_K_M,-c 512,4 threads,mmap。生成约 5.8–6.9 tok/s,短 prompt 评估约 30–36 tok/s。无 TTFT ms。
m2 原始输出(节选,未改写):
> 安徽的省会在哪里?
[Start thinking]
我们需要回答用户的问题:“安徽的省会在哪里?”这是一个关于中国地理的问题。
首先,我需要确认安徽省的省会。安徽省的省会是合肥。
...
[End thinking]
安徽省的省会是**合肥市**。
合肥市是安徽省的省会,也是全省的政治、经济、文化、科教和交通中心,位于安徽省中部的江淮之间。
[ Prompt: 36.3 t/s | Generation: 6.5 t/s ]
4. 实验 2:真实编码(执行了,不是只看了一眼)
输入:
写一个纯 Python 3 函数 parse_access_log(line: str) -> dict | None,解析 Nginx combined 日志行,返回 ip, method, path, status, bytes。无效行返回 None。只输出代码,不要解释。然后我会用这三行测:
1.2.3.4 - - [01/Sep/2026:10:00:00 +0000] "GET /health HTTP/1.1" 200 12 "-" "curl/8.0"
bad line
10.0.0.1 - - [01/Sep/2026:10:00:01 +0000] "POST /api/v1/orders HTTP/1.1" 201 84 "-" "okhttp/4.12"
4a. --reasoning on,-n 800,-c 2048:没有代码
墙钟 233.4 s,Prompt 22.8 t/s,Generation 3.8 t/s。800 token 全部耗在 [Start thinking],没有 [End thinking],没有函数。
失败模式: 默认 thinking + 不大的 -n,会把用户可见答案饿死。
4b. --reasoning off,-n 400:有代码,测试 FAIL
墙钟 47.5 s,Prompt 26.4 t/s,Generation 6.2 t/s。模型原始代码(未打补丁):
import re
def parse_access_log(line: str) -> dict | None:
pattern = r'^(\S+) \S+ \S+ \[([^\]]+)\] "((\S+) (\S+) HTTP/\d\.\d)" (\d+) (\S+)'
match = re.match(pattern, line)
if not match:
return None
ip, timestamp, method, path, protocol, status, bytes_str = match.groups()
try:
return {
'ip': ip,
'method': method,
'path': path,
'status': int(status),
'bytes': int(bytes_str)
}
except (ValueError, TypeError):
return None
实测:
CASE 1 pass=False got={'ip': '1.2.3.4', 'method': 'GET /health HTTP/1.1', 'path': 'GET', 'status': 200, 'bytes': 12}
CASE 2 pass=True got=None
CASE 3 pass=False got={'ip': '10.0.0.1', 'method': 'POST /api/v1/orders HTTP/1.1', 'path': 'POST', 'status': 201, 'bytes': 84}
OVERALL FAIL
原因:请求字符串外多包了一层捕获组,groups() 解包把整段 request 赋给了 method。无效行正确地返回了 None。ip / status / bytes 是对的。
编码题:FAIL。
5. 实验 3:边界(按验收标准必须写失败)
Spark GGUF 带 spark2_5.attention.sliding_window。默认 不开 --swa-full 时,llama.cpp 不会为 32k 上下文准备满 KV。所以:
| ctx | --swa-full |
峰值 RSS | 结果 |
|---|---|---|---|
| 8192 | 否 | ~3.57 GiB | 生成成功 |
| 32768 | 否 | ~3.73 GiB | 生成成功 |
| 32768 | 是 | ~7.03 GiB | 生成成功,系统 swap 几乎打满 |
| 131072 | 是 | HWM ~11.67 GiB + ~9.5 GiB 进程 swap | 失败 |
失败命令:
llama-cli -m Spark-X2.5-4B-Q4_K_M.gguf -p ping -n 4 -c 131072 --swa-full \
--load-mode mmap --fit off --no-warmup ...
卡在 Loading model...,没有生成任何 token。110s timeout 后进程仍占约 11.8 GiB RSS。随后内核 OOM:llama-cli 的 oom_score_adj=-1000,kernel 杀掉了其他 Chrome 进程(oom_score_adj=300)。这是有害副作用,记在这里,不是成功案例。
6. 限制与建议
- 官方 8.23GB BF16 GGUF 不适合这台 16G 共享盒;Q4_K_M 才能真正跑起来。
- thinking 默认开启时,给编码任务留足
-n,或者显式--reasoning off。 - 不要把「
-c 32k也能跑」理解成满 KV 的 32k。先确认--swa-full。 - 在 16G 机器上不要对 4B Q4 开
--swa-full+ 巨大-c。 - llama-cli 的
--top-k -1无效,用0。 - 社区量化 ≠ 官方 BF16 比特一致。本帖只对 Q4_K_M + 该 llama.cpp commit 负责。
7. 对后来者
最小可复现路径:XHToken/llama.cpp CPU 构建 + abenzerps Q4_K_M + --fit off + 显式 -c。中文常识问答在 ~6 tok/s 可用;把它当编码 agent 前,先关 thinking 并 跑测试,不要只看它会不会写函数。