Agent 开发(二)—— 设计篇:Git Commit助手系统架构与接口设计
·
一、项目需求
1.1 一句话描述
在终端运行
commit-agent,自动读取当前 git diff,调用 DeepSeek API 生成规范化的 commit message,用户确认后提交。
1.2 功能清单(v1)
| 功能 | 优先级 | 说明 |
|---|---|---|
| 读取 git diff | P0 | 自动获取当前仓库的变更 |
| 调用 DeepSeek API 生成 commit message | P0 | 使用 DeepSeek Function Calling |
| 预览确认 | P0 | 展示生成的 message,让用户 Y/N 确认 |
| CLI 入口 | P1 | 支持 --model、--stage 等参数 |
| 自动暂存 | P1 | --stage 参数自动 git add -A |
1.3 非功能性需求
- Token 消耗低:单次调用不超过 2000 tokens
- 零外部依赖:除了
openaiSDK 不需要其他第三方库 - 容错:git diff 为空、API 调用失败等场景有明确的错误提示
二、系统架构
2.1 整体架构图
┌──────────────────────────────────────────────────────┐
│ 用户终端 (CLI) │
│ $ commit-agent [--stage] [--model deepseek-chat] │
└─────────────────────┬────────────────────────────────┘
│
┌─────────────────────▼────────────────────────────────┐
│ agent.py │
│ Agent 核心流程协调器 │
│ ┌──────────────────────────────────────────────────┐ │
│ │ ① 读取 diff (git_utils) │ │
│ │ ② 调用 DeepSeek API (llm_client + 工具定义) │ │
│ │ ③ 解析响应,提取 commit message │ │
│ │ ④ 返回结果给 CLI │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────┬────────────────────────────────┘
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌──────────┐ ┌──────────┐
│ git_utils │ │llm_client│ │ prompts │
│ git 操作封装 │ │API 封装 │ │ 模板管理 │
└─────────────┘ └──────────┘ └──────────┘
2.2 数据流
Step 1: git_utils.get_full_diff()
──→ 返回 diff 字符串(或空字符串)
Step 2: agent.py 组装 system prompt + diff
──→ 调用 llm_client.send_with_tools()
Step 3: llm_client 返回 DeepSeek 响应
──→ message 中可能包含 tool_calls
Step 4: agent.py 解析 tool_calls
──→ 提取 tool_call.function.arguments 中的 title / type / body
Step 5: cli.py 展示给用户
──→ 用户确认后调用 git_utils.commit()
三、模块划分
3.1 模块总览
commit_agent/
├── __init__.py
├── cli.py # CLI 入口,参数解析,用户交互
├── agent.py # Agent 核心流程编排
├── git_utils.py # git diff/commit/stage 操作
├── llm_client.py # DeepSeek API 封装 + 工具定义
└── prompts.py # System prompt 模板
3.2 各模块职责
| 模块 | 职责 | 对外暴露 |
|---|---|---|
| cli.py | 解析命令行参数、展示预览、处理用户输入、调用 agent 和 git_utils 完成完整流程 | main() |
| agent.py | 编排 Agent 流程:读 diff → 调 API → 解析响应 → 返回结构化结果 | generate_commit_message() |
| git_utils.py | 封装所有 git 子进程调用 | get_full_diff(), commit(), stage_all() |
| llm_client.py | 封装 DeepSeek API(OpenAI 兼容 SDK) + 工具定义 | LLMClient 类 |
| prompts.py | 管理 system prompt 和消息模板 | SYSTEM_PROMPT, build_diff_prompt() |
四、核心接口设计
4.1 git_utils.py
def get_full_diff() -> str
"""获取工作区所有变更(staged + unstaged)的 diff"""
def get_staged_diff() -> str
"""仅获取已暂存的 diff"""
def stage_all() -> None
"""暂存所有变更:git add -A"""
def commit(message: str) -> None
"""执行 git commit -m "<message>"
失败时抛出 RuntimeError"""
4.2 prompts.py
# 常量
SYSTEM_PROMPT: str
"""System prompt:定义 Agent 角色、commit 规范、输出格式要求"""
# 函数
def build_diff_prompt(diff: str) -> str
"""将 diff 包装成 user message
若 diff 为空,返回特殊提示"""
4.3 llm_client.py
class LLMClient:
def __init__(self, api_key: str, model: str = "deepseek-chat"):
"""初始化 DeepSeek 客户端(OpenAI 兼容 SDK)"""
@staticmethod
def define_tools() -> list
"""返回工具定义列表(OpenAI Function Calling 格式)
定义 generate_commit_message 工具:
- 参数: title(str), type(enum: feat/fix/refactor/...), body(str?)
- 约束: title 不超过 72 字符,type 必须在枚举中
"""
def send_with_tools(self, system_prompt: str, user_message: str) -> dict
"""发送请求并返回原始响应
返回内容包含 message.content 和 message.tool_calls"""
4.4 agent.py
def generate_commit_message(
api_key: str,
model: str = "deepseek-chat"
) -> dict
"""Agent 主流程:
1. 调用 git_utils.get_full_diff()
2. 组装 prompt,调用 LLMClient
3. 解析 tool_calls
4. 返回 {"type": str, "title": str, "body": str}
或 {"error": str}
返回值格式(成功):
{"type": "feat", "title": "feat: 添加用户登录", "body": "..."}
返回值格式(失败):
{"error": "没有检测到代码变更"}
"""
4.5 cli.py
def main()
"""CLI 入口,支持参数:
--model: 模型名称(默认 deepseek-chat)
--stage: 自动暂存所有变更
--api-key: API Key(默认读环境变量 DEEPSEEK_API_KEY)
流程:
1. 解析参数
2. 可选:自动暂存
3. 调用 agent
4. 展示预览
5. 交互确认
6. 执行 commit
"""
五、工具定义设计
这是 Agent 的说明书,定义好坏直接影响 LLM 的调用准确性。采用 OpenAI / DeepSeek 兼容格式:
{
"type": "function",
"function": {
"name": "generate_commit_message",
"description": "根据 git diff 生成符合 Conventional Commits 规范的 commit message。"
"分析变更的类型(feat/fix/refactor/docs/style/test/chore)"
"和影响范围,返回格式化的提交标题与正文。",
"parameters": {
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "commit 标题,格式为 <type>: <描述>,不超过 72 字符"
},
"type": {
"type": "string",
"enum": ["feat", "fix", "refactor", "docs", "style", "test", "chore"],
"description": "变更类型:feat=新功能, fix=修复, refactor=重构, docs=文档, style=格式, test=测试, chore=构建/工具"
},
"body": {
"type": "string",
"description": "commit 正文(可选),说明为什么做这个变更而非做了什么,每行不超过 72 字符"
}
},
"required": ["title", "type"]
}
}
}
和 Anthropic 格式的对比:
| 对比项 | Anthropic | DeepSeek / OpenAI |
|---|---|---|
| 外层包装 | 无 | {"type": "function", "function": {...}} |
| 参数名 | input_schema |
parameters |
| 响应方式 | content 中的 tool_use block |
message.tool_calls 数组 |
| arguments 类型 | 直接是 dict | JSON 字符串 |
六、总结
设计要点回顾
| 方面 | 决策 | 理由 |
|---|---|---|
| 架构 | 单 Agent + 单工具 | 复杂度最低,聚焦核心概念 |
| 工具数 | 1 个 | v1 不需要多个工具 |
| API | DeepSeek(OpenAI 兼容格式) | 你有 API Key,通用性强 |
| SDK | openai (Python) | 最广泛使用的 LLM SDK |
| 框架 | 无框架,直接调 SDK | 理解底层,避免抽象泄露 |
| CLI | argparse 原生 | 零额外依赖 |
| 环境变量 | DEEPSEEK_API_KEY |
与 DeepSeek 官方推荐一致 |
更多推荐

所有评论(0)