在这里插入图片描述

摘要

本文面向需要使用 ChatGPT Plus / Pro 与 Codex 协同完成日常开发工作的程序员和团队,重点不是介绍产品功能,而是说明如何把对话式助手与仓库级编码工具放进一条可控的软件交付流程。文章首先区分 ChatGPT 与 Codex 的技术定位,随后给出从需求分析、项目阅读、计划制定、独立分支、编码修改、自动化测试到人工审查与合并的十步工作流,并用 FastAPI 任务管理 API 的完整案例演示如何让 Codex 在测试和 Git 的保护下修改代码。读者可以获得可直接复用的 Codex 提示词模板、pytest 测试、GitHub Actions 配置,以及降低错误修改、敏感信息泄露和逻辑破坏风险的具体方法。

目录

    1. 为什么开发者需要区分 ChatGPT 与 Codex
    1. ChatGPT Plus、ChatGPT Pro 与 Codex 的技术定位
    1. 一套可控的 AI 编程工作流
    1. 实战项目:使用 Codex 辅助维护一个 Python API 项目
    • 4.1 项目目录
    • 4.2 环境准备
    • 4.3 核心业务代码
    • 4.4 自动化测试
    • 4.5 持续集成配置
    • 4.6 查看并审查修改
    1. 给 Codex 的高质量任务提示词
    1. ChatGPT Plus / Pro + Codex 的协同方式
    1. 常见错误与解决方法
    1. 安全与隐私

1. 为什么开发者需要区分 ChatGPT 与 Codex

在实际工作中,“让 AI 写代码”至少包含四种不同任务:普通知识问答、技术方案讨论、仓库级项目理解和受限范围内的代码修改。它们对上下文、工具权限和验收标准的要求完全不同。ChatGPT 更适合交互式分析和方案推演,而 Codex 更擅长在给定仓库上下文中定位文件、执行修改并配合测试命令验证结果。把两者混用,容易让模型在不了解项目结构时猜测接口,或在没有测试保护时修改核心逻辑。

ChatGPT 适合解释概念、比较技术选型、起草接口设计、讨论边界条件、审阅代码差异和总结错误原因。它的价值来自对话过程,可以让开发者逐步澄清需求。Codex 则适合读取项目结构、跨文件修改、补充测试、运行命令并根据失败信息继续调整。它的价值来自与仓库和测试循环的紧密结合。

“帮我写代码”这句话的问题在于缺少任务边界。模型不知道要修改哪个文件、允许动哪些模块、是否需要保持兼容、由什么测试来验收。更安全的描述应该包含:问题背景、受影响目录、明确目标、验收方式、不允许做的事情。仓库上下文和测试要求不是附加项,而是把 AI 编码从“生成片段”变成“受控修改”的关键条件。

2. ChatGPT Plus、ChatGPT Pro 与 Codex 的技术定位

下表从开发场景出发,比较 ChatGPT Plus、ChatGPT Pro 与 Codex 类工具的定位。具体功能、模型版本和平台集成方式可能随官方发布调整,应以当前官方页面为准。

工具或方案 主要定位 适合任务 输入信息 输出结果 使用风险
ChatGPT Plus 通用对话与协作分析 需求拆分、概念解释、技术方案讨论、代码片段推演 自然语言问题、少量代码片段、设计约束 解释、方案建议、示例代码或审阅意见 无仓库上下文时容易给出脱离项目的代码
ChatGPT Pro 面向高频与复杂任务的对话分析 多轮需求梳理、复杂架构讨论、长文档与差异分析 业务规则、错误日志、代码差异、架构说明 结构化分析、方案对比、可讨论的实现建议 修改仍依赖人工落地,对话结论不宜直接视为可运行实现
Codex 类开发工具 仓库级编码代理 项目阅读、定位文件、跨文件修改、运行测试与修复 任务说明、路径约束、测试命令、验收标准 文件修改、运行结果、修改清单 可能改错文件、删除原逻辑或生成未覆盖边界情况的代码

需要特别说明:ChatGPT 订阅服务与 OpenAI API 属于不同使用体系。本文讨论的 Codex 形态偏重在开发环境中读取仓库、修改文件并执行命令的工作方式,不代表所有账号或版本都支持相同能力。是否包含 API 调用额度、可用模型、上下文长度和工具权限,应以 OpenAI 官方文档和产品页面为准。开发团队评估时应把产品能力、访问权限和内部合规要求分开确认,不要用网络上的旧经验替代当前官方信息。

3. 一套可控的 AI 编程工作流

AI 编程的风险主要来自修改范围失控、缺少自动化验证和过度信任生成结果。下面是一套适合个人开发和团队协作的最小流程:

明确需求

阅读项目

制定修改计划

创建 Git 分支

修改代码

编写并运行测试

测试是否通过

读取失败信息

查看代码差异

人工代码审查

合并代码

明确需求:把“支持优先级筛选”拆成数据模型变化、API 参数、存储逻辑和测试用例。需求越具体,模型越不容易自行扩大范围。

阅读项目:先让 Codex 读取目录、依赖和测试,输出涉及文件与调用关系。阅读阶段不修改代码,可以避免模型基于错误假设动手。

制定修改计划:将需求转成最小修改方案,说明改哪些文件、为什么改、哪些内容保持不变。计划应由开发者确认后再执行。

创建 Git 分支:独立分支是低成本回滚手段。任何 AI 修改都不应直接发生在主分支或生产环境。

修改代码:让 Codex 在限定目录内实施计划,保持向后兼容,避免重构与本次需求无关的模块。

编写并运行测试:测试必须覆盖新功能与原有行为。测试不通过时,把失败信息返回给 Codex,而不是继续叠加修改。

查看代码差异:使用 Git 检查改动范围,重点看是否出现无关文件、依赖变化和删除逻辑。

人工代码审查:AI 只能减少书写负担,不能替代所有权判断。开发者要对正确性、安全性和可维护性负责。

合并代码:只有测试通过、差异清晰、审查完成后才能合并。

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

下面以任务管理 API 为例,展示如何让 Codex 在测试与 CI 保护下完成修改。实战需求为:为现有任务管理 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 环境准备

以下命令使用 Python 3.11 或兼容版本,并需在项目根目录执行:

python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -e ".[dev]"
uvicorn app.main:app --reload
pytest -q

4.3 核心业务代码

app/models.py 使用 Pydantic v2 风格定义输入模型:

from pydantic import BaseModel, Field


class TaskCreate(BaseModel):
    title: str = Field(min_length=1, max_length=120)
    priority: int = Field(default=1, ge=1, le=3)


class TaskUpdate(BaseModel):
    title: str | None = Field(default=None, min_length=1, max_length=120)
    priority: int | None = Field(default=None, ge=1, le=3)

app/service.py 维护任务存储与筛选逻辑:

from uuid import uuid4
from fastapi import HTTPException
from app.models import TaskCreate, TaskUpdate


class TaskService:
    def __init__(self) -> None:
        self.tasks: list[dict] = []

    def create(self, payload: TaskCreate) -> dict:
        task = {
            "id": uuid4().hex,
            "title": payload.title,
            "priority": payload.priority,
        }
        self.tasks.append(task)
        return task

    def list(self, priority: int | None = None) -> list[dict]:
        if priority is None:
            return list(self.tasks)
        return [task for task in self.tasks if task["priority"] == priority]

    def update(self, task_id: str, payload: TaskUpdate) -> dict:
        task = self.get(task_id)
        data = payload.model_dump(exclude_unset=True)
        task.update(data)
        return task

    def delete(self, task_id: str) -> None:
        self.tasks = [task for task in self.tasks if task["id"] != task_id]

    def get(self, task_id: str) -> dict:
        for task in self.tasks:
            if task["id"] == task_id:
                return task
        raise HTTPException(status_code=404, detail="task not found")

app/main.py 暴露 FastAPI 路由:

from fastapi import FastAPI
from app.models import TaskCreate, TaskUpdate
from app.service import TaskService

app = FastAPI()
service = TaskService()


@app.post("/tasks")
def create_task(payload: TaskCreate):
    return service.create(payload)


@app.get("/tasks")
def list_tasks(priority: int | None = None):
    if priority is not None and not 1 <= priority <= 3:
        return {"detail": "priority must be between 1 and 3"}
    return service.list(priority)


@app.get("/tasks/{task_id}")
def get_task(task_id: str):
    return service.get(task_id)


@app.put("/tasks/{task_id}")
def update_task(task_id: str, payload: TaskUpdate):
    return service.update(task_id, payload)


@app.delete("/tasks/{task_id}", status_code=204)
def delete_task(task_id: str):
    service.delete(task_id)

pyproject.toml 定义依赖和测试配置:

[build-system]
requires = ["setuptools>=68"]
build-backend = "setuptools.build_meta"

[project]
name = "task-api"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
    "fastapi>=0.115",
    "uvicorn[standard]>=0.30",
    "pydantic>=2.7",
]

[project.optional-dependencies]
dev = [
    "pytest>=8.0",
    "httpx>=0.27",
]

[tool.pytest.ini_options]
testpaths = ["tests"]

4.4 自动化测试

tests/test_tasks.py 覆盖默认优先级、非法优先级和筛选逻辑:

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

client = TestClient(app)


def test_create_task_with_default_priority():
    response = client.post("/tasks", json={"title": "write docs"})
    assert response.status_code == 200
    data = response.json()
    assert data["title"] == "write docs"
    assert data["priority"] == 1


def test_create_task_with_priority():
    response = client.post(
        "/tasks",
        json={"title": "fix bug", "priority": 3},
    )
    assert response.status_code == 200
    assert response.json()["priority"] == 3


def test_invalid_priority_is_rejected():
    response = client.post(
        "/tasks",
        json={"title": "invalid task", "priority": 9},
    )
    assert response.status_code == 422


def test_filter_tasks_by_priority():
    client.post("/tasks", json={"title": "task one", "priority": 1})
    client.post("/tasks", json={"title": "task two", "priority": 2})
    response = client.get("/tasks", params={"priority": 2})
    assert response.status_code == 200
    data = response.json()
    assert len(data) == 1
    assert data[0]["title"] == "task two"


def test_filter_returns_empty_result():
    response = client.get("/tasks", params={"priority": 3})
    assert response.status_code == 200
    assert response.json() == []


def test_get_task_still_works():
    response = client.post("/tasks", json={"title": "backward compat"})
    task_id = response.json()["id"]
    assert client.get(f"/tasks/{task_id}").status_code == 200

测试之所以重要,是因为它们是 Codex 修改代码时的安全边界。测试明确表达了“什么行为必须保持、什么行为算正确”。当 Codex 修改字段名、默认值或查询逻辑时,测试能立即暴露回归。没有测试的 AI 修改,相当于在没有护栏的情况下高速改代码。

4.5 持续集成配置

.github/workflows/test.yml 与上述依赖和测试命令保持一致:

name: test

on:
  push:
  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: |
          python -m pip install --upgrade pip
          pip install -e ".[dev]"

      - name: Run tests
        run: pytest -q

4.6 查看并审查修改

Codex 完成修改后,开发者应执行以下命令:

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

审查重点包括:是否修改了无关文件,是否删除原有逻辑,是否引入新的依赖,是否存在硬编码密钥或路径,是否遗漏异常处理,是否存在权限或安全风险,以及测试是否真正覆盖需求而不是只覆盖正常路径。只有差异清晰且测试通过,才能进入合并阶段。

5. 给 Codex 的高质量任务提示词

下面是三个可以直接复用的 Codex 提示词模板。实际使用时,请把项目名、路径和验证命令替换为真实项目的内容。

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

请阅读 task-api 项目,不要修改任何代码。先梳理 app、tests、pyproject.toml 和 .github/workflows 中的作用,找出与任务管理 API 相关的文件,说明数据模型、路由和测试之间的调用关系。然后给出一个最小修改计划:为任务增加优先级字段,并支持按优先级筛选。计划中请列出会修改的文件、预计新增的测试范围,以及你认为不应该触碰的模块。

这样写的原因是:开头明确“不修改代码”,避免模型直接进入编辑状态;“找出相关文件”要求它先建立项目上下文;“调用关系”帮助开发者确认模型是否正确理解代码;“最小修改计划”约束范围。替换项包括项目名、任务目标和需要保护的关键模块。

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

请在 task-api 项目中为任务增加 priority 字段,默认值为 1,取值范围为 1 到 3,并让 GET /tasks 支持可选的 priority 查询参数。只允许修改 app 和 tests 目录,保持现有 API 行为和返回结构兼容,不要修改 pyproject.toml 或 CI 配置。请补充 pytest 测试,至少覆盖默认优先级、非法优先级、按优先级筛选和空结果。完成后运行 pytest -q,若失败请根据失败信息继续修复。最后汇总修改文件、运行结果和仍存在的风险。

该模板的价值在于同时设置目标、边界和验收方式。限定目录可以降低误改依赖文件的风险;要求保持兼容能避免 AI 顺手重构;要求运行测试则建立反馈闭环。替换项包括功能说明、允许修改目录、禁止修改文件和测试命令。

模板三:代码审查

请审查当前工作区中与优先级字段相关的修改,不要直接修改代码。请从逻辑错误、安全问题、边界条件、异常处理和测试覆盖五个方面检查。按严重程度分为高、中、低三档输出问题,说明每个问题的触发条件和建议修复方向。对于需要修改的点,只描述怎么做,不直接改文件。

要求“不直接修改代码”是为了把审查和执行分开。当模型既能修改又能审查时,很容易为自己的输出辩护。按严重程度分类能让开发者先处理高风险问题。替换项可以包括检查维度、输出格式和重点文件范围。

6. ChatGPT Plus / Pro + Codex 的协同方式

在真实项目中,更适合把 ChatGPT 当作方案分析层,把 Codex 当作执行层,把测试和 Git 当作验证层。三者都围绕开发者决策运行,而不是替代开发者。

需求阶段,可以用 ChatGPT 帮助拆解业务规则,例如优先级筛选是否应该支持多值、默认值对历史数据意味着什么。架构讨论适合在 ChatGPT 中进行,尤其是比较不同模型设计、路由结构和依赖组织方式。讨论结论应固化为明确的修改计划,再交给 Codex 执行。

执行阶段,先让 Codex 阅读仓库并定位文件,再在限定目录内实施计划。修改完成后,使用 pytest 和 Git diff 验证。若差异难以理解,可以让 ChatGPT 阅读代码差异并解释每处修改的影响。最终由开发者人工审查,并决定是否合并。

这种方式的关键是保留人类判断:ChatGPT 负责帮助思考,Codex 负责帮助执行,测试负责约束正确性,Git 负责保留回退能力,开发者对最终变更负全责。

7. 常见错误与解决方法

1. 提示词只有一句话。 “帮我加个优先级筛选”没有说明模型、存储和路由。改为提供目录、接口、约束和验收方式。

2. 没有限制修改范围。 Codex 可能顺手重构其他模块。应在提示词中列出允许和禁止修改的目录。

3. 没有先让 Codex 阅读项目。 项目上下文缺失时,模型容易猜测接口名称。先执行只读分析任务,再进入修改阶段。

4. 没有创建独立分支。 主分支上修改后难以回退。每次 AI 修改都应基于新分支。

5. 没有要求补充测试。 没有测试时,只能依赖人工确认。应当先定义测试行为,再让 Codex 实现。

6. 不检查 Git diff。 AI 可能同时改掉无关文件或依赖。提交前必须查看差异和提交历史。

7. 一次提交过多需求。 同时改字段、重构服务、加缓存会放大失败面。应将需求拆小。

8. 把密钥写入代码。 API Key 或数据库密码一旦进入仓库,即使删除也可能留在历史中。应使用环境变量。

9. 直接修改生产环境。 生产系统没有试错空间。应在本地分支、测试和 CI 中验证。

10. 完全相信 AI 的解释。 模型可能把失败原因讲得合理但实际上不完整。应结合堆栈、日志和复现步骤确认。

8. 安全与隐私

AI 辅助开发不应降低安全标准。访问令牌必须通过环境变量传入,并加入 .gitignore,避免写入源码或配置文件:

import os

api_key = os.getenv("API_KEY")
if not api_key:
    raise RuntimeError("API_KEY is not set")

除此之外,还应注意:不要向模型提交生产环境密码、客户数据或未脱敏的日志;检查 AI 生成代码中的异常打印是否记录了敏感字段;限制 Codex 可访问的目录和命令权限;遵循最小权限原则,不给开发工具超出任务范围的仓库或云资源权限;对外部依赖做版本和来源审查;AI 生成代码仍要经过安全测试,特别是输入校验、路径拼接、反序列化和权限检查。

最终,ChatGPT Plus / Pro + Codex 的价值不在于替代人写代码,而在于让开发者在更短时间内完成“理解、实现、验证、审查”的闭环。只要把 AI 工具放进受控流程,用需求定义目标、用仓库上下文约束方向、用测试守护正确性、用 Git 保留回退,开发者就能在提升效率的同时继续对软件质量负责。

Logo

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

更多推荐