
exo 贡献指南源码构建、Model Card TOML 规范与 API 适配器开发【免费下载链接】exoRun frontier AI locally.项目地址: https://gitcode.com/GitHub_Trending/exo8/exo本文为 exoRun frontier AI locally跨 Mac/Apple Silicon 集群运行前沿大模型的开源项目的贡献者技术指南。文章基于仓库的CONTRIBUTING.md编写并结合当前源码补全了文档中未展开的细节如何从零克隆并跑起源码版 exo含 Rust 绑定与 Svelte 仪表盘构建、TOML 格式的 Model Card 完整字段规范含内置 123 张推理模型卡与 18 张图像模型卡实例、以及 exo 多 API 格式适配器的内部架构与新增适配器的标准步骤。读完你可以独立完成源码环境搭建、为新模型提交模型卡、并为 exo 增加一个新的 OpenAI/Claude 风格 API 端点。一、从源码运行 exo前置依赖与构建流程exo 是一个 Rust Python TypeScriptSvelte混编项目从源码构建需要三类工具链Python 依赖管理工具 uv、Rust 工具链用于编译rust/exo_rs的 Python 绑定目前需要 nightly、以及 Apple Silicon 硬件监控工具 macmon。1.1 前置依赖安装uvPython 依赖管理brew install uvRust 工具链构建rust/exo_rs绑定需要 nightlycurl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh rustup toolchain install nightlymacmonApple Silicon 硬件监控worker 侧用于采集硬件指标cargo install --git https://github.com/vladkens/macmon \ --rev a1cd06b6cc0d5e61db24fd8832e74cd992097a7d \ macmon \ --force注意这里必须使用仓库固定的 fork 修订版--rev a1cd06b6...而不是 Homebrew 的 macmon——仓库 python/utils/info_gatherer 中解析 macmon 输出的逻辑是针对该版本行为对齐的用其他版本可能导致指标解析失败。1.2 克隆与构建git clone https://gitcode.com/GitHub_Trending/exo8/exo.git cd exo/dashboard npm install npm run build cd .. uv run exo构建顺序背后的原因uv run exo启动的服务会内嵌托管仪表盘页面而仪表盘是 SvelteKit 应用位于 dashboard/源码在 dashboard/src/必须先npm run build生成静态产物主进程才能找到它。这一点可以从 Python 侧对仪表盘产物路径的依赖印证——src/exo/utils/dashboard_path.py 专门负责定位 dashboard 构建输出且 src/exo/shared/constants.py 中支持通过EXO_DASHBOARD_DIR环境变量覆盖该路径。另外从 pyproject.toml 可以看到两个适用于当前仓库的重要约束requires-python 3.13.*Python 版本被严格锁在 3.13uv 会自动准备对应解释器[project.scripts]中定义了exo exo.main:main即uv run exo实际调用的是 src/exo/main.py 的main入口。推理引擎侧的 MLX 相关依赖mlx、mlx-lm、mflux、torch 等定义在mlx可选依赖组中并带有 darwin/linux 平台条件Linux 上还细分了mlx-cpu、mlx-cuda12、mlx-cuda13三组互斥 extra见pyproject.toml的[tool.uv.conflicts]非 Apple 平台开发者安装时需按目标硬件选择对应 extra。二、开发规范一次 PR 一件事注释解释为什么CONTRIBUTING 对开发流程提出了三条硬性要求开工前先拉取最新源码保证基于最新代码工作保持改动聚焦——一个 PR 只实现一个功能或修复一个 bug即使看起来很小也不要把不相关的改动混在一起。代码风格方面文档的要求与仓库的工具链配置一一对应尽量写纯函数新增代码优先使用 Rust除非有充分理由项目把 Rust 用于网络层、进程管理等贴近系统的部分见 rust/exo_rs/ 与 rust/networking/充分利用三套类型系统Rust 类型、Python type hints、TypeScript 类型。仓库对 Python 侧执行的是严格模式检查——pyproject.toml中[tool.basedpypyright]配置为typeCheckingMode strict且failOnWarnings truereportAny、reportMissingParameterType等全部提升为 error所以补全类型标注在这个仓库不是可选项注释解释为什么而不是做什么尤其是非显而易见的决策提交前运行nix fmt自动格式化仓库提供 flake.nix 与 justfile 组织开发命令。三、Model CardTOML 模型卡的完整规范这是 exo 贡献工作流中技术含量最高、也最值得深入的部分。exo 用 TOML 格式的Model Card描述每个模型的元数据与能力是调度器做节点放置placement、下载器做分片规划、引擎做并行决策的单一事实来源。3.1 模型卡的存放位置位置用途当前仓库状态resources/inference_model_cards/内置文本生成推理模型卡123 张 TOML 卡resources/image_model_cards/内置图像生成模型卡FLUX.1、Qwen-Image 等18 张 TOML 卡~/.exo/custom_model_cards/用户自定义模型卡运行时生成/添加运行时目录源码中这三处路径分别落在 src/exo/shared/models/model_cards.py 的_BUILTIN_CARD_DIRS内置两个目录与 src/exo/shared/constants.py 的EXO_CUSTOM_MODEL_CARDS_DIR EXO_DATA_HOME / custom_model_cards。加载逻辑是card_cache.refresh()先扫两个内置目录再扫自定义目录同一个model_id先加载者生效缓存以model_id为键做去重。3.2 新增一张模型卡按文档规范新建一个 TOML 文件即可完整示例原样继承自 CONTRIBUTINGmodel_id mlx-community/Llama-3.2-1B-Instruct-4bit n_layers 16 hidden_size 2048 supports_tensor true tasks [TextGeneration] family llama quantization 4bit base_model Llama 3.2 1B capabilities [text] [storage_size] in_bytes 729808896必填字段字段含义model_idHugging Face 模型标识符n_layersTransformer 层数hidden_size隐藏层维度supports_tensor是否支持张量并行TPtasks支持的任务列表TextGeneration、TextToImage、ImageToImage与 model_cards.py 中ModelTask枚举一致family模型家族如llama、deepseek、qwenquantization量化等级如4bit、8bit、bf16base_model人类可读的基座模型名capabilities能力列表见 3.5 节可选字段components多组件模型专用如图像模型有独立的 text encoder 与 transformer见 3.4 节实例uses_cfg是否使用 classifier-free guidance图像模型trust_remote_code是否允许从 HF Hub 执行远程代码安全上默认应当保持关闭。结合当前源码有两点值得补充当前 schema 还要求backends字段。ModelCard中backends: list[Backend]没有默认值内置卡都显式声明了支持的运行后端例如 resources/inference_model_cards/mlx-community--GLM-4.5-Air-8bit.tomlmodel_id mlx-community/GLM-4.5-Air-8bit n_layers 46 hidden_size 4096 num_key_value_heads 8 supports_tensor false tasks [TextGeneration] family glm quantization 8bit base_model GLM 4.5 Air capabilities [text, thinking, thinking_toggle] reasoning_dialect post_last_user context_length 131072 backends [MlxMetal, MlxCuda, MlxCpu] [storage_size] in_bytes 122406567936 # Source: https://docs.z.ai/api-reference/llm/chat-completion [sampling_defaults] temperature 0.6 top_p 0.95注意文件命名约定目录内文件名用--替代model_id中的/如mlx-community--GLM-4.5-Air-8bit.toml。这张卡还演示了文档未展开的两个高级字段reasoning_dialect推理/思维链解析方言用于决定如何剥离模型输出的 thinking 块和[sampling_defaults]该模型的官方推荐采样参数支持thinking/non_thinking两套分组默认值对应SamplingDefaults结构。num_key_value_heads也是可选字段它对 KV Cache 内存估算直接影响多机放置决策添加 MoE/多注意力头模型时建议显式给出。3.3 卡片加载与缺失时的自动抓取ModelCard的加载流程定义在 src/exo/shared/models/model_cards.py先查内存缓存card_cache以model_id为键缓存未命中则刷新全部目录后重查仍缺失时走ModelCard.fetch_from_hf(model_id)从 HF 下载config.json解析出n_layers、hidden_size、num_key_value_heads、max_position_embeddings等ConfigData兼容num_hidden_layers、n_layer、num_decoder_layers等多种别名并支持多模态配置下的text_config转发再从model.safetensors.index.json的metadata.total_size得到存储大小缺失时回退到 HF API 的 safetensors 总大小自动生成的卡片会打上is_customTrue并立即持久化到~/.exo/custom_model_cards/下次启动无需再走网络。其中两个细节值得关注ConfigData.supports_tensor是一个按架构白名单判断的属性——当前源码中仅LlamaForCausalLM、DeepseekV3ForCausalLM、Qwen3MoeForCausalLM、Glm4MoeLiteForCausalLM、GptOssForCausalLM等少数架构被列为支持张量并行其余自动判为false。贡献新模型卡时supports_tensor的取值应与这份白名单的判断口径保持一致自动抓取生成的卡片会把backends设为全部后端源码注释解释得很直白不知道任意 HF 模型实际支持什么让放置层placement gate去把关。3.4 多组件模型卡以 FLUX.1-Kontext 为例图像模型往往由多个可独立加载的组件构成text encoder、transformer、VAE。CONTRIBUTING 提到components字段用于此类模型仓库中的真实样例 resources/image_model_cards/exolabs--FLUX.1-Kontext-dev.toml 展示了完整写法model_id exolabs/FLUX.1-Kontext-dev n_layers 57 hidden_size 1 supports_tensor false tasks [ImageToImage] family flux capabilities [image_edit] backends [MlxMetal] [storage_size] in_bytes 33327437952 [[components]] component_name text_encoder component_path text_encoder/ n_layers 12 can_shard false [components.storage_size] in_bytes 0 [[components]] component_name transformer component_path transformer/ n_layers 57 can_shard true safetensors_index_filename diffusion_pytorch_model.safetensors.index.json [components.storage_size] in_bytes 23802816640对照 model_cards.py 的ComponentInfo结构可以看出每个组件的语义component_path是 HF 仓库内子目录can_shard true的组件这里是 transformer才会参与跨节点分片safetensors_index_filename指定该组件的分片索引文件名。下载协调器src/exo/download/coordinator.py据此为每个组件独立规划分片任务。3.5 capabilities 与推理能力标记capabilities定义模型能做什么当前文档与源码共同确认的取值text标准文本生成thinking支持思维链推理CoTthinking_toggle可通过enable_thinking参数开关思考模式如上文 GLM-4.5-Air 卡image_edit支持图像到图像编辑如 FLUX.1-Kontext。3.6 安全说明trust_remote_code涉及从 HF Hub 拉取并执行模型方自定义代码风险明确。CONTRIBUTING 的安全原则是默认关闭仅当模型明确依赖远程代码时才开启。实现层面需要留意一个差异ModelCard的 Pydantic 字段默认值在 model_cards.py 中声明为True但自动从 HF 抓取生成卡片的路径fetch_from_hf显式写入trust_remote_codeFalse——也就是说任何自动生成的卡片都默认不开远程代码只有人工提交的模型卡才会开启该字段提交时务必遵循非必要不开的原则。四、API 适配器让 exo 同时说 OpenAI、Claude、Ollama 的话exo 通过适配器模式对外暴露多种 API 格式。适配器的职责是一条清晰的单向边界把各 API 特有的请求格式转换成 exo 内部统一的TextGenerationTaskParams再把内部推理产生的 token 流转换回该 API 特有的响应格式。4.1 适配器架构四步模式所有适配器遵循同一模式将 API 特有请求转换为TextGenerationTaskParams同时处理流式SSE与非流式两种响应生成将内部TokenChunk对象转换为 API 特有格式管理错误处理与边缘情况如流中断、客户端断连。关键的类型边界是内部系统worker、runner、事件溯源层只看到TextGenerationTaskParams和TokenChunk对象任何 API 特有类型都不许跨越适配器边界。从源码看这条边界被严格落实——以 src/exo/api/adapters/chat_completions.py 为例其导入的内部类型只有exo.shared.types.chunks中的ErrorChunk/TokenChunk/ToolCallChunk定义在 src/exo/shared/types/chunks.py与exo.shared.types.text_generation中的TextGenerationTaskParams、InputMessage等请求/响应 DTO 则全部来自 src/exo/api/types/。一点需要指出的现状差异CONTRIBUTING 中写的适配器目录是src/exo/master/adapters/、注册入口是src/exo/master/api.py而当前代码库已将其迁移到 src/exo/api/adapters/API 入口为 src/exo/api/main.py——贡献时以实际目录结构为准。4.2 现有适配器文件支持的 API典型用途chat_completions.pyOpenAI Chat Completions最通用的兼容层支持工具调用、logprobs、图像输入base64 data URL / 远端 URL 转 base64claude.pyAnthropic Claude Messages APIClaude 客户端直连responses.pyOpenAI Responses API新版 OpenAI 接口兼容ollama.pyOllama API与 OpenWebUI 等 Ollama 生态工具兼容含chat与generate两种请求、done_reason映射各适配器均有对应自动化测试位于 src/exo/api/tests/如test_chat_completions_stream.py、test_claude_api.py、test_claude_tool_use.py、test_openai_responses_api.py等——新增适配器时补齐同级别的流式/工具调用测试是惯例。4.3 新增一个 API 适配器的标准步骤按文档给出的模板步骤如下1. 在src/exo/api/adapters/下新建适配器文件。2. 实现请求转换函数def your_api_request_to_text_generation( request: YourAPIRequest, ) - TextGenerationTaskParams: # Convert API request to internal format pass3. 实现流式响应生成async def generate_your_api_stream( command_id: CommandId, chunk_stream: AsyncGenerator[TokenChunk | ErrorChunk | ToolCallChunk, None], ) - AsyncGenerator[str, None]: # Convert internal chunks to API-specific streaming format pass4. 实现非流式响应收集async def collect_your_api_response( command_id: CommandId, chunk_stream: AsyncGenerator[TokenChunk | ErrorChunk | ToolCallChunk, None], ) - AsyncGenerator[str]: # Collect all chunks and return single response pass5. 在 API 入口当前为 src/exo/api/main.py注册适配器的端点。几个实现上的实战要点从现有适配器代码可确认CommandId用于关联哪一次内部命令产生了这条流流清理逻辑依赖它参见 src/exo/api/tests/test_instance_deleted_stream_cleanup.py 对实例删除时流清理的验证chunk 流并非只有 tokenErrorChunk承载推理错误ToolCallChunk承载解析出的工具调用适配器必须区分处理并在流末尾正确终止test_finish_reason相关测试验证了 SSE 结束帧的finish_reason语义推理模型的reasoning输出如何回传由模型卡的reasoning_dialect与请求参数共同决定见 src/exo/shared/types/text_generation.py 的resolve_reasoning_params及对应测试 src/exo/shared/tests/test_resolve_reasoning_params.py。各 API 的完整字段文档见 docs/api.md。五、测试与提交5.1 测试现状与要求文档对测试的表述很坦率exo 目前重度依赖手工测试但正在快速改善。对贡献者的具体要求是提交变更前同时测试变更前后的行为用实际输出证明你的改动改善了系统行为用手头硬件做你力所能及的测试需要协助时直接在 issue/PR 中提出尽可能补充自动化测试——项目正在系统性地提升自动化测试覆盖。当前仓库的自动化测试已具备相当规模单测使用 pytestpyproject.toml中addopts -m not slow --ignoretests即默认只跑非slow标记的用例并自动注入EXO_TESTS1环境标记覆盖模型卡应用逻辑src/exo/shared/tests/test_apply/含test_apply_custom_model_cards.py、API 各适配器、MLX 引擎与放置算法tests/ 目录还提供 1 节点、2 节点、4 节点集群与韧性resilience等端到端场景适合作为多机改动的前后对照验证脚本。5.2 提交流程Fork 仓库创建功能分支git checkout -b feature/your-feature提交改动git commit -am Add some feature推送到分支git push origin feature/your-feature发起 PR 并遵循 PR 模板。5.3 报告问题发现 bug 或提出功能请求时issue 中请包含清晰的问题/功能描述复现步骤bug 类期望行为 vs 实际行为你的环境信息macOS 版本、硬件等。六、延伸阅读路径想继续深入 exo 内部建议按以下路径阅读当前仓库模型卡数据结构与缓存src/exo/shared/models/model_cards.pyModelCard、_CardCache、fetch_from_hf内置模型卡样例库resources/inference_model_cards/、resources/image_model_cards/API 层入口与类型定义src/exo/api/main.py、src/exo/api/types/、docs/api.md内部 chunk 协议适配器的输出侧契约src/exo/shared/types/chunks.py跨节点放置决策模型卡字段的消费方src/exo/master/placement.py 及其测试 src/exo/master/tests/test_placement.py多节点端到端测试tests/test_2node.py、tests/test_resilience.py开发工具链justfile、flake.nix、rust/exo_rs/。总结来说向 exo 贡献代码的核心链路是uv 管理的 Python 3.13 环境 nightly Rust 绑定 npm 构建的 Svelte 仪表盘构成运行底座TOML 模型卡是调度与下载体系的元数据契约新增模型主要靠提交规范完整的卡片文件API 适配器则是一条严格的类型边界只要守住TextGenerationTaskParams进、chunk 流出的单向转换就能让 exo 集群无缝接入任何新的 API 生态。【免费下载链接】exoRun frontier AI locally.项目地址: https://gitcode.com/GitHub_Trending/exo8/exo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考