摘要

本文面向程序员、AI 工具使用者与软件开发团队,系统梳理 ChatGPT Plus、ChatGPT Pro 与 Codex 在真实软件开发流程中的定位与配合方式。文章从需求分析、项目理解、代码生成、测试编写、调试到代码审查,给出一个可落地、可验证的 AI 编程工作流,并以一个 FastAPI 任务管理 API 为例,完整演示如何让 Codex 在受限范围内修改代码、补充测试并通过持续集成验证。读者将获得可直接复用的 Codex 提示词模板、Git 审查清单与安全实践,从而建立安全、可控的 AI 辅助开发流程。具体可用功能以当前官方页面为准,不同账号、地区或版本可能存在差异。

目录

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

很多开发者习惯把 ChatGPT 当作一个"什么都能聊"的窗口,遇到问题就直接粘贴代码、要求"帮我写一个功能"。这种用法在讨论思路时有效,但一旦进入真实仓库,问题就会暴露:模型看不到你的项目结构,不知道哪些文件互相依赖,也不清楚测试框架和代码规范。于是它给出的代码往往"看起来合理",却无法直接落地。

ChatGPT 的核心价值在于对话式推理。它适合梳理需求、讨论架构、解释报错、评审设计,这些任务不依赖完整仓库上下文,而是依赖逻辑分析和知识储备。Codex 则不同,它被设计为面向仓库级任务的编程代理,能够读取项目文件、定位相关代码、在受限范围内修改,并运行测试来验证结果。两者不是替代关系,而是分工关系。

因此,不能只靠一句"帮我写代码"就期望得到可合并的修改。仓库上下文、测试要求和任务边界,是决定 AI 编程质量的三根支柱。没有上下文,模型只能猜测;没有测试,修改无法验证;没有边界,AI 可能改动无关文件。理解这一点,是建立可控 AI 编程流程的前提。

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

下表从开发场景出发,对比 ChatGPT Plus、ChatGPT Pro 与 Codex 的定位差异。需要说明的是,订阅服务与 OpenAI API 属于独立使用体系,是否包含 API 调用额度以官方资料为准,本文不讨论价格与购买渠道。

工具或方案 主要定位 适合任务 输入信息 输出结果 使用风险
ChatGPT Plus 通用对话与推理助手 需求梳理、架构讨论、代码解释、报错分析、文档撰写 对话文本、粘贴的代码片段、上传文件 文本回答、代码片段、改进建议 缺乏仓库上下文,可能给出不匹配项目的代码
ChatGPT Pro 面向更高强度使用的对话与推理方案 长对话、复杂推理、多轮设计讨论、大规模代码审阅辅助 对话文本、长文档、多文件内容 更深入的推理结论、结构化方案 仍非仓库级代理,需人工核对落地细节
Codex 仓库级编程代理 阅读项目、定位文件、受限修改、补测试、运行验证 仓库访问权限、任务说明、Git 分支 实际代码修改、测试结果、修改摘要 可能改错文件、破坏逻辑,必须配合 Git 与测试

从表中可以看出,ChatGPT 系列擅长"想清楚",Codex 擅长"改到位"。一个完整的开发流程,往往需要两者交替使用:先用 ChatGPT 把需求和方案讨论清楚,再用 Codex 在仓库中执行修改,最后回到 ChatGPT 对 diff 做二次解释。

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

下面是一套经过实践检验的 AI 编程工作流,核心思想是:让 AI 在受限范围内工作,用 Git 和测试作为安全边界。

需求说明

分析项目

制定修改计划

创建Git分支

修改代码

运行测试

测试是否通过

人工代码审查

合并代码

第一步是明确需求。需求必须具体、可验证,例如"为任务模型增加 priority 字段,取值 low/medium/high,默认 medium,并支持按优先级筛选"。模糊的需求会导致 AI 自行猜测,产生不可控的修改。

第二步是阅读项目。让 Codex 先分析目录结构、找出相关文件、说明调用关系,而不是直接动手改。这一步能显著降低改错文件的概率。

第三步是制定修改计划。要求 Codex 输出将要修改哪些文件、每个文件改什么、是否新增依赖。计划确认后再执行,避免 AI 擅自扩大改动范围。

第四步是创建独立 Git 分支。分支是回滚的保险,任何 AI 修改都应在分支上进行,绝不直接改主分支或生产环境。

第五步到第七步是修改、测试、再修改的循环。Codex 修改代码后必须运行测试,测试失败则继续修复,直到全部通过。测试是验证 AI 修改正确性的最重要手段。

第八步是查看代码差异。开发者必须亲自检查 git diff,确认没有无关文件被改动、没有删除原有逻辑、没有引入硬编码或密钥。

第九步是人工审查。AI 的解释不能替代人工判断,尤其是安全性和边界条件,必须由开发者最终把关。

第十步是合并代码。合并前确保测试通过、diff 干净、审查完成,必要时通过持续集成再次验证。

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

本节以一个任务管理 API 为例,演示如何让 Codex 在真实项目中完成一次受控修改。项目需求如下:

为现有任务管理 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 环境准备

以下命令在项目根目录执行,创建虚拟环境并安装依赖:

python3.11 -m venv .venv
source .venv/bin/activate
pip install "fastapi" "uvicorn[standard]" "pydantic" "pytest" "httpx"

启动项目:

uvicorn app.main:app --reload

运行测试:

pytest -q

4.3 核心业务代码

app/models.py 定义数据模型与优先级校验:

from enum import Enum
from pydantic import BaseModel, Field, field_validator


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


class Task(BaseModel):
    id: int
    title: str = Field(..., min_length=1, max_length=200)
    priority: Priority = Priority.medium


class TaskCreate(BaseModel):
    title: str = Field(..., min_length=1, max_length=200)
    priority: Priority = Priority.medium

    @field_validator("title")
    @classmethod
    def title_not_blank(cls, v: str) -> str:
        if not v.strip():
            raise ValueError("title must not be blank")
        return v.strip()

app/service.py 实现内存存储与优先级筛选逻辑:

from typing import Optional
from .models import Task, TaskCreate, Priority


class TaskService:
    def __init__(self) -> None:
        self._tasks: dict[int, Task] = {}
        self._next_id = 1

    def create(self, payload: TaskCreate) -> Task:
        task = Task(id=self._next_id, title=payload.title, priority=payload.priority)
        self._tasks[task.id] = task
        self._next_id += 1
        return task

    def list_tasks(self, priority: Optional[Priority] = None) -> list[Task]:
        tasks = list(self._tasks.values())
        if priority is not None:
            tasks = [t for t in tasks if t.priority == priority]
        return tasks

    def get(self, task_id: int) -> Optional[Task]:
        return self._tasks.get(task_id)

app/main.py 提供 API 路由与错误处理:

from fastapi import FastAPI, HTTPException, Query
from .models import Task, TaskCreate, Priority
from .service import TaskService

app = FastAPI(title="Task API")
service = TaskService()


@app.post("/tasks", response_model=Task, status_code=201)
def create_task(payload: TaskCreate) -> Task:
    return service.create(payload)


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


@app.get("/tasks/{task_id}", response_model=Task)
def get_task(task_id: int) -> Task:
    task = service.get(task_id)
    if task is None:
        raise HTTPException(status_code=404, detail="task not found")
    return task

4.4 自动化测试

tests/test_tasks.py 覆盖正常创建、默认优先级、非法优先级、筛选、空结果与原有功能:

import pytest
from fastapi.testclient import TestClient
from app.main import app

client = TestClient(app)


def setup_function() -> None:
    # 每个测试前重置服务状态
    from app.main import service
    service._tasks.clear()
    service._next_id = 1


def test_create_task() -> None:
    resp = client.post("/tasks", json={"title": "写周报"})
    assert resp.status_code == 201
    data = resp.json()
    assert data["title"] == "写周报"
    assert data["priority"] == "medium"


def test_default_priority_is_medium() -> None:
    resp = client.post("/tasks", json={"title": "默认优先级"})
    assert resp.json()["priority"] == "medium"


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


def test_filter_by_priority() -> None:
    client.post("/tasks", json={"title": "低", "priority": "low"})
    client.post("/tasks", json={"title": "高", "priority": "high"})
    resp = client.get("/tasks", params={"priority": "high"})
    data = resp.json()
    assert len(data) == 1
    assert data[0]["title"] == "高"


def test_filter_empty_result() -> None:
    resp = client.get("/tasks", params={"priority": "high"})
    assert resp.json() == []


def test_existing_get_still_works() -> None:
    created = client.post("/tasks", json={"title": "保留功能"}).json()
    resp = client.get(f"/tasks/{created['id']}")
    assert resp.status_code == 200
    assert resp.json()["title"] == "保留功能"

测试是使用 Codex 修改代码时的重要安全边界。没有测试,AI 的修改是否正确只能靠肉眼判断;有了测试,任何破坏原有逻辑的改动都会在 pytest 阶段暴露。因此,要求 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"
      - name: Install dependencies
        run: |
          pip install "fastapi" "uvicorn[standard]" "pydantic" "pytest" "httpx"
      - name: Run tests
        run: pytest -q

4.6 查看并审查修改

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

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

审查时应重点确认:是否修改了无关文件;是否删除了原有逻辑;是否引入新的依赖;是否存在硬编码;是否遗漏异常处理;是否存在安全风险;测试是否真正覆盖需求。任何一项不满足,都应要求 Codex 修正或手动回退。

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

以下三个模板可直接复用,方括号内容根据项目替换。

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

请阅读当前仓库,完成以下任务,暂时不要修改任何代码:
1. 列出项目目录结构,说明主要模块职责。
2. 找出与[任务优先级]相关的文件,说明它们之间的调用关系。
3. 分析当前实现中[任务创建与查询]的完整数据流。
4. 给出实现[按优先级筛选]的修改计划,列出涉及文件与改动点。
5. 指出可能影响现有功能的风险点。

这样写的原因:先让 Codex 建立项目认知,再要求输出计划而非直接改代码,能显著降低改错文件的概率。可替换部分为具体功能名、模块名或文件路径。

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

请实现以下功能,并严格遵守约束:
功能目标:[为任务模型增加 priority 字段,取值 low/medium/high,默认 medium,并支持按优先级筛选]。
约束:
1. 只允许修改 app/ 和 tests/ 目录下的文件。
2. 保持现有 API 的向后兼容,不得删除或重命名已有接口。
3. 必须补充 pytest 测试,覆盖正常、边界与异常场景。
4. 修改完成后运行 pytest -q,确保全部通过。
5. 汇总修改的文件清单与每个文件的改动摘要。

这样写的原因:明确功能目标、限定目录、要求兼容与测试,等于给 AI 划定了安全边界。可替换部分为功能描述、允许修改的目录、测试命令。

模板三:代码审查

请对当前分支的代码修改进行审查,不要修改代码:
1. 检查逻辑错误与边界条件,例如空列表、非法输入、重复创建。
2. 检查安全问题,例如密钥泄露、注入、越权访问。
3. 检查异常处理是否完整,是否存在未捕获的失败路径。
4. 检查测试覆盖是否真正覆盖需求,是否存在只测正常路径的情况。
5. 按严重程度(高/中/低)分类输出问题清单,并给出修改建议。

这样写的原因:审查任务要求"只读不改",避免 AI 在审查过程中擅自改动代码。可替换部分为审查范围、关注的安全类型、输出格式。

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

一个典型的协同场景如下:开发者先用 ChatGPT 梳理需求和业务规则,例如"任务优先级应该支持哪些取值、筛选时是否包含默认值",把模糊想法变成明确规格。接着用 ChatGPT 讨论架构与技术选型,例如是否引入数据库、是否使用枚举类型,形成方案后再交给 Codex。

Codex 负责仓库级执行:阅读项目、定位文件、在受限范围内修改、补充测试并运行验证。修改完成后,开发者可以把 git diff 粘贴回 ChatGPT,请它对代码差异做第二次解释,检查是否有遗漏的风险点。最终由开发者完成人工审查并合并代码。

需要强调的是,这套流程不是全自动的。ChatGPT 与 Codex 是辅助工具,决策权始终在开发者手中。AI 可能生成看似合理但存在隐患的代码,人工审查与测试是最后两道防线。

七、常见错误与解决方法

  1. 提示词只有一句话。改进:给出功能目标、约束、测试要求与输出格式,参考第五节模板。
  2. 没有限制修改范围。改进:在提示词中明确允许修改的目录或文件,防止 AI 改动无关代码。
  3. 没有先让 Codex 阅读项目。改进:先执行"分析项目"任务,再进入修改阶段。
  4. 没有创建独立分支。改进:任何 AI 修改前先 git checkout -b feature/xxx,保留回滚能力。
  5. 没有要求补充测试。改进:把"补充测试并运行通过"写进提示词,作为硬性约束。
  6. 不检查 Git diff。改进:合并前必须执行 git diff 并逐项核对,参考 4.6 节清单。
  7. 一次提交过多需求。改进:把大需求拆成多个小任务,每个任务独立分支、独立验证。
  8. 把密钥写入代码。改进:使用环境变量或密钥管理服务,并在审查时检查硬编码。
  9. 直接修改生产环境。改进:所有修改先在分支与测试环境验证,通过后再合并发布。
  10. 完全相信 AI 的解释。改进:AI 的解释只是参考,必须结合测试结果与人工审查做最终判断。

八、安全与隐私

使用 AI 编程工具时,安全与隐私必须放在首位。API Key 和访问令牌绝不能直接写入代码或提交到 Git 仓库,应通过环境变量注入。例如:

import os

api_key = os.environ.get("OPENAI_API_KEY")
if not api_key:
    raise RuntimeError("OPENAI_API_KEY is not set")

同时,不要向模型提交生产环境密码、数据库连接串或用户隐私数据。检查日志输出,避免把敏感信息打印到控制台或写入日志文件。在配置 Codex 等工具时,遵循最小权限原则,只授予完成任务所需的最小仓库权限,不授予生产环境访问权。对外部依赖进行审查,确认来源可信、版本明确。最后,AI 生成的代码仍需进行安全测试,包括输入校验、越权访问与依赖漏洞扫描,不能因为代码由 AI 生成就跳过安全审查。

九、总结

ChatGPT Plus、ChatGPT Pro 与 Codex 在软件开发中各有定位:前者擅长对话式推理与方案设计,后者擅长仓库级修改与验证。通过"明确需求、分析项目、制定计划、独立分支、受限修改、测试验证、人工审查"这套工作流,开发者可以把 AI 变成可控的编程助手,而不是不可控的代码生成器。本文的 FastAPI 案例、提示词模板与审查清单,可直接用于日常开发。具体产品功能与额度以当前官方页面为准,不同账号、地区或版本可能存在差异,本文重点讨论技术工作流,不对动态额度作固定承诺。

Logo

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

更多推荐