[控场AI]
· 6 分钟阅读· 3,163 字

relnotes:用本地开源模型把 Git 历史变成发布日志

relnotes:用本地开源模型把 Git 历史变成发布日志

relnotes 用本地开源模型把 git log 改写成分组的用户向 changelog,一条命令、无依赖。

relnotes 是 Mystical89 在 Hacktoberfest 开源 AI 挑战赛第二周提交的 Python CLI,目标是解决「发版了但没人写 changelog」这一长期痛点。它读取两个 ref 之间的 git log,把提交记录改写成按 Added / Fixed / Changed 分组、面向用户的英文要点,输出效果接近人工整理的版本。核心设计是把推理放在本机完成,默认走 Ollama 的 qwen2.5:3b,兼容任何 OpenAI 端点,也可切换到 LM Studio、llama.cpp 或 vLLM。作者强调本地推理不是可选项,因为提交历史会泄露内部项目名、未发布功能甚至误粘贴的密钥。Conventional Commits 驱动分组,使 --offline 回退输出与模型输出结构一致,模型只负责语言改写而非决定骨架。项目还提供 Hermes skill,可被 agent 直接调用。

每次发版最容易被跳过的环节是什么?写 changelog。代码合并完、tag 打完,到了更新日志这里就只剩一句「bug fixes and improvements」。开发者 Mystical89 在 Hacktoberfest 开源 AI 挑战赛第二周提交的项目 relnotes,正是冲着这个场景来的:读取两个 ref 之间的 git log,把它改写成分组、面向用户的英文要点。

relnotes 项目来源

relnotes 解决了什么问题

项目的定位很克制——不是又一个 changelog 生成器,而是把「没人愿意写」这件事压缩成一条命令。

作者在项目说明里描述的痛苦相当具体:项目要发布,changelog 没人写,最后要么空着,要么写一句「bug fixes and improvements」。relnotes 读取 --since v1.2.0 这类区间内的提交记录,渲染成 Added / Fixed / Changed 分组的纯英文条目,效果接近一个有时间写日志的人手动整理出来的版本。

目标用户也说得直白:按节奏发版的团队、按月给客户交付的自由职业者、维护公开 changelog 的小团队,以及那些「半年前就放弃更新日志」的副业项目维护者。这恰好是提示词里说的那种「有人一直在抱怨、但一直没人做的枯燥任务」。

本地开源模型是核心,不是装饰

relnotes 最值得看的设计选择,是把推理全部放在本机完成。它不绑定某一家模型服务,而是对接任何 OpenAI 兼容端点:默认走 Ollama 的 qwen2.5:3b,也可以一个 flag 切到 LM Studio、llama.cpp 或 vLLM。

改写质量靠一段严格的 system prompt 兜底:按 Added / Fixed / Changed 分组,每条不超过 12 个词,不允许出现 commit hash、文件名,也不允许「refactor」「chore」这类黑话,无信息量的提交直接丢掉。温度设为 0.3,让同一次发布跑两遍能得到基本一致的输出。

你可能没注意到离线回退路径。项目用 Conventional Commits 驱动分组,所以在没有模型可用时(--offline)生成的 changelog,结构与模型输出保持一致:

$ relnotes.py --since v1.2.0 --offline


**OpenAI 兼容端点**指的是任何实现了 OpenAI Chat Completions API 请求与响应格式的推理服务。它以 `/v1/chat/completions` 为标准路径,请求体包含 `model`、`messages`、`temperature` 等字段,返回结构也保持一致。这一约定最初由 OpenAI 建立,如今已成为本地推理生态的事实标准:Ollama、LM Studio、llama.cpp 的 server 模式、vLLM 都提供该接口。对 relnotes 这类工具而言,这意味着它只需实现一套 HTTP 客户端,就能在任意后端之间切换,模型只是一个可替换的参数,而不需要为每家服务写适配层。

**Conventional Commits** 是一套提交信息格式约定,形如 `feat(api): add bulk import endpoint` 或 `fix: stop dropping empty rows`。前缀(feat、fix、chore、refactor 等)声明了这次改动的类型,可选的作用域括号标注模块,冒号后是描述。relnotes 依赖这一约定来驱动 Added / Fixed / Changed 分组:没有解析到标准前缀的提交会被归入其他类别或被丢弃,因此项目的输出质量与仓库是否遵循该规范直接相关。
## Added
- api: add bulk import endpoint

## Fixed
- stop dropping empty rows

换句话说,模型负责把技术语言改写成用户语言,而不是决定 changelog 的骨架。这个分工让整个工具在模型不可用时依然可用,也让输出格式具备可预测性。

为什么本地推理在这里不是可选项

作者给出的三条理由里,第二条最有说服力:提交历史不应该离开这台机器。

commit message 会泄露内部项目名、未发布的功能,偶尔还有被误粘贴进去的密钥。把这段历史发给第三方 API,本身就是一次不该发生的数据外泄。这意味着托管版的 relnotes 只有两条路——要么要求用户信任服务方保管全部提交历史,要么把有意思的内容都过滤掉,而过滤之后就没什么可总结的了。本地推理让「安全的版本」直接成为默认版本。

另外两条理由同样成立。成本上,笔记本上的 3B 模型替代了按次计费的托管 API,对每周发一次的团队来说是噪音级差异,但对隔天就发版的独立开发者来说,决定了这个工具是被长期使用还是试两次就丢掉。锁定风险上,模型只是一个参数:硬件允许就换更大的,或者指向另一台服务器,代码不用动。

与 Agent 生态的衔接

relnotes 的另一个接口层面设计是 Hermes skill,遵循 Agent Skill Open Standard。这意味着可以直接对 agent 说「把 v1.2.0 以来的 release notes 写出来」,由 agent 调用这个 CLI 完成任务。

把 changelog 生成做成 agent 可调用的技能,比做成一个独立网页工具有更长的生命周期:它嵌进已有的工作流里,而不是要求用户记住再打开一个新站。作者同时提供了 skills/relnotes/ 目录作为技能定义,说明这条路径是有意设计的,不是事后补的。

Agent Skill Open Standard 是一套让 AI agent 发现并调用外部能力的规范,通常以一份技能描述文件为核心,声明技能名称、用途、调用方式与参数。相比把功能封装成独立网页或 GUI,技能形式的优势在于 agent 可以自主判断何时调用它:用户只需用自然语言说出「写一下 v1.2.0 以来的 release notes」,agent 便会匹配到该技能并执行相应 CLI 命令。relnotes 在仓库中提供 skills/relnotes/ 目录,正是把 CLI 本身注册成这样一个可被发现的技能,从而嵌进已有的开发工作流。

代码与成熟度

项目在 github.com/Mystical89/relnotes 开源,MIT 协议,Python 3.10+,无第三方依赖,附带 5 个通过的测试,覆盖解析、分组和端到端 CLI 流程。仓库结构很简单:relnotes.py 是 CLI 主体,test_relnotes.py 是测试,skills/relnotes/ 是 agent 技能。

需要如实说明的是,作者自己承认还没有真实用户——这是项目第一天。计划是拿这个仓库的下一次发布当第一个试验对象,把生成的 changelog 贴回评论区。作者对这件事的表述挺诚实:要么是个好 demo,要么是份如实的 bug 报告。对一个刚起步的 CLI 来说,这种自我认知比任何功能清单都更值得信任。

如果你也长期在「发版了但没人写日志」的状态里,这个工具的门槛足够低——一条命令、无依赖、模型可选。

#relnotes#changelog 生成#Git 发布日志#开源模型本地推理#Ollama#CLI 工具#Agent Skill#Conventional Commits
分享:

相关推荐