188 lines
9.4 KiB
Markdown
188 lines
9.4 KiB
Markdown
# Sparkle
|
||
|
||
本地 **Qwen3-Next-80B-A3B Instruct 8bit** 流式推理引擎,对接 ccSparkle Agent(模型源:**Sparkle**)。
|
||
|
||
在约 64GB 统一内存的 Apple Silicon 上,把约 77GB 专家权重放在 SSD,运行时按需装入 + 预取,从而跑通 80B 8bit(oMLX / Ollama 全量加载做不到的档位)。动机见 [`models/README.md`](./models/README.md):用 80B@64G 验证流式路径,对应下游 **30B 8bit A3B** 进 32G/16G、统一内存省 50%+。
|
||
|
||
| 项 | 值 |
|
||
|----|----|
|
||
| Python | **3.14.***(与 `native_moe_ext.cpython-314-darwin.so` 对齐;见 `pyproject.toml`) |
|
||
| 已验证机器 | MacBook Pro M2 Max / 64GB |
|
||
| 安装目录 | 本仓库根目录(下文记为 `$SPARKLE_HOME`,即 `clone` 后的路径) |
|
||
| 引擎端口 | `8317`(经中台 `8088` 启停与代理) |
|
||
| 模型 / 专家 / MTP | 见 [`models/README.md`](./models/README.md)(不入库,约 160GB) |
|
||
| 性能基线 | 稳态约 9–10 tok/s(贪心+MTP);采样约 4–6 tok/s;常驻约 23–33GB 量级 |
|
||
|
||
依赖安装走清华 PyPI 镜像(`pyproject.toml` 的 `tool.uv.index`)。
|
||
|
||
---
|
||
|
||
## 1. 系统组成
|
||
|
||
```
|
||
浏览器前端(8090) ← 日常对话界面
|
||
│ 顶部选 Sparkle 源
|
||
▼
|
||
中台代理(8088) ← 转发请求,规避跨域
|
||
▼
|
||
Sparkle 引擎(8317) ← 80B 8bit 流式推理
|
||
├─ /v1/chat/completions OpenAI 兼容接口
|
||
└─ /admin 调参页(槽位 / 投机宽度 / 状态)
|
||
```
|
||
|
||
专家权重留在 SSD,运行时按需读取 + 预测式预取;首次启动和切换话题时偶有停顿(读盘)。
|
||
|
||
**AUTOPIN**(默认开启):记录专家路由热度(`models/experts_8bit_g64/pool_usage.json`),启动时把最热一批 pin 进常驻池(默认占槽位 50%,定死不驱逐)。冷启动命中率可从约 72% 升到 **98%+**。`AUTOPIN=0` 关闭;`AUTOPIN_BUDGET_FRAC` 调比例(0–1)。
|
||
|
||
---
|
||
|
||
## 2. 启动
|
||
|
||
**推荐**:打开对话界面 → 顶部选 **Sparkle** → 中台自动加载引擎(约 90 秒,状态变绿后再对话)。
|
||
|
||
1. 中台(桌面应用常会自动拉起;路径按你本机 Agent 工程根目录,下文记 `$AGENT_HOME`):
|
||
```bash
|
||
cd "$AGENT_HOME" && node scripts/zhongtai-server.js
|
||
```
|
||
2. 前端静态服务:
|
||
```bash
|
||
cd "$AGENT_HOME/<前端静态目录>" && python3 -m http.server 8090
|
||
```
|
||
3. 浏览器打开对话页,顶部点 **Sparkle**——未运行时会自动启动(也可在 `配` → Sparkle tab「引擎管理」点**加载**)。
|
||
|
||
就绪:`配` → Sparkle 状态点变绿,或 `curl -s http://127.0.0.1:8088/sparkle-engine/status` 见 `"loaded":true`。
|
||
|
||
**手动启动(调试)**:
|
||
|
||
```bash
|
||
cd "$SPARKLE_HOME" # 本仓库根目录
|
||
.venv/bin/python -m mlx_streaming.server --port 8317 \
|
||
--model models/Qwen3-Next-80B-A3B-Instruct-MLX-8bit \
|
||
--expert-dir models/experts_8bit_g64 \
|
||
--qn-config models/Qwen3-Next-80B-A3B-Instruct-MLX-8bit/config.json \
|
||
--mtp-out models/qn_mtp_weights.safetensors \
|
||
--expert-slots 96
|
||
```
|
||
|
||
- Admin:`http://127.0.0.1:8317/admin`
|
||
- 健康:`curl -s http://127.0.0.1:8317/api/stats`(`unplaced_experts` 应为 `0`)
|
||
|
||
中台默认 `SPARKLE_ENGINE_DIR` → 本目录。改目录名后若「卸载」失灵,先杀 `8317` 再重启中台。
|
||
|
||
> **工具白名单**:默认只放画像 4 工具(`profile_list_employees` / `profile_get_portrait_overview` / `profile_get_person_report` / `profile_get_team_report`)。中台动态工具集会改 system 头部哈希,导致前缀快照 miss;钉死工具集后快照才稳定。排班 `metro_*` 等会被裁掉。临时放开:`TOOLS_ALLOW=`;换名单:`TOOLS_ALLOW=a,b,c`。裁剪结果见 `logs/server.log` 的 `[TOOLS_ALLOW]`。
|
||
|
||
> **不要自己设 `PREFILL_CHUNK`**。安全上限由槽位决定;引擎启动时按槽位自算(96 槽 → 4,64 槽 → 3),超限会被钳制并打日志。
|
||
|
||
---
|
||
|
||
## 3. 日常对话
|
||
|
||
1. 打开对话页(`http://localhost:8090`),顶部选 **Sparkle**
|
||
2. 首次:`配` → Sparkle tab:Base URL `http://127.0.0.1:8317`,API Key 任意非空(如 `sparkle`),刷新选模型 `Qwen3-Next-80B-A3B-Instruct-MLX-8bit`,保存
|
||
3. 正常对话;工具调用链路与 oMLX 源相同
|
||
|
||
---
|
||
|
||
## 4. 调参与引擎管理
|
||
|
||
`配` → **本地 Sparkle** tab「引擎管理」(与 `http://127.0.0.1:8317/admin` 等价):
|
||
|
||
状态点:灰(未启动)→ 黄(加载中,约 90 秒)→ 绿(就绪)。`加载` / `卸载` 启停;就绪时显示 tok/s 与 RSS。
|
||
|
||
| 参数 | 范围 | 说明 | 生效 |
|
||
|------|------|------|------|
|
||
| expert-slots | 32–160 | 常驻专家数,越大命中率越高、越占内存(每槽 ~160MB)。64GB + AUTOPIN:64 槽约 9 tok/s;**96 槽约 10.3 tok/s(推荐)**;≥128 近红线;**160 会卡死,勿用** | 应用后进程级重启(约 90 秒) |
|
||
| K(投机宽度) | 1–5 | MTP 草稿 token 数,默认 3;只影响速度 | 即时 |
|
||
| max_tokens | — | 单次回答最大长度 | 即时 |
|
||
|
||
日常 64 够用;长文档可试 96–128;系统开始 swap 就降回 64。
|
||
|
||
---
|
||
|
||
## 5. 故障排查
|
||
|
||
| 现象 | 原因 | 处理 |
|
||
|------|------|------|
|
||
| 503 / engine reloading | 加载或重建中 | 等 60–90 秒后再试 |
|
||
| `EADDRINUSE ... 8317` | 旧 server 未关 | `lsof -tiTCP:8317 -sTCP:LISTEN \| xargs kill` |
|
||
| 中台 `EADDRINUSE ... 8088` | 已有健康中台 | 直接用;要重启先 kill |
|
||
| 改名后「卸载」无效 | 旧进程挂在旧路径 | 杀 8317,重启中台再加载 |
|
||
| 明显变慢 | swap 或槽位太低 | 看内存压力;调槽;关其他大应用 |
|
||
| 首轮特别慢 | 冷启动 | 正常,第二轮起恢复 |
|
||
| 长文中途停顿 | 读盘装冷门专家 | 正常;调高槽位可缓解 |
|
||
| 刷新拉不到模型 | server 未起或端口错 | `curl http://127.0.0.1:8317/v1/models -H "Authorization: Bearer x"` |
|
||
|
||
---
|
||
|
||
## 6. 常见问题
|
||
|
||
**Q: 为什么 oMLX / Ollama 里看不到这个 8bit 模型?**
|
||
A: 权重远超 64GB 整模上限,只有 Sparkle 流式能跑。oMLX 继续跑中小模型即可。
|
||
|
||
**Q: 投机宽度 K 是什么?**
|
||
A: MTP 每步草稿 token 数;主模型批量验证,猜中白赚。只影响速度,不影响内容。
|
||
|
||
**Q: 回答乱编 / 不调工具 / 幻觉?**
|
||
A: Qwen3-Next 官方要求采样(temp 0.7 / top_p 0.8 / top_k 20)。贪心+MTP 在该模型上易幻觉。默认走采样(约 4–6 tok/s);显式 `temperature: 0` 才走贪心+MTP(约 10 tok/s)。Sparkle 客户端对真实对话会把 `0` 改回采样。
|
||
|
||
**Q: 模块分析比 oMLX 7B 还空?**
|
||
A: 多为分析轮传了 `temperature: 0` 进贪心导致指令遵循崩坏,不是花名册数据错。另查 `unplaced_experts`(非 0 = 错专家)与是否需清空 `prefix_snapshots`。
|
||
|
||
**Q: 回答里夹「<E5A4B9>」乱码?**
|
||
A: 已修:byte-level BPE 流式反分词用 `StreamingDetokenizer`,避免半字符 U+FFFD 丢字。
|
||
|
||
**Q: 8bit 比 7B 还笨?**
|
||
A: 曾因 prefill 超槽静默映射到 0 号专家。现自动算 `PREFILL_CHUNK`、超容量走正确慢路径,并用 `unplaced_experts` 告警(健康值恒为 0)。非 0 时回答不可信;若错算过,删 `models/prefix_snapshots/` 再预热。
|
||
|
||
**Q: 和云端略有不同?**
|
||
A: 量化 + KV 压缩的正常差异;语义质量不受影响。
|
||
|
||
**Q: 首轮为什么要等?**
|
||
A: 新对话要 prefill 系统提示+工具定义。有前缀快照后:重启后首会话约百秒级,之后新会话约数十秒,同会话追问约数秒。`PREFIX_SNAPSHOT_HEAD` 调长度(默认 2048,0 关闭)。
|
||
|
||
**Q: 速度还能再快吗?**
|
||
A: 96 槽 + AUTOPIN + prefill 分块约 9–10 tok/s,接近本机 8bit 上限。160 槽会卡死,勿试。
|
||
|
||
**Q: 能跑多长上下文?**
|
||
A: KV 量化默认开;对话侧另有约 24k token 压缩阈值(中台配置)。
|
||
|
||
**Q: 想换模型或其它量化档?**
|
||
A: 本引擎面向 Qwen3-Next-80B 流式 8bit 部署;换档需按当前模型重新准备专家 blob 与 MTP。
|
||
|
||
---
|
||
|
||
## 7. 目录要点
|
||
|
||
```
|
||
sparkle/
|
||
├── mlx_streaming/ # 引擎 Python 包(含已编译 native_moe_ext*.so)
|
||
├── native/ext/ # C++/Metal 扩展源码(重编 .so 用)
|
||
├── models/ # 权重与专家 blob(约 160GB,勿删)
|
||
│ ├── Qwen3-Next-80B-A3B-Instruct-MLX-8bit/
|
||
│ ├── experts_8bit_g64/
|
||
│ └── qn_mtp_weights.safetensors
|
||
├── .venv/
|
||
├── pyproject.toml / uv.lock
|
||
└── benchmarks/reports/ # 性能基线报告
|
||
```
|
||
|
||
`models/` 三者缺一不可。不要把模型目录移进 oMLX 等其它运行时的模型扫描目录(会列出但整模加载不了)。
|
||
换 Python 小版本时需 `make -C native/ext native_moe_ext` 重编 `.so`。`native/ext/build/` 已忽略。
|
||
|
||
---
|
||
|
||
## 8. 质量与速度(摘要)
|
||
|
||
- **默认应对话走采样解码**(约 temperature 0.7 / top_p 0.8 / top_k 20)。`temperature=0` 会进贪心+MTP,本机实测指令遵循差于同表 oMLX 7B。
|
||
- 稳态 decode:采样约 **4–6 tok/s**;贪心+MTP 约 **9–10 tok/s**(速度更高,但质量风险大,生产默认勿用)。
|
||
- 专家池命中率健康时约 **94%+**;`unplaced_experts ≠ 0` 表示曾用错专家权重,回答不可信。
|
||
|
||
---
|
||
|
||
## 9. 相关文档
|
||
|
||
| 文档 | 内容 |
|
||
|------|------|
|
||
| [models/README.md](./models/README.md) | 为何做流式、NAS 下载与专家/MTP 准备 |
|
||
| [benchmarks/reports/8bit-g64-baseline-2026-07-25.md](./benchmarks/reports/8bit-g64-baseline-2026-07-25.md) | 8bit 性能基线 |
|