AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

AI资讯 20小时前 charles
300 0

一、如何充分使用模型能力

关键要点完整+精确+聚焦的上下文是充分使用模型能力的关键。在这个认知之下思考如何系统性的构建满足这个条件的上下文?

  • 合理的任务分解:本质上是在有限上下文宽度和注意力的约束下,怎么恰当的把握任务的复杂度边界,让模型能够在一个聚焦的任务上作业。

  • 完整的背景信息:在一个真实的项目中写代码,需要理解系统架构和规范、了解业务需求、清楚关键代码实现路径、知道如何修改代码满足新的需求,完整了解这些背景信息才能真正的写代码,这对于人类和AI来说是一样的。

  • 精确的指令描述:使用能够让AI更容易理解的方式,清晰无歧义的表达要完成的任务,如强调语法**、mermaid画图等。

  • 有效的验证和反馈:信息从我们表达出来->AI理解->生成代码,每一层都会有损失,而且往往我们自己也会遗漏一些细节,这一步的关键是自己要根据AI的产出验证和思考,将错漏的内容反馈AI自行反思、纠偏。

这4个关键点的应用中还涉及到尺度的把握(信息的细致程度),而这个尺度会随着模型的能力提升而变化。如早期的模型需要非常详尽的内容输入,当模型能力提升后可以自主从代码中获得足够的背景知识。

二、AI协作编程的方法

2.1. 应用级记忆结构

关键要点像设计系统架构一样设计上下文架构,暗合近期讨论比较多的上下文工程(context engineering)的概念。在这个认知之下思考如何高效、准确的维护这个上下文工程?

  • 第一层-应用基础记忆:是应用比较基础的架构、技术栈、规范、通用工具等长期稳定记忆,是与AI交互的System Prompt,就像系统架构中的基础组件。

  • 第二层-功能模块记忆:是对某个具体功能的完整描述,包括链路图、代码入口、关键逻辑、依赖关系等相对稳定的功能记忆,是与AI交互关键背景知识,就像系统架构中由基础组件+业务需求组成的具体功能。

  • 第三层-需求迭代记忆:是AI基于项目迭代中业务需求+功能模块背景知识+项目系统架构产出的技术方案,包括明确的业务需求、代码改造范围、约束条件、边界情况等,是作为提供给AI进行代码生成的最终输入。

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

2.2. AI辅助记忆维护

记忆维护关键点向AI提供的输入内容和产出验收,本身也可以由AI来辅助生成和验证,同时记忆的维护是渐进的,可跟随实际项目逐步完善。

  • 应用基础记忆构建:一般AI编程工具都有生成项目顶层记忆文档的功能,如Cursor的/Generate Cursor Rules、ClaudeCode的/init,在某个应用没有任何记忆时,可以作为冷启动的快速建立记忆的方法,生成初始记忆后,可以根据自己的要求让AI辅助调整。

  • 功能模块记忆构建:由人类提供提供简洁的功能描述和关键代码入口,让AI自动根据代码入口作为线索去检索,建立完整链路的记忆文档,再根据自己的要求让AI辅助调整。

  • 需求迭代记忆构建:引用与需求相关的背景知识记忆,并且以Markdown格式描述本次需求内容,要求其生成技术方案,就产出了需求迭代记忆。需求开发完成后反向更新功能模块记忆。

  • 记忆文档的规范:建立一些基础的记忆文档规范,如应用记忆保持整洁、功能模块记忆需要有链路图、需求迭代记忆需要建立在指定目录等。

  • 要求AI辅助检查和反思:每一层的记忆文档生成后,都可以要求AI进行自我检查和反思,是否有错漏的地方。

  • 通用的记忆格式:统一以.md作为记忆格式,未来使用任何AI编程工具都可以无缝切换。(cursor的.mdc本质上也是.md)

总结:核心是系统性的分层分模块管理上下文,最大程度让AI辅助维护上下文,每次变更的知识负担就可以大幅度下降(输入具体需求即可),配合渐进式的更新维护,使用AI编程工具的效率正循环就形成了。

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

2.2.1. 记忆示例

功能模块基于、需求迭代记忆的示例涉及到敏感业务代码,不再此处展示

项目结构和技术栈

---description: globs: alwaysApply: true---AE评测系统开发指南
## 项目结构
- [demo-start](mdc:demo-start): 项目启动模块,**这个模块中没有业务逻辑, 在我没有明确指令是不要修改此模块中的代码**。- [demo-api](mdc:demo-api): HSF API接口定义模块**对于Demo系统的开发,只关心 [demo](mdc:demo-api/src/main/java/com/aliexpress/demo) package下的内容, 其他package内容忽略**  - [demo/api](mdc:demo-api/src/main/java/com/aliexpress/demo/api): Demo系统的HSF API的interface均在这个package下定义, 命名后缀为Service  - [demo/model](mdc:demo-api/src/main/java/com/aliexpress/demo/model): Demo系统的HSF API的model均保存在这个package, 命名后缀为RequestDTO  - [demo/common](mdc:demo-api/src/main/java/com/aliexpress/demo/common): Demo系统的HSF API的enum均保存在这个package下, 命名后缀为Enum  - [demo/base](mdc:demo-api/src/main/java/com/aliexpress/demo/base): Demo系统的HSF API的model的基类均保存在这个package下- [demo-biz](mdc:demo-biz): 业务逻辑实现模块, **对于Demo系统的开发,只关心 [demo](mdc:demo-api/src/main/java/com/aliexpress/biz/demo) package下的内容, 其他package内容忽略**  - [demo/api](mdc:demo-biz/src/main/java/com/aliexpress/biz/demo/api): Demo系统的HSF API的实现类均在这个package下定义, 命名后缀为ServiceImpl    - [demo/api/converter](mdc:demo-biz/src/main/java/com/aliexpress/biz/demo/api/converter): Demo系统的HSF API的实现类使用的Converter类均保存在这个package下, 命名后缀为Converter    - [demo/api/validate](mdc:demo-biz/src/main/java/com/aliexpress/biz/demo/api/validate): Demo系统的HSF API的实现类使用的校验类均保存在这个package下, 命名后缀为Validate  - [demo/common](mdc:demo-biz/src/main/java/com/aliexpress/biz/demo/common): Demo系统的内部的公共类均保存在这个package下, 命名后缀为EnumConstant  - [demo/config](mdc:demo-biz/src/main/java/com/aliexpress/biz/demo/config): Demo系统的内部的DiamondHSF配置类均保存在这个package下, 命名后缀为ConfigConfiguration  - [demo/consumer](mdc:demo-biz/src/main/java/com/aliexpress/biz/demo/consumer): Demo系统的MetaQ Consumer类均保存在这个package下, 命名后缀为Consumer(消费MetaQ)    - [demo/consumer/listener](mdc:demo-biz/src/main/java/com/aliexpress/biz/demo/consumer/listener): Demo系统的Consumer的消费逻辑实现类均保存在这个package下, 命名后缀为Listener(实现消费逻辑)  - [demo/demouator](mdc:demo-biz/src/main/java/com/aliexpress/biz/demo/demouator): Demo系统的评估器实现类均保存在这个package下, 命名后缀为demouator, **此处的代码相对比较稳定,在我没有明确指令时不要自行修改**  - [demo/executor](mdc:demo-biz/src/main/java/com/aliexpress/biz/demo/executor): Demo系统的通用业务逻辑实现类均保存在这个package下, 命名后缀为Executor  - [demo/invoker](mdc:demo-biz/src/main/java/com/aliexpress/biz/demo/invoker): Demo系统的调用AI应用的通用封装类均保存在这个package下**此处的代码相对比较稳定,在我没有明确指令时不要自行修改**  - [demo/task](mdc:demo-biz/src/main/java/com/aliexpress/biz/demo/task): Demo系统的任务提交和任务执行的的通用封装类均保存在这个package下**此处的代码相对比较稳定,在我没有明确指令时不要自行修改**  - [demo/util](mdc:demo-biz/src/main/java/com/aliexpress/biz/demo/util): Demo系统的工具类均保存在这个package下**此处的代码相对比较稳定,在我没有明确指令时不要自行修改**- [demo-core](mdc:demo-core): 核心功能模块, 包含基础设施和通用组件, **对于Demo系统的开发, 任何时候都不需要关注这个模块中的内容**- [demo-job](mdc:demo-job): 定时任务模块, **对于Demo系统的开发, 任何时候都不需要关注这个模块中的内容**- [demo-workflow](mdc:demo-workflow): 工作流相关模块, **对于Demo系统的开发, 任何时候都不需要关注这个模块中的内容**- [demo-infrastructure](mdc:demo-infrastructure): 基础设施模块, 包含数据访问外部服务集成等, **对于Demo系统的开发, 主要关心其中操作数据库的相关代码**  - [dao/demo](mdc:demo-infrastructure/src/main/java/com/aliexpress/infrastructure/dao/demo): Demo系统的Mybatis-Plus的Mapper类均保存在这个package下,后缀为Mapper  - [model/demo](mdc:demo-infrastructure/src/main/java/com/aliexpress/infrastructure/model/demo): Demo系统的Mybatis-Plus的实体类均保存在这个package下,其中PO后缀的是与数据库表直接映射的实体类,其中/model文件夹下的类是和业务层交互的实体类  - [model/convert](mdc:demo-infrastructure/src/main/java/com/aliexpress/infrastructure/model/convert): Demo系统的Mybatis-Plus的PO与Model之间的转换类均保存在这个package下,后缀为Converter  - [repository](mdc:demo-infrastructure/src/main/java/com/aliexpress/infrastructure/repository): Demo系统的数据库操作类均保存在这个package下,接口后缀为Repository,实现类后缀为RepositoryImpl,核心的作用是调用Mapper与数据库操作转换PO与Model- [demo-provider](mdc:demo-provider): 服务提供者模块  - [hsf/provider](mdc:demo-provider/src/main/java/com/aliexpress/provider/hsf/provider): 增加新的HSF服务Provider需要在 [HsfProviderConfig.java](mdc:demo-provider/src/main/java/com/aliexpress/provider/hsf/provider/HsfProviderConfig.java)类中增加配置- [demo-sdk](mdc:demo-sdk): Demo系统SDK工具模块,**此处的代码相对比较稳定,在我没有明确指令时不要自行修改**
## 主要技术栈
- Pandora Boot: 基于Spring Boot的阿里内部框架- HSF: 阿里内部的RPC框架- Diamond: 阿里内部的配置中心- Tair: 阿里内部的缓存服务- MetaQ: 阿里内部的消息服务- MyBatis-Plus: 轻量级的ORM框架

DAO层代码规范

---description: 根据创建表的SQL生成操作数据库层增删改查代码时引用此文件globs: alwaysApply: false---## 操作数据库编码规范#### 操作DB框架1. 开发框架:使用MyBatis-Plus进行编码2. 调用逻辑:上层通过注入的方式调用Repository的实现,在Repository的实现的实现中调用Mapper,调用Mapper后返回的对象是PO,再通过Converter转换成Model后返回为上层调用方3. 数据类型的选择:时间字段使用java.util.Date类型4. 使用MyBatis-Plus方法注意事项:注意不要调用deprecated的方法5Repository层的删除方法:统一使用逻辑删除,逻辑删除字段是is_deleted6Repository层需操作时需要附加对当前环境的处理:调用 [EnvUtil.java](mdc:task-infrastructure/src/main/java/com/aliexpress/qa/task/infrastructure/util/EnvUtil.java)的getEnv().getCode()方法7Repository层的的分页方法:调用MyBatis-Plus的selectPage方法   #### DAO层PO1DAO层PO的命名规范为${TableName}PO2DAO层PO的存放目录[model](mdc:task-infrastructure/src/main/java/com/aliexpress/qa/task/infrastructure/model)
#### DAO层Mapper1DAO层Mapper命名规范为${TableName}Mapper2DAO层Mapper的存放目录[dao](mdc:task-infrastructure/src/main/java/com/aliexpress/qa/task/infrastructure/dao)   #### Repository层1Repository层interface命名规范为${TableName}Repository2Repository层实现命名规范为${TableName}RepositoryImpl3Repository层Model命名规范为${TableName}Model4Repository层interface的存放目录[repository](mdc:task-infrastructure/src/main/java/com/aliexpress/qa/task/infrastructure/repository)5Repository层实现的存放目录[repositoryimpl](mdc:task-infrastructure/src/main/java/com/aliexpress/qa/task/infrastructure/repository/impl)6Repository层Model存放目录[model](mdc:task-infrastructure/src/main/java/com/aliexpress/qa/task/infrastructure/model)
#### Converter层1Converter层命名规范位${TableName}Converter2Converter层的存放目录[convert](mdc:task-infrastructure/src/main/java/com/aliexpress/qa/task/infrastructure/model/convert)3Converter代码规范:使用字段进行映射,禁止使用json序列化BeanUtils.copyProperties等方式
## 参考代码1DAO层PO参考代码``` javaimport com.baomidou.mybatisplus.annotation.TableName;import lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;
${必要的引用}
/** * @author chigong.zxn */@Data@Builder@TableName(value = "${tableName}")@AllArgsConstructor@NoArgsConstructorpublicclass ${TableName}PO {    ${注释}    ${只可以使用包装类型,禁止使用基础类型}    ${columnName}}```2DAO层Mapper参考代码,注意:不需要增加增删改查方法,MyBatis-Plus已经默认通过继承BaseMapper提供``` javaimport com.aliexpress.qa.task.infrastructure.model.eval.${TableName}PO;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import org.apache.ibatis.annotations.Mapper;
/** * @author chigong.zxn */@Mapperpublic interface ${TableName}Mapper extends BaseMapper<${TableName}PO> {}```3Repository层interface参考代码,注意:生成基础的增删改查方法``` javaimport com.aliexpress.qa.task.infrastructure.model.eval.${TableName}PO;import com.aliexpress.qa.task.infrastructure.model.eval.${TableName}Model;
/** * @author chigong.zxn */@Mapperpublic interface ${TableName}Repository {    ${注释}    ${增删改查方法}}```4Repository层实现参考代码,注意:继承Repository接口实现基础增删改查方法,调用Mapper生成基础的增删改查方法``` javaimport com.aliexpress.qa.task.infrastructure.model.eval.${TableName}PO;import com.aliexpress.qa.task.infrastructure.model.eval.${TableName}Model;
/** * @author chigong.zxn */@Mapperpublic interface ${TableName}RepositoryImpl implements ${TableName}Repository {    ${注释}    ${实现Repository增删改查方法}}```5Repository层Model参考代码``` javaimport lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;
${必要的引用}
/** * @author chigong.zxn */@Data@Builder@AllArgsConstructor@NoArgsConstructorpublicclass ${TableName}Model {    ${注释}    ${只可以使用包装类型,禁止使用基础类型}    ${columnName}}```6Converter层参考代码,注意:生成2个静态方法,PO转ModelModel转PO``` javaimport com.aliexpress.qa.task.infrastructure.model.eval.${TableName}PO;import com.aliexpress.qa.task.infrastructure.model.eval.${TableName}Model;
/** * @author chigong.zxn */publicclass ${TableName}Converter {    ${注释}    ${PO转换为Model}
    ${注释}    ${Model转换为PO}}```

API层代码规范

---description: 增加HSF接口时引用此文件globs: alwaysApply: false---## API开发规范### 服务实现* 验证器存放目录:[validate](mdc:task-biz/src/main/java/com/aliexpress/qa/task/biz/eval/api/)* 实现要求:必须实现服务验证器* 服务实现代码参考:``` javaimport com.alibaba.fastjson.JSON;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Service;@Servicepublicclass ${服务名}ServiceImpl implements ${服务名}Service {    privatestaticfinal Logger logger = LoggerFactory.getLogger(${服务名}ServiceImpl.class);    @Autowired    private ${服务校验器}Validate validate;    // 如果需要调用其他bean也可以在此处引入    // 如:    // @Autowired    // private EvalDatasetDetailRepository evalDatasetDetailRepository;    @Override    public ${服务方法出参} ${服务方法名}(${服务方法请求体} request) {        logger.info("${服务名}Service.${服务方法名} request:{}", JSON.toJSONString(request));        ${服务方法出参} response = new ${服务方法出参}();        try {            String validateMsg = validate.${服务方法校验器}Validate(request);            if (StringUtils.isNotBlank(validateMsg)) {                return Response.fail(ErrorCode.PARAM_ERROR.name(), validateMsg);            }            // 在此处实现业务逻辑            ${业务逻辑}        } catch (Exception e) {            logger.error("${服务名}Service.${服务方法名} error", e);            response = Response.fail(ErrorCode.SYSTEM_ERROR.name(), e.getMessage());        }        logger.info("${服务名}Service.${服务方法名} response:{}", response);        return response;    }}```### 服务验证器* 验证器存放目录:[validate](/task-biz/src/main/java/com/aliexpress/qa/task/biz/eval/api/validate/)* 验证器代码参考:验证失败则返回失败原因字符串,验证成功则返回空字符串``` javaimport com.aliexpress.qa.task.biz.eval.util.ValidateUtil;import org.springframework.stereotype.Component;@Componentpublicclass ${服务名}Validate {    // 如果需要调用其他bean也可以在此处引入    // 如:    // @Autowired    // private EvalDatasetDetailRepository evalDatasetDetailRepository;    public String ${服务方法名}Validate(${服务方法请求体} request) {        // 请求体不能为空        if (request == null) {            return"请求参数不能为空";        }        // 基础校验,使用ValidateUtil校验net.sf.oval annotation        String validateMsg = ValidateUtil.validate(request);        if (StringUtils.isNotBlank(validateMsg)) {            return validateMsg;        }        // 写明校验注释        #{文档要求的其他校验逻辑}        // 返回空字符串则校验成功        return StringUtils.EMPTY;    }}```### 分布式锁使用* 服务实现代码参考:``` javaimport com.alibaba.fastjson.JSON;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Service;import com.aliexpress.qa.task.infrastructure.util.lock.DistributedLockUtil;@Servicepublicclass ${服务名}ServiceImpl implements ${服务名}Service {    privatestaticfinal Logger logger = LoggerFactory.getLogger(${服务名}ServiceImpl.class);    @Autowired    private ${服务校验器}Validate validate;    @Autowired    private DistributedLockUtil distributedLockUtil;    // 如果需要调用其他bean也可以在此处引入    // 如:    // @Autowired    // private EvalDatasetDetailRepository evalDatasetDetailRepository;    @Override    public ${服务方法出参} ${服务方法名}(${服务方法请求体} request) {        logger.info("${服务名}Service.${服务方法名} request:{}", JSON.toJSONString(request));        ${服务方法出参} response = new ${服务方法出参}();        try {            String validateMsg = validate.${服务方法校验器}Validate(request);            if (StringUtils.isNotBlank(validateMsg)) {                return Response.fail(ErrorCode.PARAM_ERROR.name(), validateMsg);            }            // 根据业务逻辑要求构建lockKey            String lockKey = ...;            // 分布式锁,避免并发调度            DistributedLock lock = distributedLockUtil.getLock(lockKey);            // 获取分布式锁            try {                lock.tryLock(1000L);            } catch (GetLockErrorException lockException) {                return Response.fail(ErrorCode.LOCK_ERROR.name(), ErrorCode.LOCK_ERROR.getMessage());            }            try {                // 在此处实现业务逻辑                ${业务逻辑}             } finally {                lock.unlock();            }        } catch (Exception e) {            logger.error("${服务名}Service.${服务方法名} error", e);            response = Response.fail(ErrorCode.SYSTEM_ERROR.name(), e.getMessage());        }        logger.info("${服务名}Service.${服务方法名} response:{}", response);        return response;    }}```

单元测试规范

---description: globs: alwaysApply: false---# 单元测试指南
## 测试框架- JUnit Jupiter 5.9.2- Mockito 4.11.0- JUnit Platform 1.9.2
## 严格执行- 禁止改变被测试方法的任何行为- private方法测试: 使用反射的方式测试private方法, 禁止改变被测试方法的private  ```java  @BeforeEach  voidsetUp() throws NoSuchMethodException {      // 获取私有方法      Method privateMethod = TargetClass.class.getDeclaredMethod("privateMethodName",           ParameterType1.class, ParameterType2.class);      privateMethod.setAccessible(true);  }
  @Test  voidprivateMethodName_Should_ExpectedBehavior_When_StateUnderTest() throws Exception {      // given      // when      Object result = privateMethod.invoke(targetObject, arg1, arg2);      // then      // assertions  }  ```- 静态方法Mock: 使用MockedStatic方式- staticfinal字段处理: 避免直接测试或mock staticfinal字段(如日志记录器),专注于测试核心业务逻辑和返回值- Mybatis-Plus初始化实体类元数据: mock Mybatis-Plus的```LambdaUpdateWrapper、LambdaQueryWrapper```时,在```@BeforeEach```中使用```TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""),${实体类名}PO.class);```初始化实体类元数据
## 测试命名规范- 使用 `@Test` 注解标记测试方法- 测试方法名应该清晰表达测试目的,并且测试方法名必须包含被测试的方法名- 格式:`${被测试方法名}_Should_ExpectedBehavior_When_StateUnderTest`- 示例:`buildQuery_Should_ReturnQueryWithEntrustBizId_When_UserHasEntrustPermission`
## 测试最佳实践### Mock策略- 优先测试核心业务逻辑,避免过度依赖基础设施组件的验证- 对于不可变的静态组件(如staticfinal字段),采用行为验证而非状态验证- 当无法直接mock某个组件时,考虑通过测试输出结果来间接验证行为- Mock对象使用: 只能对`mock()`创建的对象使用`when()`进行stub,禁止对真实对象(如通过builder模式创建的对象)使用`when()`### 测试重点- 专注于方法的返回值、异常抛出、状态变更等核心行为- 避免测试框架细节、日志输出等非核心功能- 保持测试的简洁性和可维护性

模块功能文档规范

---description: globs: alwaysApply: false---## 生成记忆- 创建记忆文件夹:记忆文件统一存放在 [.cursor/memory](mdc:.cursor/memory) ,如果我提供了指定了文件目录则按照我提供的文件夹存放,如果我没提供则根据需要梳理的链路自动起名创建文件夹- 创建记忆文件:如果我提供了名字,则按照我提供的名字创建,如果我没有提供,则根据需要梳理的链路自动创建文件,已`.md`格式的文件维护记忆。- 记忆文件内容要求:必须包含一个完整的链路图,并且将必要的代码入口、核心的代码逻辑放在记忆文档中。


技术方案文档规范
---description: globs: alwaysApply: false---## 生成开发任务- 创建任务文件夹:当我要求你创建一个开发任务时,你需要根据`当前分支`的名称在 [.cursor/task](mdc:.cursor/task) 文件中查找是否有对应任务的文件,如果没有则创建一个任务文件夹- 创建任务文件:在以`当前分支`命名的文件夹中,创建当前任务的详细描述文件,使用`.md`的文件格式生成文档内容,文件名根据我的要求自动生成一个中文名
## 文档内容规范- 文档结构:保持简洁,专注技术方案。在没有明确要求时不包含开发计划、风险控制、上线计划等管理内容- 测试要求:单元测试要求,覆盖率达到80%以上- 尽量简洁:在满足要求的情况下尽量简洁,如果有需要补充的内容,我会明确的向你表达
## 代码设计规范- 枚举使用:新增字符串类型字段时优先考虑枚举定义,避免硬编码- 历史兼容:新增字段时考虑历史数据兼容性,提供默认值处理



2.3. 代码生成与测试

平衡效率和质量核心是控制单个任务不要过大,当下过大的任务质量和验证过程都会失控。

  • 拆解子任务分步执行:和AI共同完成技术方案后,可以要求其将技术方案分成多个子任务,然后子任务分步执行、验证、调整。

  • 让AI按照技术方案写测试代码:确保核心场景单元测试都能覆盖到,避免我们成为AI的填坑奴隶。更进一步是让AI生成集成测试、端到端测试(尝试中)。

  • AI自Review代码:根据技术方案生成代码之后,可以要求AI根据技术方案检查下当前的代码变更,是否有错漏的。

对AI的约束模型为了获得奖励,有时候会用作弊的方式假装满足用户的要求

  • 作弊问题:当AI反复多次无法完成任务时,就会出现作弊现象,比如硬编码绕开测试、模型自己直接给出结果等。可以在规则中明确禁止,禁止绕开需求直接生成结果,如无法完成时可以明确表示无法完成。

  • 超额输出问题:无论是技术方案还是代码都存在超额输出的问题,AI可能会输出一些不着边际的方案或代码,可以将这个问题尽量在技术方案阶段限制住,在生成技术方案时要求尽量简洁、专注技术方案,不必生成工期之类的内容,在生成代码时要求严格按照技术方案生成代码。

多任务并行开发Cursor本身支持多任务并行开发的能力

  • Cursor多子任务:将技术方案分成多个子任务后,可以在CursorIDE中同一个项目开启多个子任务并行开发,每个子任务分别验证。

  • Cursor Background Agent:异步编程Agent,在云端环境启动虚拟环境执行开发任务,但是需要上传代码到Cursor的云端环境,在团队版的Cursor中强制开启因素模式,无法使用Background Agent。

开发过程持续更新记忆类似上文提到的,记忆是逐步完善的,不是一蹴而就的,需要在过程中持续完善记忆。

  • 记忆与代码不匹配:无论是哪一层的记忆,如果开发过程中发现有缺少或不恰当的,可以直接要求AI根据特定代码修正记忆文档。

  • 经验总结回写记忆:如果在开发过程中,发现有一些规范或场景在规则中没考虑到的,可以完成一个子任务后,要求AI总结经验,并且使用简洁的方式回写到对应记忆文档中。

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

2.3.1. 对AI的约束示例

AI作弊的CASE:在一个JSON转HTML的任务中,cursor在多轮循环无法解决问题之后,直接生成了一个html的结果文件给我,绕开了使用代码生成html的要求。

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

严格按照要求执行示例

- 禁止作弊:对于生产代码和测试代码的生成,需要完全遵循框架和需求的要求,**禁止通过硬编码的方式直接生成结果或绕开测试等行为**。- 严格按照要求写代码:如果我提供了开发任务的.md文档,请严格按照文档要求生成代码,不要擅自发挥。- 保持简洁:专注按照我的需求生成技术方案。在没有明确要求时不包含开发计划、风险控制、上线计划等冗余内容

2.4. 工程师的基础能力

  • 对模型能力的动态认知清晰的认知当前AI的能力特征和极限,并且随着模型能力的提升,能够快速的形成对新模型的新认知,改变自己的行为模式获得更高的效率、质量。

  • 管理多个AI编程工具通过上下文工程、AI并行开发协作方法驱动多个AI编程工具,放大技术杠杆的效果。如Cursor多子任务、Cursor Background Agent、Claude Code多子Agent实例等并行开发手段。

  • 软件架构设计能力AI已经能帮助我们很好的处理细节,但是在企业级复杂系统中,AI当下依然是个执行角色,我们需要作为软件系统的主导者、控制者、设计者,让系统在预期之内演进。(自己能够处理细节的能力依然重要)

  • 业务理解与表达当AI已经能够处理很多的技术细节时,深入的产品业务理解能力和清晰的表达能力,未来是新的编程技巧。

三、真实的使用案例

3.1. 初始记忆维护

使用示例

Cursor规则描述

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

Cursor自动生成

应用基础记忆

输入指令:/Generate Cursor Rules 

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

要求生成特定的规则

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

基于应用基础记忆

结合代码入口生成

功能模块记忆文档

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

3.2. 技术方案生成

使用示例

基于功能

模块记忆

生成迭代

技术方案

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

3.3. 代码开发与测试

使用示例

执行开发任务

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

执行开发任务

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

复杂任务拆解

输入指令

将这个方案拆分为多个子任务,并且细化到可供Cursor执行的程度。

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

任务过程中反思

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

同项目并行开发

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

Playwright 

MCP

端到端测试

基础处于不可用状态,执行了5~10分钟,无法处理日期组件等复杂组件。

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

四、AI编程领域的最新趋势

4.1. 编程工具对比

Cursor依然是当下实用性和性价比较高的编程工具,但Claude Code的高任务完成度和其形态的高可玩性正在快速蚕食Cursor的用户市场。以Devin为代表的端到端异步Agent由于其较低的任务完成度,已经逐渐失去了用户的信任,处在黑暗中挣扎的阶段。(此处仅对比当下有代表性的2款热门工具)

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?
AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

近期Cursor的订阅模式的改变(Pro不限量)也可以侧面感受到来自ClaudeCode的竞争压力,从能力层面上ClaudeCode目前更强一些,但是Cursor放开Pro订阅的使用限制,是从成本和用量上拉开优势进行错位竞争,先留住用户,再追赶能力。(个人理解)

4.2. ClaudeCode使用体验

  • 特点:原生任务规划能力+Claude4任务完成度比Cursor更高,但是费用也更高。

  • 费用:费用高主要体现在20$每个月的订阅版本无法作为主力开发,其额度5小时刷新一次,但是1个额度周期只够开发1小时(真实使用),达到额度后要等下一个5小时周期。解决额度问题需要升级每月100$/200$的MAX版本,或者使用API访问。不过API的费用更加高昂,使用claude 4 sonnet1个任务要花掉2$(opus5倍价格)。

  • 并行开发:Claude Code原生集成Agent功能,在任务分解后可以让其自行启动多个子Agent并行开发,由Claude Code统一管理。

  • 解决复杂问题:在一个真实需求中,需要将格式不固定的JSON转成HTML,在Cursor使用了100次的额度、2-3个小时、尝试了3个方案依然无法符合要求。Claude Code沟通了3-4次完成了可运行的MVP,10次左右达到预期效果。

  • 无监督运行时长:Claude Code跳过权限提示后(--dangerously-skip-permissions),在无额度限制的情况下连续运行的时间远超过Cursor,社区有连续运行数个小时的例子。(Cursor的连续工作最大限制是25个tools)

  • 无监督自主开发的Agent是否具备条件:强如Claude Code,虽然持续执行的时间更长,但是依然很难做到长期无监督的运行。核心的问题是前期输入信息的完备性和后期的代码验收依然是个很大的挑战,执行任务的复杂度越高、无监督时间越长,结果越容易失控。

使用示例

安装和启动

# 安装(需要NPM)npm install -g @anthropic-ai/claude-code# 进入项目目录cd ~/your-project# 启动claude


启动视图

使用了claude-code-router介入openrouter api的界面,订阅用户稍有区别

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

运行模式

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

创建技术方案

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

拆解子任务

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

并行开发

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

达到限额

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

ClaudeCode

工具集

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

ClaudeCode

解决真实问题

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

AI写代码的“上下文陷阱”:为什么AI总是写错?如何系统性解决?

相关文章