- 人工智能
- NLP
- 强化学习
【免费下载链接】laya
Non-autoregressive System 1 decision engine. Typed choice, score and yes/no decisions over any text in a single forward pass, in 100+ languages, with a router that picks the right checkpoint per request.
导读
AGENTS.md 是 Laya 仓库为 Claude Code、Codex、Cursor、Copilot、Gemini CLI 等 AI 编码助手准备的协作契约:它把人类维护者在 CONTRIBUTING.md 中沉淀的提交规范、测试约定和 CI 门禁浓缩成一套编码代理"开机即读"的规则。本文以该文档为骨架,结合仓库中 laya/、tests/、docs/ 的源码与测试实现,逐条讲解这些规则背后的真实约束,并给出可直接执行的检查命令,帮助你在该仓库中提交改动时不踩红线、一次通过 review。
一、文档定位:为什么编码助手需要一份专属规则
AGENTS.md 开篇即点明其定位:"Context for AI coding assistants (Claude Code, Codex, Cursor, Copilot, Gemini CLI) working in this repository."它是贡献规则的"助手侧摘要",之所以单独存在,是因为各类 Coding Agent 打开仓库时会自动读取这份文件,而不会先去读完整的人类贡献指南。文中明确说明:
These rules mirror CONTRIBUTING.md; the assistant-facing summary lives here because coding agents read this file automatically.
也就是说,AGENTS.md 与 CONTRIBUTING.md 是一对"同一契约的两种面向":前者是给机器读的浓缩版,后者是给人类读的完整版。理解这一点很重要——当你作为 Agent 在 Laya 仓库中工作,AGENTS.md 就是你唯一的"快速入门手册",但它背后的完整理由(范围界定、开发环境、测试分类、提交规范)都要回到 CONTRIBUTING.md 里找依据。本文后续每一条规则都会给出它在仓库中对应的源码或测试证据,保证"规则可验证、命令可运行"。
二、Do NOT:七条不可逾越的边界
AGENTS.md 用一张清单定义了编码助手在本仓库的禁区,逐条展开如下,并附上仓库内的证据与理由。
1. 禁止引入托管服务或外部 API 依赖
Introduce a dependency on a hosted service or external API. Features must run in the user's own process or on their own hardware; a feature that only works against a hosted backend belongs in a separate integration, not here.
Laya 的自我定位是 "a fast, local, on-device decision engine"(README 与 CONTRIBUTING.md 的 Scope 一节都有同样表述)。核心包laya的所有推理路径——laya/agent.py、laya/router.py、laya/fast.py——都运行在用户自己的进程与硬件上。这一约束的工程后果是:任何只对托管后端生效的功能都不能进核心包,只能做成独立集成(如 laya/integrations/langchain.py 这类可插拔模块)。从 pyproject.toml 可以看到,serve、fast、mcp、onnx、langchain、langgraph全部是 optional-dependencies,核心依赖只有torch、transformers、safetensors、huggingface_hub、numpy——这就是"本地、无托管服务"原则在依赖清单上的直接体现。
2. 改动公共 API 必须同步更新 test_hooks_api.py
Change the public API without updating
tests/test_hooks_api.pyin the same pull request — that suite is the API contract.
这是全仓库最硬的一条 API 稳定性约束。打开 tests/test_hooks_api.py 可以看到它被明确定义为 "API-stability guard":它用inspect.signature逐个钉死Agent.__init__、load、Router.__init__、ONNXAgent.__init__的构造参数(hooks、on_predict_start、on_predict_end、hooks_raise、hooks_concurrent的默认值),以及Agent.predict_batch、Agent.system_one、Router.predict、ONNXAgent.system_one的调用面,连Router特有的lang_guess、revisions参数也单独校验(tests/test_hooks_api.py)。任何让调用者行为发生变化的改动,都会先在这个文件里失败。所以规则很明确:同一 PR 内,改了签名就改这个文件。这正是 CONTRIBUTING.md 中 "Keep the public API stable" 的机器化落地。
3. 跳过 CI 门禁不算完成
AGENTS.md 给出两条必须在宣告完成前运行的命令(CONTRIBUTING.md 亦复述):
ruff check laya/ --select=E9,F63,F7,F82,F401,F811 --line-length=120 python -m compileall -q laya/ tests/- ruff 选择器:
E9(语法错误)、F63(f-string 语法错误)、F7(函数定义后语法错误)、F82(未定义的局部变量)、F401(未使用导入)、F811(重定义名称),并强制--line-length=120。这是一组"低误报、高信号"的快速检查,不是全量 lint。 - compileall:以
-q静默模式编译laya/与tests/,确保所有改动文件语法可编译。
这两条对应 .github/workflows/ci.yml(CONTRIBUTING.md 明确指向该文件)中的 CI 步骤,本地跑通是"完成"的最低门槛。
4. 禁止整文件格式化、重排 import、"现代化"周边代码
Reformat files wholesale, reorder imports, or "modernize" surrounding code. Match the style of the file being edited; a diff full of formatting noise gets a change rejected.
这一条直接针对 AI 编码助手最常见的坏习惯:顺手把整个文件"美化"一遍。仓库的立场是匹配被编辑文件的既有风格,而不是风格统一运动。原因在 CONTRIBUTING.md 的 Style 一节有对应表述:"Match the surrounding style rather than a personal preference",以及 "Comment only where the code cannot say it"。噪声 diff 会导致改动被拒,哪怕功能正确。从 laya/hooks.py、laya/router.py 的实际代码看,仓库保持着一致的、带详尽 docstring 的 Python 风格,改一处就应仿照一处。
5. 禁止提交密钥、令牌、大型二进制文件
Commit secrets, tokens, or large binary files.
这是通用安全底线,CONTRIBUTING.md 的 Pull requests 一节也明确 "Do not commit secrets, tokens, or large binary files"。仓库的模型权重(三个 checkpoint,见 laya/router.py 的DEFAULT_MODELS)从不进入 git 仓库,而是首次使用时从 Hub 下载到~/laya_models,这与"仓库只读、权重外置"的架构一致。
6. 只用英文提交 PR
Open pull requests in a language other than English. The project is triaged in English.
项目维护与 triage 均以英文进行(CONTRIBUTING.md 的 Reporting issues 一节同样要求尽量用英文写 issue),因此 PR 描述、commit message、issue 都应是英文。
7. 禁止发明约定:遵循 conventional commit 前缀
Invent conventions. Use conventional commit prefixes matching the history (
feat(agent):,fix(router):,perf(common):,docs(hooks):,test(batch):), and keep one logical change per commit.
仓库历史使用 conventional commits,前缀按模块划分:feat(agent)、fix(router)、perf(common)、docs(hooks)、test(batch)。前缀的 scope 直接对应仓库结构——laya/agent.py、laya/router.py、laya/common.py、laya/hooks.py、tests/test_batch.py。规则要求"一个 commit 只做一件逻辑变更",这也和 Pull requests 一节的 "Keep it focused; split unrelated work into another PR" 相互呼应。
三、Where to look:按改动面选择读什么、跑什么
AGENTS.md 的核心价值之一是一张"改哪 → 读什么 → 跑什么"的对照表,这是它比普通贡献指南更贴近 Agent 工作流的地方。逐行拆解:
| 改动面 | 读什么 | 跑什么 |
|---|---|---|
laya/核心 | — | 纯脚本套件:python tests/test_router.py、tests/test_criteria.py、tests/test_hooks.py、tests/test_hooks_api.py |
| server 路径 | tests/test_serve.py | python -m pytest tests/test_serve.py(缺serveextra 时跳过) |
| ONNX 路径 | tests/test_onnx.py | python -m pytest tests/test_onnx.py(缺onnxextra 时跳过) |
| fast / 本地路径 | tests/test_fast.py、tests/test_local_e2e.py、tests/test_mcp_local_e2e.py | 需要 CUDA 或~/laya_models下的 checkpoint,否则跳过 |
docs、laya/内 docstring | docs/、docs/.nav.yml(控制页面顺序) | pip install -r requirements-docs.txt,然后zensical build --strict --clean,输出不得出现griffe:行 |
这条表至少揭示了仓库的三个工程事实:
- 测试以纯脚本为主,pytest 为辅。核心套件(router、criteria、hooks、hooks_api)都是可直接
python tests/test_xxx.py运行的 assert 风格脚本,例如 tests/test_hooks.py 的 docstring 写明 "Run: python tests/test_hooks.py";只有 server、ONNX、truncation 等路径是 pytest 风格(CONTRIBUTING.md 明确列出这三个)。这降低了运行门槛,也符合 AGENTS.md 末尾 "an assert-based script is enough" 的精神。 - 测试按依赖分层跳过。
serve、onnx是 optional extra,缺了就跳过;fast/本地路径需要 CUDA 或真实权重(~/laya_models)。对应关系在 pyproject.toml 的[project.optional-dependencies]中一一可查:fast = ["tilelang>=0.1.14"]、onnx = ["onnx", "onnxruntime"]等。 - 文档构建有严格的 CI 校验。文档站由 Zensical 构建(zensical.toml),API 参考从
laya/的 docstring 生成。zensical build --strict --clean输出中一旦出现griffe:行——例如 docstring 里写了签名不存在的参数——CI 即失败(CONTRIBUTING.md 的 Documentation 一节给出了这个失败语义)。
补充一句:optional extras 只装改动所需的那一个即可("install only what the change needs"),不要为了图方便把所有 extra 全装进环境。
四、Pull requests:把 diff 收敛到最小、可复核
AGENTS.md 对 PR 的要求有三条,均有 CONTRIBUTING.md 的完整展开:
- 先 rebase 到最新
main,让 diff 只含你的改动。理由很直白:噪声 diff 会被拒(见第二节第 4 条)。 - 保持聚焦,拆分散改动。一个 PR 一件事,大的改动拆成多个 PR。
- 如果改动动了数字,报告前后对比。这是 Laya 仓库最独特的验收文化:
If a change moves numbers, report the before and after. The maintainer verifies decisions against real checkpoints, and measured deltas (probability changes, latency, memory) are what gets a change merged.
Laya 是一个决策引擎,改动的价值最终体现在概率、延迟、内存等可测量量的变化上。README 的 Benchmarks 一节展示了这种文化的产物:例如 "Batched throughput reaches 103–332 questions/sec on a single T4"、"After temperature scaling, mean ECE moves 0.466 → 0.081"——这些都是带前后对比的测量陈述。因此提交任何会影响模型输出的改动时,带上before/after的实测数据是合并的前提。
配套要求是为非常规逻辑留一个可运行的检查:"Leave one runnable check behind for non-trivial logic; an assert-based script is enough." 这正是 tests/test_hooks.py、tests/test_hooks_api.py 这类 assert 脚本存在的形态,与仓库"测试即脚本"的风格一致。
五、与源码互证:规则背后的实现细节
AGENTS.md 的若干规则表面上是流程约束,实际对应着具体的代码结构。以下三组互证最能说明"规则为何如此"。
5.1 API 契约测试钉死的是钩子生命周期
test_hooks_api.py 守护的公共 API,其对象正是 laya/hooks.py 中定义的钩子机制:PredictContext(每次调用传给所有钩子的可变状态,含states、questions、run_id、results、model、elapsed_ms、error等字段,以及可短路推理的skip()方法)和Hook协议(on_predict_start、on_predict_end、on_route、on_load、on_evict、on_error六个生命周期方法,另提供全 no-op 的BaseHook便于子类化)。AGENTS.md 要求"改公共 API 必改此测试",正是因为钩子参数(hooks、on_predict_start、on_predict_end、hooks_raise、hooks_concurrent)横跨Agent、Router、ONNXAgent三个类,任何一个签名的变动都会波及所有调用方——机器化校验是防止"静默破坏"的最低成本手段。
5.2 纯 Python 钩子与"本地优先"原则
laya/hooks.py 的模块 docstring 写着 "Everything here is pure Python: importinglayamust not start pulling torch"。这是 AGENTS.md "不引入托管服务/外部 API" 原则的实现级体现:钩子机制可以完全不依赖 torch 运行,从而让审计、缓存、重写等横切能力保持轻量。测试侧同样遵守这一约束——tests/test_hooks.py 用 stubbed 的 fake Agent 跑通整个钩子生命周期,"without a model or a download"。
5.3 路由器的"三 checkpoint"结构与改动验证
AGENTS.md 要求"报告数字前后对比"并非无的放矢。laya/router.py 管理三个 checkpoint(english、multilingual、typed-decisions),自动路由在英文与多语言 checkpoint 之间按脚本/语言选择;任何改动都可能改变某条路径的选型或概率,而 README 明确警示"the English checkpoint does not gracefully degrade off English, it collapses"(Khmer 上 0.000 准确率却报 95.2% 置信度)。在这种"高置信度错误"风险下,维护者坚持用真实 checkpoint 复核决策、用实测 delta 验收改动,就是 AGENTS.md 那条规则的直接动机。
六、可执行的提交前清单
综合 AGENTS.md 全部规则,落地成一份提交前 checklist:
- 范围自查:改动是否只在用户进程/硬件内运行?若依赖托管后端,请移出核心包。
- API 自查:是否触碰了
Agent/Router/ONNXAgent的构造参数或 predict 面?若是,同一 PR 内更新 tests/test_hooks_api.py。 - 门禁命令:
ruff check laya/ --select=E9,F63,F7,F82,F401,F811 --line-length=120 python -m compileall -q laya/ tests/ - 测试选择:核心改动跑
python tests/test_router.py、tests/test_criteria.py、tests/test_hooks.py、tests/test_hooks_api.py;server/ONNX 路径用 pytest 且注意 extra 缺失时跳过;fast/本地路径确认 CUDA 与~/laya_models权重就绪。 - 文档改动:若改了 docstring,本地执行
pip install -r requirements-docs.txt && zensical build --strict --clean,确保无griffe:行。 - diff 卫生:只改目标文件、不重排 import、不整文件格式化;rebase 到最新
main,一个 commit 一件事。 - 数字可复核:任何动概率/延迟/内存的改动,附 before/after 实测,并为非平凡逻辑留一个 assert 脚本。
- 语言与安全:PR 与 commit 用英文;绝不提交密钥、令牌或大型二进制文件。
七、总结
AGENTS.md 表面上是一份简短的 Agent 规则清单,实质上是 Laya 仓库工程文化的浓缩:本地优先(不依赖托管服务)、API 稳定(机器化契约测试)、低噪声 diff(匹配既有风格)、数字说话(改动必须有可测量的前后对比)、可运行验证(assert 脚本即测试)。对任何在该仓库工作的编码助手而言,遵循这份文件不仅是"守规矩",更是理解"这个决策引擎项目如何验收质量"的最短路径。完整的规则原文、issue 模板要求与行为规范,可继续查阅 CONTRIBUTING.md、CODE_OF_CONDUCT.md 与 LICENSE。
- 人工智能
- NLP
- 强化学习
【免费下载链接】laya
Non-autoregressive System 1 decision engine. Typed choice, score and yes/no decisions over any text in a single forward pass, in 100+ languages, with a router that picks the right checkpoint per request.
相关推荐
Sunshine 仓库工程协作规范全解:面向 AI Agent 与贡献者的 AGENTS.md 实战指南
Sunshine 仓库工程协作规范全解:面向 AI Agent 与贡献者的 AGENTS.md 实战指南 AGENTS.md 是 Sunshine(面向 Moo
音视频后端Vim 仓库开发协作指南:面向 AI Coding Agent 与贡献者的贡献规范、构建测试与代码风格全解析
Vim 仓库开发协作指南:面向 AI Coding Agent 与贡献者的贡献规范、构建测试与代码风格全解析 本文以 Vim 官方仓库根目录的 AGENTS.m
开发工具代码编辑器Java Design Patterns 项目指南:面向 AI Agent 的仓库结构与贡献协作规范
Java Design Patterns 项目指南:面向 AI Agent 的仓库结构与贡献协作规范 本指南以 java design patterns 仓库根
示例工程教程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考