从 2022 年 6 月底正式上线的 GitHub Copilot 开始,AI 编程逐步开始进入工作的环境中,开始成为一个真正的 Copilot。据当时微软的评测报告以及当时公司内部使用的问卷反馈调查显示提升效率大概在 10% ~ 30%。
这一数据在当时已经令人惊叹,但随着大语言模型的飞速发展,以及 Cursor、Windsurf 等新一代 AI 编程工具以更直接的 IDE 方式的加入,效率提升的天花板被彻底打破。
从个人体感来说,部分场景有超过 10 倍的提升,特别是通用类功能实现,如爬虫、CRUD 功能、脚本类处理等。但并不等于以前一个项目要 10 个人,现在只需要 1 个人了,毕竟编码在整个项目过程中只占用的时间资源的一部分。
而且,这里的提升并不是说给 AI 说一句话:「给我完成 XXX 功能」,就能直接提效 10 倍 ,当前阶段,我们还需要有一些使用技巧才能较好的使用 AI 编程,让 AI 编程成为一个实实在在的助手。以下为过程中的一些注意事项和一些可能遇到的问题。
1. 使用 AI 编程的注意事项
1.1 不要求一次性完成所有的工作
AI 编程工具暂时并不擅长处理复杂且模糊的任务,而是更适合解决清晰、具体的小问题。因此,任务分解是高效使用 AI 编程的第一步。
如何实现?
-
需求分解:将大任务拆解为小模块,可以人工分解,也可以让 AI 协助分解。例如: -
开发一个后端服务时,可以分解为:数据库表设计、路由框架搭建、业务逻辑实现、测试用例编写。
-
-
框架优先:先让 AI 生成代码框架,例如接口的骨架代码、类和方法的定义,然后再逐步实现具体功能。
以一个简单的任务管理系统为例,你直接告诉 Cursor 「帮我实现任务管理功能」,他会提示你给出更多的输入,比如所要使用的技术栈等等,如果我们输入:请用 python 语言作为后端,vue 作为前端帮我实现任务管理功能。他会给出完整的看起来可以使用的架子,实际不太能用。
如果是在一个已有项目的基础上增加模块,以 CRUD 管理任务来说,较好的做法是:
-
分解需求: -
第一步:设计任务表(表结构设计),也是明确核心需求的过程; -
第二步:实现核心的接口和界面; -
第三步:添加权限管理,一般是有权限体系,可以给参考或者表结构之类的实现;
-
-
逐步实现: -
先让 AI 生成数据库表的定义,明确需求及约束; -
再生成 API 的路由框架。 -
最后逐一实现各个功能模块。 -
在各功能模块上再扩展其它的需求,如在任务添加的时候要调起弹性接口去完成任务等。
-
1.2 明确和细化需求
明确和细化需求和第一点有一些不同,这里所要表达的是我们在需求描述时要尽可能的明确和细致,以及需要有我们的转化和理解。
当前阶段,我们用 AI 编程并不是把产品需求扔给 AI,而是我们思考过整个实现的过程,有自己的认知后让 AI 来做会更好,当然,这个思考的过程也可以让 AI 来辅助。
-
明确需求的层级 假设你需要实现一个用户登录功能,可以先从高层次的需求入手「实现用户登录功能」,然后逐步细化为:
-
数据库中需要存储哪些信息? -
前端需要提供哪些输入?有没有什么安全输入策略? -
后端服务的接口设计是什么样的?格式是怎样的?返回码规范是怎样的? -
需要哪些验证逻辑?使用 JWT 还是 Auth2.0?有哪些安全策略?
-
-
细化到函数级别 在某些情况下,有必要直接将需求分解到函数的输入输出、核心逻辑或算法。比如:
-
函数应该接受哪些参数? -
输出的结果应该是什么样的?是什么类型的数据结构? -
核心逻辑是否需要特殊的算法优化?
-
以上这个细化的过程也是个 AI 交互的过程,从大到小,从整体到部分,逐步完成整个需求。
在使用 AI 编程的过程中,确定需求并细化需求是最难,也是整个过程中最复杂的环节,因为它是对现实世界的建模。
把产品需求没有歧义的描述出来,这个过程远没有很多人想象中那么简单。期待 AI 进一步进化后能优化这部分理解的工作。
1.3 善用 AI 的上下文记忆
AI 编程的生成效果在很大程度上依赖于上下文信息。
Cursor 支持上下文记忆功能,可以根据当前项目的代码结构或对话历史生成更精准的结果。并且对于已有代码的项目,提供示例代码给 Cursor 参考,可以帮助它更好地理解项目的整体风格、编码规范以及约定。
-
参考已有代码 比如,我们可以将公司内部的编码规约或项目约定通过已有代码的形式提供给 AI,这样生成的代码更符合项目需求,减少后续调整的工作量。
-
让 AI 理解当前代码环境 在和 Cursor 对话时,可以特别的指出关键代码片段(如数据模型、核心函数),这种方式是为了规避 LLM 的上下文记忆的限制问题,突出当前要解决的问题和场景。
-
补充上下文 如果项目中有复杂的业务逻辑或特定的技术约定,可以通过注释、文档或已有代码的形式向 AI 提供相关背景信息。这样,AI 生成的代码不仅能够「跑通」,还更贴近实际需求。如使用 Cursor 的 @ 符号,除了本地的代码、文档、还可以有多模态的图片、外部链接的文档,Web 网页等等。
2. AI 编程使用中的问题及解决方案
在使用 AI 编程工具(如 Cursor、Windsurf 等)时,尽管其效率提升显著,但也有一些问题亟待解决。
2.1 额度不够了
以 Cursor 为例,即使在不大量使用的情况下,Pro 版本(如 GPT-4、GPT-4o、Claude 3.5 Sonnet 的高速请求)两周内就可能用完额度。高级模型的调用成本较高,尤其是当需要生成大量代码或反复调试时,消耗会非常快。
解决方案:
-
分工明确,优化工具使用场景 -
代码相关任务交给 Cursor:专注于代码生成、函数实现等任务,减少对 Cursor 的非核心调用。 -
知识性问题交给 ChatGPT或其它大语言模型:对于纯知识性或逻辑性的问题,使用 ChatGPT 或其他不限量的模型(如 GPT-3.5 免费版本)来查询。
-
-
分层实现代码 -
先写框架:在开发项目时,先用 Cursor 生成代码框架,明确主流程。 -
逐步细化:将需求明确的函数(尤其是复杂的小块代码)交由 Cursor 实现,而非一次性生成庞大的代码段。
-
-
结合其他无限制的大模型 -
对于通用型函数(如工具类代码、简单的逻辑实现),可以利用免费的语言模型完成。 -
配合使用多个编辑器(如 Windsurf 、Cursor、豆包),减少单一工具的使用频率。
-
-
节约上下文消耗 -
避免在上下文中反复输入无关信息,尽量精简对话内容。 -
善用工具内的上下文管理功能,如 Cursor 提供的 Add context
或@
引用功能,将关键信息外部化,减少重复输入。
-
当然,对于不差钱的小主来说,可以忽略此问题。
2.2 上下文限制:会「失忆」
当前的 LLM 上下文窗口有限,当输入信息超出限制时,模型可能会「遗忘」之前的内容。这种「失忆」表现尤其明显,例如在多次会话后,最前面的一些关键信息可能会被遗忘,导致生成的代码出现不一致的问题。
解决方案
-
简要总结关键信息 -
当模型开始「失忆」时,可以总结项目的关键信息并重新输入。例如, 核心配置或表结构可以作为关键信息,在对话开始时就输入给 LLM,确保其随时可用。
-
-
外部化核心信息 -
将一些不变的核心信息(如数据库表结构、配置文件、接口定义等)存储到单独的文件中。 -
在对话中通过 @
或Add context
,将这些文件动态添加到上下文中,避免重复输入。
-
-
引用外部文档 -
将外部帮助文档、链接或者参考资源作为上下文的一部分添加到对话中。例如,直接粘贴代码库的 README 文件、API 文档链接等,可以帮助模型更好地理解当前任务。 -
Cursor 自身支持这些外部的引用,具体方法参见 Cursor 的帮助文档,探索上下文扩展功能。
-
-
优化上下文使用策略 -
尽量减少对话中的无关内容(如闲聊或冗长描述)。 -
定期总结对话内容并清理上下文,确保关键信息占用优先位置。
-
2.3 修改代码混乱:会改乱代码
AI 工具在生成代码时,可能覆盖或修改原有代码,导致逻辑混乱,甚至出现功能性错误,一不小心原来能跑通的功能就不通了。这种情况常发生在对已有代码进行修改时,尤其是在多次修改的情况下。
解决方案
-
结合版本控制工具 -
在完成每一阶段的明确功能后,及时使用 Git 提交代码,确保已有的工作成果被保存。 -
在尝试新的修改时,可以创建分支或临时提交,确保不影响主分支的代码完整性。
-
-
分步引导 AI -
避免一次性让 AI 修改大量代码,而是按功能模块逐步进行修改。例如,先让 AI 修改某个函数,再验证其效果,而不是直接让它大规模重构代码。
-
-
生成新代码替代旧代码 -
在涉及复杂逻辑的修改时,建议让 AI 生成新的代码片段,而不是直接修改现有代码。我们可以手动选择将新代码合并到项目中,避免出现覆盖错误。
-
-
代码审查 -
对 AI 生成或修改的代码进行人工审阅,尤其是涉及关键逻辑的部分,确保生成代码符合预期。
-
2.4 无法解决复杂问题:可能进入死循环
在调试复杂问题或某个难点时,AI 工具可能陷入死循环,反复尝试生成代码但无法有效解决问题。例如,AI 对某个 bug 的修复建议多次尝试后仍然无效,甚至可能导致代码更加混乱。
解决方案
-
重新整理问题 -
如果问题复杂而模糊,先关闭当前对话,重新开启一个新的会话。 -
将问题简化为多个子问题,并逐步整理关键信息后输入给 AI。例如,将错误日志、上下文代码片段和预期行为整理成清晰的描述。
-
-
结合搜索引擎 -
对难以解决的问题,可以将错误信息、bug 的关键描述扔给搜索引擎,结合开发者社区(如 Stack Overflow)寻找答案。 -
搜索的过程中可以收集更具体的上下文,再反馈给 AI,增加其解决问题的可能性。
-
-
寻求多工具协作 -
如果单个 AI 工具陷入死循环,可以尝试切换到其他工具或模型。例如,Cursor 无法解决的问题,可以切换到 ChatGPT 或 Claude 进行尝试。 -
结合传统的调试手段(如 IDE 的调试功能、日志分析工具等),帮助定位问题。
-
-
分阶段测试 -
将复杂问题拆解为多个小问题,逐步测试每一部分的结果。例如,如果某个模块的逻辑无法正常运行,可以先测试其输入输出,再逐步调试内部逻辑。
-
3. 小结
用 AI 编程,也就是和 AI 协作,本质上是一种双向的沟通过程。
我们需要像与团队成员协作一样,清晰表达需求、提供必要的背景信息,并通过持续的反馈和迭代优化,逐步引导 AI 生成符合预期的结果。只有做到有效沟通,AI 才能真正成为开发者的高效助手,而不是一个需要频繁纠错的工具。
以上。