关于 ember
ember 为编码 Agent 的决策提供校准后的概率估计,例如判断是否先提问或审查更改。其 MCP 工具可在本地或指定服务上运行 Cloudflare 的 Clef-Flash 决策模型,决策权仍由 Agent 掌握。
主要功能
- 01为类型化选项返回概率
- 02在本地或指定服务运行推理
- 03接入编码 Agent 运行环境
- 04提供 Agent 指南和 MCP 资源
适用场景
- 01评估更改是否需要审查
- 02辅助判断行动前是否先提问
- 03评估测试失败判断的可信度
- 04推送前检查更改风险
MCP 相关
提供 `advise` 工具,接收状态和类型化问题架构,并为每个选项返回校准概率;另提供 `ember://guide` MCP 资源。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
为编码 Agent 带来直觉。 Claude Code、Codex、 opencode 和 Kilo Code 等 AI 编码助手总是需要做出判断:现在开始,还是先提个问题?这个测试失败是真的吗?这项更改可以安全推送吗?ember 是一个小型附加工具,能在这些时刻为它们提供快速的第二意见,以数字形式给出结果(“有 93% 的可能需要审核”),让它们不再无谓地打断你,也不会再未经询问就做出有风险的更改。你不需要亲自调用它;你的助手会调用。它免费且开源,你可以选择模型的运行位置:在你的 Apple Silicon Mac 上(需要 32 GB 或更多内存,需一次性下载约 18 GB)、在你托管的服务器上,或在你团队已经运行的服务器上。ember 提供建议;由 Agent 做决定。
在底层,ember 运行 Cloudflare 的 Clef-Flash 决策模型,该模型来自其
公开的 Hugging Face 仓库,并将其封装为一个 MCP 工具 advise,为每个选项返回校准后的概率。
网站: shapeandshare.github.io/ember
运行 ember 的方式
三种方式都同样受支持;ember init 会询问你想使用哪一种。
| 在你的 Mac 上 | 在你托管的服务器上 | 在其他人运行的服务器上 | |
|---|---|---|---|
| 模型运行位置 | 你的 Apple Silicon Mac | 你运行的 Mac 或 NVIDIA GPU 机器 | 其运营者运行的位置 |
| 请求发送到哪里 | 不会发送到任何地方:请求保留在你的 Mac 上 | 你的服务器 | 那台服务器 |
| 所需条件 | 32 GB 内存、约 18 GB 磁盘空间 | 服务器:与本地运行相同,或配备 CUDA GPU;客户端:只需服务器地址 | 服务器地址,以及服务器要求时提供的令牌 |
| 配置方式 | ember model pull,然后运行 ember init | 远程推理或托管部署 | ember init --server-url URL |
任何内容都不会发送到你未配置的服务器。如果没有终端可供询问(例如脚本或 CI),ember init 会配置本地推理;使用 --local 或 --server-url 可直接回答该问题。
工作原理
决策模型不是聊天模型:它接收一个 state 和一组带类型的问题模式,并为每个选项返回一个概率,不会生成文本。因此,ember 作为一个工具接入 Agent,而它们的推理仍由常用的大模型完成:
- 模型服务(
ember/serving/server.py)加载一次模型,并在多个 Agent 会话期间保持热运行。 - MCP 服务(
ember/mcp/mcp_server.py)不会加载模型;它会在首次调用工具时启动模型服务,因此 MCP 握手能够即时完成。
名称
| 项目 | 名称 |
|---|---|
| 产品、Python 导入名、仓库 | ember |
发行包(uv tool install、PyPI) | ember-advise,因为 PyPI 上的 ember 已被占用,而 gut 被一个空项目占用 |
| CLI | ember(短别名:gut;也支持 ember-advise,因此 uvx ember-advise mcp 可用) |
| MCP 服务 / 命令 | ember / ember-mcp |
| 工具 | advise — opencode:ember_advise;Claude Code:mcp__ember__advise(插件:mcp__plugin_ember_ember__advise);Kilo Code:ember_advise |
| Playbook skill / MCP 资源 | ember-advise / ember://guide |
| 环境变量 | EMBER_* |
“Clef”始终指 Cloudflare 的上游模型,而不是本产品。使用 ember model pull <name> / EMBER_MODEL=<name> 选择模型;运行 ember model list 查看所有已注册条目(flash、full)。
托管部署(例如 Outerbounds)如果在启动时直接提供模型的 S3 位置,则完全不会使用此注册表——请参阅下文“托管部署:启动时提供模型位置”。
已验证
已测试的版本和硬件见 COMPATIBILITY.md。最新一次有记录的基准测试运行所测得的当前准确率和延迟,见基准测试报告。
安装(Apple Silicon)
要求
若要使用由他人运行的服务,只需要 Python 3.12(由 uv 管理)和服务地址;请跳过 ember model pull。若要自行运行模型:
- Apple Silicon Mac(M 系列),使用 macOS 进行本地运行(MPS)。Intel Mac 暂不支持。有关在 NVIDIA/CUDA 计算环境(例如 Outerbounds)上的托管部署,请参阅下文“托管部署”和
deployment/README.md。 - 统一内存需大于模型大小:
flash(9B)需要 32 GB 或更多,full(27B)需要 96 GB 或更多。目前仅验证过 128 GB。 - 磁盘空间:
flash约需 18 GiB,full约需 55 GiB,位于 Hugging Face 的共享缓存中(~/.cache/huggingface)。配置、状态和日志保存在~/Library/Application Support/ember。 - Python 3.12,由 uv 管理。
uv tool install --python 3.12 ember-advise
ember model pull # ~18 GB, resumable, disk-space checked
ember doctor # platform, dependencies, model, server, and agent registration
ember init --opencode --global # register with opencode for every repo on this machine
请保留 --python 3.12:否则 uv 会选择你最新的解释器,而固定版本的 torch/transformers 技术栈尚未在该解释器上测试。
此操作会从 PyPI 安装最新发布的 wheel。
若要改为固定安装 GitHub 上的某个特定发布标签(无需 PyPI):
uv tool install --python 3.12 "ember-advise @ git+https://github.com/shapeandshare/[email protected]"
该仓库是公开的,因此通过 git 安装无需凭据。若要改用 SSH,请从 git+ssh://[email protected]/shapeandshare/[email protected] 安装。
如果你使用 conda、mamba 或 pixi 管理 Python,可从 Anaconda.org 上的临时 joshburt channel 安装同一工具(待该 feedstock 发布后会迁至 conda-forge):
conda install -c joshburt -c conda-forge ember-advise # mamba and pixi take the same flags
如果你在重命名前以 gut 的名称安装过 ember?请先运行 uv tool uninstall gut:这两个发行包提供相同的命令。
重启 opencode 后,这台机器上的每个仓库都会获得 ember_advise。模型服务保持惰性启动——在首次调用工具时启动(或使用 ember start 启动)。
每个项目的 skill 和策略(在你希望让 Agent 了解 ember 的每个仓库中运行一次):
cd /path/to/your/repo
ember agents install --agent opencode # installs the ember-advise playbook skill
ember agents show snippet >> AGENTS.md # then edit the project policy block at the end
skill 会教 Agent 何时咨询 ember 以及如何提问;AGENTS.md 片段则添加可自定义的项目专属策略(例如“每次推送前检查变更风险”)。有关所有 harness 和选项,请参阅下文的Agent 入门。
flash 指向已在 MPS 上验证的提交(17f0b0a),full 指向其发布提交(2f3de3d,尚未在本地验证),这只是为了方便下载;torch/torchvision 则固定在已测试的小版本系列——但 ember 不会将自身限制在人工维护的、逐个验证过的权重允许列表中;它会运行任何符合其加载器约定的模型(宪章第 V 条,“模型加载”)。设置 EMBER_MODEL_DIR 即可运行另一个权重目录。
云端
ember 以 Apple Silicon 本地运行优先,同时支持 NVIDIA GPU 托管部署
(章程第 VI 条“Apple Silicon 和 CUDA”)——总共支持三种设备:在内存满足上述要求的 Apple Silicon 主机上运行(MPS);在 NVIDIA GPU 主机上运行(EMBER_DEVICE=cuda,
float16——参见“托管部署:在启动时指定模型位置”和
deployment/README.md,了解完整的 Outerbounds 示例);或者在任何主机上使用 CPU 回退模式运行
(EMBER_DEVICE=cpu——float32,内存用量约为两倍,速度慢得多)。HTTP 服务默认绑定到回环地址;若要供其他机器访问,请设置 EMBER_HOST,并设置
EMBER_SERVER_AUTH_TOKEN 以要求提供 Authorization: Bearer <token>(客户端也可以通过
EMBER_AUTH_HEADER 指定其他标头名称,例如 x-api-key)。Ember 不会终止 TLS——请在远程服务部署前置代理。客户端通过 EMBER_SERVER_URL 指向该服务。参见
COMPATIBILITY.md 和 SECURITY.md。
Agent 入门
安装工具只完成了一半;另一半是让 Agent 愿意在恰当时机咨询它,并合理解读它的回答。ember/agent_kit/ 会通过每个 Agent 实际会读取的渠道提供这些指导:
| 渠道 | opencode | Kilo Code | Claude Code | Codex CLI | 获取方式 |
|---|---|---|---|---|---|
| MCP 服务说明(何时咨询、如何提问、如何解读回答) | ✅ 位于系统提示词中 | ✅ 位于系统提示词中 | ✅(上限 2 KB) | — | 内置,无需操作 |
ember://guide 资源(完整手册) | ✅ 通过 read_mcp_resource | ✅ 通过 read_mcp_resource | ✅ | — | 内置 |
ember-advise 技能(按需加载的手册) | ✅ | ✅ | ✅ | ✅ | ember agents install --agent <agent> |
| AGENTS.md / CLAUDE.md 策略块 | ✅ | ✅ | ✅ (CLAUDE.md) | ✅ | ember agents show snippet >> AGENTS.md |
ember init --opencode # opencode: config entry, plugin, and skill
ember init --kilocode # Kilo Code: kilo.json entry and skill
ember init --codex # Codex CLI: .codex/config.toml entry and skill
ember agents install --agent claude # .claude/skills/ember-advise/SKILL.md
ember agents install --agent codex # .agents/skills/... (opencode reads this too)
ember agents show snippet >> AGENTS.md # then edit the project policy at the end
该技能是一份操作手册,而非速查卡:其中包含值得咨询 ember 的决策时机、用于确认意图和就绪状态的复制粘贴式问题集、故障排查、变更风险、路由和工作量,以及根据观测到的模型输出校准的初始置信度阈值(每当固定的模型修订版本变更时都会重新测量)。代码片段以一段项目策略结尾——请编辑它,将 ember 接入你自己的工作流,例如“每次推送前检查变更风险”。
特定 Agent 的注意事项:
-
opencode 会从
.opencode/skills、.claude/skills和.agents/skills读取技能,因此请为每个项目安装一份,以免列表重复。 -
Kilo Code:
ember init --kilocode会将mcp.ember条目写入kilo.json(配置结构与 opencode 相同),并将技能安装到.kilo/skills/ember-advise/SKILL.md;该工具显示为ember_advise。Kilo Code 也会自动读取AGENTS.md。 -
Claude Code:使用
claude mcp add --scope user ember -- ember-mcp注册服务(所有项目均可使用;移除--scope user可仅为当前项目注册);该工具显示为mcp__ember__advise。或者安装 ember 插件,它包含 MCP 条目和ember-advise技能(因此无需执行ember agents install --agent claude):claude plugin marketplace add shapeandshare/ember claude plugin install ember@ember该插件仍会运行你通过
uv tool install安装的ember-mcp,其工具显示为mcp__plugin_ember_ember__advise。请二选一,不要同时使用,否则工具会重复列出。 -
Codex CLI:
ember init --codex会将[mcp_servers.ember]写入.codex/config.toml(--global:~/.codex/config.toml,或$CODEX_HOME/config.toml),并将技能安装到.agents/skills/ember-advise/SKILL.md。Codex 只会为受信任的项目加载项目级.codex/config.toml,而ember init --codex会告知你当前项目是否受信任。该条目会按名称转发EMBER_AUTH_TOKEN(env_vars),绝不会传递其值。MCP 服务说明和资源的支持情况尚未确认,因此请依赖技能和其中的 AGENTS.md 代码片段。
检查已注册的配置
ember doctor 的输出末尾会为每个运行环境列出两行:它在 PATH 中的二进制文件,以及 ember 在何处为其注册——在当前目录和全局范围内的注册位置,或用于注册它的命令。它只读取各运行环境的配置文件,不会运行任何运行环境的 CLI。
| 运行环境 | 注册方式 | 项目范围 | 全局范围 | doctor 还会标记 |
|---|---|---|---|---|
| opencode | ember init --opencode [--global] | opencode.json、.opencode/plugins/ember.js | ~/.config/opencode/opencode.json、~/.config/opencode/plugins/ember.js | 较旧版本的 ember init 遗留的 mcp.vault 条目 |
| Kilo Code | ember init --kilocode [--global] | kilo.json | ~/.config/kilo/kilo.json | — |
| Codex CLI | ember init --codex [--global] | .codex/config.toml | ~/.codex/config.toml | 因项目未受信任而被 Codex 忽略的项目文件 |
| Claude Code | claude mcp add --scope user ember -- ember-mcp,或 ember@ember 插件 | .mcp.json(--scope project);每个项目的 ~/.claude.json(--scope local);.claude/settings.json / settings.local.json 中的 enabledPlugins | ~/.claude.json;.claude/settings.json 中的 enabledPlugins | Claude Code 会要求你批准的项目 .mcp.json |
每个运行环境也有自己的检查命令:opencode mcp list、codex mcp list、claude mcp list。
较旧版本的 ember init 还会将此仓库的 vault MCP 服务添加到它写入的每个配置中;如果你运行过 ember init --global,doctor 会指出全局 opencode 配置中的遗留条目,供你删除。
ember init 会记录它在 PATH 中找到的 ember-mcp,若未找到,则使用运行它的 Python。因此,请从已安装的工具(uv tool install …)运行 ember init --global,而不要从检出目录的 .venv 运行。它会合并现有配置;如果某个配置无法解析(例如含注释的 opencode.json),则拒绝重写并保持文件不变。
CLI
gut 是以下所有命令的简短别名。
# lifecycle
ember doctor # platform, dependencies, model, server, agent registration
ember serve # run the model server in the foreground
ember start | stop | restart | status | logs
ember config path | show
ember uninstall [--purge-models] # also removes global opencode/Kilo Code/Codex and skill installs
# models
ember model pull [flash|full] # flash = 9B (default)
ember model list | path [name] | rm [name]
# opencode, Kilo Code, Codex CLI, and agents
ember init [--opencode] [--kilocode] [--codex] [--global] [--local | --server-url URL] [--auth-header NAME]
ember agents install [--agent opencode|claude|codex|kilocode] [--global]
ember agents show instructions|skill|snippet
ember mcp # the MCP stdio server agents launch
用法
用自然语言向 Agent 提问——“这份 Bug 报告紧急吗?应该由哪个团队负责?”——它会调用 ember_advise,并传入状态和类型化问题:
{
"model": "clef-flash",
"answers": {
"urgent": { "type": "noul", "noul": 0.967 },
"team": {
"type": "choice",
"choice": "db",
"confidence": 0.9782,
"probabilities": { "db": 0.9782, "frontend": 0.0218 }
}
},
"usage": {
"input_tokens": 220, "output_tokens": 0,
"state_tokens": 34, "fixed_tokens": 186, "media_tokens": 0
},
"latency_ms": 930.9
}
问题类型:noul(是/否 → P(true))、choice(命名选项)、score(有序选项 → 预期得分及图例)。model 字段会回显上游模型标签。usage 会将 input_tokens 拆分为状态、固定开销(问题、架构、提示词包装器)和媒体,这样调用方就能了解请求各部分的成本;基准测试工具要求提供此拆分。
证据为视觉内容时,可内联附加图片或视频帧:images 是 data:image/png;base64,... URI 列表(或 {"content_type": "image/png", "base64": "..."} 对象列表),videos 是视频列表,每个视频均为帧引用列表。远程 URL 和本地路径都会被拒绝——模型服务端不会读取主机文件,也不会代表 Agent 获取 URL。
配置
设置的解析优先级为 CLI 标志 > 环境变量 > 配置文件 > 默认值。配置文件是位于 ember config path 的 JSON 文件(键为 model、host、port、device、max_length、server_url、auth_token、auth_header、allow_insecure_transport、request_timeout、server_auth_token、max_request_length;max_length 为 0 表示使用模型自身的最大值;未设置 max_request_length 表示使用已加载模型自身的默认上限)。
| 变量 | 默认值 | 用途 |
|---|---|---|
EMBER_HOST / EMBER_PORT | 127.0.0.1 / 8765 | 本地模型服务绑定地址 |
EMBER_DEVICE | auto | auto、mps、cuda 或 cpu |
EMBER_TORCH_DISABLE_NATIVE_JIT | 1 | 禁用 torch 2.14 中由 Triton 支持的 torch._native 算子覆盖(例如 Qwen3.5 的 RoPE 前向计算在 CUDA 上会触发的 aten::bmm 外积特化)。这些覆盖会通过 C 编译器进行 JIT 编译,而精简的 CUDA 容器(例如 Outerbounds 的 Fast Bakery)通常没有该编译器;如果不禁用,首次实际 CUDA 请求会失败,并报错 RuntimeError: Failed to find C compiler。在具备可用编译器工具链的主机上设为 0,即可重新启用(可能更快的)Triton 路径;对 MPS/CPU 无影响 |
EMBER_MODEL | flash | flash(9B,默认)或 full(27B),两者均来自 Cloudflare 的公开 Hugging Face 仓库 |
EMBER_MODEL_DIR | — | 从此目录运行权重,而非使用固定缓存 |
EMBER_MAX_LENGTH | 0(模型最大值:262,144) | 模型处理的最大 token 数;0 会根据模型的 config.json 确定此值,超过该值的设置会被限制为此最大值 |
EMBER_MAX_REQUEST_LENGTH | 未设置:已加载模型自身的默认值、其测得的上限,或在尚未测量前使用的回退值,即为其内存预算保留 4 GiB 后所允许的最长长度(flash 为 24,576,full 为 65,536)。不在注册表中的模型(EMBER_MODEL_DIR、EMBER_MODEL_S3_URI)使用注册表中最低的上限,目前为 24,576 | 单个请求的完整编码内容(状态、媒体、问题、架构、提示词包装)的上限,在推理前检查。超过上限的请求会被拒绝,并返回说明 token 划分情况的 413 错误;请求绝不会被截断。0 表示禁用此上限;最大值限制仍然适用 |
EMBER_SERVER_URL | http://127.0.0.1:8765 | 客户端发送请求的推理端点;默认为环回地址,也可以是远程地址 |
EMBER_AUTH_TOKEN | — | 远程端点的客户端凭据 |
EMBER_AUTH_HEADER | Authorization | 携带凭据的标头;Authorization 会发送 Bearer <token>,其他名称则会原样发送 token |
EMBER_ALLOW_INSECURE_TRANSPORT | 0 | 允许通过明文 http 访问非环回端点(默认关闭) |
EMBER_REQUEST_TIMEOUT | 900 | MCP 客户端等待每个 advise 请求的秒数,无论是本地还是远程。接近 full 上限的请求在 M4 Max 上需要约 12 分钟,且请求会逐个运行,因此多个耗时较长的 full 请求重叠时应增大此值 |
EMBER_SERVER_AUTH_TOKEN | — | 设置后,服务端会要求访问 /v1/systemone 时提供 Authorization: Bearer <token> |
EMBER_AUTOSTART | 1 | 允许 MCP 服务按需启动本地服务(仅限环回地址) |
EMBER_START_TIMEOUT | 300 | 等待模型服务启动的秒数 |
EMBER_STATE_DIR | Application Support | pid 文件和日志的存放位置 |
EMBER_MODEL_S3_URI | — | 指定要加载的确切模型位置的 s3://bucket/prefix URI,适用于在启动时提供模型 S3 位置、而非提供 REGISTRY 键的部署(例如 Outerbounds)。请参阅下文“托管部署:在启动时提供模型位置”。 |
EMBER_S3_ACCESS_KEY_ID / EMBER_S3_SECRET_ACCESS_KEY | — | EMBER_MODEL_S3_URI 使用的 AWS 凭据。可选 — 未设置时,将使用 boto3 自带的默认凭据链(附加到计算资源的 IAM 角色,例如 Outerbounds;环境变量;~/.aws/credentials)。仅在未附加角色时才显式设置(例如本地开发人员的计算机) |
EMBER_S3_REGION | — | 传递给 S3 客户端的 AWS 区域 |
ember doctor 和 GET /health(engine)会报告当前生效的限制及其来源:模型、回退值、运维人员设置或测得的默认值。
托管部署:在启动时指定模型位置
某些部署(例如 Outerbounds 应用)会在启动时直接提供模型的 S3
位置,而不是选择 REGISTRY 条目。设置:
export EMBER_MODEL_S3_URI=s3://my-bucket/clef-flash
export EMBER_DEVICE=cuda # Outerbounds compute is Linux — no MPS; cuda is the GPU path
ember serve # foreground, container-friendly (not `ember start`)
如果计算环境已附加 IAM 角色(这是 Outerbounds 上的预期情况),则无需显式设置 AWS 凭据——boto3 的默认凭据链会自动获取该角色。仅在未附加角色时,才显式设置
EMBER_S3_ACCESS_KEY_ID/_SECRET_ACCESS_KEY。
此设置会在启动时、服务开始运行前检查一次,并完全优先于
EMBER_MODEL/model 配置键——此路径不会查找 REGISTRY。
ember 支持任何能够按照其加载器约定运行的模型(章程第 V 条,
“模型加载”);它并非一个经过人工维护、逐个验证哈希的权重许可列表,因此,对于通过 URI 指定的位置,会直接加载,不会检查固定版本或哈希值。
完整的 Outerbounds 部署示例——flash.yaml/full.yaml(每个模型一个,因为它们需要不同的计算资源)、生成的
requirements.txt,以及 make deployment-requirements 目标——位于 deployment/。
远程推理
运行一个服务并共享给团队、CI,或内存不足以运行模型的另一台 Mac。在主机上启动服务,然后让每个客户端连接到它。
在主机上(装有模型的机器)
# Bind to all interfaces so other machines can reach it
EMBER_HOST=0.0.0.0 ember start
# Recommended: also require a bearer token so only your client can use it
EMBER_HOST=0.0.0.0 EMBER_SERVER_AUTH_TOKEN=your-secret ember start
Ember 不会终止 TLS。在可信的局域网上,使用普通 HTTP 即可(见下方客户端说明)。在互联网上,请在前面设置 TLS 代理(nginx、Caddy),并使用 https://。
在客户端上(运行 Agent 的机器)
export EMBER_SERVER_URL="http://<host-ip>:8765" # use https:// if behind a TLS proxy
export EMBER_AUTH_TOKEN="your-secret" # matches EMBER_SERVER_AUTH_TOKEN on the host
export EMBER_AUTOSTART=0 # nothing local to start
ember status # reports remote endpoint + reachability
默认情况下,发往非回环主机的普通 http 请求会被拒绝;在可信的局域网上,可设置
EMBER_ALLOW_INSECURE_TRANSPORT=1 以允许此类请求。凭据也可以作为自定义请求头发送(EMBER_AUTH_HEADER=X-API-KEY)。ember status / ember doctor
会报告端点类型、可访问性、远程端点公布的 auth_required,以及是否已配置凭据;只需一次更改(取消设置这些变量)即可切回本地模式。
针对托管端点配置客户端
ember init 可以直接为远程端点生成 mcp.ember 条目,无需手动编辑生成的 opencode.json / kilo.json / .codex/config.toml:
ember init --opencode --kilocode \
--server-url https://decisions.example.com \
--auth-header X-API-KEY # omit for the default Authorization: Bearer header
在未使用 --server-url 的情况下于终端运行 ember init,它会提示输入地址。Claude Code 使用自己的 CLI 注册,因此在那里传入相同的设置:
claude mcp add --scope user ember -e EMBER_SERVER_URL=https://ember.example.com -e EMBER_AUTOSTART=0 -- ember-mcp
这会将 EMBER_SERVER_URL(以及如有提供的 EMBER_AUTH_HEADER)写入配置文件,并强制设置 EMBER_AUTOSTART=0——这里没有本地服务需要自动启动。凭据本身绝不会写入文件:应在启动 Agent 的 shell(或 GUI 应用的环境)中导出 EMBER_AUTH_TOKEN,以免密钥落入可能被提交到项目中的配置文件。未指定 --server-url 时,ember init 会在终端中提示输入;若没有可供询问的终端(或使用了 --local),则会写入本地回环条目。之后重启运行环境,以加载新的 MCP 注册信息。
这只会更新生成的运行环境配置——如果不同时在 shell 中导出相同的
EMBER_SERVER_URL/EMBER_AUTH_HEADER/EMBER_AUTH_TOKEN,或将
server_url/auth_header(绝不要保存令牌)写入 ember 自身的配置文件
(ember config path),那么直接从 shell 运行的 ember status/ember doctor 仍会检查本地默认设置。具体步骤及正常响应示例,请参阅 deployment/README.md 中的“从 shell 验证”。
通过 Tailscale 部署在 AWS 上
make aws-up 会将 ember 部署到 AWS 上的一台 NVIDIA GPU 实例,并且只允许通过你的 Tailscale 网络访问,不开放任何公共端口。该实例运行 ember serve,并设置 EMBER_DEVICE=cuda,从私有 S3 模型缓存加载权重。客户端通过节点的 MagicDNS 名称(https://ember-<name>.<tailnet>.ts.net)使用 HTTPS 连接;绝不会需要 EMBER_ALLOW_INSECURE_TRANSPORT。
make aws-tools # install the tailscale CLI (macOS: brew; Linux: prints URL)
make aws-cache MODEL=flash # upload the pinned model to S3 once per region (~18 GiB)
make aws-up # deploy; prints the URL and the ember init line
export EMBER_AUTH_TOKEN="$(make -s aws-token)"
ember init --opencode --server-url https://ember-default.<tailnet>.ts.net
ember 提供建议;由 Agent 做决定——此部署只改变模型的运行位置,不改变 Agent 调用模型的方式。有关先决条件(AWS 配额、Tailscale OAuth 客户端、MagicDNS、HTTPS 证书)、费用、所有生命周期命令和拆除步骤,请参阅 deployment/aws/README.md。
指标
模型服务运行时,会在 http://127.0.0.1:8765/metrics(EMBER_HOST/EMBER_PORT 地址)公开 Prometheus 指标:
| 指标 | 类型 | 含义 |
|---|---|---|
ember_advise_requests_total{status} | 计数器 | 按 HTTP 状态码统计的 advise 请求(200、413、422、503、500) |
ember_advise_latency_seconds | 直方图 | 按状态码统计的 advise 请求延迟 |
ember_advise_input_tokens_total | 计数器 | 已处理的输入 token 数 |
ember_advise_output_tokens_total | 计数器 | 已生成的输出 token 数 |
ember_model_info{model,device,dtype} | 计量器 | 模型已加载时为 1 |
该端点与 API 的其余部分绑定到同一地址(默认仅限本机回环),因此只能从该地址访问,除非你更改 EMBER_HOST。Ember 的指标使用专用的 Prometheus 注册表,因此不包含标准的 python_*/process_* 收集器——/metrics 只显示上表中的指标。
开发
ember/
cli.py # the `ember` command (alias `gut`): argparse wiring + main()
commands/ # subcommand handlers: lifecycle, doctor, models, agents, eval, config
models.py # pinned model registry + pull/list/rm
serving/ # HTTP model server, MPS runtime, lifecycle, media
server.py # FastAPI: POST /v1/systemone, GET /health (reports pid)
runtime.py # MPS-safe loader (CPU load → .to("mps")) + Engine
process.py # model-server lifecycle (pid file + HTTP health)
media.py # base64 data-URI / {content_type,base64} → PIL decoder
mcp/ # MCP stdio server and wire types
mcp_server.py # MCP stdio server: advise tool, instructions, ember://guide
mcp_types.py # Pydantic wire types (Question, AdviseInput)
cfg/ # configuration, endpoint, and platform paths
config.py # config resolution (CLI flag > env > file > default)
endpoint.py # client endpoint: loopback check, transport guard, auth headers
paths.py # platform-aware app dirs (macOS Library, XDG)
repo_root.py # checkout / main-worktree root from .git on disk
opencode/ # opencode integration
opencode_config.py # generates opencode.json
opencode_plugin.py # installs the npm plugin
kilocode/ # Kilo Code integration: generates kilo.json
codex/ # Codex CLI integration: .codex/config.toml entry, project trust
claude/ # Claude Code registration detection (read-only)
agent_kit/ # what agents read: instructions, ember-advise skill, AGENTS snippet
api.py # public API: instructions(), skill(), snippet(), install_skill()
packages/opencode-plugin/ # opencode plugin source (unpublished; `ember init --opencode` writes the installed copy)
packages/claude-plugin/ # Claude Code plugin (MCP entry + mirrored ember-advise skill), listed by .claude-plugin/marketplace.json
server.json # MCP Registry entry (io.github.shapeandshare/ember), published by release-ember.yml
scripts/ # make-only dev tools: MPS smoke, MCP e2e, site build, provenance/vault audits
evals/eval/ # benchmark harness: run, report, export, snapshot, agent-in-the-loop
tests/ # pytest suite (unit + model-backed, host-isolated)
vault/ # project memory (Obsidian): decisions, discoveries, session logs
.specify/ # spec-kit; memory/constitution.md governs this repo
AGENTS.md CLAUDE.md # guidelines for agents working on this repo
Makefile # contributor lifecycle (wraps the CLI)
make bootstrap # deps + pinned weights + opencode.json + doctor (idempotent)
make start # model server in the background; stop | restart | status | logs
make opencode # this checkout's opencode plugin and skill
opencode.json、.opencode/plugins/ember.js 和 .opencode/skills/ember-advise/(与 kilo.json、.codex/config.toml 以及其他工具环境中的 ember-advise 技能副本一样)包含此克隆的绝对路径或打包文件副本,因此会被 git 忽略——克隆后使用 make init / make opencode 重新生成。.opencode/opencode.json 是共享文件并已提交:它注册了 Agent 用于读写 vault/ 的 vault MCP 服务(从仓库根目录启动 opencode)。
Make 目标
| 目标 | 功能 |
|---|---|
make help | 列出所有目标(默认) |
make bootstrap | 从全新克隆的仓库开始:setup + download + init + doctor |
make setup / sync / download | 仅安装依赖 / 仅安装依赖(别名)/ 将固定版本的权重下载到 .models/ |
make init / make opencode | 为此检出版本运行 ember init / ember init --opencode |
make serve / start / stop / restart / status / logs | 通过 CLI 管理模型服务的生命周期 |
make mcp / make mcp-list | 运行 MCP 服务 / opencode mcp list |
make test / test-fast / test-strict | 完整测试套件 / 仅单元测试 / 缺少权重时会失败的完整测试套件 |
make test-evals | 校准评估套件:正向与负向配方用例(会加载模型) |
make eval-run | 使用运行中的服务运行基准测试数据集;将结果写入 results/ |
make eval-snapshot | 将最新运行结果复制到 benchmark/,供网站呈现 |
make eval-context | 长上下文探测:测量 MPS 上每个模型的请求上限(数小时) |
make eval-context-smoke | 长上下文探测冒烟测试:flash、2K 和 4K,3 个项目(数分钟) |
make eval-report | 将最近一次运行结果呈现为 Markdown 表格 |
make dataset-lint / dataset-card | 检查基准测试数据集(报告模式;强制执行 no-live-secret)/ 重新生成 evals/dataset/card.json + CARD.md |
make audit-sources | 在线重新检查数据源登记表中的每一行(发布数据集前) |
make mcp-check / make smoke | MCP 端到端检查 / 直接执行 MPS 推理 |
make compile / make check | 编译字节码 / 编译并运行单元测试 |
make ci | bootstrap + check + test-strict |
make doctor | ember doctor |
make vault-audit | 检查 vault/ 笔记:frontmatter、标签、wikilinks、code-refs、孤立项 |
make site / make site-serve | 将 Pages 网站构建到 site/_site / 在 :4000 预览;每次编辑后都会重新构建并在浏览器中重新加载(需要 Docker) |
make aws-tools / aws-tools-rm | 安装 / 移除 tailscale CLI(macOS:brew;Linux:打印 URL) |
make aws-preflight | 创建任何资源前,检查 AWS 身份、配额、Tailscale OAuth 和 MagicDNS |
make aws-cache | 创建 S3 模型缓存堆栈(如果不存在),并上传固定版本的模型 |
make aws-cache-list / aws-cache-rm | 列出缓存的模型 / 移除一个缓存的版本 |
make aws-cache-destroy | 删除缓存存储桶(需要 CONFIRM=<bucket>;存在部署时会拒绝操作) |
make aws-up | 部署(或更新)ember GPU 实例并等待健康检查通过 |
make aws-status | 显示部署状态、实例、tailnet URL、健康状态和成本估算 |
make aws-stop / aws-start | 停止 / 启动 EC2 实例 |
make aws-replace | 使用最新的 DLAMI 替换实例并等待健康检查通过 |
make aws-logs | 通过 Tailscale SSH 流式传输实例日志(UNIT=ember|converge|idle|tailscale) |
make aws-ssh | 在实例上打开 Tailscale SSH shell |
make aws-token | 打印服务身份验证令牌 |
make aws-rotate-token | 生成新的服务令牌并重启实例 |
make aws-down | 销毁部署(需要 CONFIRM=<name>;保留 S3 缓存) |
make aws-verify | 通过 Tailscale SSH 运行 CUDA 验证门禁,并在此处运行基准测试 |
make release-dry | 预览下一次 ember 版本升级,不做任何更改 |
make release-ember | 在 main 上触发发布工作流(升级 PR → GitHub Release → PyPI) |
make clean / make clean-model | 清理缓存和构建产物 / 权重(设置 EMBER_FORCE=1 可跳过提示) |
pyproject.toml 或 uv.lock 发生变化时,Make 会自动重新同步环境。
测试
make test # full suite (~30 s, loads the model once)
make test-fast # unit tests only, no model load (~12 s)
make check # compile + test-fast
make test-strict # full suite; fails (not skips) if weights are missing
make ci # bootstrap + check + test-strict
tests/ 覆盖受支持的调用路径:
- 对
noul/choice/score执行GET /health和POST /v1/systemone,验证概率归一化和请求验证422错误 - MCP 工具发现、通过 stdio 调用
advise、可操作的错误(服务已关闭、缺少模型、问题格式错误),以及在已配置端口上自动启动并清理 pid - Agent 套件:指令长度、技能 frontmatter、
ember://guide资源 - CLI:
agents、init --opencode、在未使用的端口上执行status/stop、doctor、uninstall - 进程安全:
stop绝不会向并非由它启动的 ember 服务 pid 发送信号
可在运行其他 opencode 实例的主机上安全执行。 测试套件使用随机可用端口(绝不使用
8765),将状态保存在临时目录中,只停止它启动的进程,绝不调用 opencode CLI 或触碰全局 opencode 配置。
CI(.github/workflows/ci.yml)运行 uv sync --locked,随后将以下任务作为独立作业运行:格式检查和 lint、mypy --strict、bandit、make check、uv build,以及在托管 Apple Silicon 运行器上对构建出的 wheel 进行安装冒烟测试、SonarCloud 扫描(需要仓库密钥 SONAR_TOKEN),以及对工作流进行 zizmor 审计。CI 不会运行依赖模型的测试:约 19 GB 的 fp16 模型无法装入可用的运行器(托管运行器或组织的 8 GiB 自托管 VM),因此对模型有影响的更改请在本地运行 make test。
覆盖率会被跟踪并设为门槛(章程第 XI 条)。运行 make test-cov 查看完整报告。强制下限(pyproject.toml 中的 fail_under)为当前测得的水平,且只能提高——目前为 94 %。降低门槛须根据第 XI 条第 11.2 节获得明确且有记录的批准。
基准测试
evals/clef-flash.jsonl 是基准数据集。它涵盖五种 Agent 套件配方(意图与就绪度、故障分类、变更风险、路由、工作量与方法)、从维护者的资料库中挖掘出的两种配方(tag_assignment、note_placement),以及四种视觉配方(vision_noul、vision_choice、vision_score、vision_video);每个条目都属于 dev 或 test 划分;基准测试报告列出了当前的条目数和问题数。视觉条目在 state 和 questions 旁还包含 images 或 videos 字段(base64 data: URI)。每一行都是独立完整的(包含 state、配方固定的问题集、每个问题的黄金标签、rationale 和结构化的 source),因此其他实现无需使用此测试框架也能为其评分。
每个条目都会注明来源:source.kind 的取值为 authored(为基准测试编写)、mined(公开记录,由其登记表条目命名)、captured(经同意记录的真实会话)、perturbed(对 parent_id 的受控变体)、templated、drafted(由模型起草后经审核),或 imported(依据其许可证使用的外部数据集)。公开来源会在数据源登记表中跟踪(evals/dataset/register.json:许可证审阅、快照、镜像、判定);发布数据集前,make audit-sources 会在线重新检查每一项,只有登记表条目许可导入时才会导入数据。
make eval-run # or: ember eval run [--split dev|test] [--category <recipe>] [--resume]
make eval-report # Markdown report of the most recent run
make eval-export # or: ember eval export; the reviewer bundle described below
make eval-snapshot # or: ember eval snapshot [--rebuild]; copy a run into benchmark/
make dataset-lint # or: ember eval dataset lint [--dataset PATH]
make dataset-card # or: ember eval dataset card [--check]; the data card
ember eval dataset hash # content, file, per-recipe, and register hashes
ember eval dataset check # provenance check: every item's source and register row
ember eval report --compare results/<a>_results.json results/<b>_results.json
该数据集有两个哈希。内容哈希涵盖评分内容(id、category、split、state、media、questions、gold labels),也是数据集的版本标识:条目类型、难度级别、来源或理由等注释不会改变它,而金标、状态、问题或 split 的变更会改变它。文件哈希则涵盖文件字节,用于溯源。每次运行都会记录这两个哈希,以及每个配方的哈希;排行榜按内容哈希分别显示一个表格,并按最新版本优先排列;不同版本的结果绝不进行比较。在每个表格中,每个模型、部署和引擎设置对应一行,每个配方对应一列:重新运行单个配方(--category)只会更新相应列;只有在该版本上为每个决策配方都完成评分后,才会显示总体结果。视觉配方单独显示在能力面板中,绝不纳入总体结果。splits.lock 永久固定每个条目的 split,versions.lock 记录已发布的每个数据集版本(并标明每条协议规则和量表名称首次适用的版本),每个版本的变更日志都包含一行 Benchmark dataset: <content hash>,注明其测评所用的版本。
基准测试计划的第 1 阶段将完善数据规范。risk 和 effort 配方在每个级别都附有评分标准锚点,并通过盲法重新标注轮次发布标签稳定性测量结果——由单个评审员完成,报告会明确说明这一点。同一数据集会分别在 MPS 上以 float16 运行,以及在 CUDA 部署上运行,作为一组受控比较,并以一对 bundle 的形式提交,同时设置构建门禁。每个条目都附有类型和难度级别(这些注释不会改变数据集版本),报告还会单独列出非简单样本的准确率。每个排行榜条目都会记录其长上下文特征——请求上限、首次丢失长度、最差深度——若尚无探测运行结果,则标注为“未测量”。真实 Agent 会话可通过 ember eval capture import 成为候选条目;该命令会拒绝任何没有脱敏记录或仍含有密钥的会话;绝不会使用模型来标注。
只要数据集版本、配方、模型和设置与清单一致,运行中断后即可恢复(ember eval run --resume);ember eval snapshot --rebuild 则会在报告代码变更后,利用已存储的跟踪记录重新生成现有 bundle,无需重新运行模型。测试框架需要一个会在 usage 中报告令牌拆分的服务(ember 0.12.0 或更高版本),并按条目记录拆分结果。
ember eval export 会生成 results/<run_id>_report/,供外部评审人员使用:
report.html(单个独立文件,包含内嵌图表、浅色和深色主题、打印布局以及条目筛选器;不会从网络加载任何内容)、带有 figures/*.svg 的 report.md,以及包含本次运行的结果、跟踪记录和实际评分所用数据集的 data/。报告涵盖上下文、被测系统、基准测试设计、附有参考资料的指标定义、结果、校准情况、Agent 工具包的决策规则在每个条目上的重放结果、每个错误项的评审卡片、局限性和复现所需的固定信息。
报告会给出准确率及其 95% bootstrap 区间、宏平均 F1、顶级标签 ECE 和 Brier 分数(choice、noul);排序概率分数和 MAE(score);Agent 工具包在“采取行动”阈值下的覆盖率和准确率;风险配方的危险选项召回率;按来源类型和条目难度级别划分的准确率;同一父项不同扰动变体之间的一致性;以及每个请求的令牌拆分(state、fixed、media)。每次运行都会记录 git 哈希、引擎及其设置,以及数据集的哈希;若 --compare 比较的两次运行评分所用的条目集不同,则会发出警告。
金标准标签仅根据 state 与配方的选项描述进行判定,并在任何运行开始前固定:当且仅当 risk 为 Medium 或 High 时,needs_review 才为 true;只有 flaky 故障才会设置 retry。由人工审核分歧;绝不会为了匹配模型而更改标签。make check 会验证数据集(tests/test_eval_benchmark.py),数据集 lint 会报告相对于每个配方设计的缺陷(选项平衡、拆分之间的数据泄漏、近似重复项);其唯一强制规则 no-live-secret 会拦截任何看起来像真实凭据的内容。ember eval 会读取检出版本中的 evals/ 和 scripts/,因此只能在克隆仓库中运行。
长上下文探测
make eval-context(或 ember eval context)会测量每个已注册模型在请求不断增长时的表现:它会用公有领域的填充文本,将每个纯文本基准测试项扩展到 2K–64K 个 token,并将证据放在开头、中间或末尾,然后记录准确率、校准情况、MPS 峰值内存和延迟。随后,一条预先声明的规则会为每个模型选定默认上限:在所有深度下,准确率与 2K 结果的差距不超过 2 个百分点、Brier 分数与 2K 结果的差距不超过 0.02,且峰值内存不超过 32 GB(flash)或 96 GB(full)时所能达到的最长长度。该流程会在 MPS 上以进程内方式运行数小时,不会触碰正在运行的服务,并将结果写入 results/context/<run_id>/;决策所引用的运行结果会通过 --snapshot 复制到 evals/context/runs/。--rescore 会逐字节重建摘要,--reproduce 会使用某次运行中固定的输入重新运行并进行比较。
Agent 参与评测
上述基准测试评估的是模型。ember eval agent 会按 ember 的实际使用方式评估 ember:通过编码 Agent。它会向 opencode 提供 54 条脚本化请求(含糊和明确的要求、未通过的测试、有风险和简单的提交、路由与投入程度问题,以及对照项),每条请求都在一次性 git 仓库中运行,并且只根据 Agent 的实际操作(文件、提交、测试及其回复)进行评判。每个场景都会在四种条件下运行:none(不使用 ember)、mcp(使用 MCP 服务及其说明)、skill(再加上 ember-advise 技能)和 full(再加上 AGENTS.md 策略)。
ember start # the agent sessions call the warm server
make eval-agent-smoke # 6 scenarios x 4 conditions x 2 models, 1 trial
make eval-agent # or: ember eval agent [--models ...] [--trials 3] [--parallel 8]
ember eval export --agent latest # put the agent results first in the reviewer report
每个会话都会通过 opencode run --pure 运行,并使用私有的 HOME 和 XDG 目录,且不开放 TCP 端口,因此不会影响你的 opencode 配置、插件、会话和运行中的实例。提供方密钥从环境变量或 opencode 的身份验证文件中读取,并且只传递给子进程。运行报告会按模型和条件列出:金标准操作准确率、相较于 none 的配对变化、Agent 在决策节点(以及对照项)咨询 ember 的频率、是否在采取行动前咨询、是否询问工具包中的配方问题、是否提供证据、是否遵循 ember 的回答,以及每个会话的费用和耗时。该流程会消耗真实的提供方额度,绝不会纳入 make check、make test 或 CI。
注意事项
- Gated DeltaNet 回退。 Qwen3.5 的骨干网络采用混合线性注意力模型。Apple Silicon 不支持优化的 CUDA 内核(
causal_conv1d、flash-linear-attention),因此会使用纯 PyTorch 参考路径:结果正确,但速度较慢。你会看到两行“正在回退”日志,这是预期现象。 - MPS 上的 fp16。
bfloat16可以运行,但在 MPS 上是模拟实现,且经过的实战验证较少,因此加载器使用float16;CPU 模式使用float32。 - 视觉功能可在 MPS 上运行。 图片和视频帧会像文本一样通过相同的 fp16 路径处理。请将它们以内联的 base64
data:URI 放入images/videos;远程 URL 和本地路径会被刻意拒绝,以免 Agent 让服务读取主机文件或获取 URL。纯文本输入会完全跳过视觉塔。 - 数值差异。 MPS 的结果可能与 CUDA/CPU 略有不同。如果校准概率很重要,请通过
EMBER_DEVICE=cpu ember restart交叉核对。 - 使用固定依赖栈时,
device_map={"": "mps"}会导致段错误。 加载器会先在 CPU 上加载模型,然后再将其移到 MPS 上——不要“简化”掉这一步。
故障排除
- 先运行
ember doctor,然后运行ember logs(~/Library/Application Support/ember/logs/server.log)。 - Agent 看不到工具:
ember doctor会显示 ember 在各个运行环境中的注册位置(并标记不受信任的 Codex 项目,或等待批准的 Claude Code.mcp.json);opencode mcp list应显示✓ ember connected。 - “model … is not pulled”:运行
ember model pull,或将EMBER_MODEL_DIR指向权重文件。 Qwen3VLVideoProcessor requires Torchvision→ torchvision 是固定版本依赖;运行uv sync(或重新安装该工具)。- 任何单个未实现的 MPS 操作都会回退到 CPU(由运行时设置
PYTORCH_ENABLE_MPS_FALLBACK=1)。
许可证
MIT(见 LICENSE)。Cloudflare 的 Clef 权重和 joint_schema_model.py 使用 Apache-2.0 许可证;它们会在运行时从 Hugging Face 下载,不会在此重新分发。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。