编者按: 如何有效利用大语言模型(LLMs)生成高质量代码?这是当下开发者们比较关心的一个问题。在生成代码的过程中,提示词的设计是否精确,直接决定了模型输出的质量。
本文深入探讨了提示词优化的 12 条策略,给出了清晰的操作指南和示范案例,读者可以了解到如何通过精准编写提示词引导模型生成性能优越、符合实际需求的代码。
作者 | Ayush Thakur@Potpie
(https://github.com/potpie-ai/potpie)
编译 | 岳扬
大语言模型(LLMs)已经彻底改变了代码生成领域,但要想获得高质量、有用的输出结果,编写有效的提示词至关重要。LLMs 生成代码的质量高度依赖于所提供提示词的质量。一句表述不当的提示词可能导致不完整、不正确或虽然正确但不具备针对性的响应,而逻辑性、完整性和易读性良好的提示词则能最大化发挥模型的潜力。 本文将探讨编写有效提示词的高级策略,以便使用 LLMs 生成高质量的代码。
01 提供详细的上下文
在与 LLMs 进行交互生成代码时,所提供上下文的深度和质量直接影响模型输出的相关程度和准确程度。
上下文需要包含的关键要素有:
- Specific problem domain(译者注:指的是你试图解决的问题所在的特定专业或技术领域。例如,如果你正在开发一个系统来处理金融交易,那么你的问题领域就是金融科技(FinTech)。)
- Existing codebase characteristics(译者注:指的是当前项目中已有代码的特点、风格和结构等信息。)
- Implementation constraints(译者注:在实现解决方案时必须遵守的各种限制条件,如只能使用某些技术栈等。)
- Performance requirements(译者注:指的是系统或应用程序需要达到的性能标准。)
- Architectural patterns already in use(译者注:指的是在当前项目或组织中已经采用的软件架构模式。架构模式是一种通用的、可重复的设计模板,用于解决软件架构中的常见问题。例如,微服务架构、分层架构(n-tier architecture)或是事件驱动架构等。)
此外,你可以使用 @references 指向特定文件或函数(译者注:大部分“对话式编程” Apps 都支持该功能),使你的请求更加精准。与其用文字描述某个函数,不如直接引用它。
❌ 欠佳的提示词:创建一个用户身份验证系统。
✅ 更好的提示词:为我们的 Node.js Express API 创建一个基于 JWT 的身份验证系统,该系统需要与 MongoDB 的 user 集合集成。该系统应使用 bcrypt 处理密码哈希,签发有效期为 24 小时的令牌,并实现刷新令牌(refresh token)轮换机制增强安全性。现有的中间件模式采用 async/await 语法。请参考 @authMiddleware.js 的中间件结构和 @userModel.js 的 user 集合结构。
通过使用 @authMiddleware.js 和 @userModel.js,可以确保生成的代码与现有架构保持一致,减少一些集成问题和手动调整工作量。
02 将问题分解为多个步骤
复杂的编码任务需要系统性地拆解为可管理单元。该方法论的实施路径如下:
- 从明确的功能需求出发
- 分析目录结构和代码组织方式
- 引导 LLM 按照逻辑步骤实现目标功能,同时遵循既定的架构边界和设计模式。
例如,在实现一个数据处理 pipeline 时,首先需明确输入的数据结构、转换逻辑、错误处理的相关要求及预期的输出格式。随后分析目录结构,并确定新功能的实现位置。
需要综合考量代码之间的依赖关系(dependency relationships)、模块的职责划分与隔离(module boundaries)以及代码的目录结构与命名规范(code organization principles)。这一步骤可确保生成的代码能无缝集成到现有代码库中。
03 选择合适的模型完成任务
不同 LLM 在代码生成任务中展现出的优势不同。某模型可能擅长理解复杂需求并生成逻辑一致性强的代码,而另一模型可能在特定编程语言或框架上具有优势。 在评估使用哪种 LLM 时,需着重关注以下技术因素:
- 上下文窗口大小(处理大型代码库时至关重要)
- 对编程语言/技术框架的掌握程度
- 特定领域的专业知识
- 多轮交互的稳定性
对比示例:
任务类型 | 模型选择考量因素 |
---|---|
复杂的企业级架构 | 更大的上下文窗口大小有助于在大型代码库中保持多轮交互的稳定性 |
机器学习 pipeline | 数学基础扎实且经过数据科学专项训练的模型更具优势 |
前端组件 | 采用新近框架数据训练的模型,可输出符合业界最新标准的代码模式 |
04 具体参照现有的代码实现模式
在提示词中明确具体细节能大大提升代码生成的质量。 技术细节需明确指向代码库中的既有实现范式,而非笼统要求通用方案。例如:
❌ 欠佳的提示词: “写一个处理用户数据的函数”
✅ 更优的提示词:“在 UserProcessor 类 (src/services/UserProcessor.js) 中创建一个新方法,沿用 transformPaymentData 方法的函数式编程风格实现用户数据的转换。因采用异步机制,实现时应以可读性为第一准则,性能次之。”
该方法也同样适用于命名规范、编码标准和架构模式。需明确说明采用函数式或面向对象范式,指定设计模式类型,并澄清性能与代码可读性的优先级。
05 请重新生成而非回滚
当生成的代码出现问题时,重新生成有问题的模块通常比逐步去修复代码中的问题效果更好。 此方法源于大语言模型理解上下文和生成模型响应的机制。
为何重新生成效果更好?
- 脱离原有错误实现方式的思维定式
- 防止旧代码中的错误代码逻辑污染新的代码实现
- 支持加入新的约束条件
这种方法对解决一些算法难题或实现复杂的代码逻辑特别有效,因为在这些场景下一点细微的错误都可能影响整体解决方案。
示例:
“请尝试用不同的方法实现排序算法。当前版本的时间复杂度为 O(n²),无法满足数据集规模要求,请基于我们其他的数据处理函数使用的归并排序模式,重新生成 O(n log n) 时间复杂度的解决方案”
06 决策前请生成多套方案进行对比
利用大语言模型能够生成多套解决方案的能力,通过对比分析提升代码质量。首先,要求模型生成 2-3 种不同的实现策略,每种策略需包含对该方案优缺点的分析。
生成多套方案后,引导模型分析时间复杂度、空间复杂度、代码可读性和可维护性等因素,并分析如何权衡这些因素。这一反思(reflection)过程使模型能根据具体需求选择并完善最合适的解决方案。
示例:
“请为 API 响应缓存系统(caching system for our API responses)提供三套实现方案:
1) 基于自定义数据结构的 LRU 内存缓存方案
2) 基于 Redis 的分布式缓存方案
3) 支持 TTL 的本地文件系统缓存
请分别分析各方案的时间复杂度、内存占用、多服务器扩展能力和实现复杂度”
07 实施自我审查机制
Self-review prompting 可通过引导大语言模型对其生成的代码进行系统化评估来提升代码质量。具体实施时需明确要求模型在完成代码生成后交叉检查其生成的代码。自我审查(Self-review)应评估以下这几个方面:
- 代码正确性(是否有逻辑错误)
- 效率(是否存在性能问题)
- 边界情况的处理情况
- 安全漏洞
- 是否严格满足需求
在自我审查过程中,模型可识别潜在问题,例如并发代码中的竞态条件漏洞(译者注:一种常见安全漏洞,源于系统或程序在处理并发操作时因时序问题导致的逻辑错误。)、资源管理中的内存泄漏,或直接影响系统安全的核心逻辑中的漏洞风险点。发现问题后,模型可立即优化代码实现来解决问题。此方法对应成熟的软件工程实践(如代码审查和静态分析),但将其置于同一 prompt-response 周期内执行,大大提升了初始的代码生成质量。
08 为模型赋予技术人设或给出参考框架
为大语言模型分配技术人设,可确保其代码生成保持统一的专业视角。当要求模型以"精通分布式系统的高级后端工程师"的思维模式运作时,其生成的代码会优先考虑可扩展性、容错性和性能优化。同理,若赋予"安全专家"人设,其生成的代码会重点强化内容输入区的验证、规范认证流程,并预先规避潜在的漏洞风险。
技术参考框架需与任务需求相匹配。
根据不同任务选择不同的专业人设:
- 后端系统:"具备分布式系统专业知识的高级后端工程师"
- 安全模块:"熟悉 OWASP 规范的安全架构师"
- 基础设施:"专攻云原生解决方案的 DevOps 工程师"
- 前端开发:"关注用户体验且具有无障碍化开发经验的前端工程师"
这种方法利用模型模仿领域专家的能力,使生成的代码更精准体现特定技术领域的行业最佳实践。
示例:
“扮演高级安全工程师进行代码审查。用 Python/Django 创建用户注册系统,需实现合规的密码处理、输入验证功能,并防御常见 Web 漏洞。”
09 明确编程语言、开发框架或第三方库的限制条件
明确说明技术限制条件,才能确保代码与运行环境完美兼容。首先应清晰说明编程语言版本(例如 Python 3.9、TypeScript 4.5),确保生成的代码所使用的语言特性在生产环境中可用。同时需指定框架版本及其特定规范,例如"使用 Pydantic v2 模型的 FastAPI 0.95 进行数据验证"。
此外,还要交代清楚:用哪些第三方库、具体怎么接入。例如,在请求生成数据库交互代码时,应指定使用 SQLAlchemy 等 ORM 还是原始的 SQL queries,并明确数据库连接的处理要求。抠到这种细节程度,才可以避免生成依赖了不可用的组件或版本不兼容的代码。
示例:
“请使用以下技术栈开发 REST API 接口:
- Python 3.9
- 搭载 Pydantic v2 模型的 FastAPI 0.95 框架
- 使用 SQLAlchemy 2.0 执行数据库操作
- 通过 auth_utils.py 文件中现有 AuthManager 实现 JWT 身份认证
- 必须兼容 PostgreSQL 13 数据库”
10 实施思维链这一提示词工程技术
思维链(Chain of thought prompting)通过引导大语言模型进行逻辑推理,可以大大提升代码生成质量。这个方法的精髓是:让 AI 先拆解问题再写代码。
要求模型按这个顺序分步思考:
- 用大白话解释实现思路
- 搭建解决方案的伪代码框架
- 每个模块的具体实现逻辑
- 最终完整可运行的代码成品
思维链技术对于包含复杂逻辑或数据转换的算法特别有效。这种方法可以减少逻辑错误,提高代码的一致性,并可视化模型的推理过程,便于在最终代码生成前进行修正。
与侧重任务分解的"分步执行"方法不同,思维链技术着重于显性化模型的推理路径,确保在确认最终方案前保持逻辑的严谨性。
11 针对不同大语言模型(LLM)的特长设计专属的提示词策略,以最大化发挥其优势
不同的大语言模型具备各自独特的优势,通过针对性的提示词技巧可以充分发挥它们的潜能。
提示词策略如下:
- 针对上下文窗口有限的模型:聚焦分步算法指导
- 针对擅长函数式编程的模型:使用函数式思维提问
- 针对精通某一特定开发框架的模型:直接使用该框架的核心 API、类名或设计模式等特定术语提问,减少解释成本。
了解模型在训练过程中接触的数据集特点是优化提示词的关键。 不同的模型因其训练数据分布不同,往往只对特定编程范式或语言有更强的理解力。例如,若某模型在训练中接触了大量函数式编程内容,那么当问题本身适合使用函数式编程解决时,用函数式编程术语构建提示词,将获得更精准的响应。
12 指定边界情况和约束条件
全面覆盖边界场景能大幅提升代码健壮性 。技术领域的边界情况因场景而异,但通常包含临界值(译者注:如数值溢出、空输入)、资源限制(译者注:如内存耗尽、超时)和异常状态(译者注:如网络中断、并发冲突)。在向模型发送请求生成代码时,应明确列出这些要素,例如说明数据处理函数应如何处理空输入、格式错误的数据或超出预期范围的值。
通过预先考虑这些约束条件,生成的代码可包含与指定限制条件相匹配的验证逻辑、错误处理机制和性能优化方案。
示例:
“实现一个能处理以下情况的文件处理函数:
- 空文件(返回空结果)
- 超过 1GB 的文件(分块读取处理)
- 格式错误的 CSV 数据(记录错误并跳过错误行,继续处理后续有效行)
- 多进程/线程同时操作同一文件(需加锁(如文件锁、数据库锁)避免数据竞争)
- 网络中断(需支持断点续传)”
掌握代码生成的提示词工程既是一门艺术,也是一门科学,它能大幅提升开发效率。通过运用这些策略方法,开发者可以将大语言模型(LLM)从简单的代码生成工具升级为智能开发助手,从而打造出更健壮、高效且易于维护的软件系统。
About the author
Ayush Thakur
Developer Advocate | Community Manager | Technical Writer
END
本期互动内容 🍻
❓文中提到「重新生成代码优于修复 Bugs」,你在实际使用“对话式编程”时有这种感受吗? 欢迎在评论区分享~
本文经原作者授权,由 Baihai IDP 编译。如需转载译文,请联系获取授权。
原文链接:
https://github.com/potpie-ai/potpie/wiki/How-to-write-good-prompts-for-generating-code-from-LLMs
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。