# 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: 回答里夹「�」乱码?** 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 性能基线 |