第 9 章 · 01 coli CLI 与 resource_plan.py


文档摘要

第 9 章 · 01 coli CLI 与 resourceplan.py 本节摘要:本节深潜 Colibrì 的用户接入层入口—— CLI。它是一个纯 Python 脚本( ),把所有用户操作收敛成一组子命令: (交互流式)/ (OpenAI 兼容服务)/ (Web UI)/ (RAM/VRAM 规划)/ (环境诊断)/ / / / / / / / 。 是 pip 安装后的入口包装, 是 / 背后的规划器——检测 RAM/VRAM 预算和后端,生成磁盘/RAM/VRAM 三级放置配置。本节贴 与 、 的关键源码。 内容来源:原项目源码 、 、 ⚠️ 注意: 是 Python 脚本不是编译产物,直接 就能跑。 后它被放到 ,引擎和支持模块( / / )放到 —— 内部会去找它们。

第 9 章 · 01 coli CLI 与 resource_plan.py

本节摘要:本节深潜 Colibrì 的用户接入层入口——coli CLI。它是一个纯 Python 脚本(c/coli),把所有用户操作收敛成一组子命令:chat(交互流式)/serve(OpenAI 兼容服务)/web(Web UI)/plan(RAM/VRAM 规划)/doctor(环境诊断)/info/mirror/bench/convert/build/run/tune/stopcolibri/cli.py 是 pip 安装后的入口包装,resource_plan.pyplan / doctor 背后的规划器——检测 RAM/VRAM 预算和后端,生成磁盘/RAM/VRAM 三级放置配置。本节贴 colicli.pyresource_plan.py 的关键源码。

内容来源:原项目源码 c/colicolibri/cli.pyc/resource_plan.py

⚠️ 注意:coli 是 Python 脚本不是编译产物,直接 ./coli chat 就能跑。make install 后它被放到 $(PREFIX)/bin/coli,引擎和支持模块(resource_plan.py/doctor.py/openai_server.py)放到 $(PREFIX)/libexec/colibri——coli 内部会去找它们。

学习目标

  1. 列出 coli 的全部子命令并说清各自用途。
  2. 读懂 colibri/cli.py 为什么是"薄包装"——它把所有逻辑委托给 c/coli
  3. 解释 resource_plan.py 如何从模型 safetensors 头 + 硬件探测 + 后端检测生成三级放置 plan。
  4. 理解 coli doctor 检查哪些项(依赖、模型、磁盘、版本)。
  5. 区分 run-in-place 与 installed 两种布局,以及 COLI_ENGINE/COLI_MODEL 环境变量的作用。

一、coli 子命令一览

coli 用 argparse 注册子命令。源码 1337-1406 行把全部子命令注册出来:

1337 sub=ap.add_subparsers(dest="cmd") 1338 sub.add_parser("build", parents=[common]); sub.add_parser("info", parents=[common]) 1339 pp=sub.add_parser("plan",parents=[common]) 1341 pm=sub.add_parser("mirror", parents=[common], ...) 1349 pd=sub.add_parser("doctor",parents=[common]) 1353 pt=sub.add_parser("tune", parents=[common], ...) 1363 pr=sub.add_parser("run", parents=[common]); pr.add_argument("prompt", nargs="*") 1364 pc=sub.add_parser("chat", parents=[common]) 1372 ps=sub.add_parser("serve", parents=[common]) 1383 pst=sub.add_parser("stop", parents=[common], help="shut down a running coli serve ...") 1385 pw=sub.add_parser("web", parents=[common], help="serve + open the dashboard ...") 1398 pb=sub.add_parser("bench", parents=[common]); pb.add_argument("tasks", nargs="*") 1406 pc=sub.add_parser("convert", parents=[common]); pc.add_argument("--repo",default="zai-org/GLM-5.2-FP8")

coli 顶部 docstring 把核心子命令的用途直接列出:

coli chat interactive chat (loads the model once) coli serve OpenAI-compatible HTTP API (persistent engine) coli run "prompt" one-shot generation coli info model, RAM, disk, and configuration status coli plan Disk / RAM / VRAM resource plan coli mirror Plan, stage, or verify a learned partial mirror coli doctor installation and execution-plan diagnostics coli bench [task...] quality benchmarks (MMLU/HellaSwag/...) coli convert convert GLM-5.2-FP8 to int4, one shard at a time coli build build the engine

最常用的五个(本教程主线):

  • coli chat:交互式流式聊天,引擎只加载一次,后续 turn 复用同一进程(配合第 7 章 02 节的 KV 前缀复用);
  • coli serve:启动 OpenAI 兼容 HTTP 服务(openai_server.py),引擎持久驻留,第 9 章 02 节展开;
  • coli web:serve + 自动开浏览器加载 dashboard(第 9 章 03 节);
  • coli plan:不跑模型,只探测硬件 + 解析模型头,生成三级放置 plan;
  • coli doctor:环境诊断,检查依赖、模型完整性、磁盘空间、版本一致性。

二、colibri/cli.py:pip 安装的薄入口

colibri/cli.py 全文 27 行,核心是把控制权交给 c/coli:

"""Entry point for `coli` when installed via pip. Delegates to the original c/coli script which handles all subcommands. This wrapper exists so `pip install colibri-engine` creates a `coli` console script that works without the user having to add c/ to PATH manually. """ import os, sys, runpy def main(): here = os.path.dirname(os.path.abspath(__file__)) engine_dir = os.path.join(os.path.dirname(here), "c") coli_script = os.path.join(engine_dir, "coli") if not os.path.exists(coli_script): sys.exit("colibri engine directory not found.\n" "Install from source: git clone + pip install -e .") sys.path.insert(0, engine_dir) sys.argv[0] = coli_script runpy.run_path(coli_script, run_name="__main__")

这是 PyPI 包 colibri-engine 的 console_script 入口——pip install colibri-engine 后,coli 命令就是这层壳。它做的事只有三件:

  1. 定位 c/coli 脚本(在已安装布局里找 c/ 目录);
  2. c/ 加入 sys.path(让 import resource_plan 等能解析);
  3. runpy.run_path__main__ 身份执行 c/coli,完整转发命令行参数。

💡 深潜要点:为什么不一上来就把所有逻辑写在 Python 包里?因为 coli 还要启动 C 编译出来的引擎二进制(colibri / glm)。Python 部分只是"参数解析 + 引擎 subprocess 调度 + 工具脚本粘合",真正的推理逻辑全在 C 侧。这种"薄 Python 壳 + 厚 C 内核"是 Colibrì 一贯的工程取向。

三、resource_plan.py:三级放置规划器

resource_plan.pycoli plancoli doctor 背后的核心。它做四件事:

  1. 解析模型(analyze_model):读所有 *.safetensors 的头,把张量按"稠密部分"和"专家组"分类,统计各自字节;
  2. 探测硬件(memory_available / discover_gpus / physical_cpu_count):查可用 RAM、NVIDIA/AMD GPU 及显存、物理核数、NUMA socket 数;
  3. 生成 plan(build_plan):把模型 + 硬件 + 上下文长度喂给 _auto_tune,输出三级放置配置(dense 常驻多少、专家 cache 多大、VRAM 驻留多少);
  4. 渲染环境变量(environment_for_plan / format_plan):把 plan 翻译成 COLI_* 环境变量集合 + 人类可读的表格。

analyze_model 的核心是分类稠密张量和专家张量:

18 def _tensor_sizes(path): 19 file_size = path.stat().st_size 20 with path.open("rb") as stream: 21 raw = stream.read(8) ... 25 header = json.loads(stream.read(length)) 26 for name, meta in header.items(): ... 30 yield name, end - start 37 def analyze_model(model): ... 43 EXPERT_RE = re.compile(r"model\.layers\.(\d+)\.mlp\.experts\.(\d+)\.") 44 dense_bytes = 0 45 expert_groups = {} 46 for shard in shards: 47 for name, size in _tensor_sizes(shard):

EXPERT_RE 正则把 model.layers.N.mlp.experts.K.* 形式的张量识别为专家权重,按 layer 分组;其他归稠密部分。这正是第 1 章/第 4 章的"稠密常驻 RAM + 专家放磁盘"在 Python 规划层的落地。

build_plan(523 行起)综合 RAM/VRAM 预算、上下文长度、GPU 列表、_auto_tune 的瓶颈分类(CPU-bound/disk-bound/bandwidth-bound),给出 COLI_RAM_GBCUDA_EXPERT_GBPIN_GBCOLI_MODEL_MIRROR 等配置——这些就是第 4-8 章所有 C 侧开关的"上层来源"。

四、coli doctor:环境诊断

cmd_doctor(740 行起)调用 doctor.py,逐项检查:

  • 依赖:Python 版本、gcc/clang、(可选)CUDA/Metal/Vulkan 工具链、OpenMP;
  • 模型:配置文件 config.json、safetensors 完整性、专家张量计数与 config.json 声明是否一致;
  • 磁盘:模型目录所在盘剩余空间、是否支持 O_DIRECT、是否能开镜像;
  • 版本:引擎二进制版本与 version.py 是否一致,与 PyPI 已发布版本是否匹配;
  • plan 健康性:跑一遍 resource_plan.build_plan,看输出是否合理(比如 RAM 是否塞得下稠密部分)。

每一项都给出明确的修复建议,而不是"失败 = 报错退出"。这呼应 coli 顶部第 65-67 行的"no invented default"哲学:永远不发明一个数,失败要让用户知道下一步该做什么

五、run-in-place vs installed:COLI_ENGINE/COLI_MODEL

coli 内部需要定位两样东西:引擎二进制和支持模块。源码用三层 fallback 实现:

_EXE = ".exe" if sys.platform == "win32" else "" _LIBEXEC = os.path.join(os.path.dirname(HERE), "libexec", "colibri") _here_colibri = os.path.join(HERE, "colibri" + _EXE) _here_glm = os.path.join(HERE, "glm" + _EXE) if os.environ.get("COLI_ENGINE"): GLM = os.environ["COLI_ENGINE"] TOOLS = os.path.join(os.path.dirname(GLM), "tools") elif os.path.exists(_here_colibri): GLM = _here_colibri # run-in-place: c/colibri elif os.path.exists(_here_glm): GLM = _here_glm # 老布局回退: c/glm else: GLM = os.path.join(_LIBEXEC, "colibri" + _EXE) # installed: libexec/colibri/colibri ...

环境变量优先级:

  • COLI_ENGINE:显式指定引擎二进制路径,覆盖一切自动检测(自定义打包布局用);
  • COLI_MODEL:模型目录,所有子命令的默认值。coli 顶部明确写"no invented default"——不设就没默认值,每个子命令用各自的方式报"pass --model , or set COLI_MODEL="。

六、setup.sh 与安装流程

c/setup.sh 是构建脚本,coli build 内部调用它。典型流程:

  • 检测平台(Linux/macOS/Windows)、编译器(gcc/clang/MinGW);
  • 根据可选开关(CUDA=1/METAL=1/VULKAN=1)决定编译哪些后端;
  • 编译产出 c/colibri(主引擎二进制);
  • make installcoli 放到 $(PREFIX)/bin/,把 colibri + 支持模块放到 $(PREFIX)/libexec/colibri/

coli 自身可以独立于引擎二进制存在——doctor/plan 这些不依赖推理引擎,纯 Python 就能跑,这也是为什么"先 coli doctorcoli build"是排查问题的标准流程。

本节要点回顾

  • coli 是 Python CLI,子命令包括 chat/serve/web/plan/doctor/info/mirror/bench/convert/build/run/tune/stop,核心五个是 chat/serve/web/plan/doctor。
  • colibri/cli.py 是 pip 安装后的 27 行薄入口,用 runpy.run_path 把控制权交给 c/coli,让 pip install colibri-engine 自动创建 coli console script。
  • resource_plan.py 是 plan/doctor 的核心:analyze_model 分类稠密/专家张量,discover_gpus/physical_cpu_count 探测硬件,build_plan 给出 COLI_* 环境变量配置——这就是第 4-8 章 C 侧开关的上层来源。
  • coli doctor 检查依赖/模型/磁盘/版本/plan 健康性,每项给修复建议,不"发明默认值"(#724 教训)。
  • COLI_ENGINE/COLI_MODEL 是两个核心环境变量;run-in-place 找 c/colibri,installed 找 libexec/colibri/colibri;setup.sh 是构建脚本,coli build 调用它。

下一节我们看 coli serve 启动的 openai_server.py——OpenAI 兼容 HTTP 网关,以及它如何把 continuous batching、grammar 约束、speculative decoding、kv_prefix 串联起来。


作者与出处
原作者: 灏天文库
整理: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U