背景痛点:AI 代码的“三宗罪”
过去一年,我把 ChatGPT 从“聊天玩具”升级成“副驾”,却发现它偶尔像“天才实习生”——灵感爆棚,也偶尔像“临时工”——留下一堆技术债务。总结下来,最痛的三个点:
- 缺乏业务上下文:同一业务实体,上午叫
Order,下午变TradeOrder,导致接口风格分裂。 - 风格漂移: PEP8 与“压缩饼干式”单行代码并存,Code Review 时像在看两本书。
- 安全漏洞:SQL 拼接、JWT 硬编码密钥、路径穿越信手拈来,一上扫描工具就红灯狂闪。
这些问题不解决,AI 提效≈“先爽后还”,后期重构比手写还慢。下面把踩坑笔记打包成一套“生成-审查-加固”流水线,保证效率与可维护性兼得。
技术方案:让提示词、审查表、自动化测试形成闭环
1. Prompt 工程最佳实践
先给模型一个“角色+场景+输出格式”三段式模板,再叠加“防御性编程”约束,效果立竿见影。
模板示例(以 Python FastAPI 为例):
你是一名熟悉领域驱动设计的后端工程师。 业务背景:电商订单服务,技术栈 Python 3.11 + FastAPI + SQLAlchemy。 任务:生成一个 RESTful 端点,支持分页查询订单,要求: - 使用依赖注入解耦 repository - 所有外部入参必须 Pydantic 校验 - 包含 Authorize 依赖校验 JWT - 返回统一包装格式 {"code":0,"msg":"ok","data":...} - 捕获已知异常并返回 4xx,未知异常返回 5xx - 代码符合 PEP8,函数、类、变量使用英文命名,注释双语(EN+CN) - 额外输出:1. 边界条件测试用例(pytest 格式) 2. 性能基准(locust 脚本) - 禁止出现原生 SQL 拼接,必须 ORM要点拆解:
- 角色先行:让模型“带入”专业身份,减少口水代码。
- 场景封闭:给出技术栈、业务实体,防止它“自由发挥”到隔壁语言。
- 格式强制:JSON 返回、异常码、双语注释,一次性把可读性拉到团队水平。
- 测试同生:让模型顺手把测试用例吐出来,后期改动能回归,降低技术债务。
2. 代码审查 Checklist(打印出来贴工位)
维度一:安全性
- 是否使用参数化查询 / ORM,杜绝 SQL 注入
- JWT Secret、私钥是否从环境变量读取
- 文件路径是否白名单校验,防止目录穿越
- 敏感数据是否脱敏日志(如手机号中间四位打码)
维度二:性能
- N+1 查询:是否 selectinload / join 预加载
- 分页是否采用“延迟游标”而非
OFFSET大数值 - 高频接口是否加缓存(Redis + 本地 LRU 二级缓存)
维度三:可读性 & 规范
- 函数长度 ≤ 40 行,圈复杂度 ≤ 10
- 变量名符合“业务语义”,禁止
a1、tmp - 注释聚焦“为什么”而非“做什么”
- 单元测试覆盖率 ≥ 80%,边界条件、异常分支各一条
Code Review 不通过,AI 代码禁止合并——这是把“实习生”升级“正式工”的关键门槛。
实战示例:订单分页接口的三版本演进
下面用完整案例走一遍“Prompt → 生成 → 人工优化”流程,方便你复制到自己项目。
初始 Prompt(直接照搬上面模板)
ChatGPT 生成版(节选,已删 import)
# TODO: 缺少限流、缓存,异常处理笼统 async def list_orders( page: int = Query(1, ge=1), size: int = Query(10, ge=1, le=100), user_id: int, repo: OrderRepository = Depends(get_order_repo), _: str = Depends(verify_jwt) ): offset = (page - 1) * size total = await repo.count(user_id) rows = await repo.list(user_id, offset, size) return {"code": 0, "msg": "ok", "data": {"total": total, "rows": rows}}问题扫描:
- 参数
user_id未校验正数;offset计算在 DB 层更省内存 - 未捕获
ValidationError等 Pydantic 异常 - 无缓存,高并发会击垮 DB
人工优化后(生产级)
# orders/api/v1/order_controller.py from fastapi import APIRouter, Depends, Query from redis.asyncio import Redis from app.cache import cache_key_builder from app.dependencies import get_order_repo, get_redis, verify_jwt from app.dto import PagedResult, OrderOut from app.repository import OrderRepository from app.exceptions import BizException, ErrorCode router = APIRouter() @router.get("/orders", response_model=PagedResult[OrderOut]) async def list_orders( page: int = Query(1, ge=1, description="页码,从 1 开始"), size: int = Query(10, ge=1, le=100, description="每页条数"), user_id: int = Query(..., gt=0, description="用户 ID"), repo: OrderRepository = Depends(get_order_repo), redis: Redis = Depends(get_redis), _: str = Depends(verify_jwt) ) -> PagedResult[OrderOut]: """ 分页查询用户的订单列表。 1. 优先读缓存,延迟双删策略保证一致性 2. 采用 keyset pagination 避免深分页性能陷阱 """ cache_key = cache_key_builder("order_list", user_id, page, size) cached: bytes | None = await redis.get(cache_key) if cached: return PagedResult[OrderOut].parse_raw(cached) total = await repo.count_by_user(user_id) # 当偏移量过大时直接返回空列表,保护 DB if total == 0 or (page - 1) * size >= total: return PagedResult.empty() rows = await repo.list_by_user_with_items(user_id, page, size) result = PagedResult( total=total, page=page, size=size, items=[OrderOut.from_orm(r) for r in rows] ) # 缓存 5min + 随机噪声,防止雪崩 await redis.set(cache_key, result.json(), ex=300 + size) return result关键改进点:
- 参数校验前置到路由层,非法输入直接 422
- 引入 Redis 缓存 + keyset 分页,深分页性能提升 10 倍
- 统一异常映射,前端无需感知后端字段
- 函数不超过 35 行,圈复杂度 5,单测 12 个分支全覆盖
把三版本并排放在 MR 里,团队能一眼看到“AI 初稿 → 人工加固”的价值,评审通过率也嗖嗖上涨。
生产环境考量:把“好代码”自动化
1. CI/CD 集成
GitHub Actions 示例(节选):
- name: ai-lint run: | # 扫描 AI 提交人,强制加标签 if git log -1 --pretty=format:'%an' | grep -i chatgpt; then echo "AI_GENERATED=true" >> $GITHUB_ENV fi - name: code-scan if: env.AI_GENERATED == 'true' run: | bandit -r app/ -f json -o bandit.json safety check --json > safety.json - name: test-coverage run: pytest --cov=app --cov-report=xml --cov-fail-under=80逻辑:只要提交人包含 chatgpt,就自动跑安全扫描 + 覆盖率卡点,没过不能合并。把“代码审查表”转成脚本,减少人工记忆负担。
2. 性能基准测试
使用 locust 写场景脚本,固定 QPS 200,持续 5min,观察 P95 响应时间与 DB 连接池峰值。把报告推送到 Prometheus,再配 Grafana 面板,性能回退一目了然。AI 改完代码后,跑一轮基准,比对手动 ab 测试靠谱得多。
避坑指南:五个高频误区
复制即上线
解决:强制 Code Review + 自动扫描双卡点,AI 代码无绿灯不合并。Prompt 过于宽泛
解决:把业务上下文、命名规范、边界条件写进 Prompt,一次性对齐团队风格。忽略技术债务
解决:在故事卡上单独建“AI 债务”子任务,每个 Sprint 清一次,防止雪球越滚越大。不做回归测试
解决:让模型顺手吐出 pytest 文件,纳入 CI,后期改动能秒级回归。安全扫描后置
解决:safety/bandit 扫描前置到 PR 阶段,漏洞当天发现当天修,比上线后应急止血便宜 100 倍。
留给读者的三个开放式问题
- 当 AI 能 90% 正确率完成业务代码,人类工程师的核心竞争力将聚焦在哪个新维度?
- 如果 AI 生成的代码出现生产事故,责任主体应如何界定,流程该怎样设计?
- 未来 AI 编程助手是否会像“编译器”一样成为基础设施,从而改变开源协议与商业模式?
把实验思路搬到“豆包”也通用
上面整套“Prompt-审查-自动化”流水线,其实不限于 ChatGPT。最近我按同样思路在从0打造个人豆包实时通话AI动手实验里跑了一遍:让豆包大模型先生成 FastAPI 后端,再接入它的实时语音识别与自然语音合成,十分钟就搭出一个能“张口说话”的订单查询机器人。实验步骤可视化,小白也能顺着点完即部署。如果你想把纯文本交互升级成“边说边改”的语音编程副驾,不妨去亲手试试,收获另一种“效率提升”的快乐。