AI 软件设计项目规范
模块化架构与迭代演进指南 —— 为 AI 驱动的软件项目建立可维护、可扩展的工程标准
01规范概述
AI 软件项目的核心矛盾在于:模型能力快速变化,而工程结构需要长期稳定。本规范的目标是建立一套模块自治、接口契约、渐进增强的项目结构标准,让团队能够在不牵动全局的前提下替换、升级或新增任何单个模块。
适用范围
本规范适用于所有包含 AI 能力的软件项目,涵盖模型推理服务、数据处理管道、应用业务逻辑及对外接口。无论项目采用单体还是微服务架构,模块层面的设计约定一致。
核心设计哲学
模块自治
每个模块拥有独立的目录、接口定义、测试套件和版本号。模块内部的结构决策由模块负责人全权决定,外部不干预。
接口契约
模块之间通过显式声明的接口通信,而非直接引用内部实现。接口变更需经评审流程,并遵循版本兼容承诺。
渐进增强
新功能以新模块或模块扩展形式加入,而非修改已有模块的核心逻辑。旧接口在废弃期内保持可用,平滑过渡到新实现。
可观测性内置
每个模块从设计第一天起即包含日志、指标和追踪能力,不作为事后补充。模块的运行状态可被独立监控和诊断。
文中使用 MUST / SHOULD / MAY 关键字遵循 RFC 2119 语义。MUST 级条款为强制约束,违反即视为规范不合规。
02架构设计原则
模块化不是把代码拆到不同目录,而是让系统在结构上具备独立替换的能力。以下六条原则贯穿从设计到实现的每个决策。
分层依赖,单向流转
系统按职责分层,上层依赖下层,同层之间通过接口通信。依赖方向自上而下单向流转,MUST NOT 出现下层反向引用上层的循环依赖。分层的意义在于:修改下层实现时,上层接口不变即无需改动。
flowchart TD
subgraph 接口层
GW["API Gateway"]
UI["UI / BFF"]
end
subgraph 应用层
BIZ["业务编排"]
AUTH["认证鉴权"]
end
subgraph AI 能力层
MODEL["模型管理"]
PROMPT["Prompt 管理"]
INFER["推理服务"]
EVAL["评估体系"]
end
subgraph 数据层
PIPE["数据管道"]
STORE["存储服务"]
end
subgraph 基础设施层
CFG["配置中心"]
LOG["日志 / 追踪"]
MQ["消息队列"]
end
GW --> UI
UI --> BIZ
BIZ --> AUTH
BIZ --> INFER
INFER --> MODEL
INFER --> PROMPT
INFER --> EVAL
BIZ --> PIPE
PIPE --> STORE
MODEL --> STORE
BIZ -.-> CFG
INFER -.-> LOG
BIZ -.-> MQ
高内聚,功能闭环
一个模块内的所有代码围绕同一个业务能力组织。判断标准:如果移除这个模块,系统失去的是一个完整功能而非零散片段。模块内部的数据结构、工具函数、配置项不暴露给外部。
接口先行,实现随后
新增或修改模块时,先产出接口定义文件(OpenAPI / Protobuf / TypeScript interface / Protocol),评审通过后才开始编写实现。接口是模块间的合约,实现是合约的履行——合约变更的成本远低于实现重构,因此接口设计值得花更多时间打磨。
单一职责,粒度适中
一个模块只承担一个明确的业务职责。判断粒度是否合适的方法:用一句话描述模块的功能,如果需要”和”连接两个不同动词,说明粒度过大需拆分;如果描述词过于泛化(如”工具模块”),说明职责不清需重新界定。
无状态优先,状态外置
模块的逻辑层不持有运行时状态。会话状态、缓存、任务队列等持久化数据外置到数据层或基础设施层。无状态模块可以水平扩展、独立部署、随时重启,这些特性在 AI 推理服务的高并发场景下尤为关键。
失败隔离,优雅降级
单个模块的故障不阻断整个系统。模块间的调用 SHOULD 设置超时、熔断和降级策略。AI 模型推理服务宕机时,应用层 SHOULD 能回退到规则引擎或缓存结果,而非直接报错。
03模块体系设计
模块是本规范的核心调度单位。一个标准的模块包含四个组成部分:接口契约(对外声明的能力和数据格式)、实现逻辑(内部如何履行契约)、测试套件(验证实现符合契约)、运行清单(依赖、配置、版本信息)。
模块分类
按依赖层级和职责类型,模块分为四类:
| 类型 | 职责 | 依赖方向 | 典型示例 |
|---|---|---|---|
| 核心模块 | 承载项目核心业务价值 | 依赖服务层 + 数据层 | 推理服务、业务编排、模型管理 |
| 服务模块 | 提供可复用的领域能力 | 依赖数据层 | 认证服务、检索服务、评估服务 |
| 数据模块 | 管理数据的读写和持久化 | 依赖基础设施层 | 数据管道、存储适配器、缓存服务 |
| 工具模块 | 提供无状态的工具函数和类型定义 | 无依赖或仅依赖标准库 | 日志工具、类型定义、格式转换 |
依赖规则
模块间的依赖遵循以下约束:
- 核心模块
MAY依赖服务模块和数据模块 - 服务模块
MAY依赖数据模块和工具模块 - 数据模块
MAY依赖工具模块 - 工具模块
MUST NOT依赖任何非工具模块 - 同层模块之间
MAY通信,但MUST通过接口契约,不直接引用内部实现 - 任何模块
MUST NOT形成循环依赖(A → B → A)
flowchart TD
CORE["核心模块"] --> SVC["服务模块"]
SVC --> DATA["数据模块"]
DATA --> UTIL["工具模块"]
CORE --> DATA
SVC --> UTIL
CORE --> UTIL
UTIL -.->|"禁止依赖"| CORE
DATA -.->|"禁止反向"| SVC
SVC -.->|"禁止反向"| CORE
接口契约三要素
每个对外暴露的接口 MUST 包含三部分声明:
- 数据契约 —— 输入输出的数据结构,使用语言无关的 schema 描述(OpenAPI / Protobuf / JSON Schema),字段含义、类型约束、必选/可选均有明确定义。
- 行为契约 —— 接口的前置条件(调用方需满足什么前提)、后置条件(调用完成后系统处于什么状态)、以及异常场景(输入不合法、依赖不可用时返回什么)。
- 版本契约 —— 接口的语义版本号,以及当前版本的状态(草案 / 稳定 / 废弃中)。
模块注册与发现
项目维护一份模块清单文件(modules.yaml),记录每个模块的名称、版本、路径、接口文件位置、依赖声明和当前状态。新模块加入或旧模块废弃时,同步更新此文件。这份清单是整个系统的”地图”,CI 管道 SHOULD 校验清单与实际代码的一致性。
模块清单文件同时充当依赖检测的输入源。CI 管道可解析 modules.yaml 中的依赖关系,自动检测循环依赖和越层引用,在代码合并阶段拦截违规。
04项目目录结构
统一的目录结构让任何开发者在任何模块中都能快速定位代码。以下约定适用于使用 TypeScript / Python 的 AI 软件项目,其他语言遵循等价原则。
顶层目录
# 标准项目顶层结构 project-root/ ├── modules/ # 所有业务模块 │ ├── inference/ # 推理服务模块 │ ├── model-manager/ # 模型管理模块 │ ├── prompt-engine/ # Prompt 管理模块 │ ├── data-pipeline/ # 数据管道模块 │ └── ... ├── packages/ # 可复用的工具包 │ ├── types/ # 共享类型定义 │ ├── utils/ # 通用工具函数 │ └── config/ # 配置管理工具 ├── gateway/ # API 网关 / 入口层 ├── infra/ # 基础设施配置 │ ├── docker/ # 容器化定义 │ ├── k8s/ # 编排配置 │ └── terraform/ # 基础设施即代码 ├── tools/ # 开发工具与脚本 │ ├── cli/ # 项目专用 CLI │ └── scripts/ # 运维脚本 ├── docs/ # 项目文档 ├── modules.yaml # 模块清单(依赖地图) ├── CONTRACT.md # 模块间接口契约汇总 └── CHANGELOG.md # 变更日志
模块内目录
每个模块内部遵循统一结构,让跨模块协作时无需重新适应:
# 单个模块的标准内部结构 modules/inference/ ├── interface/ # 接口契约(对外暴露) │ ├── openapi.yaml # REST API 定义 │ └── types.ts # TypeScript 类型 ├── src/ # 实现代码 │ ├── handler/ # 请求处理 │ ├── service/ # 核心逻辑 │ └── adapter/ # 外部依赖适配器 ├── tests/ # 测试套件 │ ├── unit/ # 单元测试 │ ├── integration/ # 集成测试 │ └── fixtures/ # 测试数据 ├── config/ # 模块级配置 ├── README.md # 模块说明 ├── module.yaml # 模块元信息 └── CHANGELOG.md # 模块变更日志
命名约定
| 对象 | 约定 | 示例 |
|---|---|---|
| 模块名 | kebab-case,名词或名词短语 | model-manager, data-pipeline |
| 接口文件 | snake_case | openapi.yaml, proto/inference.proto |
| 源码文件 | kebab-case(TS)或 snake_case(Python) | inference-handler.ts, model_loader.py |
| 测试文件 | 与被测文件同名加 .test / _test |
handler.test.ts, test_loader.py |
| 环境变量 | UPPER_SNAKE_CASE,模块名前缀 | INFER_PORT, MODEL_REGISTRY_URL |
| 配置键 | dot.notation,模块名为首段 | inference.timeout_ms |
不要在模块内部创建 common/ 或 misc/ 目录。这类目录会逐渐堆积不属于任何模块的”流浪代码”,破坏模块边界。如果一段逻辑被多个模块需要,提取为 packages/ 下的独立工具包。
05AI 能力层规范
AI 能力层是本规范与普通软件项目规范的主要差异点。这一层包含四个核心模块,它们的协作方式决定了 AI 功能的质量和迭代速度。
模型管理模块
模型管理模块负责模型的注册、版本控制、加载与卸载。每个模型在注册时 MUST 记录以下元信息:
- 模型标识符(name + version,如
gpt-classifier/v2.1.0) - 模型来源(训练任务 ID / 外部下载地址 / 基座模型 + 微调配置)
- 输入输出 schema(字段名、类型、维度、取值范围)
- 资源需求(GPU 型号、显存、CPU、内存)
- 性能基线(准确率、延迟 P99、吞吐量,及评估数据集标识)
- 生命周期状态(draft → staging → production → deprecated → retired)
模型加载采用延迟加载 + 预热机制:模块启动时仅加载配置元信息,实际模型权重在首次请求或定时预热任务触发时加载到内存。卸载时 MUST 等待正在进行的推理请求完成,然后释放资源。
Prompt 管理模块
Prompt 是 AI 系统中的”源代码”,需要与代码同级的管理待遇。Prompt 管理模块 MUST 提供以下能力:
模板版本控制
每个 Prompt 模板有独立的语义版本号,变更历史可追溯。模板使用变量插值,运行时渲染,不在代码中硬编码。
A/B 测试支持
同一功能的多个 Prompt 版本可并行运行,按流量比例分配,结果按版本维度统计对比效果。
变量校验
模板中的变量 MUST 有类型声明和必选/可选标记。渲染时校验变量值是否符合 schema,不合法则拒绝渲染并报错。
审计追踪
每次 Prompt 渲染记录模板版本、变量值、输出结果和调用方标识。用于事后排查输出异常和效果回归。
推理服务模块
推理服务模块是 AI 能力层的对外窗口,接收请求、调度模型、返回结果。它的设计核心是将模型选择逻辑与推理执行逻辑分离。
# 推理请求标准结构 { "request_id": "uuid", "model": "gpt-classifier/v2.1.0", # 指定模型,或使用 "auto" 让路由器选择 "inputs": { "text": "待推理内容", "context": { ... } # 可选上下文 }, "params": { # 推理参数,有默认值 "temperature": 0.7, "max_tokens": 1024, "stream": false }, "metadata": { "caller": "service-x", "trace_id": "..." } }
推理服务 SHOULD 支持三种调用模式:同步请求(低延迟场景)、异步批处理(高吞吐场景)、流式返回(生成式任务)。三种模式共用同一套模型加载和 Prompt 渲染逻辑,仅在外层处理调度差异。
评估体系模块
评估体系模块是 AI 能力层的质量保障。它独立于推理服务运行,定期对模型和 Prompt 的输出质量进行回归测试。评估 MUST 覆盖三个维度:
- 质量指标 —— 准确率、F1、BLEU、ROUGE 等领域相关指标,按评估数据集分组统计。
- 性能指标 —— 延迟分布(P50 / P95 / P99)、吞吐量、资源占用。
- 安全指标 —— 有害内容检测率、PII 泄露检测、越狱攻击防御成功率。
评估结果 SHOULD 接入可视化看板,历史趋势可追溯。当指标低于设定阈值时自动触发告警,阻止相关模型版本进入 production 状态。
RAG 模块(如适用)
检索增强生成(RAG)能力拆分为三个子模块独立管理:索引模块负责文档解析、分块、向量化、索引写入;检索模块负责查询改写、向量检索、混合排序;重排模块负责对检索结果做二次排序和过滤。三个子模块各有独立版本,可分别迭代而不影响其他环节。
06数据层规范
数据层管理 AI 系统中所有数据的生命周期:采集、清洗、标注、存储、版本控制。数据的正确性和可追溯性直接决定模型效果,因此数据层规范的核心是不可变 + 可版本化 + 可审计。
数据管道模块
数据管道模块以 DAG(有向无环图)方式编排数据处理流程。每个处理节点是一个独立的函数或服务,接收输入数据集,输出处理后的数据集。管道设计遵循以下规则:
- 每个节点
MUST记录输入数据的哈希值和输出数据的哈希值,用于追溯数据血缘 - 节点的处理逻辑
MUST是确定性的——同一输入永远产出同一输出,不依赖随机状态 - 引入随机性的节点(如数据增强)
MUST显式传入随机种子,种子与输出一起记录 - 管道执行失败时
MAY从失败节点重试,不重新执行已成功的前置节点
数据版本管理
每次数据集变更(新增、修改、删除记录) MUST 产生一个新的数据版本。版本记录包含变更时间、变更人、变更类型、变更前后的数据量。数据版本与模型版本关联:模型的评估结果 MUST 标注使用的数据版本号,确保结果可复现。
数据集的版本控制不同于代码的 Git 版本控制。数据量大、二进制格式多、变更频繁,SHOULD 使用专门的数据版本工具(如 DVC / LakeFS)而非直接存入 Git。
存储策略
| 数据类型 | 存储方式 | 版本化 | 保留策略 |
|---|---|---|---|
| 原始数据 | 对象存储(S3/OSS) | 不可变,追加写入 | 永久保留或按合规要求 |
| 清洗后数据 | 对象存储 + 元数据索引 | DVC/LakeFS 版本 | 保留最近 N 个版本 |
| 标注数据 | 数据库 + 版本快照 | 每次标注变更产生版本 | 永久保留 |
| 评估数据集 | Git 仓库(小规模)或对象存储 | Git 提交或 DVC 版本 | 永久保留 |
| 推理日志 | 时序数据库 + 冷存储归档 | 按时间分区 | 热数据 30 天,冷数据 1 年 |
数据安全与隐私
含 PII(个人身份信息)的数据 MUST 在进入数据管道前完成脱敏处理。脱敏规则在配置文件中声明,不硬编码在处理逻辑中。数据访问 MUST 经过认证授权,访问日志记录操作人、时间、数据范围。模型训练使用的数据 MUST 可追溯到数据来源和授权状态。
07接口层规范
接口是模块间的合约。一份好的接口定义让消费方无需阅读实现代码即可正确调用,让提供方在不破坏消费方的前提下重构实现。
API 设计原则
- 资源导向 —— URL 表达资源而非动作,动词由 HTTP method 表达:
GET /models/:id而非GET /getModel?id= - 幂等性 —— GET 请求
MUST幂等,PUT 请求SHOULD幂等,POST 请求不要求幂等但SHOULD返回幂等键 - 分页 —— 列表接口
MUST支持分页,默认使用游标分页(cursor-based)而非偏移分页(offset-based),在数据量增长后性能更稳定 - 字段筛选 —— 列表接口
SHOULD支持fields参数,让调用方按需获取字段,减少不必要的数据传输 - 批量操作 —— 批量接口
SHOULD接受数组输入,返回逐条结果和状态,而非整体成功或失败
错误处理标准
所有接口 MUST 使用统一的错误响应格式:
# 错误响应标准结构 { "error": { "code": "MODEL_NOT_FOUND", # 机器可读的错误码 "message": "Model 'gpt-x/v3' not found", # 人类可读的描述 "target": "model", # 出错的字段或资源 "details": { # 可选的补充信息 "available_models": ["gpt-x/v2", "gpt-y/v1"] }, "request_id": "uuid", # 用于追踪的请求 ID "trace_id": "..." # 分布式追踪 ID } }
HTTP 状态码使用约定:
| 状态码 | 语义 | 使用场景 |
|---|---|---|
| 200 | 成功 | 请求处理完成,返回结果 |
| 202 | 已接受 | 异步任务已提交,返回任务查询地址 |
| 400 | 客户端错误 | 请求格式不合法、参数缺失、类型错误 |
| 401 | 未认证 | 缺少或无效的认证凭据 |
| 403 | 无权限 | 已认证但无权访问该资源 |
| 404 | 不存在 | 请求的资源未找到 |
| 409 | 冲突 | 请求与当前资源状态冲突(如版本冲突) |
| 422 | 语义错误 | 格式正确但语义不合法(如温度参数超出范围) |
| 429 | 限流 | 超出调用频率限制 |
| 500 | 服务端错误 | 非预期异常,需运维介入 |
| 503 | 不可用 | 依赖服务不可用,可稍后重试 |
接口版本策略
接口在 URL 路径中标注主版本号:/api/v1/models/:id。主版本号变更意味着存在不向后兼容的 breaking change,消费方需要适配。次版本号和修订号在响应头或响应体中返回,不体现在 URL 中。
接口废弃流程:标记为 deprecated 后 MUST 保持至少 2 个次版本周期的可用期,响应头中返回 Deprecation 和 Sunset 字段告知消费方迁移时间。废弃期结束后移除接口,移除操作记录在 CHANGELOG 中。
08迭代演进机制
模块化架构的最终价值体现在迭代效率上。当系统能够在不牵动全局的情况下替换或升级单个模块,迭代速度就从”系统级”降低到了”模块级”。本章定义模块从创建到退役的全流程。
模块生命周期
每个模块经历五个阶段,阶段转换需满足该阶段的准入条件和退出条件:
stateDiagram-v2
[*] --> Draft : 提案通过
Draft --> Dev : 接口定义评审通过
Dev --> Stable : 测试覆盖率达标 + 文档完成
Stable --> Maintenance : 进入维护期(不新增功能)
Maintenance --> Deprecated : 标记废弃
Deprecated --> Retired : 迁移完成 + 废弃期满
Retired --> [*]
Stable --> Refactor : 技术债触发重构
Refactor --> Stable : 重构完成
| 阶段 | 准入条件 | 退出条件 | 约束 |
|---|---|---|---|
| Draft(草案) | 模块提案通过评审 | 接口定义完成并评审通过 | 不可被其他模块依赖 |
| Dev(开发中) | 接口定义评审通过 | 单元测试覆盖率 ≥ 80%,文档完成 | 接口可变,不承诺稳定 |
| Stable(稳定) | 测试覆盖 + 文档 + 评估达标 | 触发重构或进入维护 | 接口变更遵循版本策略 |
| Maintenance(维护) | 不再新增功能 | 标记为 deprecated | 仅修复严重 bug 和安全漏洞 |
| Deprecated(废弃中) | 有替代模块或接口 | 迁移完成 + 废弃期满 | 文档标注替代方案 |
| Retired(已退役) | 废弃期满 + 无引用 | — | 代码从仓库移除 |
语义版本控制
每个模块遵循 SemVer(Semantic Versioning)规范,版本号格式为 MAJOR.MINOR.PATCH:
- MAJOR —— 接口存在不向后兼容的变更(删除接口、修改参数类型、修改返回结构)。MAJOR 变更
MUST产出迁移文档。 - MINOR —— 新增功能或接口,向后兼容。消费方不升级也能继续工作,升级后可使用新能力。
- PATCH —— Bug 修复或性能优化,不改变接口契约。
版本号记录在模块的 module.yaml 中,模块清单 modules.yaml 同步更新。CI 管道 SHOULD 校验版本号变更与实际 diff 的一致性——如果接口发生了 breaking change但版本号只升了 MINOR,CI SHOULD 发出警告。
迭代工作流
一个典型的功能迭代按以下步骤推进:
flowchart LR
A["需求分析"] --> B["模块影响评估"]
B --> C["接口变更评审"]
C --> D["开发实现"]
D --> E["测试验证"]
E --> F["集成测试"]
F --> G["灰度发布"]
G --> H["全量发布"]
G --> I["回滚"]
I --> D
模块影响评估是迭代流程中容易被跳过但最关键的环节。评估的产出是一份影响范围清单:本次变更涉及哪些模块、哪些接口、哪些数据格式,下游消费方有哪些,需要什么适配。影响范围超出单个模块的变更 MUST 升级为跨模块评审。
技术债务管理
技术债不是需要消灭的敌人,而是需要管理的资源。每个模块维护一份技术债清单,记录已知的设计缺陷、待优化的实现、硬编码的临时方案。技术债条目 SHOULD 包含:
- 描述:什么问题,为什么当初这样处理
- 影响:不处理的后果(性能、可维护性、安全性)
- 优先级:按影响范围和严重程度排序
- 偿还方案:预期的修复方向和预估工作量
每个迭代周期 SHOULD 预留 15-20% 的容量用于偿还高优先级技术债。技术债清单在每季度的架构评审中重新审视和排序。
09工程实践规范
工程实践规范覆盖代码到部署之间的全部环节。这些约定不是风格偏好,而是保证模块化架构在团队协作中不退化的约束条件。
代码风格
项目使用统一的代码格式化工具(Biome / Prettier + ESLint for TS, Ruff + Black for Python),配置文件提交到仓库根目录。格式化在提交前自动执行,CI 管道校验格式一致性,不符合的 PR MUST NOT 合并。
代码注释遵循”只解释为什么,不解释是什么”的原则。函数和类型的命名 SHOULD 足以表达意图,注释用于补充命名无法传达的上下文:业务约束、外部依赖的限制、历史决策的原因。自动生成的文档(如 JSDoc / docstring) SHOULD 覆盖所有对外暴露的接口和公共类型。
测试策略
测试分为三层,各有不同的关注点和覆盖率要求:
| 层级 | 关注点 | 覆盖率要求 | 执行位置 |
|---|---|---|---|
| 单元测试 | 模块内函数和类的逻辑正确性 | ≥ 80% 行覆盖 | 每次提交 |
| 集成测试 | 模块间接口契约的兼容性 | 关键路径 100% 覆盖 | 合并到主分支前 |
| 端到端测试 | 用户视角的核心业务流程 | 核心场景全覆盖 | 每日定时 + 发布前 |
AI 相关模块的测试 MUST 额外包含模型回归测试:使用固定的评估数据集,对比当前版本与基线版本的输出。模型输出的回归测试不要求逐字匹配,而是评估指标在容差范围内——延迟变化不超过基线的 10%,质量指标波动不超过 2 个百分点。
CI/CD 管道
CI 管道在每次代码推送时执行以下检查,按顺序串行:
- Lint & Format —— 代码风格和格式校验,失败即阻断
- Unit Tests —— 单元测试,失败即阻断
- Build —— 编译和构建,验证类型正确性
- Integration Tests —— 集成测试,验证模块间接口兼容
- Security Scan —— 依赖漏洞扫描和敏感信息检测
CD 管道在 CI 全部通过后执行,部署策略取决于模块类型:核心模块使用灰度发布(先 5% → 25% → 50% → 100%),工具模块可直接全量发布。每个部署批次 MUST 设置自动回滚触发条件:错误率超过阈值或延迟超过基线 150%。
环境管理
项目维护四套环境,各有明确用途和隔离要求:
- local —— 开发者本地,用于开发和单元测试。使用 mock 依赖,不连接真实模型服务。
- staging —— 预发布环境,使用脱敏后的真实数据,连接 staging 版本的模型和依赖服务。集成测试在此执行。
- production —— 生产环境,连接真实的模型和数据。变更
MUST经过灰度流程。 - benchmark —— 性能基准环境,配置与 production 一致但隔离流量。用于模型评估和性能回归测试。
环境之间的配置差异通过环境变量注入,MUST NOT 在代码中通过 if env === 'production' 分支处理。配置管理使用专门的配置中心或环境变量文件,敏感信息(API Key、数据库密码)MUST 使用密钥管理服务,不提交到代码仓库。
10协作与发布规范
模块化架构的长期健康取决于团队协作纪律。本章定义代码从编写到发布到生产的过程中,团队需要共同遵守的流程约定。
分支策略
项目采用 Trunk-Based Development,所有人向主分支(main)提交代码,不维护长期的功能分支。功能开发在短期分支(存活不超过 3 天)上进行,完成后合并回 main。发布从 main 的标记版本切出 release 分支,release 分支仅用于修复发布阻塞的 bug。
功能分支:feat/<module>-<description>(如 feat/inference-stream-support)。修复分支:fix/<module>-<description>。Release 分支:release/v<version>。
代码审查
所有代码变更 MUST 经过至少 1 人的审查后合并。涉及接口变更的 PR MUST 由模块负责人或架构师审查。PR 审查关注以下维度:
- 接口合规 —— 变更是否符合接口契约,版本号是否正确
- 模块边界 —— 是否引入了越层依赖或循环依赖
- 测试覆盖 —— 新增代码是否有对应的测试覆盖
- 文档同步 —— 接口变更是否同步更新了文档和契约文件
PR 描述 MUST 包含变更摘要、影响范围、测试方法和关联的 issue/任务。大型 PR(超过 500 行变更)SHOULD 拆分为多个小 PR 依次提交,降低审查难度和合并风险。
发布流程
发布流程标准化为五个步骤:
- 发布准备 —— 冻结新功能合并,创建 release 分支,运行完整 CI 套件
- 灰度部署 —— 部署到 production 的 5% 流量,监控错误率和延迟指标 30 分钟
- 扩大灰度 —— 指标正常则扩大到 25% → 50% → 100%,每阶段观察 30 分钟
- 发布确认 —— 全量部署后观察 24 小时,确认无异常后标记发布完成
- 发布归档 —— 更新 CHANGELOG,归档 release 分支,记录发布摘要
灰度期间的监控指标和回滚阈值:
| 指标 | 回滚阈值 | 观察窗口 |
|---|---|---|
| 错误率(5xx) | > 1% | 滑动 5 分钟 |
| P99 延迟 | > 基线 150% | 滑动 10 分钟 |
| 推理质量指标 | 偏离基线 > 5% | 滑动 30 分钟 |
| 资源使用率 | GPU 显存 > 95% | 实时 |
变更日志
每个模块维护独立的 CHANGELOG.md,项目根目录维护汇总的 CHANGELOG.md。变更日志遵循 Keep a Changelog 格式,按版本倒序排列:
# CHANGELOG.md
## [Unreleased]
### Added
- 推理服务支持流式返回(modules/inference)
### Changed
- 模型管理接口返回增加 `lifecycle_status` 字段(modules/model-manager)
### Fixed
- Prompt 模板渲染时变量类型校验失效(modules/prompt-engine)
### Deprecated
- `GET /api/v1/models` 的 `verbose` 参数,使用 `fields` 替代
## [1.2.0] - 2026-08-15
### Added
- RAG 重排模块(modules/reranker)
- 数据管道支持增量更新模式(modules/data-pipeline)
变更日志的维护 SHOULD 通过 Conventional Commits + 自动化工具(如 changesets / standard-version)完成。提交信息使用约定式格式(feat:, fix:, break:),CI 管道在发布时自动生成 CHANGELOG 条目,减少人工遗漏。
事故响应
生产事故按严重程度分级响应。P0(服务不可用)要求 15 分钟内响应、1 小时内恢复或回滚;P1(核心功能降级)要求 1 小时内响应、4 小时内恢复。事故处理完成后 MUST 在 3 个工作日内产出事故复盘文档,包含时间线、根因分析、影响范围和改进措施。改进措施录入相关模块的技术债清单,在下一次迭代中安排处理。
发表回复