摘要在这里插入图片描述

本文面向程序员、AI 工具使用者与软件开发团队,系统梳理 ChatGPT Plus、ChatGPT Pro 与 Codex 在真实软件开发流程中的定位与配合方式。文章从需求分析、项目理解、代码生成、测试编写、调试到代码审查,给出可落地的技术工作流,并提供一个基于 FastAPI 的任务管理 API 实战案例,展示如何用 Codex 在受控范围内完成功能开发。读者将获得一套可复用的 AI 编程协作方法,包括高质量任务提示词模板、Git 分支策略、测试安全边界与持续集成验证手段,从而在提升效率的同时守住代码质量与安全底线。

目录

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

在日常开发中,很多开发者习惯把"AI 编程"等同于"在聊天框里让 AI 写一段代码"。这种理解在简单脚本场景下勉强够用,但一旦面对真实项目,就会暴露出严重问题:AI 不了解项目结构、不知道现有接口约定、无法运行测试,甚至可能把无关文件改坏。

ChatGPT 与 Codex 是两类不同的工具。ChatGPT 擅长对话式推理,适合需求梳理、方案讨论、代码解释和知识问答;而 Codex 面向仓库级任务,能够读取项目文件、定位相关代码、在受控范围内修改并运行测试。二者不是替代关系,而是上下游协作关系。

为什么不能只靠一句"帮我写代码"?因为真实项目包含大量隐式约束:目录结构、依赖版本、命名规范、既有测试、数据库模型、API 路由约定等。这些信息不在对话上下文中,而在仓库里。只有让 AI 先读项目、再给任务边界、最后用测试验证,才能得到可靠结果。

仓库上下文、测试要求和任务边界,是决定 AI 编程成败的三个关键因素。仓库上下文让 AI 知道改哪里;测试要求让 AI 知道怎样算完成;任务边界防止 AI 越权修改无关代码。三者缺一不可。

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

下表从开发场景角度对比三类方案。需要说明的是,具体可用功能、模型版本与额度以当前官方页面为准,不同账号、地区或版本可能存在差异,本文不对动态额度作固定承诺。

工具或方案 主要定位 适合任务 输入信息 输出结果 使用风险
ChatGPT Plus 通用对话助手 需求梳理、架构讨论、代码解释、文档撰写 自然语言描述、粘贴的代码片段 文本回答、代码片段、方案建议 无仓库上下文,可能给出与项目不符的建议
ChatGPT Pro 高强度对话与推理 复杂问题分析、长文档理解、多轮深度讨论 自然语言、长文本、多文件粘贴 深度分析、方案对比、详细解释 上下文仍受对话窗口限制,不直接操作仓库
Codex 仓库级编码代理 阅读项目、定位文件、实现功能、补测试、跑测试 仓库访问权限、自然语言任务说明 代码修改、测试结果、文件变更汇总 可能改错文件、破坏逻辑,需人工审查

从表中可以看出,ChatGPT 系列解决"想清楚"的问题,Codex 解决"改到位"的问题。开发者应把前者当作思考伙伴,把后者当作受控的执行者,而不是让任何一方独立完成整个开发流程。

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

下面是一套经过实践检验的 AI 编程工作流,核心思想是:让 AI 在受限范围内工作,用测试和人工审查守住质量边界。

需求说明

分析项目

制定修改计划

创建Git分支

修改代码

运行测试

测试是否通过

人工代码审查

合并代码

第一步,明确需求。把业务目标写清楚,包括输入、输出、边界条件和验收标准。第二步,阅读项目。让 Codex 先分析目录结构、找出相关文件、说明调用关系,这一步不修改任何代码。第三步,制定修改计划。要求 Codex 输出将要改动哪些文件、每个文件改什么、是否新增依赖。第四步,创建独立 Git 分支。确保 AI 的修改与主分支隔离,便于回滚和审查。

第五步,修改代码。在计划确认后,让 Codex 在限定目录内实现功能。第六步,编写测试。要求 Codex 为新增功能补充单元测试,并确保原有测试不被破坏。第七步,运行测试。用 pytest 等工具验证全部用例通过。第八步,查看代码差异。通过 git diff 检查改动范围,确认没有触碰无关文件。第九步,进行人工审查。开发者逐行检查逻辑、安全性和边界条件。第十步,合并代码。只有测试通过且审查无异议后,才合并到主分支。

这套流程的关键在于:每一步都有明确的输入输出和验收标准,AI 的自主性被限制在"改代码"和"跑测试"两个环节,而"决定改什么"和"确认改对了"始终由开发者掌控。

四、实战项目:使用 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>=0.110" "uvicorn>=0.29" "pydantic>=2.6" "pytest>=8.0" "httpx>=0.27"

启动项目:

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 cannot be blank")
        return v.strip()

业务逻辑 app/service.py

from typing import Optional

from .models import Priority, Task, TaskCreate


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(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)

API 路由 app/main.py

from typing import Optional

from fastapi import FastAPI, HTTPException, Query, status

from .models import Priority, Task, TaskCreate
from .service import TaskService

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


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


@app.get("/tasks", response_model=list[Task])
def list_tasks(
    priority: Optional[Priority] = Query(default=None, description="Filter by priority"),
) -> list[Task]:
    return service.list(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

app/__init__.py 保持为空文件即可。以上代码覆盖了数据模型、API 路由、参数校验、优先级筛选和基本错误处理。

4.4 自动化测试

测试文件 tests/test_tasks.py

import pytest
from fastapi.testclient import TestClient

from app.main import app
from app.models import Priority

client = TestClient(app)


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


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


def test_default_priority_is_medium() -> None:
    resp = client.post("/tasks", json={"title": "default priority"})
    assert resp.status_code == 201
    assert resp.json()["priority"] == "medium"


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


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


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


def test_existing_endpoint_not_broken() -> None:
    created = client.post("/tasks", json={"title": "keep me"}).json()
    resp = client.get(f"/tasks/{created['id']}")
    assert resp.status_code == 200
    assert resp.json()["title"] == "keep me"

为什么测试是使用 Codex 修改代码时的重要安全边界?因为测试把"AI 说改好了"变成"测试证明改好了"。没有测试,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>=0.110" "pydantic>=2.6" "pytest>=8.0" "httpx>=0.27"
      - name: Run tests
        run: pytest -q

该配置在每次推送和拉取请求时自动运行测试,确保 AI 的修改在合并前经过自动化验证。

4.6 查看并审查修改

常用 Git 命令:

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

开发者应重点检查以下内容:是否修改了无关文件;是否删除了原有逻辑;是否引入新的依赖;是否存在硬编码;是否遗漏异常处理;是否存在安全风险;测试是否真正覆盖需求。例如,如果 git diff 显示 Codex 顺手改了 service.py 中与优先级无关的函数,就应该要求它撤销这部分改动。

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

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

请阅读当前仓库,完成以下任务,但不要修改任何代码:
1. 列出项目目录结构,说明每个主要模块的职责。
2. 找出与"任务管理"相关的所有文件,说明它们之间的调用关系。
3. 分析现有数据模型和 API 路由,指出新增"优先级"字段需要改动哪些文件。
4. 给出一个分步修改计划,包括每个文件的具体改动点。
5. 最后汇总你计划修改的文件清单,等待我确认后再动手。

为什么这样写?因为先分析后动手,可以避免 AI 在错误的方向上浪费修改。其中"项目目录结构"“调用关系”"文件清单"都可以根据实际项目替换为更具体的模块名或路径。

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

请基于以下需求实现功能,并严格遵守约束:
需求:为任务管理 API 增加 priority 字段,支持 low/medium/high 三个值,默认 medium,并支持按优先级筛选。
约束:
1. 只允许修改 app/ 和 tests/ 目录下的文件,禁止改动其他目录。
2. 保持现有 API 的向后兼容,已有接口的请求和响应格式不得破坏。
3. 为新增功能补充 pytest 测试,覆盖正常创建、默认值、非法值、筛选和空结果。
4. 修改完成后运行 pytest -q,确保全部测试通过。
5. 最后汇总你修改和新增的文件列表,并说明每个文件的改动内容。

为什么这样写?"只允许修改 app/ 和 tests/"限定了修改范围;"保持向后兼容"防止破坏既有接口;"补充 pytest 测试"把验收标准明确化;"运行 pytest -q"要求 AI 自证结果;"汇总文件列表"方便人工审查。目录名、需求描述和测试要求都可以按项目替换。

模板三:代码审查

请对当前分支的代码变更进行审查,不要修改任何代码:
1. 检查逻辑错误,包括空指针、越界、类型不匹配和错误处理缺失。
2. 检查安全问题,包括硬编码密钥、注入风险、敏感信息泄露。
3. 检查边界条件,包括空输入、超长输入、重复提交和并发访问。
4. 检查测试覆盖,指出哪些关键路径缺少测试。
5. 按严重程度(高/中/低)分类列出发现的问题,每条给出文件、行号和修改建议。

为什么这样写?"不要修改任何代码"让 AI 专注于审查而非动手;"按严重程度分类"帮助开发者优先处理高风险问题;"给出文件、行号和修改建议"让问题可定位、可执行。审查范围、关注点类型都可以根据项目调整。

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

在实际开发中,两类工具可以形成明确的分工。以本文的实战案例为例,一个典型的协同流程如下:

首先,使用 ChatGPT 梳理需求和业务规则。开发者可以这样提问:"任务管理 API 需要支持优先级,请帮我列出字段取值、默认值、筛选逻辑和边界情况。"ChatGPT 会给出结构化的需求清单,帮助开发者把模糊想法变成可执行的任务说明。

其次,使用 ChatGPT 讨论架构和技术选型。例如,询问"优先级字段应该用枚举还是字符串?筛选应该放在 service 层还是路由层?"这类讨论有助于在动手前确定设计方向。

然后,使用 Codex 阅读仓库并定位文件。通过模板一,让 Codex 分析项目结构、找出相关文件、给出修改计划。这一步把"改哪里"的问题交给代码级工具解决。

接着,使用 Codex 执行受限范围内的修改。通过模板二,让 Codex 在限定目录内实现功能并补充测试。此时 ChatGPT 的讨论结果已经转化为明确的任务说明,Codex 只需按计划执行。

之后,使用测试验证修改。运行 pytest 确认全部用例通过,再通过 git diff 检查改动范围。如果测试失败,可以让 Codex 根据失败信息修复,也可以把失败信息粘贴给 ChatGPT 分析原因。

最后,使用 ChatGPT 对代码差异进行第二次解释。开发者可以把 git diff 的输出粘贴给 ChatGPT,请它解释每个改动的意图、潜在风险和优化空间。这相当于多了一双"AI 眼睛"帮助审查,但最终决策权仍在开发者手中。

需要强调的是,这套流程不是完全自动化的。ChatGPT 和 Codex 都是辅助工具,需求确认、方案决策、代码审查和合并操作始终由开发者完成。

七、常见错误与解决方法

  1. 提示词只有一句话。例如"帮我加个优先级功能"。改进方法:使用模板二,明确需求、约束、测试要求和输出格式。

  2. 没有限制修改范围。AI 可能改动无关文件。改进方法:在提示词中明确"只允许修改 app/ 和 tests/ 目录"。

  3. 没有先让 Codex 阅读项目。AI 在不了解结构的情况下盲目修改。改进方法:先使用模板一进行分析,确认计划后再动手。

  4. 没有创建独立分支。AI 的修改直接落在主分支,难以回滚。改进方法:先 git checkout -b feature/priority 再让 Codex 工作。

  5. 没有要求补充测试。AI 改完代码但无法证明正确性。改进方法:在提示词中明确要求补充 pytest 测试并运行。

  6. 不检查 Git diff。AI 可能删除了原有逻辑而不自知。改进方法:合并前执行 git diff 逐行审查。

  7. 一次提交过多需求。AI 难以同时处理多个不相关变更。改进方法:一次只让 Codex 完成一个功能,保持提交粒度小。

  8. 把密钥写入代码。AI 可能把 API Key 硬编码进文件。改进方法:在提示词中明确禁止,并在审查时检查。

  9. 直接修改生产环境。AI 的未验证代码直接上线。改进方法:所有修改先在分支和 CI 中验证,通过后再合并部署。

  10. 完全相信 AI 的解释。AI 可能自信地给出错误结论。改进方法:用测试和人工审查验证 AI 的说法,不盲信。

八、安全与隐私

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

API Key 和访问令牌不能直接写入代码。应使用环境变量或密钥管理服务。示例:

import os

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

不向模型提交生产环境密码、数据库凭据或客户数据。在让 Codex 分析项目前,检查仓库中是否包含敏感信息,必要时使用 .gitignore 排除配置文件。

检查日志中的敏感信息。确保应用不会在日志中打印请求体、令牌或个人信息。可以在日志配置中过滤敏感字段。

限制工具权限。只授予 Codex 访问必要仓库的权限,不要使用具有全局写权限的账号。使用最小权限原则,让 AI 只能修改它需要修改的内容。

对外部依赖进行审查。AI 可能建议引入新的第三方库,合并前应检查该库的维护状态、许可证和已知漏洞。

AI 生成的代码仍需进行安全测试。不要因为代码由 AI 生成就跳过安全审查,应像对待人工代码一样进行输入校验、权限检查和依赖审计。

九、总结

本文围绕 ChatGPT Plus、ChatGPT Pro 与 Codex 在软件开发中的协同工作方式,给出了一套从需求分析到代码合并的完整流程。核心结论是:ChatGPT 系列负责"想清楚",Codex 负责"改到位",而开发者始终掌握决策权。通过限定修改范围、补充自动化测试、检查 Git 差异和进行人工审查,可以在提升效率的同时守住代码质量与安全底线。具体可用功能以当前官方页面为准,不同账号、地区或版本可能存在差异,但本文所述的技术工作流具有通用性,适用于大多数软件开发团队。

Logo

葡萄城是专业的软件开发技术和低代码平台提供商,聚焦软件开发技术,以“赋能开发者”为使命,致力于通过表格控件、低代码和BI等各类软件开发工具和服务,一站式满足开发者需求,帮助企业提升开发效率并创新开发模式。

更多推荐