LocalAI 贡献者工程指南:构建、测试门禁与 AI 协作提交规范
本文基于 LocalAI 仓库的 CONTRIBUTING.md 及其引用的构建、测试与 AI 协作策略文件,完整梳理向该项目贡献代码前的全部准备工作:如何搭建满足 CGo/gRPC 要求的开发环境、如何使用 Makefile 完成构建与多模式运行、如何用环境变量配置开发实例、分支与提交规范、Go/Python 代码风格,以及 Ginkgo 测试体系与只增不减的覆盖率门禁。读完本文,你可以独立复现 LocalAI 的本地构建与测试闭环,并按项目要求提交合规的(包括 AI 辅助的)PR。
一、开发环境前置要求
LocalAI 的主程序是 Go 编写的(./cmd/local-ai),但需要 CGo 与 C/C++ 工具链支持原生 backend,因此开发机上的依赖比纯 Go 项目多一些。
1.1 基础工具链
按 CONTRIBUTING.md 的要求:
- Go 1.21+:当前仓库 go.mod 声明的版本为
go 1.26.0,1.21 是最低支持版本。macOS 可用brew install go;Ubuntu/Debian 上通过apt安装的 Go 往往版本过旧,建议按 Go 官方渠道安装; - Git;
- GNU Make;
- GCC / C/C++ 工具链:CGo 与原生 backend 必需;
- protoc(Protocol Buffers 编译器):gRPC 代码生成必需,构建流程中的
protogen-go步骤会用到。
可用 go version 验证 Go 版本。
1.2 各平台系统依赖
Ubuntu / Debian:
sudo apt-get update
sudo apt-get install -y build-essential gcc g++ cmake git wget \
protobuf-compiler libprotobuf-dev pkg-config \
libopencv-dev libgrpc-dev
CentOS / RHEL / Fedora:
sudo dnf groupinstall -y "Development Tools"
sudo dnf install -y cmake git wget protobuf-compiler protobuf-devel \
opencv-devel grpc-devel
macOS:
xcode-select --install
brew install cmake git protobuf grpc opencv wget
Windows: 使用 WSL 2 搭配 Ubuntu 发行版,然后按上面的 Ubuntu 步骤安装。
二、构建、运行与容器化
2.1 克隆与标准构建
# 克隆仓库后进入目录
cd LocalAI
make build
从 Makefile 的定义可以看到 build 目标的完整依赖链:build: protogen-go generate install-go-tools core/http/react-ui/dist,随后执行 go build -ldflags ... -tags "$(GO_TAGS)" -o local-ai ./cmd/local-ai。也就是说 make build 会依次完成:
- protobuf 代码生成(
protogen-go); - 生成物准备(
generate); - 安装 Go 构建工具(
install-go-tools); - 构建 React UI(
core/http/react-ui下执行npm install && npm run build,若dist已存在则跳过); - 编译
local-ai二进制。
构建时常用的可调变量:
| 变量 | 说明 | 示例 |
|---|---|---|
BUILD_TYPE |
GPU/加速器类型(cublas、hipblas、intel 或留空表示 CPU) |
BUILD_TYPE=cublas make build |
GO_TAGS |
追加的 Go 构建标签 | GO_TAGS=debug make build |
CUDA_MAJOR_VERSION |
CUDA 大版本号(默认 13) |
CUDA_MAJOR_VERSION=12 |
2.2 运行与热重载开发模式
# 直接运行构建产物
./local-ai
开发时推荐使用带热重载的模式:
make build-dev
从 Makefile 的 build-dev 目标可以看到:若 air 未安装会先执行 go install github.com/air-verse/air@latest,然后以 air -c .air.toml 启动文件监听,每次保存即自动重建并重启服务。此外 make run 提供不经编译的 go run ./cmd/local-ai 快速运行方式。
2.3 容器化构建(无需本地工具链)
make docker
Makefile 中还提供了 docker-build-e2e 等 docker-build-* 系列目标,可构建特定变体的镜像(通过 BUILD_TYPE、BASE_IMAGE、CUDA_MAJOR_VERSION 等 build-arg 控制);GPU 专属 Docker 构建的详细 backend 构建说明可参考 CLAUDE.md。
三、开发常用的环境变量
LocalAI 主要通过环境变量(或等价的 CLI flag)配置。对开发阶段最常用的一组如下,其默认值与 core/cli/run.go 中 kong 选项的 env/default 标签一致:
| 变量 | 说明 | 默认值 |
|---|---|---|
LOCALAI_DEBUG |
启用调试模式 | false |
LOCALAI_LOG_LEVEL |
日志级别(error、warn、info、debug、trace) |
— |
LOCALAI_LOG_FORMAT |
日志格式(default、text、json) |
default |
LOCALAI_MODELS_PATH |
模型文件路径 | ./models(源码中为 ${basepath}/models) |
LOCALAI_BACKENDS_PATH |
backend 二进制路径 | ./backends(源码中为 ${basepath}/backends) |
LOCALAI_CONFIG_DIR |
动态配置文件目录(API keys、外部 backends) | ./configuration(源码中为 ${basepath}/configuration) |
LOCALAI_THREADS |
推理线程数 | — |
LOCALAI_ADDRESS |
API 服务绑定地址 | :8080 |
LOCALAI_API_KEY |
API 密钥(可多个),设置后所有请求必须认证 | — |
LOCALAI_CORS |
启用 CORS | false |
LOCALAI_DISABLE_WEBUI |
禁用 Web UI,仅暴露 API | false |
完整的支持列表见 core/cli/run.go。
四、开发工作流
4.1 先提 Issue
发现 bug 或希望提出功能请求时,先检查 issue tracker 中是否已有类似报告,再创建新 issue 并尽可能提供细节。对于大型功能或重大改动,更推荐先通过 issue 讨论,而不是直接开 PR。
4.2 分支命名规范
使用能说明改动类型与范围的描述性分支名:
feature/<short-description>— 新功能fix/<short-description>— bug 修复docs/<short-description>— 文档变更refactor/<short-description>— 代码重构
4.3 提交信息规范
- 使用简短的祈使句标题,例如
feat: add whisper backend support,而不是Added whisper backend support; - 标题保持 72 字符以内;
- 在正文中解释为什么做这个改动(当标题不足以表达时);
- 遵循 Conventional Commits 规范。
4.4 创建 Pull Request 的标准流程
- Fork 仓库;
- 创建新分支:
git checkout -b feature/my-change; - 进行修改,保持 commit 聚焦、原子化;
- 推送前在本地跑通测试(见下文测试章节);
- 推送到自己的 fork:
git push origin feature/my-change; - 向
master分支发起 PR; - PR 描述中写清楚:改动内容与动机、测试方式、是否有破坏性变更或迁移步骤;
- 及时响应 review 反馈——推送后续 commit 而不是 force-push 修改过的 commit,方便 reviewer 看到增量变化;
- 通过审核后由 maintainer 合并。
五、编码规范
项目使用 .editorconfig 定义格式标准。从该文件可以看到具体规则:全局默认 2 空格缩进、LF 换行、UTF-8、去除行尾空白、文件末尾保留换行;*.go 与 Makefile 使用 Tab 缩进;*.py 为 4 空格;*.js、*.yaml 为 2 空格。请配置编辑器遵循该文件。
5.1 通用原则
- 编写可测试的代码。所有新功能和 bug 修复都应包含测试覆盖;
- 注释要克制,解释代码为什么这样做,而不是做了什么——注释应提供仅凭读代码难以推断的上下文;
- 保持改动聚焦:不要在同一 PR 中夹带无关的重构、格式化或新功能。
5.2 Go 代码
- 优先使用现代 Go 惯用法,例如用
any替代interface{}; - 提交 PR 前用
golangci-lint检查常见问题(Makefile 提供了lint/lint-all目标); - 日志统一使用
github.com/mudler/xlog(与slog相同的 API),不要使用fmt.Println或标准log包做运维日志; - Go 文件使用 Tab 缩进(由
.editorconfig规定)。
5.3 Python 代码
- 使用 4 空格缩进;
- 引入新依赖时提供对应的
requirements.txt。
5.4 代码评审
所有贡献都通过 PR 走代码评审。Reviewer 会关注正确性、测试覆盖、对规范的遵守以及意图清晰度。对 review 反馈保持响应,讨论保持建设性。
六、AI 辅助开发的提交规范
LocalAI 对 AI 辅助贡献采用了与 Linux 内核项目相同的准则。完整策略见 .agents/ai-coding-assistants.md,面向 AI 编码助手的入口索引则是 AGENTS.md(或其等价入口 CLAUDE.md)。核心规则:
-
AI agent 不得添加
Signed-off-by标签。只有人类可以认证 Developer Certificate of Origin(DCO)。唯一例外是 maintainer 自行操作的自动化:它以该 maintainer 的身份签署,因为没有其他人可以代为认证; -
AI agent 不得添加把自己列为 co-author 的
Co-Authored-Bytrailer; -
用
Assisted-bytrailer 标注 AI 参与,格式为:Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]例如
Assisted-by: Claude:claude-opus-4-7 golangci-lint。基础开发工具(git、go、make、编辑器)不应列入。.agents/ai-coding-assistants.md中给出了一个完整提交信息示例:fix(llama-cpp): handle empty tool call arguments Previously the parser panicked when the model returned a tool call with an empty arguments object. Fall back to an empty JSON object in that case so downstream consumers receive a valid payload. Assisted-by: Claude:claude-opus-4-7 golangci-lint Signed-off-by: Jane Developer <jane@example.com> -
人类提交者负责审查、测试并完全理解每一行 AI 生成的代码,包括核实所引用的 API、flag 或文件路径在代码树中真实存在(模型可能“幻觉”出不存在的标识符);
-
所有贡献必须与 LocalAI 的 MIT License(见 LICENSE)兼容,不得引入不兼容许可(如 GPL)的代码。
策略文件还明确了 maintainer 自动化例外的边界:仅适用于 maintainer 自行操作并在合并前审查其输出的自动化;签名必须指向一个承担 DCO 责任的真实个人;协助外部贡献者的 AI 依然不得签署,bot 也不得代替其操作者以外的任何人签署。
七、测试体系与覆盖率门禁
项目使用 Ginkgo 作为测试框架(外部链接略,见 go.mod 中的依赖声明 github.com/onsi/ginkgo/v2)。
7.1 单元测试
make test
需要注意 Makefile 中 test 目标当前的实际行为与历史描述的差异:按 Makefile 注释,测试套件重组后,默认的 make test 不再下载多 GB 的 GGUF/whisper 模型 fixtures,而是先执行 prepare-test(protogen-go + build-mock-backend 构建 mock backend),然后以 --flake-attempts $(TEST_FLAKES) --fail-fast -v -r 运行 Ginkgo 全量套件;core/http/app_test.go 通过 mock-backend 二进制驱动测试。真实 backend 的推理测试已移入 tests/e2e-backends/(按 backend 路径过滤)与 tests/e2e-aio/(nightly)。首次运行仍可能因 protobuf 生成与 mock backend 构建而较慢。
针对特定包运行:
go test ./core/config/...
go test ./pkg/model/...
按名称运行某个测试(Ginkgo 的 --focus):
go run github.com/onsi/ginkgo/v2/ginkgo --focus="should load a model" -v -r ./core/
7.2 端到端测试(Docker 容器内)
make test-e2e
该目标会构建 mock backend、cloud-proxy backend 与测试镜像,并在容器内以 5390 端口暴露 API 后执行 e2e 套件(见 Makefile 的 test-e2e 定义)。
7.3 E2E 容器测试(AIO)
这类测试构建标准 LocalAI Docker 镜像,用预配置的模型配置验证大多数端点可用:
# 构建 LocalAI 测试镜像
make docker-build-e2e
# 运行 e2e 测试(模型配置来自 tests/e2e-aio/models/)
make e2e-aio
对应测试代码位于 tests/e2e-aio/ 目录。
7.4 Python backend 测试
准备并测试额外的(Python)backend:
make prepare-test-extra # 为测试构建 Python backends
make test-extra # 运行 backend 特定测试
从 Makefile 可见 prepare-test-extra 依赖 protogen-python,而 test-extra 依赖 prepare-test-extra;每个具体 backend(llama-cpp、vllm、sglang、tinygrad 等)还有独立的 test-extra-backend-* 目标。
7.5 覆盖率门禁(Coverage Ratchet)
LocalAI 的测试策略文档 .agents/building-and-testing.md 对覆盖率门禁有严格规定,这是贡献者必须遵守的“只增不减”规则:
- Go 核心套件(
./pkg、./core及进程内集成套件./tests/e2e)受严格、单调递增的覆盖率棘轮约束:make test-coverage以covermode=atomic运行并输出合并 profile;make test-coverage-check会在总覆盖率低于已提交基线 coverage-baseline.txt 时让构建失败;make test-coverage-baseline用于覆盖率确实上升后重新生成基线。Go 门禁是严格的、无容差的。 - React UI(
core/http/react-ui/)由 Playwright e2e 规格覆盖,同样有单调棘轮(make test-ui-coverage-check,在 CI 中运行)。由于 UI 覆盖率指标是非确定性的(机器快慢会影响懒加载渲染是否赶在覆盖率采集前完成),因此保留一个小容差。如果你的改动降低了 UI 覆盖率,正确做法是补规格把它拉回来——不要放宽容差或手工下调基线。一个 render-smoke 规格(导航到页面并断言其标题可见)就能廉价地覆盖整个懒加载页面,参考 core/http/react-ui/e2e/page-render-smoke.spec.js。 - 两条门禁的共同红线:绝不通过降低基线或放宽容差来把红色门禁变绿。棘轮只允许向上移动。
八、文档贡献与 Gallery YAML 校验
文档位于 docs/ 目录(内容页在 docs/content/)。贡献文档同样通过 PR 或 issue 进行。
此外,AGENTS.md 中记录了“docs-with-code”规则:当你改变用户可见行为(API 端点、CLI flag、配置键或功能)时,必须在同一个改动中更新 docs/content/ 下对应的页面——没有配套文档更新的用户可见变更是不完整的。
LocalAI 为 gallery 模型 YAML 文件提供了 JSON Schema:core/schema/gallery-model.schema.json。该 Schema 与内部 gallery 模型配置一一对应,编辑器(如 VS Code)可利用它提供自动补全、校验与行内文档。在 gallery YAML 文件顶部加入以下注释即可启用 YAML 语言服务器校验:
# yaml-language-server: $schema=../core/schema/gallery-model.schema.json
九、社区与沟通
- 通过 GitHub issue tracker 联系维护者;
- 在项目的 Discussions 中开启新讨论;
- 加入项目官方 Discord 频道(入口见仓库首页说明)。
对于不确定如何构建或测试某个组件的开发者,.agents/ 目录下还有大量细分指南可供深入,例如 .agents/building-and-testing.md(构建与测试)、.agents/coding-style.md(代码风格)、.agents/adding-backends.md(新增 backend 的完整清单)、.agents/adding-gallery-models.md(向模型 gallery 添加模型)。这些文件与本文所述规范互为补充,共同构成 LocalAI 的完整贡献者工程体系。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00