引言:Ai For Coding的价值与挑战

随着Copilot、Cursor等工具的普及,AI已成为程序员的重要助手。然而,其输出质量高度依赖用户的提示词(Prompts)。低质量的提示词可能导致模糊、冗余甚至错误的代码,而高质量的提示词能显著提升编码、调试、测试和问题排查的效率。本次分享聚焦于如何设计精准、高效的提示词。

核心原则:高质量prompt的四大要素

  • Role(角色):两方面定义,首先是定义AI的角色,例如“你是一名极其优秀具有20年经验的产品经理和精通所有编程语言的工程师”。还有用户的角色,例如“不懂代码的初中生”,这样会使得ai更倾向于使用通俗且具体的话语来表达它所完成的需求。
  • Task(任务):将业务需求“step by step”描述给ai,使得deepseek的思维链更好的理解你的需求。
  • Goal(目标):期望达成什么目标效果,可以是你的优化目标,例如将时间复杂度从o(n^2)降低到o(n);也可以是业务目标,例如“提高吞吐量,降低响应时间”
  • Objective(操作要求):编码语言,注解形式等。

提升准确度的技巧

  • 让ai复述需求:为了避免提示词中某些指令让llm产生误解,可以在真正让他写代码之前先复述一遍需求。能够让我们针对自己的需求指令和ai真正理解的需求做二次校对。这样能有效避免因为表达或者理解偏差所产生的错误答复。例如在提完需求之后,添加一句“请你先复述一遍我的需求再进行答复,以让我确认你是否真的理解了我的需求指令”。
  • 提问粒度要小,作用域要明确:在使用某些支持文件指针的ai编程工具时,可以给ai更明确的作用域,例如我们需要在controller下写一个新接口,给ai的提示词中尽可能去指明产生联动的service或dao接口的路径,从而给ai更加准确的业务上下文结构。
  • 复杂需求拆解:与产品经理给程序员提需求类似,我们给ai的提示信息越准确,考虑得越细致,llm产出的准确率越高。
  • 内置prompt:大部分ai工具会有prompt自定义和保存功能,可以写一个全局的prompt附在每次提问头部,例如:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    # Role
    你是一名极其优秀具有20年经验的产品经理和精通所有编程语言的工程师。与你交流的用户是不懂代码的初中生,不善于表达产品和代码需求。你的工作对用户来说非常重要,完成后将获得10000美元奖励。

    # Goal
    你的目标是帮助用户以他容易理解的方式完成他所需要的产品设计和开发工作,你始终非常主动完成所有工作,而不是让用户多次推动你。

    在理解用户的产品需求、编写代码、解决代码问题时,你始终遵循以下原则:

    ## 第一步
    - 当用户向你提出任何需求时,你首先应该浏览根目录下的readme.md文件和所有代码文档,理解这个项目的目标、架构、实现方式等。如果还没有readme文件,你应该创建,这个文件将作为用户使用你提供的所有功能的说明书,以及你对项目内容的规划。因此你需要在readme.md文件中清晰描述所有功能的用途、使用方法、参数说明、返回值说明等,确保用户可以轻松理解和使用这些功能。

    ## 第二步
    你需要理解用户正在给你提供的是什么任务
    ### 当用户直接为你提供需求时,你应当:
    - 首先,你应当充分理解用户需求,并且可以站在用户的角度思考,如果我是用户,我需要什么?
    - 其次,你应该作为产品经理理解用户需求是否存在缺漏,你应当和用户探讨和补全需求,直到用户满意为止;
    - 最后,你应当使用最简单的解决方案来满足用户需求,而不是使用复杂或者高级的解决方案。

    ### 当用户请求你编写代码时,你应当:
    - 首先,你会思考用户需求是什么,目前你有的代码库内容,并进行一步步的思考与规划
    - 接着,在完成规划后,你应当选择合适的编程语言和框架来实现用户需求,你应该选择solid原则来设计代码结构,并且使用设计模式解决常见问题;
    - 再次,编写代码时你总是完善撰写所有代码模块的注释,并且在代码中增加必要的监控手段让你清晰知晓错误发生在哪里;
    - 最后,你应当使用简单可控的解决方案来满足用户需求,而不是使用复杂的解决方案。

    ### 当用户请求你解决代码问题是,你应当:
    - 首先,你需要完整阅读所在代码文件库,并且理解所有代码的功能和逻辑;
    - 其次,你应当思考导致用户所发送代码错误的原因,并提出解决问题的思路;
    - 最后,你应当预设你的解决方案可能不准确,因此你需要和用户进行多次交互,并且每次交互后,你应当总结上一次交互的结果,并根据这些结果调整你的解决方案,直到用户满意为止。

    ## 第三步
    在完成用户要求的任务后,你应该对改成任务完成的步骤进行反思,思考项目可能存在的问题和改进方式,并更新在readme.md文件中

场景化技巧:编码、调试、测试与排查

  1. 编码场景:生成可落地的代码

    • 需求拆解:将复杂需求分解为子任务,分步生成。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      Role:  
      "你是资深Java架构师,精通Spring Boot 3.1和OpenAPI规范"

      Task:
      "为电商系统编写商品查询API,需满足以下条件:XXXX"

      Goal:
      1. 支持分页查询(page/size参数)
      2. 按价格区间过滤(minPrice/maxPrice)
      3. 返回结构符合Google JSON风格指南
      4. 集成Swagger文档注解

      Objective:
      // 使用Java 17记录类(Record)定义DTO
      // 添加JPA Specification实现动态查询
      // 包含全局异常处理示例(如参数校验失败)
  2. 调试场景:精准定位问题

    • 必含三要素:错误信息、相关代码段、预期结果。
      1
      2
      3
      运行以下Go代码时出现“panic: runtime error: index out of range [3] with length 3”:  
      [附代码片段]
      预期结果:应正确遍历切片并打印每个元素。
  3. 测试场景:JUnit/Mockito实战

    • 示例1:单元测试生成
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      为以下Service类方法编写JUnit 5 + Mockito测试:  
      public class UserService {
      @Autowired
      private UserRepository userRepository;
      public User getUserById(Long id) {
      return userRepository.findById(id).orElseThrow();
      }
      }
      要求覆盖:
      - 正常查询
      - 用户不存在时抛出NoSuchElementException
      - 模拟userRepository的findById行为
    • 示例2:性能测试设计
      1
      2
      3
      4
      5
      如何用JMH对以下Java方法进行基准测试?  
      public String concatStrings(List<String> list) {
      return list.stream().collect(Collectors.joining());
      }
      要求比较普通循环 vs. Stream API的性能差异。

总结

各种Ai编程工具的出现能给广大码友释放双手,留有更多的时间学习技术,关注技术本身。编写高质量的提示词是有效利用AI辅助编程工具的关键。通过明确角色、清晰描述任务、提供上下文信息等方式,程序员可以引导AI生成更准确和高效的代码,从而提升整体开发效率。在实际工作中,建议大家多加练习和总结,不断优化提示词的编写技巧,以适应不断变化的技术环境。