告别无效提示!开发者必学的AI协作提示框架全解析

AITNT-国内领先的一站式人工智能新闻资讯网站
# 热门搜索 #
告别无效提示!开发者必学的AI协作提示框架全解析
6283点击    2025-06-28 11:57

让AI编程助手成为更可靠的开发伙伴


神译局是36氪旗下编译团队,关注科技、商业、职场、生活等领域,重点介绍国外的新技术、新观点、新风向。


编者按:开发者们越来越依赖AI编程助手来加速日常工作流程,但AI编程助手输出质量取决于提示词水平。本文系统拆解调试、重构、开发三大场景的提示工程框架,并附上可复用的模板及对比案例,助开发者释放AI协作潜能。文章来自编译。


告别无效提示!开发者必学的AI协作提示框架全解析


开发者们越来越依赖AI编程助手来加速日常工作流程。这些工具可以自动补全函数、建议修复bug,甚至生成整个模块或最小可行产品(MVP)。不过,正如我们许多人已经了解到的那样,AI输出的质量在很大程度上取决于你提供的提示(prompt)的质量。换句话说,提示工程已经成为一项必备技能。一个措辞不当的请求可能会得到无关或泛泛的答案,而一个精心设计的提示则可能生成深思熟虑、准确甚至富有创意的代码解决方案。本文旨在从实用角度探讨如何系统地为常见开发任务设计有效的提示。


AI结对编程工具很强大,但并非魔法——它们缺乏有关你的项目或意图的先验知识,只知道你告诉它们或作为上下文所包含的内容。你提供的信息越丰富,输出结果就越好。我们将提炼出关键的提示模式、可复用的框架以及让开发者产生共鸣的难忘示例。你将看到好提示与坏提示及其实际AI响应的对比,并附有评论说明为什么一个成功了而另一个却失败了。以下是一份入门速查指南:


告别无效提示!开发者必学的AI协作提示框架全解析


高效编码提示基础


向AI编码工具发出提示,有点像是跟一位非常刻板(有时候还知识渊博)的合作者沟通。要想获得有用的结果,你需要清晰设定场景,并引导AI了解你想要什么以及你想要的方式。


以下是支撑本指南所有示例的基本原则:


  • 提供丰富的上下文。始终假设AI除了你提供的信息外,对你的项目一无所知。要提供相关细节,如编程语言、框架和库,以及有问题的具体函数或代码片段。如果有错误,提供确切的错误信息并描述代码本应实现的功能。具体性和上下文决定了你得到的是含糊的建议还是精确、可操作的解决方案。在实践中,这意味着你的提示可能要有一个大概的设定,比方说:“我有一个使用Express和Mongoose的Node.js函数,它应该通过ID获取用户,但它抛出了一个TypeError。这是代码和错误信息……”。你提供的设置信息越多,AI需要猜测的部分就越少。


  • 明确你的目标或问题。模糊的查询会导致模糊的答案。与其问“为什么我的代码工作不了?”,不如明确指出你需要什么样的洞察。比方说:“这个JavaScript函数返回的是undefined,而不是预期的结果。根据下面的代码,你能帮我找出原因以及如何修复吗?” 这样更有可能得到有用的答案。一个用于调试的提示公式是:“预期行为是[预期行为],但当输入[示例输入]时,实际行为却是[当前行为]。问题出在哪里?”。同样地,如果你想做优化,请具体说明需要哪种优化(比方说:“如何改进这个排序函数在处理1万个项目时的运行时性能?”)。明确性可以引导AI该关注哪里。


  • 分解复杂任务。在实现新功能或处理多步骤问题时,不要即将整个问题塞进一个冗长的提示里面。更有效的做法通常是将工作拆分成更小的部分并进行迭代。比方说,“首先,为产品列表页面生成一个React组件骨架。接下来,我们将添加状态管理。然后,我们将集成API调用。” 每个提示都建立在前一个的基础上。通常不建议一次性要求实现整个大功能;相反,从一个高级目标开始,然后迭代地请求实现每一部分。这种方法不仅让AI的响应更专注、更易于管理,也是人类逐步构建解决方案的体现。


  • 把输入/输出或预期行为的示例放进去。如果你能用例子说明你想要什么,那就这么做。比方说,“给定数组 [3,1,4],这个函数应该返回 [1,3,4]。” 在提示中提供一个具体的例子有助于AI理解你的意图并减少歧义。这就像给初级开发人员一个快速的测试用例——可明确要求。在提示工程术语中,这有时候被称为“少样本提示”(few-shot prompting),即你向AI展示一个要遵循的模式。即便是一个正确行为的例子也能为模型的响应起到很好的引导作用。


  • 利用角色或人设。在许多广泛传播的提示示例里,流行着一个强大技巧,就是要求AI“扮演”(act as)某个特定的人设或角色。这可以影响答案的风格和深度。比方说,“扮演一位资深React开发者,审查我的代码是否存在潜在错误”或“你是一位JavaScript性能专家。优化以下函数。” 通过设定一个角色,可引导助手采取相关的语气——比如严格的代码审查员、乐于帮助初级开发者的老师,还是寻找漏洞的安全分析师等。社区共享的提示已经证明了这种方法的成功,比方说“扮演一个JavaScript错误处理程序,帮我调试这个函数。API调用并没有正确渲染数据。”。我们自己在使用时,仍然需要提供代码和问题细节,但这种角色扮演提示可以得到更结构化的输出和专家级的指导。

告别无效提示!开发者必学的AI协作提示框架全解析


  • 迭代优化对话。提示工程是一个互动过程,不是一锤子买卖。开发者通常需要审查AI的首次回答,然后提出后续问题或进行修正。如果解决方案不太合适,你可以说:“那个解决方案用了递归,但我更喜欢迭代方法——你能不用递归再试一次吗?” 或者,“很好,现在你能优化一下变量名并添加注释吗?” AI会记住聊天会话中的上下文,因此你可以逐步将其引导至期望的结果。关键是把AI看作一个你可以指导的伙伴——追求进步,而非第一次就要求完美。


  • 保持代码清晰度和一致性。最后这条原则不是那么直截了当,但对于处理你代码上下文的工具来说非常重要。即便在使用AI之前,也要编写干净、结构良好的代码和注释。有意义的函数和变量名、一致的格式以及文档字符串(docstrings)不仅让你的代码更容易被人理解,也能为AI了解你在做什么提供更强烈的线索。如果你展示出一致的模式或风格,AI会延续的。将这些工具视为极其专注的初级开发者——它们会从你的代码和注释中获取所有提示。


牢记这些基本原则后,让我们深入探讨具体场景。我们将从调试开始,这可能是最直接的用例:你的代码行为异常,你想让AI帮忙找出原因。


调试代码的提示模式


调试天然适合AI助手。这就像拥有一个橡皮鸭,它不仅会听你说话,还会提出建议。不过,成功与否很大程度上取决于你如何向AI呈现问题。以下是系统性地请求帮助查找和修复bug的方法:


1.清晰描述问题和症状。首先在提示中描述哪里出了问题,以及代码本应实现什么功能。务必包含确切的错误信息或错误行为。比方说,与其只是说“我的代码不工作”,你可以这样写提示:“我有一个JavaScript函数,它应该计算一个数字数组的总和,但它返回的是NaN(非数字)而不是实际的总和。代码如下:[包含代码]。对于像[1,2,3]这样的数字数组,它应该输出一个数字(总和),但我得到的是NaN。这个bug可能是什么原因造成的?” 这个提示明确了编程语言、预期行为、观察到的错误输出,并提供了代码上下文——所有这些都是关键信息。提供结构化的上下文(代码 + 错误 + 预期结果 + 你尝试过的方法)为AI奠定了坚实的基础。相比之下,像“为什么我的函数不工作?”这种泛泛的问题收效甚微——模型在没有上下文的情况下只能提供最笼统的猜测。


2.对棘手的bug采用分步或逐行方法。对于更复杂的逻辑错误(没有抛出明显的错误消息但输出错误),你可以提示AI逐步执行代码。比方说:“逐行分析这个函数,并在每一步跟踪`total`的值。这个值累加不正确——逻辑是在哪里出错的?” 这是一个橡皮鸭调试提示的示例——本质上是在要求AI模拟人类用打印语句或调试器进行的调试过程。这类提示常常能揭示一些微妙的问题,比如变量未重置或条件逻辑错误,因为AI会详细说明每一步的状态。如果你怀疑代码的某个特定部分,可以放大关注点:“解释一下这里的`filter`调用在做什么,它排除掉的项是否比预期的要多?” 让AI扮演解释者的角色,可以在解释过程中暴露bug。


3.尽可能提供最小可复现示例。有时候你的实际代码库很大,但bug可以在一个小片段中复现。如果能提取或简化仍然能复现问题的代码,就把它提供给AI。这不仅让AI更容易集中注意力,也迫使你澄清问题(这本身通常就是一次有用的练习)。比方说,如果你在一个深度嵌套的函数调用中得到了一个TypeError,尝试用几行可分享的代码来复现它。目标是用最少的代码隔离掉bug,对问题所在做出假设,进行测试并迭代。你可以让AI参与这个过程:“这是一个简化后的示例,它仍然会触发错误[包含代码片段]。为什么会出现这个错误?” 通过简化,可消除干扰,帮助AI精确定位问题。(这种技术反映了许多资深工程师的建议:如果不能立即找到bug,就简化问题空间。如果你向AI呈现一个更小的案例,它可以协助进行分析。)


4.提出有针对性的问题和后续跟进。在提供上下文后,直接询问你需要的内容通常很有效,比方说:“可能导致这个问题的原因是什么,以及我该如何修复它?”。这会促使AI既进行诊断又提出解决方案。如果AI的首次回答不清楚或只部分有用,不要犹豫,继续追问。你可以说:“这个解释有道理。你能告诉我如何修复代码吗?请提供修正后的代码。” 在聊天设置中,AI是掌握对话历史的,因此它可以直接输出修改后的代码。如果你使用的是像VS Code中的Copilot或Cursor这样的内联工具(没有聊天功能),你可能需要在代码上方写一条注释,如`// BUG: returns NaN, fix this function`,然后看看它如何自动补全——但通常来说,互动式聊天能产生更详尽的解释。另一种跟进模式:如果AI给出了修复方案但你不理解原因,就问:“你能解释一下为什么这个改动能解决问题吗?” 这样你就能学到东西以备下次使用,同时也复核了AI的推理是否合理。


现在,让我们用一个具体示例来说明这些调试提示原则,展示一个糟糕提示与改进提示的对比以及AI响应的差异:


调试示例:糟糕提示 vs 改进提示


想象我们有一个简单的Node.js函数,目的是将用户对象列表转换为按用户ID索引的查找映射(lookup map)。但是,它抛出了一个错误。以下是包含bug的代码:


// Buggy function: converts array of users to a map by ID

function mapUsersById(users) {

const userMap = {};

for (let i = 0; i <= users.length; i++) {

// Note: using <= will go out of bounds on the last iteration

const user = users[i];

userMap[user.id] = user;

}

return userMap;

}

// Example usage:

const result = mapUsersById([{ id: 1, name: "Alice" }]);


这段代码应该遍历用户数组并构建一个对象,其键是用户ID。不过,存在一个bug:循环使用了`i <= users.length`而不是`i < users.length`。这会导致在最后一次迭代时`users[i]`是undefined,很可能引发运行时错误(比方说,尝试访问undefined的属性`id`)。让我们看看AI助手可能如何回应关于此问题的两个不同提示。


糟糕提示:“为什么我的mapUsersById函数不工作?”


AI对糟糕提示的响应(模拟):


> *没有更多信息很难说。你确定函数是用一个有效的用户数组调用的吗?可能是`users`为空或不是数组,导致循环无法正常执行。也可能是在`userMap`上设置属性时出错。确保每个用户都有`id`属性。如果`users`是undefined或null,也会导致它不工作。*


分析:这个答案相当含糊。提示只提供了函数名,没有任何细节,所以AI在猜测一些常见原因(“可能数组为空或不是数组”、“确保每个用户都有id”)。它没有识别出实际的bug。当问题描述不足时,你就会得到这种回应——模型只能复述常见的调试技巧。作为开发者,这并没什么帮助,因为它没有解决真正的错误。提示中缺乏上下文和具体性导致得出泛泛的答案(本质上相当于AI在说“你试过关机再开机吗?”)。这印证了社区的建议:模糊的提示会导致无关或笼统的答案。


改进提示:“我有一个JavaScript函数`mapUsersById`,它应该将用户对象数组转换为按用户ID索引的映射(对象)。但是,当我运行它时会抛出错误。比方说,当我传入`[ {id: 1, name: "Alice"} ]`时,我得到`TypeError: Cannot read property 'id' of undefined`。函数代码如下:


function mapUsersById(users) {

const userMap = {};

for (let i = 0; i <= users.length; i++) {

const user = users[i];

userMap[user.id] = user;

}

return userMap;

}


它应该返回`{ "1": {id: 1, name: "Alice"} }`。bug是什么?如何修复?”


AI对改进提示的响应(模拟):


> *错误`Cannot read property 'id' of undefined`表明在某个时刻`user`是undefined,然后你尝试访问`user.id`。查看你的循环,问题出在循环边界上。你使用了`i <= users.length`。如果`users.length`是1(数组里有一个用户),循环会在i=0和i=1时运行。当i为1时,`users[1]`是undefined(因为数组中唯一的索引是0)。因此`user`在这一次迭代中变成了undefined,`user.id`就会抛出TypeError。修复方法是将循环条件改为`i < users.length`,这样i的范围是从0到`users.length-1`。比方说:*


for (let i = 0; i < users.length; i++) {

const user = users[i];

userMap[user.id] = user;

}

> *这样,对于第一个(也是唯一一个)元素,i将是0,然后循环停止。经过此修改,你的函数将不会再遇到undefined的user,并且应该按预期工作,对于给定的输入返回`{"1": {id: 1, name: "Alice"}}`。*


分析:这个响应直接指出了bug(在循环中使用了`<=`),并解释了它为什么导致`user`变成undefined。然后它提供了正确的代码解决方案(`i < users.length`)并确认了预期结果。改进提示之所以成功,是因为它遵循了我们的原则:明确了语言(JavaScript),描述了函数目的,包含了确切的错误消息和示例输入,甚至还提供了相关的代码片段。注意AI是如何利用错误消息作为线索,将注意力集中在循环边界上的——一个有明确目标的提示使AI能够进行真正的问题解决,有效地模拟了人类调试者的思考方式:“undefined可能从哪里来?很可能来自循环索引”。这具体展示了详细提示的好处。


额外的调试策略:除了识别明显的bug,你还可以利用提示工程辅助进行更深层次的调试:


  • 询问潜在原因。如果你真的卡住了,可以稍微拓展一下问题:“这段代码中出现`TypeError: cannot read property 'foo' of undefined`的一些可能原因是什么?”,同时提供代码。模型可能会列出几种情况(比方说对象未初始化、竞态条件、错误的变量作用域等)。这可以为你提供一些未曾考虑的调查角度。就像与同事进行头脑风暴。


  • “问问橡皮鸭”——即向AI解释你的代码。这可能听起来违反直觉(为什么要向助手解释?),但写下解释的行为可以澄清你自己的理解,然后你可以让AI验证或批评它。比方说:“我来解释一下这个函数在做什么:[你的解释]。基于此,我的推理正确吗?它是否揭示了bug在哪里?” AI可能会发现你解释中的一个缺陷,而这个缺陷指向了实际的bug。这种技术将AI利用为一个主动的橡皮鸭,它不仅愿意听还会回应。


  • 让AI创建测试用例。你可以问:“你能提供几个可能破坏这个函数的测试用例(输入)吗?” 助手可能会提出你没想到的边界情况(空数组、极大的数字、null值等)。这对于调试和生成未来增强健壮性的测试都很有用。


  • 扮演代码审核员。作为直接“调试这个”提示的替代方案,你可以说:“扮演一位代码审核员。这是一个没有按预期工作的代码片段。请审查它并指出任何可能导致问题的错误或不良实践:[代码]”。这会让AI进入批判模式。许多开发者发现,将请求表述为代码审查会生成非常详尽的分析,因为模型会评论代码的每个部分(通常在这个过程中,它就能发现bug)。事实上,一个提示工程技巧就是明确要求AI表现得像一个一丝不苟的审查员。这不仅可以揭示手头的bug,还可能发现其他问题(比方说潜在的空值检查缺失),这可能会很有用。


总之,在使用AI助手进行调试时,细节和方向性是关键。提供场景、症状,然后提出有针对性的问题。正如我们上面所看到那样,慌乱无措地提示“它不工作了,救命!”和一个精准的手术式调试提示之间有着天壤之别。接下来,我们将转向另一个主要用例:重构和改进现有代码。


重构与优化的提示模式


重构代码——在不改变其功能的前提下使其更清晰、更快或更符合语言习惯——是AI助手可以大放异彩的领域。它们基于海量代码进行训练,里面就有很多结构良好、优化解决方案的示例。不过,要有效利用这些知识,你的提示必须明确说明在你的情况下“更好”意味着什么。以下是如何为重构任务编写提示:


1、明确说明你的重构目标。 光说“重构这段代码”就太过开放了。你是想提高可读性?降低复杂度?优化性能?使用不同的范式或库?AI需要一个目标。一个好的提示会框定任务,比方说:“重构以下函数以提高其可读性和可维护性(减少重复,使用更清晰的变量名)。”或者“优化这个算法来提高速度——它在处理大型输入时太慢了。”通过说明具体目标,你帮助模型决定应用哪些转换。比方说,告诉它你关心性能可能会让它使用更高效的排序算法或缓存,而关注可读性则可能会让它将一个函数拆分成更小的函数或添加注释。如果你有多个目标,把它们列出来。来自Strapi指南的一个提示模板甚至建议列举问题:“我想解决的问题:1) [性能问题], 2) [代码重复], 3) [过时的API使用]。” 这样,AI就知道具体要修复什么。记住,它本身并不知道你觉得代码中存在的问题是什么——你必须告诉它。


2、提供必要的代码上下文。 重构时,你通常会在提示中纳入需要改进的代码片段。重要的是把你想要重构的函数或代码完整放进来,有时候如果相关的话,还需要把周边的上下文放进来(比如函数的用法或相关代码,这可能会影响你重构的方式)。同时要介绍语言和框架,因为“符合语言习惯”的代码在不同环境(比方说,符合Node.js习惯 vs 符合Deno习惯,或者React类组件 vs 函数组件)下是不一样的。比方说:“我有一个用类写的React组件。请将其重构为使用Hooks的函数组件。”然后AI会应用典型的步骤(使用useState, useEffect等)。如果你只是说“重构这个React组件”而没有说明风格,AI可能不知道你特指想要Hooks。


  • 如果相关,把版本或环境细节信息放进来。 比方说,“这是一个Node.js v14的代码库”或“我们使用的是ES6模块”。这会影响AI是否使用某些语法(如import/export vs require),这是正确重构的一部分。如果你想确保它不会引入不兼容的东西,请说明你的约束条件。


3、鼓励附带代码的解释。 从AI主导的重构中学习(并验证其正确性)的一个好方法是要求对更改进行解释。比方说:“请建议一个重构后的代码版本,并解释你所做的改进。”这甚至被内置在我们引用的提示模板里面:“……建议重构后的代码并附上对更改的解释。” 当AI提供解释时,你可以评估它是否理解了代码并满足了你的目标。解释可能会是这样:“我将两个相似的循环合并为一个以减少重复,并且我使用了一个字典来加速查找”,等等。如果解释有任何听起来不对劲的地方,那就是需要仔细检查代码的危险信号。简而言之,利用AI的解释能力作为保障——这就像让AI对其自身的重构进行代码审查。


4、 利用角色扮演设定高标准。如前所述,要求AI扮演代码审查员或资深工程师可能非常有效。对于重构,你可以说:“扮演一位经验丰富的TypeScript专家,重构这段代码以符合最佳实践和现代标准。”结果往往不仅是肤浅的更改,还会带来更有见地的改进,因为AI试图符合“专家”的形象。提示指南有个流行的例子是让AI扮演导师:“扮演一位经验丰富的Python开发者指导初级开发者。提供解释并编写文档字符串(docstrings)。重写代码来优化。” 在那个案例里,结果是AI使用了更高效的数据结构(用集合set去重),并为原本使用循环的函数提供了一行式的解决方案。角色扮演不仅帮助它进行了重构,还解释了为什么新方法更好(在那种情况下,使用集合是一种众所周知的用于唯一性的优化)。


现在,让我们通过一个重构示例来看看提示是如何影响结果的。我们将使用一个JavaScript (Node.js)场景,里面有一段不太理想的代码,我们想改进它。

重构示例:糟糕提示 vs 改进提示


假设我们有一个函数,它进行两次数据库调用并进行一些处理。函数能工作,但不够优雅——有重复的代码且难以阅读。我们想重构它来提升清晰度和效率。以下是原始代码:


// Original function: Fetches two lists and processes them (needs refactoring)

async function getCombinedData(apiClient) {

// Fetch list of users

const usersResponse = await apiClient.fetch('/users');

if (!usersResponse.ok) {

throw new Error('Failed to fetch users');

}

const users = await usersResponse.json();

// Fetch list of orders

const ordersResponse = await apiClient.fetch('/orders');

if (!ordersResponse.ok) {

throw new Error('Failed to fetch orders');

}

const orders = await ordersResponse.json();

// Combine data (match user to orders)

const result = [];

for (let user of users) {

const userOrders = orders.filter(o => o.userId === user.id);

result.push({ user, orders: userOrders });

}

return result;

}

这段代码的问题:我们看到获取用户和订单的逻辑重复(可以重构为辅助函数或循环),错误信息缺乏细节(只是通用错误消息),并且可以并行执行获取操作以提高速度。让我们看看两种提示方法:


**提示1(描述不足):“重构上面的getCombinedData函数。”**


AI对提示1的响应:


> *好的。以下是getCombinedData的重构版本:*


async function getCombinedData(apiClient) {

// Fetch users and orders in parallel

const [usersResponse, ordersResponse] = await Promise.all([

apiClient.fetch('/users'),

apiClient.fetch('/orders')

]);

if (!usersResponse.ok || !ordersResponse.ok) {

throw new Error('Failed to fetch data');

}

const [users, orders] = await Promise.all([

usersResponse.json(),

ordersResponse.json()

]);

// Map orders by userId for efficient lookup

const ordersByUser = {};

for (const order of orders) {

if (!ordersByUser[order.userId]) {

ordersByUser[order.userId] = [];

}

ordersByUser[order.userId].push(order);

}

// Combine data

return users.map(user => ({

user,

orders: ordersByUser[user.id] || []

}));

}

> *我并行获取了用户和订单以提高性能。我还合并了错误处理,并使用了一个映射(ordersByUser)来按用户分组订单,这使得组合步骤更简洁且可能更快。*


分析:这实际上是一个相当好的重构,实现了多项改进:并行获取、按用户分组订单以提高效率、使用`.map`进行更简洁的组合并默认为空数组。AI也解释了它的做法。**那么为什么我们将此提示标记为描述不足或“差”?** 在这个案例中,AI碰巧做出了好的选择,但由于提示是开放式的,它做了很多假设。它假设性能应该被改进(并行请求,这是一个聪明的改动,但如果在这里并行不安全呢?),并且它将错误处理改成了一个通用的消息“Failed to fetch data”,这**丢失了**具体是哪个调用失败的**特异性**。


使用通用的“重构这个”提示的风险在于,AI可能以非预期方式做出改变行为的更改。在这里,合并错误处理可能可以接受,也可能不行,这取决于需求。助手还做了一个结构性更改(使用字典分组订单)——这没问题,可能更好,但如果我们没有告知特定的约束(比如想要流式传输结果或保持低内存使用),AI是不知道的。所以,虽然结果看起来不错,但AI自己对“重构”的理解恰好与我们想要的相符,这多少有些运气成分。这说明了描述不足的提示有时候在简单案例上能得到好结果,但对于复杂代码,它可能会偏离期望的方向或遗漏你关心的某些改进。


**提示2(目标导向):“重构上面的getCombinedData函数,目标是消除重复代码并提高性能。具体来说:(1) 避免重复获取用户和订单的逻辑——也许可以利用辅助函数或一并获取它们。(2) 如果可能,并行获取两个列表。(3) 保留每个获取操作的错误处理(我们想知道哪个调用失败了)。(4) 改进数据的组合方式,可能可以使用更高效的结构进行查找,而不是嵌套循环。提供重构后的代码,并附带注释解释更改。”**


AI对提示2的响应:


> *好的!以下是按照要求重构后的改进版getCombinedData:*


async function getCombinedData(apiClient) {

// 1. Fetch users and orders in parallel to improve performance

const [usersResponse, ordersResponse] = await Promise.all([

apiClient.fetch('/users'),

apiClient.fetch('/orders')

]);

// 2. Handle errors separately to know which call failed

if (!usersResponse.ok) {

throw new Error('Failed to fetch users');

}

if (!ordersResponse.ok) {

throw new Error('Failed to fetch orders');

}

// Parse JSON responses in parallel

const [users, orders] = await Promise.all([

usersResponse.json(),

ordersResponse.json()

]);

// 3. Use a lookup map for orders by userId for efficient matching

const ordersByUser = orders.reduce((map, order) => {

if (!map[order.userId]) {

map[order.userId] = [];

}

map[order.userId].push(order);

return map;

}, {});

// 4. Combine data using the lookup map

return users.map(user => ({

user,

orders: ordersByUser[user.id] || [] // empty array if no orders for user

}));

}

> *更改说明:*


> *并行获取:我使用Promise.all同时获取用户和订单(第1点)。*


> *保留单独的错误处理:我保留了针对usersResponse.ok和ordersResponse.ok的单独检查,以便任何错误都能清楚地表明哪个获取操作失败了(第2点)。*


> *并行JSON解析:也对response.json()调用使用了Promise.all,这是一个小改进。*


> *高效组合:我没有使用嵌套循环,而是创建了一个ordersByUser映射(第3点)。这通过单次遍历将订单按userId分组。然后我遍历users构建结果,在O(1)时间内从映射中提取每个用户的订单(第4点)。这更高效且简洁。*


分析:这个响应直接处理了**所有**指定的目标。代码被重构得更清晰、更快,并且按要求保留了单独的错误消息。AI的解释确认了我们列出的每一点,这表明它仔细遵循了提示指令。这是一个很好的结果,因为作为提示者,我们定义了在这个上下文中“重构”意味着什么。如此,我们引导AI产生了一个符合我们需求的解决方案,让来回沟通最小化。如果AI忽略了其中一点(比如说它仍然合并了错误处理),我们很容易就可以再次提示:“看起来不错,但请确保区分用户和订单的错误消息。”——不过,在这个案例中,因为我们的提示很详尽,所以不需要这样做。


这个例子展示了一个关键教训:**当你知道你想要改进什么时,要明确说出来。** AI擅长遵循指令,但它不会读心术。一句宽泛的“让它更好”可能适用于简单的事情,但对于复杂的代码,通过列举“更好”对你意味着什么,才能获得最佳结果。这符合社区的见解:清晰、结构化的提示能显著改善结果。


额外的重构技巧:


  • 分步重构:如果代码量很大或者你有很长的更改列表,你可以一次处理一条。比方说,先让AI“重构以提高可读性”(侧重于重命名、拆分函数),然后再“优化这个函数中的算法”。这可以防止一次性给模型太多指令而造成负担,并让你逐步验证每个更改。


  • 要求替代方法:也许AI的第一次重构有效,但你对不同的角度感到好奇。你可以问:“你能用另一种方式重构它吗?也许使用函数式编程风格(比方说,使用数组方法代替循环)?”或者“在这里使用递归代替迭代方法怎么样?只是为了比较一下?”这样,你可以评估不同的解决方案。这就像与同事一起头脑风暴多个重构选项。


  • 将重构与解释结合来学习模式:我们提到过这一点,但值得再强调一次——将AI用作学习工具。如果它以巧妙的方式重构了代码,请研究它的输出和解释。你可能会发现一个你以前从未使用过的新的API或技术(比如使用reduce构建映射)。这是要求解释的原因之一:它将答案变成了一个迷你教程,强化你对最佳实践的理解。


  • 验证和测试:在任何AI生成的重构之后,务必运行你的测试或用示例输入尝试代码。AI可能会无意中引入一些很小的错误,特别是如果提示没有指定重要的约束条件的话。比方说,在我们的重构中,如果原始代码为了日志记录而有意分开获取操作的错误,但我们没有提到日志记录,那么合并的错误可能用处不大。在审查中发现这是我们的责任。AI也可以通过编写测试来提供帮助——你可以要求“为重构后的函数生成几个单元测试”,以确保它在预期输入下的行为与之前相同。


至此,我们已经讲完了调试和重构——对现有代码的改进。下一个合乎逻辑的步骤是使用AI辅助来实现新功能或生成新代码。我们将探讨如何有效地为这种场景编写提示。


现代的调试场景


**React Hook依赖项问题**


**糟糕提示:** “我的useEffect工作不正常”


**增强提示:**


I have a React component that fetches user data, but it's causing infinite re-renders. Here's my code:

const UserProfile = ({ userId }) => {

const [user, setUser] = useState(null);

const [loading, setLoading] = useState(true);

useEffect(() => {

fetchUser(userId).then(setUser).finally(() => setLoading(false));

}, [userId, setUser, setLoading]); // Problem is here

return loading ? <div>Loading...</div> : <div>{user?.name}</div>;

};

预期行为:应在userId变化时获取一次用户数据


实际行为:组件无限重新渲染


控制台错误:"Warning: Maximum update depth exceeded"


是什么导致了这个无限循环?如何修复依赖项数组?


为什么有效:提供了确切的代码、错误消息、预期与实际行为,并聚焦于一个常被误解的特定React模式。


现代的状态架构


**糟糕提示:** “为我的Next.js电商应用构建状态管理”


**增强提示:**


我正在构建一个Next.js 14电商应用,需要设计状态管理架构。以下是我的要求:


组件


* 产品列表页(需要:products[], 筛选器, 分页)


* 购物车(需要:购物车商品, 总计, 配送信息)


* 用户认证(需要:用户资料, 认证状态, 偏好设置)


* 实时通知(需要:toast消息, 错误状态)


技术约束


* Next.js 14 带App Router和服务器组件


* TypeScript严格模式


* 服务端数据获取(用于SEO)


* 购物车/用户操作的客户端交互性


* 状态应在导航间保持


我应该使用:


* 每个域(cart, auth, notifications)使用独立的Zustand store


* React Query/TanStack Query用于服务器状态 + Zustand用于客户端状态


* 一个带切片(slices)的Zustand store


请提供一个推荐的架构,并附带代码示例,展示如何构建store以及如何与Next.js App Router模式集成。


为什么有效:真实场景,包含具体技术栈、需求清晰,并要求提供带有实现细节的架构指导。


实现新功能的提示模式


AI 代码助手最令人兴奋的用途之一,就是帮助你从头开始编写新代码,或者将新功能集成到现有代码库中。这可能包括生成 React 组件的样板代码,或者在 Express 应用中编写一个新的 API 端点。这里的挑战通常在于这些任务是开放式的——实现一个功能有很多种方法。用于代码生成的提示工程,就是引导 AI 生成符合你需求和风格的代码。以下是一些策略:


1. 从高阶指令开始,然后逐步深入。先用通俗语言概述你想开发什么,可能的话将其分解成更小的任务(类似于我们之前关于分解复杂任务的建议)。比方说,假设你想在现有的 Web 应用当中添加一个搜索栏功能。你可以先提示:“写一个计划概述,在我的 React 应用里面添加一个按名称过滤产品列表的搜索功能。产品数据是从 API 获取的。”


AI 可能会给你一个分步计划:“1. 添加一个输入框用于搜索查询。2. 添加状态来保存查询。3. 根据查询过滤产品列表。4. 确保不区分大小写,等等。”一旦你有了这个计划(可以在 AI 的帮助下完善它),你就可以通过针对性的提示来搞定每一条。


比方说:“好的,实现第 1 步:创建一个 SearchBar 组件,要有一个能更新 searchQuery 状态的输入框。”之后,“实现第 3 步:给定 searchQuery 和一个产品数组,过滤产品(按名称进行不区分大小写的匹配)。”通过将功能分解,你可以确保每个提示都是具体的,并且响应是易于管理的。这也是迭代开发过程的体现——你可以在开发的时候测试每一部分。


2. 提供相关上下文或参考代码。如果你要将功能添加到现有项目中,向 AI 展示项目的类似功能是如何实现的会很有帮助。比方说,如果你已经有了一个与你想要实现的组件相似的组件,你可以说:“这是一个现有的 UserList 组件(代码……)。现在创建一个类似的 ProductList 组件,但要包含一个搜索栏。”

AI 会识别模式(可能你用了某些库或风格约定)并加以应用。在提示中打开相关文件或引用之,可以提供上下文信息,从而得到更符合项目需求、更一致的代码建议。另一个技巧是:如果你的项目使用了特定的编码风格或架构(比如用 Redux 管理状态或某个 CSS 框架),一定要提一下。“我们使用了 Redux 进行状态管理——请将搜索状态集成到 Redux store 中。”


训练有素的模型就会生成符合 Redux 模式等的代码。本质上,你是在向 AI 介绍你的项目环境,这样它才能定制化输出。有些助手甚至可以将你的整个代码库作为上下文来源;如果使用这类助手,确保你将其指向代码库中相似的模块或文档。


  • 如果是开始一个新项目,但你偏好某个方法,你也可以提出来:“我想用函数式编程风格来实现这个(无外部状态,使用数组方法)。”或者,“确保遵循 MVC 模式,把逻辑放在控制器里,而不是视图里。”这些都是高级工程师可能会提醒初级工程师注意的细节,在这里,你就是那个告诉 AI 的高级工程师。


3. 使用注释和 TODO 作为内联提示。如果是直接在带有 Copilot 的 IDE 来开发,一个有效的工作流是:写一条描述你接下来所需要的代码块的注释,然后让 AI 自动补全它。比方说,在 Node.js 后端,你可以写:`// TODO: 验证请求负载(确保提供了姓名和邮箱)`,然后开始新的一行。Copilot 通常都能理解你的意图,并生成执行该验证的代码块。这之所以有效,是因为你的注释本质上就是一个自然语言提示。不过,如果 AI 理解错了,你要准备好编辑生成的代码——并一如既往地,验证其正确性。


4. 提供预期的输入/输出或用法示例。跟我们之前讨论过的情况类似,如果你要求 AI 实现一个新函数,请包含一个它将如何被使用的快速示例或一个简单的测试用例。比方说:“用 JavaScript 实现一个函数 `formatPrice(amount)`,它将接收一个数字(比如 2.5),并返回一个格式化为美元货币的字符串(比如 `$2.50`)。比方说,`formatPrice(2.5)` 应该返回 `'$2.50'`。”


通过提供这个例子,你就约束了 AI 去生成一个与之相符的函数。没有这个例子,AI 可能会假设使用其他格式或货币。虽然感觉差别不大但很重要。另一个在 Web 上下文中的例子:“实现一个 Express 中间件来记录请求。比方说,一个到 `/users` 的 GET 请求应该在控制台记录 `‘GET /users’`。” 这清楚地表明了输出应该是什么样子。在提示中包含预期行为相当于给 AI 一个它要努力通过的测试。


5. 当结果不是你想要的时,用更多细节或约束重写提示。第一次尝试生成新功能时常常不尽如人意,这很常见。可能代码能运行但不地道,或者遗漏了某个需求。与其沮丧,不如把 AI 当作一个提交了初稿的初级开发者对待——现在你需要给出反馈。比方说,“这个方案可行,但我更希望你使用内置的数组 `filter` 方法,而不是 `for` 循环。”或者,“你能重构生成的组件,使用 React Hooks 来管理状态,而不是类组件吗?我们的代码库都是函数式组件。”你还可以添加新的约束:“另外,确保函数在 O(n) 时间复杂度或更好的情况下运行,因为 n 可能很大。”这种迭代式的提示非常强大。一个真实场景:一位开发者要求 LLM 生成使用 JS Canvas 库绘制冰淇淋甜筒的代码,但它一直给出不相关的输出,直到他们用更多具体细节和上下文优化了提示。教训是,不要一次尝试后就放弃。找出提示中缺少或被误解的内容,并澄清它。这就是提示工程的精髓——每一次调整都能引导模型更接近你的设想。


让我们通过一个示例场景来说明功能实现的提示:


功能实现示例:在 AI 辅助下开发 React 组件


假设我们有一个 React 应用,我们想添加一个新组件:一个带有搜索过滤器和排序下拉框的产品列表。这在 Web 应用中是一个相当典型的功能。为简洁起见,我们将重点放在为该组件内的搜索功能进行提示。


**原先提示(功能请求):** “创建一个名为 `ProductList` 的 React 函数组件,它显示一个产品列表,并包含一个文本输入框用于按名称过滤产品。该组件应该:从 `/api/products` 获取产品数组(假设它返回 `{id, name, ...}` 的 JSON 数组),将它们存储在状态中,并允许用户在搜索框中输入内容以按名称过滤显示的产品(不区分大小写匹配)。在一个简单的 `<ul>` 列表中显示过滤后的产品名称。包含基本的错误处理(比方说,如果 API 调用失败则显示错误信息)以及获取数据时的加载状态。”


这是一个很长的提示,但很具体。假设我们在聊天中把这个提示给了一个 LLM。


AI 的响应(可能生成的摘要):AI 很可能会输出一个类似下面这样的 `ProductList` 组件:


import React, { useState, useEffect } from 'react';

function ProductList() {

const [products, setProducts] = useState([]);

const [search, setSearch] = useState('');

const [loading, setLoading] = useState(true);

const [error, setError] = useState(null);

useEffect(() => {

async function fetchProducts() {

try {

const res = await fetch('/api/products');

if (!res.ok) throw new Error('Network response was not ok');

const data = await res.json();

setProducts(data);

} catch (err) {

console.error('Failed to fetch products:', err);

setError('Failed to load products.');

} finally {

setLoading(false);

}

}

fetchProducts();

}, []);

const handleSearchChange = (e) => {

setSearch(e.target.value);

};

// Filter products by search query (case-insensitive)

const filteredProducts = products.filter(product =>

product.name.toLowerCase().includes(search.toLowerCase())

);

if (loading) return <div>Loading products...</div>;

if (error) return <div>{error}</div>;

return (

<div className="product-list">

<input

type="text"

placeholder="Search products"

value={search}

onChange={handleSearchChange}

/>

<ul>

{filteredProducts.map(prod => (

<li key={prod.id}>{prod.name}</li>

))}

</ul>

</div>

);

}

export default ProductList;

(如果我们提出要求,代码中可能还会包含一些解释各部分的注释。)

现在,我们来分析这个结果,并考虑如何优化提示:


  • 假设上面这段代码返回了,但我们的项目使用 Context 或全局存储(如 Redux)来进行数据获取,而不是在组件内部获取。这是我们没有明确指出的。AI 选择了在 `useEffect` 中获取数据。如果我们更倾向于使用自定义 Hook 或 Context,我们应该在提示中暗示这一点。因此我们可以优化提示:**“实际上,在我们的应用中,我们使用一个自定义 Hook `useProducts()` 来处理数据获取。请重构组件,使用 `useProducts` Hook,而不是直接调用 fetch。”** AI 随后会进行调整,可能会假设 `useProducts` 返回 `{ products, loading, error }`,并相应地简化组件。


  • 另一个优化点:也许我们意识到还想要一个排序下拉框(这是我们最初没有提到的)。我们现在可以扩展对话:**“很好,现在添加一个下拉框,用于按名称排序产品(A-Z 或 Z-A)。下拉框应让用户选择升序或降序,列表在过滤的基础上还应相应排序。”** 因为 AI 有现有代码的上下文,它可以插入一个排序状态并调整渲染。我们提供了一个清晰的新需求,它会尝试完成这个需求,可能会添加类似下面的代码:


const [sortOrder, setSortOrder] = useState('asc');

// ... a select input for sortOrder ...

// and sort the filteredProducts before rendering:

const sortedProducts = [...filteredProducts].sort((a, b) => {

if (sortOrder === 'asc') return a.name.localeCompare(b.name);

else return b.name.localeCompare(a.name);

});


  • (以及下拉框的 UI 代码)。


  • 通过像这样逐个功能地迭代,我们模拟了一个与 AI 协作的开发周期。这比一开始就试图用单个提示获取包含所有功能的整个复杂组件有效得多。这种做法减少了错误,并允许在需求变得更清晰时进行中途修正。


如果 AI 犯了一个小错误(比如它忘记了让搜索过滤器不区分大小写),我们只需指出:**“让搜索不区分大小写。”** 它会调整过滤器使用小写比较(在我们的伪代码输出中它已经这么做了,但如果没有,它会修复)。


这个例子表明,用 AI 实现功能的核心在于渐进式开发和提示优化。一篇 Twitter 帖子可能会惊叹于某人如何通过持续、针对每一部分向 LLM 发出提示来构建一个小型应用——这本质上就是这种方法:开发、审查、优化、扩展。每个提示就像是开发过程中的一次提交(commit)。


实现功能的额外技巧:


* 让 AI 搭建脚手架,然后你填充细节:有时候让 AI 生成一个粗略的结构,然后你再进行调整是很有用的。比方说,“生成一个用于用户注册的 Node.js Express 路由的骨架,包含验证和错误处理。”它可能会生成一个带有占位符的通用路由。然后你可以填入特定于你的应用程序的实际验证规则或数据库调用。AI 省去了你编写样板代码的麻烦,而你可以处理那些敏感的自定义逻辑。


* 要求处理边界情况:在生成功能时,你可以提示 AI 考虑边界情况:**“我们应该为这个功能考虑哪些边界情况(并且你能在代码中处理它们吗)?”** 比方说,在搜索示例中,边界情况可能是“如果用户输入时产品数据还没加载完怎么办?”(尽管我们的代码通过加载状态处理了)或者“如果两个产品同名怎么办”(不是什么大问题,但也许可以提一下)。AI 可能会提到空结果处理、非常大的列表(搜索输入可能需要防抖)等。这是利用 AI 对常见陷阱训练的一种方式。


* 文档驱动开发:有些人的做法很妙,就是先写一个文档字符串(docstring)或用法示例,然后让 AI 实现与之匹配的函数。比方说:


/**

* Returns the nth Fibonacci number.

* @param {number} n - The position in Fibonacci sequence (0-indexed).

* @returns {number} The nth Fibonacci number.

*

* Example: fibonacci(5) -> 5 (sequence: 0,1,1,2,3,5,…)

*/

function fibonacci(n) {

// ... implementation

}


  • 如果你写了上面的注释和函数签名,LLM 可能会正确地帮你填充实现,因为注释准确地描述了要做什么,甚至给出了一个例子。这种技术确保你先用文字阐明功能(这本身也是很好的实践),然后 AI 将其作为规范来编写代码。


在介绍了用于调试、重构和新代码生成的提示策略之后,让我们把注意力转向编码提示工程中的一些常见陷阱和反模式。理解这些将帮助你避免在无效的交互上浪费时间,并在 AI 没有给出你需要的东西时快速调整。


常见提示反模式及应对策略


不是所有提示的有效性都一样的。我们已经看过许多高效提示的案例,但识别反模式——那些导致AI表现不佳的常见错误——同样具有指导意义。


告别无效提示!开发者必学的AI协作提示框架全解析


以下是几种常见的提示失误及其改进方法:


  • 反模式:模糊提示。典型表现是"它不工作了,请修复"或"写个实现X功能的东西"这种缺乏细节的指令。当"为什么我的函数不工作?"这种问题得到的是无用的回复时就是例子。模糊提示迫使AI去猜测上下文,通常导致泛泛而谈的建议或不相关代码。改进方法很简单:补充上下文和具体信息。如果你发现自己的提问得到像魔法八号球那样的回应("你检查过X吗?"),请暂停并补充细节重构问题(错误信息、代码片段、预期与实际结果等)。建议自问一下:"这个问题能套用到几十种不同场景吗?"如果答案是肯定的,说明提示太含糊了。要让提示具体到只适用于你的独特场景。


  • 反模式:超载提示。这是另一个极端:要求AI同时处理的任务太多。比方说"生成完整的Node.js应用,包含身份验证、React前端和部署脚本",或者规模小点的,类似"一次性修复这5个bug并添加3个新功能"。AI可能会做处理尝试,但结果往往很混乱,残缺不全,或会忽略部分需求。即便全部处理,回复也会很冗长难验证。解决方案是拆分任务:像之前强调的那样,每次专注一件事。这样更易发现错误并保持模型专注。当发现指令段落包含多个"并且"时,就应考虑拆分为独立提示或分步执行。


  • 反模式:缺失明确诉求。 有时候用户提供大量信息却未说明需求。比方说丢出大段代码只说"这是我的代码"。这会让AI困惑——它不知道你要什么。务必包含明确指令,如"找出上方代码的bug"、"解释代码功能"或"完成代码中的TODO"。每个提示都应有目的。若仅提供文本而无指令,AI可能产生错误预判(比如总结代码而非修复)。确保AI明白你展示代码的意图。简单加上"这段代码有什么问题?"或"请继续实现这个函数"就能指明方向。


  • 反模式:模糊成功标准。 这个更隐蔽——要求优化改进时未定义成功标准。比方说"让这个函数更快",但"更快"的标准是什么?若AI不知道性能约束,可能优化无关紧要的部分,或采用理论更快但实际无感的方案。"让代码更整洁"中的"整洁"也是主观的。我们应明确目标如"减少重复"或"改进变量命名"。改进方法是量化或限定优化方向,比方说"优化此函数至线性时间复杂度(当前为平方级)"或"重构以移除全局变量改用类"。本质上要阐明重构或功能具体解决什么问题,否则AI可能解决非目标问题。


  • 反模式:忽视AI的澄清请求。 AI有时候会回应澄清性问题或假设,比方说"您使用的是React类组件还是函数组件?"或"假设输入是字符串——请确认"。若忽略这些直接重复请求,就错过了优化提示的机会。AI在暗示需要更多信息。务必回应问题或在提示中补充细节。另外,若AI输出明显偏离(如误解问题),不要原封不动重试相同提示。花时间调整措辞:可能提示存在歧义或遗漏关键点。像在跟人对话那样——如果对方误解,你会换种方式解释;对AI也应如此。


  • 反模式:风格反复无常。 若频繁变换提问方式或混用多种格式,模型可能困惑。比方说指令中第一人称和第三人称切换,或伪代码与真实代码混淆不清。单个提示中应保持风格统一。提供示例时确保明确区分(用Markdown三引号标记代码,引号标注输入输出示例等)。一致性帮助模型正确解析意图。若有偏好风格(如ES6与ES5语法),需始终明确说明,否则模型可能在不同提示中会给出不同方案。


  • 反模式:模糊指代(如'上方代码')。在聊天中使用"上方函数"或"之前的输出"时,确保指代明确。若对话较长时说"重构上方代码",AI可能跟丢或选错代码片段。更安全的做法是重新引用代码或具体命名要重构的函数。模型注意力有限,尽管多数LLM能回溯对话,但重新提供明确上下文可避免混淆。若距离代码展示已过较长时间(或经历多轮对话),这点尤为重要。


当出现问题时的提示重写策略:


  • 先定位AI回复中缺失或错误的部分:是否解决了错误问题?是否产生错误或不符合要求的方案?比方说要求TypeScript方案却得到普通JavaScript,或明确要求迭代方案却给出递归实现。精准定位差异点。


  • 在新提示中补充或强调该要求。比方说:"方案需用TypeScript而非JavaScript,请包含类型注解",或"我明确要求迭代方案——请避免递归改用循环"。有时候直接使用"注意:"或"重要:"等短语突显关键约束很有效(模型虽无情绪,但会权衡短语重要性)。比方说:"重要:请勿使用任何外部库"或"注意:代码需在浏览器运行,故不可用Node专属API"。


  • 必要时进一步分解请求。若AI在复杂需求上反复失败,先尝试请求更小的模块。或提出澄清性问题:"你理解我说的X是指什么吗?"模型可能复述其理解,你可据此纠正错误。这种元提示法(讨论提示本身)有时候能消除误解。


  • 对话卡住时考虑重启。多次尝试后对话可能陷入混乱状态。新建会话(或暂时清空聊天记录)后,基于先前失败经验重构更精确的提示重新开始会很有帮助。模型不介意重复,而新上下文能消除之前积累的混淆信息。


了解这些反模式及解决方案后,调整实时提示就能更快。对开发者而言,提示工程本质是迭代的、反馈驱动的过程(如同所有编程任务!)。好消息是你现在拥有丰富的模式案例可供参考。


结论


提示工程既是艺术也是科学——正如我们所见,它正迅速成为开发者使用AI编程助手的必备技能。通过构建清晰、上下文丰富的提示,你本质上是在教导AI你的需求,如同引导新团队成员或向同事解释问题。本文系统探讨了如何构建用于调试、重构和功能实现的提示:


  • 我们学会向AI提供求助同事时的同类信息:代码预期功能、异常表现、相关代码片段等——从而获得更精准的帮助。


  • 我们见证了与AI迭代协作的力量:无论是逐行梳理函数逻辑,还是通过多轮提示优化方案(如将递归方案转为迭代方案再改进变量命名)。耐心迭代使AI成为真正的结对编程伙伴,而非一次性代码生成器。


  • 我们运用角色扮演提升回复质量——将AI视为代码审查员、导师或特定技术栈的专家。这通常可生成更严谨、解释更丰富的输出,不仅能解决问题,还在此过程中给予我们启发。


  • 重构优化时我们强调定义"优秀"标准(更快/更简洁/更地道等),而AI展示了在引导下应用最佳实践的能力(如并行调用、消除重复、正确处理错误)。这如同获得了无数代码审查员的集体智慧——但需通过正确提问来激活。


  • 我们还演示了在AI协助下逐步构建新功能,表明即便复杂任务也能分解为单次提示处理。AI可搭建基础框架、建议实现方案,甚至在被提示时强调边界情况——如同随时待命的资深协作者。


  • 过程中我们识别了需规避的陷阱:提示既不过于模糊也不超载、始终明确意图和约束、随时准备在AI偏离目标时调整。通过具体反面案例,我们看到微小改动(如添加错误信息或预期输出)如何显著提升结果。


将这些技巧融入工作流后,你会发现AI协作变得更直观。你将逐步掌握获取最佳结果的表达方式,以及模型偏离时如何引导。记住AI是其训练数据的产物——它见过无数代码和问题解决案例,但由你决定哪些案例与当前相关。本质上,你设定上下文,AI负责执行。


值得注意的是,提示工程是不断发展的实践。开发者社区持续发现新技巧——一个聪明的单行提示或结构化模板可能突然在社交媒体爆火,因为它解锁了人们未曾意识到的能力。关注这些讨论(如Hacker News、Twitter等)可激发个人技术灵感。同时勇于自我实验:将AI视为灵活工具——若有想法(如"让它用ASCII字符画架构图会怎样?"),尽管尝试。结果可能令你惊喜,即便失败也无妨——你由此了解了模型的局限或需求。


总之,提示工程可赋能开发者更高效利用AI助手。有没有提示工程,就是挫败体验("这工具没用,尽说废话")与高效体验("如同专家结对编程帮我写基础代码")之别。应用本文的策略手册——从提供完整上下文到引导AI风格思路——你就能将这些代码导向的AI工具转化为开发流程的真正延伸。最终结果不仅是编码提速,更常在过程中收获新见解和模式(当AI解释或建议替代方案时),从而提升自身技能水平。


最后一个关键点:记住提示是一场循序渐进的对话。要像跟其他工程师沟通时那么清晰、耐心和严谨地对待这场对话。如此你将发现AI助手能极大增强你的能力——助你更快地调试、更智能地重构、更轻松地实现功能。


祝你享受编写提示和代码的过程!


文章来自于“36氪网”。


AITNT-国内领先的一站式人工智能新闻资讯网站
AITNT资源拓展
根据文章内容,系统为您匹配了更有价值的资源信息。内容由AI生成,仅供参考
1
AI工作流

【开源免费】n8n是一个可以自定义工作流的AI项目,它提供了200个工作节点来帮助用户实现工作流的编排。

项目地址:https://github.com/n8n-io/n8n

在线使用:https://n8n.io/(付费)


【开源免费】DB-GPT是一个AI原生数据应用开发框架,它提供开发多模型管理(SMMF)、Text2SQL效果优化、RAG框架以及优化、Multi-Agents框架协作、AWEL(智能体工作流编排)等多种技术能力,让围绕数据库构建大模型应用更简单、更方便。

项目地址:https://github.com/eosphoros-ai/DB-GPT?tab=readme-ov-file



【开源免费】VectorVein是一个不需要任何编程基础,任何人都能用的AI工作流编辑工具。你可以将复杂的工作分解成多个步骤,并通过VectorVein固定并让AI依次完成。VectorVein是字节coze的平替产品。

项目地址:https://github.com/AndersonBY/vector-vein?tab=readme-ov-file

在线使用:https://vectorvein.ai/(付费)

2
AI小镇

【开源免费】ai-town是MIT授权的一个AI虚拟小镇,该项目可以让研发人员轻松构建和定制你自己的AI小镇版本,其中居住在小镇的AI角色可以进行交流和社交。该项目受到研究论文《生成代理:人类行为的交互模拟》的启发。

项目地址:https://github.com/a16z-infra/ai-town

3
prompt

【开源免费】LangGPT 是一个通过结构化和模板化的方法,编写高质量的AI提示词的开源项目。它可以让任何非专业的用户轻松创建高水平的提示词,进而高质量的帮助用户通过AI解决问题。

项目地址:https://github.com/langgptai/LangGPT/blob/main/README_zh.md

在线使用:https://kimi.moonshot.cn/kimiplus/conpg00t7lagbbsfqkq0