摘要

本文围绕 ChatGPT Plus / Pro + Codex 的组合,讲解如何把 AI 对话工具与仓库级编码工具接入一条可控的软件开发流程。文章先厘清 ChatGPT 与 Codex 的定位差异,再给出从需求分析、代码生成、测试、调试到代码审查的完整工作流,并用一个 FastAPI 任务管理 API 作为实战案例,演示如何让 Codex 在独立 Git 分支上完成受限修改、补充 pytest 测试并通过 GitHub Actions 验证。读者可以获得可直接复用的 Codex 提示词模板、Git 审查清单与安全实践,建立“AI 辅助、人工把关”的开发方法。

目录

一、为什么开发者需要区分 ChatGPT 与 Codex

很多开发者习惯在 ChatGPT 里粘贴一段代码,然后说“帮我改一下”。这种用法适合讨论思路,却不适合直接落地到真实仓库。原因在于:ChatGPT 的对话上下文通常来自你手动粘贴的片段,它看不到整个项目的目录结构、依赖关系、既有测试和调用链。当问题涉及多个文件、需要理解历史改动或要保证不破坏既有功能时,仅靠对话很难给出可靠结果。

Codex 则面向仓库级任务:它可以读取项目文件、定位相关模块、在受限范围内修改代码,并配合 Git 与测试工具完成验证。它更适合“读仓库、改代码、跑测试”这类需要项目上下文的操作。

因此,正确做法不是二选一,而是分工:用 ChatGPT 梳理需求和讨论方案,用 Codex 在仓库里执行受限修改,再用测试和人工审查兜底。这也是本文反复强调“任务边界”的原因——没有明确边界,AI 很容易改错文件或破坏原有逻辑。

二、ChatGPT Plus、ChatGPT Pro 与 Codex 的技术定位

下表从开发场景出发,对比 ChatGPT Plus、ChatGPT Pro 与 Codex 的定位差异。表格只讨论技术能力与适用任务,不涉及价格、购买方式或充值问题。

工具或方案 主要定位 适合任务 输入信息 输出结果 使用风险
ChatGPT Plus 通用对话与推理 需求梳理、方案讨论、代码解释、文档撰写 对话文本、粘贴的代码片段 文本回答、示例代码、方案建议 缺少仓库上下文,可能给出脱离实际的建议
ChatGPT Pro 面向更高强度使用的对话与推理 长对话、复杂推理、多轮技术讨论、架构权衡 对话文本、较长上下文、粘贴资料 更深入的分析与方案 仍需人工核对,不能直接操作仓库
Codex 仓库级编码与修改 阅读项目、定位文件、受限修改、补测试、跑测试 仓库文件、Git 状态、任务提示词 代码改动、测试结果、修改摘要 可能改错文件、引入回归或泄露敏感信息

需要说明的是:ChatGPT Plus 与 ChatGPT Pro 属于 ChatGPT 订阅服务,Codex 是面向开发者的编码工具,二者与 OpenAI API 属于不同的使用体系。具体功能、可用范围和套餐权益可能随版本、账号和地区变化,请以 OpenAI 当前官方页面为准。本文重点讨论技术工作流,不对动态额度作固定承诺。

三、一套可控的 AI 编程工作流

要让 AI 修改代码而不失控,建议遵循下面这条流程。它的核心是:把 AI 的修改限制在独立分支上,用测试作为客观闸门,用 Git diff 作为人工审查入口

需求说明

分析项目

制定修改计划

创建Git分支

修改代码

运行测试

测试是否通过

人工代码审查

合并代码

逐步解释每个环节:

  1. 明确需求:把要解决的问题写清楚,包括功能目标、允许修改的文件、禁止修改的内容和验收标准。
  2. 阅读项目:先让 Codex 分析仓库结构、定位相关文件,输出理解和计划,不急着改代码。
  3. 制定修改计划:让 AI 列出将要改动哪些文件、每个文件改什么、如何验证,由你确认后再动手。
  4. 创建独立 Git 分支:所有 AI 修改都在 fix/feat/ 等前缀的分支上进行,保证主分支始终干净。
  5. 修改代码:在受限范围内让 Codex 执行修改,提示词里明确“允许修改”和“禁止修改”。
  6. 编写测试:要求 Codex 为新增或修改的逻辑补充单元测试,覆盖正常路径和异常路径。
  7. 运行测试:用 pytest 等工具验证,测试失败时先分析根因,再决定是修代码还是修测试。
  8. 查看代码差异:用 git diff 逐行检查 AI 到底改了什么,确认没有动无关文件。
  9. 进行人工审查:由开发者对逻辑、边界条件、安全性和测试覆盖做最终判断。
  10. 合并代码:确认无误后合并分支,必要时打标签以便回退。

四、实战项目:使用 Codex 辅助维护一个 Python API 项目

下面用一个任务管理 API 作为案例。需求是:为现有任务管理 API 增加任务优先级字段,并支持按照优先级筛选,同时补充单元测试和持续集成检查

4.1 项目目录

task-api/
├── app/
│   ├── __init__.py
│   ├── main.py
│   ├── models.py
│   └── service.py
├── tests/
│   └── test_tasks.py
├── pyproject.toml
└── .github/
    └── workflows/
        └── test.yml

4.2 环境准备

cd task-api
python -m venv .venv
source .venv/bin/activate
pip install "fastapi" "uvicorn" "pydantic" "pytest" "httpx"
uvicorn app.main:app --reload
pytest -q

这里用 httpx 是因为 FastAPI 的 TestClient 依赖它发起测试请求。所有命令都在项目根目录执行,前后保持一致。

4.3 核心业务代码

先定义数据模型。优先级使用枚举,避免非法字符串进入系统:

# app/models.py
from enum import Enum

from pydantic import BaseModel, Field


class Priority(str, Enum):
    low = "low"
    medium = "medium"
    high = "high"


class Task(BaseModel):
    id: int
    title: str
    priority: Priority = Priority.medium

业务逻辑放在 service.py,用内存列表模拟存储,便于测试:

# app/service.py
from app.models import Priority, Task

_tasks: list[Task] = []
_next_id = 1


def create_task(title: str, priority: Priority) -> Task:
    global _next_id
    task = Task(id=_next_id, title=title, priority=priority)
    _tasks.append(task)
    _next_id += 1
    return task


def list_tasks(priority: Priority | None = None) -> list[Task]:
    if priority is None:
        return list(_tasks)
    return [t for t in _tasks if t.priority == priority]

API 路由负责参数校验和错误处理:

# app/main.py
from fastapi import FastAPI, HTTPException, Query

from app.models import Priority, Task
from app.service import create_task, list_tasks

app = FastAPI()


@app.post("/tasks", response_model=Task, status_code=201)
def add_task(title: str = Query(..., min_length=1), priority: Priority = Priority.medium):
    return create_task(title, priority)


@app.get("/tasks", response_model=list[Task])
def get_tasks(priority: Priority | None = None):
    return list_tasks(priority)


@app.get("/tasks/{task_id}", response_model=Task)
def get_task(task_id: int):
    for task in list_tasks():
        if task.id == task_id:
            return task
    raise HTTPException(status_code=404, detail="task not found")

Priority 枚举让 FastAPI 自动校验非法优先级,非法值会返回 422 而不是进入业务逻辑。Query(min_length=1) 保证标题非空。

4.4 自动化测试

# tests/test_tasks.py
from fastapi.testclient import TestClient

from app.main import app

client = TestClient(app)


def test_create_task_normal():
    resp = client.post("/tasks", params={"title": "写周报", "priority": "high"})
    assert resp.status_code == 201
    body = resp.json()
    assert body["title"] == "写周报"
    assert body["priority"] == "high"


def test_default_priority_is_medium():
    resp = client.post("/tasks", params={"title": "默认任务"})
    assert resp.status_code == 201
    assert resp.json()["priority"] == "medium"


def test_invalid_priority_rejected():
    resp = client.post("/tasks", params={"title": "非法", "priority": "urgent"})
    assert resp.status_code == 422


def test_filter_by_priority():
    client.post("/tasks", params={"title": "低优先级", "priority": "low"})
    client.post("/tasks", params={"title": "高优先级", "priority": "high"})
    resp = client.get("/tasks", params={"priority": "high"})
    assert resp.status_code == 200
    assert all(t["priority"] == "high" for t in resp.json())


def test_filter_empty_result():
    resp = client.get("/tasks", params={"priority": "low"})
    assert resp.status_code == 200
    assert resp.json() == []


def test_existing_route_still_works():
    resp = client.get("/tasks/1")
    assert resp.status_code in (200, 404)

测试是使用 Codex 修改代码时的重要安全边界:它把“改对了没有”变成可客观判断的问题。只要测试覆盖了正常路径、默认值、非法输入、筛选和空结果,AI 的改动是否破坏原有功能就能被快速发现。

4.5 持续集成配置

# .github/workflows/test.yml
name: test

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - run: pip install "fastapi" "uvicorn" "pydantic" "pytest" "httpx"
      - run: pytest -q

这个配置在每次推送和 PR 时自动运行测试。文件名、依赖和测试命令与前面项目保持一致,确保 CI 能真实反映本地结果。

4.6 查看并审查修改

Codex 完成修改后,用以下命令检查改动:

git status
git diff
git diff --stat
git log --oneline -5
pytest -q

审查时应重点确认:是否修改了无关文件、是否删除了原有逻辑、是否引入新的依赖、是否存在硬编码、是否遗漏异常处理、是否存在安全风险、测试是否真正覆盖需求。这些检查项是人工审查的核心,AI 无法替代。

五、给 Codex 的高质量任务提示词

模板一:分析项目,不修改代码

请阅读 task-api 项目,重点分析 app/ 目录下的文件。
任务目标:理解任务管理 API 的现有结构,找出新增优先级字段需要改动的文件。
允许修改范围:暂不修改任何代码。
禁止修改内容:不要改动 tests/ 目录,不要改动项目结构。
测试要求:不需要运行测试。
验证方式:只输出分析结论。
最终输出要求:
1. 列出相关文件及其调用关系;
2. 说明新增优先级字段需要改动哪些位置;
3. 给出修改计划,但不要写代码。

这样写是因为:先让 AI 建立对项目的理解,再动手,能显著降低改错文件的概率。项目名、目录和功能描述可以根据实际情况替换。

模板二:实现功能并补充测试

请为 task-api 项目新增任务优先级字段,并支持按优先级筛选。
任务目标:
1. 在 app/models.py 中新增 Priority 枚举,默认值为 medium;
2. 在 app/service.py 中支持按优先级筛选;
3. 在 app/main.py 中暴露筛选参数;
4. 补充对应单元测试。
允许修改范围:app/ 目录和 tests/test_tasks.py。
禁止修改内容:不要改动 pyproject.toml,不要改动 .github/ 目录,不要改动项目结构。
测试要求:新增测试必须覆盖正常创建、默认优先级、非法优先级、按优先级筛选、空结果五种场景。
验证方式:修改完成后运行 pytest -q,确保全部测试通过。
最终输出要求:列出修改的文件、每个文件的改动要点、pytest 运行结果。

这个模板的关键是“允许修改范围”和“禁止修改内容”成对出现,配合测试要求,把 AI 的行为约束在可控范围内。文件列表和功能描述按项目替换即可。

模板三:代码审查

请审查当前 Git 分支上的全部改动。
任务目标:找出代码中的逻辑错误、安全问题、边界条件遗漏和测试覆盖不足。
允许修改范围:不修改代码,只输出审查意见。
禁止修改内容:不要改动任何文件。
测试要求:不需要运行测试。
验证方式:基于 git diff 输出逐文件审查。
最终输出要求:
1. 按严重程度分类列出问题(严重、中等、轻微);
2. 每个问题说明影响和修改建议;
3. 检查是否包含硬编码或敏感信息;
4. 检查测试是否真正覆盖需求。

这个模板让 AI 扮演审查者而不是修改者,避免它在审查过程中顺手改代码。严重程度分类便于你决定先处理哪些问题。

六、ChatGPT Plus / Pro + Codex 的协同方式

两者不是替代关系,而是分工协作。一个典型的协同场景如下:

  1. 用 ChatGPT 梳理需求和业务规则:把产品需求贴给 ChatGPT,让它列出边界条件、异常场景和验收标准。
  2. 用 ChatGPT 讨论架构和技术选型:例如“优先级字段用枚举还是字符串”,让 ChatGPT 给出权衡。
  3. 用 Codex 阅读仓库并定位文件:让 Codex 分析项目结构,找出需要改动的模块。
  4. 用 Codex 执行受限范围内的修改:在独立分支上,按提示词模板二完成编码和测试。
  5. 用测试验证修改:运行 pytest,确认新增功能和原有功能都正常。
  6. 用 ChatGPT 对代码差异进行第二次解释:把 git diff 输出贴给 ChatGPT,让它从另一个角度解释改动的影响。
  7. 最终由开发者完成人工审查:所有 AI 输出都只是参考,合并决定权始终在开发者手里。

需要强调的是,这套流程不是全自动的。ChatGPT 负责“想清楚”,Codex 负责“改到位”,测试负责“验证对”,开发者负责“拍板”。任何一环都不能省略。

七、常见错误与解决方法

错误 1:提示词只有一句话

例如只说“帮我加个优先级字段”。AI 不知道改哪些文件、要不要补测试、怎么验证。

改进:按模板二写清楚目标、范围、测试要求和验证方式。

错误 2:没有限制修改范围

AI 可能顺手改了无关文件,甚至重构了不该动的模块。

改进:在提示词里明确“允许修改范围”和“禁止修改内容”。

错误 3:没有先让 Codex 阅读项目

直接让 AI 改代码,它可能基于猜测而不是真实代码结构。

改进:先用模板一让 Codex 输出理解和计划,确认后再动手。

错误 4:没有创建独立分支

AI 改坏代码后无法快速回退,主分支被污染。

改进:所有 AI 修改都在 fix/feat/ 分支上进行。

错误 5:没有要求补充测试

AI 只改代码不补测试,回归风险无法被发现。

改进:提示词里明确要求补充单元测试,并覆盖异常路径。

错误 6:不检查 Git diff

测试通过就直接合并,可能漏掉无关改动或安全隐患。

改进:合并前必须 git diff 逐行审查。

错误 7:一次提交过多需求

让 AI 同时改多个功能,任何一个出错都难以定位。

改进:一次只让 AI 处理一个需求,保持改动小而聚焦。

错误 8:把密钥写入代码

API Key、密码直接写进源码,AI 可能把它复制到日志或提交记录里。

改进:敏感配置一律用环境变量,并明确告诉 AI 禁止读取或输出密钥。

错误 9:直接修改生产环境

让 AI 直接改线上代码,风险极高且无法回退。

改进:所有改动先在分支和测试环境验证,通过后再走发布流程。

错误 10:完全相信 AI 的解释

AI 说“测试通过了”“逻辑没问题”,不代表真的没问题。

改进:以测试结果和 git diff 为准,AI 的解释只作参考。

八、安全与隐私

使用 AI 编程工具时,安全必须放在首位。以下是必须遵守的原则:

  • API Key 和访问令牌不能直接写入代码,统一使用环境变量;
  • 不向模型提交生产环境密码,即使是测试环境也要谨慎;
  • 检查日志和配置文件,确认没有泄露敏感信息;
  • 限制工具权限,只给 AI 完成当前任务所需的最小访问范围;
  • 使用最小权限原则,不要给 AI 开放整个仓库的写权限;
  • 对外部依赖进行审查,AI 引入的新依赖要先确认来源和安全性;
  • AI 生成代码仍需进行安全测试,不能因为“AI 写的”就跳过检查。

安全配置示例:

import os

api_key = os.environ.get("OPENAI_API_KEY")
if not api_key:
    raise RuntimeError("OPENAI_API_KEY 未设置,请通过环境变量注入")

这段代码从环境变量读取密钥,而不是硬编码在源码里。这样即使代码被提交到仓库,也不会泄露敏感信息。开发者应养成“密钥永远不进代码”的习惯。

九、总结

ChatGPT Plus / Pro + Codex 的组合,本质是用对话工具想清楚,用编码工具改到位,用测试和审查守住质量。ChatGPT 适合需求梳理、方案讨论和代码解释,Codex 适合在仓库里执行受限修改,而最终的质量判断必须由开发者完成。

本文给出的工作流可以概括为:明确需求 → 分析项目 → 制定计划 → 创建分支 → 修改代码 → 补充测试 → 运行测试 → 检查 diff → 人工审查 → 合并代码。配合三个可复用的提示词模板,你可以在真实项目中建立一套安全、可控的 AI 编程流程。

记住:AI 是效率工具,不是质量保证。测试通过、diff 干净、人工审查到位,才是合并代码的前提。用好这套方法,你就能既享受 AI 的速度,又守住代码的质量底线。

Logo

AtomGit AI 社区提供模型库、数据集、Agent、Token等资源

更多推荐