提示词工程实战:用DeepSeek把低效代码改写成工业级实现
最近这一个月我基本泡在一件事里用 DeepSeek 这类代码模型批量重构一个老项目的中枢模块。一开始我的用法特别糙就是把老代码直接扔给模型丢一句“帮我优化一下”。模型确实会给出一版新代码但仔细看下来大多只是改了改变量名性能没提升可读性也没质变。后来我逐步调整了“代码改写提示词”的写法把目标、约束、边界和验收标准一条条写清楚结果才真正开始不一样——不仅能拿到符合生产要求的代码还能让模型解释每一步修改的理由。这篇文章准备把我打磨提示词的全过程拆给你看为什么会失效、怎么写才管用、实战里如何一步步把低效代码改写成工业级实现以及我踩过的那些坑。适合正在折腾 AI 辅助开发的程序员特别是想用提示词工程提升代码质量又不想被 AI 改出“看起来花哨跑起来出事”的结果的人。1. 先想清楚提示词凭什么能把代码改成工业级1.1 模型改代码的机制不是玄学是工程很多人把 AI 改写代码理解成“扔进去一段代码吐出来一段新代码”这个理解没错但太粗了。DeepSeek 这类模型本质上是一个基于海量文本训练出来的条件概率模型它生成每一行代码都是在预测“在当前上下文里下一个 token 最可能是什么”。你给它的上下文越明确、约束越具体它预测出来的内容就越靠近你真正想要的方向。这跟找一位资深工程师评审代码是一样的。你直接把一段代码拍在桌上说“帮我优化”对方能做的多半只是局部调整因为他不知道业务背景、不知道性能目标、不知道哪些函数是外部依赖的边界。但如果你提前整理好接口契约、性能瓶颈数据和改动的限制条件他就能有针对性地做架构调整、算法替换和防御性编程。提示词的作用就是把这些“评审前应该提供的背景信息”打包成文字塞进模型的上下文窗口。它不是魔法咒语而是信息压缩协议。理解了这一点你就会明白为什么“帮我优化一下”这种写法效果差——信息量太少了模型只能做最保守的猜测或者干脆按训练数据里的通用套路来一套模板化重构。我在实际测试中还发现一个有意思的现象同样一段低效代码如果你在提示词里补充了“这个函数会被高频调用平均单次耗时在 300 毫秒左右”模型会更倾向于选择算法层面的优化而不是只在循环里抠几个小细节。这说明上下文里的量化信息真的会影响模型的优化策略。1.2 为什么很多人的提示词没效果我前后写过几十版提示词外加对比过身边同事的习惯发现提示词失效通常不是因为模型不行而是因为这几个原因。第一目标过于模糊。“优化一下”“改善代码质量”这类描述没有提供任何可验证的指标。模型只能按自己的理解随意发挥完全随机。更关键的是模糊目标会导致输出结果的评判标准也模糊——你拿到新代码后根本说不清楚它到底算不算达标。第二缺少约束边界。你本来只打算让它优化一段函数但模型可能会“顺手”把函数签名改了、把依赖库换了、把数据结构推倒重来。如果代码库里有多个模块调用这段逻辑这种过度重构会直接引发连锁故障。第三没有指定差异说明和验证要求。多数人拿到的 AI 改写代码里模型不会自动告诉你“我改了什么、为什么这么改、有没有引入新的副作用”。这就导致人工 review 的难度极高只能逐行去比对新旧代码效率很低。第四不会利用示例对齐格式。想让模型按特定格式输出或者按特定的代码风格改写最好的办法是给一小段输入-输出示例。光用语言描述“请用类型注解和 dataclass 风格”远不如贴一个示例来得直接。这里我特别想强调验证闭环。提示词工程里有一条经验法则你的提示词必须明确要求模型给出验证方案比如测试命令、边界用例或者必要的运行结果。否则你拿到的就是未经证明的代码——看着很好跑起来可能立刻爆炸。我在后文会专门展开这一点。2. 一套能复用的代码改写提示词框架2.1 五段式提示词模板角色、任务、约束、示例、输出格式经过反复迭代我把代码改写提示词固定成了一套五段式结构表格对比一下各部分的作用会更清楚。段落作用常见坑角色段指定模型以资深工程师视角分析而不是只会“翻译”的工具角色写太泛模型理解不到工程语义任务段明确优化方向性能、可读性、健壮性、可测试性任务混在一起模型无从取舍约束段划定边界不改接口、不升依赖、不破坏外部行为缺约束时模型会自由发挥示例段用输入-输出示例对齐格式让模型模仿表达方式没有示例时格式千奇百怪输出段要求包含修改清单、完整代码、验证建议缺输出格式时 review 成本居高不下下面是我常用的一版模板可以直接复制去改【角色】 你是一名有十年一线开发经验的资深工程师擅长在保证行为不变的前提下对代码做工业级改进。 【任务】 请分析以下 Python 函数拆解其性能瓶颈和潜在缺陷并给出优化版本。 【约束】 1. 保持函数签名和对外行为完全不变 2. 不引入新的第三方依赖 3. 保持代码风格与项目现状一致优先使用标准库 4. 改完后必须保证原有调用方无需任何改动 【示例】 输入低效版 def get_names(ids): result [] for id in ids: for u in users: if u.id id: result.append(u.name) return result 输出高效版 def get_names(ids): lookup {u.id: u.name for u in users} return [lookup.get(i) for i in ids] 【输出】 1. 先用一段话说明原代码的问题 2. 给出完整优化后的代码放在代码块中 3. 用列表说明新增的测试用例或验证方式 4. 指出所有涉及行为不变假设的风险点这个模板最核心的地方在于把“约束”和“示例”放到了同等重要的位置。约束用来框定模型的发挥空间示例则用来对齐模型的表达格式。两者缺一个输出结果都会跑偏。2.2 参数细节上下文窗口与生成温度的影响除了提示词内容本身模型调用参数也在悄悄影响改写质量。如果你用的是 API 方式调用有两个参数值得关注。第一个是 temperature。这个参数控制输出的随机性取值范围通常在 0 到 1 之间。代码改写任务是强逻辑任务不是创意写作我会把 temperature 调到 0.1 到 0.3。温度太高时模型可能在语义等价的位置换用完全不同的实现方式看起来有创造性但稳定性很差。温度太低则可能让它过度保守只是做表面调整。第二个是上下文窗口的利用方式。DeepSeek 这类模型都有上下文长度限制但并不是说塞得越满越好。多次实践下来我的体会是代码改写任务的上下文里最有价值的是被改模块的依赖接口定义、关键业务规则说明以及调用方的使用方式。无关文件、超长历史输出、重复的对话轮次都会稀释模型的注意力。还有一点经验如果代码库非常大千万不要一次性把所有相关代码都塞进对话里。先只给目标函数和它直接依赖的少量类型定义让模型完成初步改写再逐步迭代。这就像给人类工程师看代码你一次性给他五百个文件他反而记不住重点只给一张模块图和几个核心接口他能在最短时间内找到问题所在。3. 实战拆解一段低效代码如何变成工业级实现3.1 低效代码样本我们用一段典型的老项目遗留代码来演示。这段函数从一批用户记录里筛选出指定 ID 的用户名并按输入顺序返回。它的问题非常普遍兼具性能、可读性和健壮性三个维度的问题。def get_user_names(ids): result [] for i in ids: for u in users: if u[id] i: result.append(u[name]) break return result我来说说为什么这段代码让人头疼。第一嵌套循环导致时间复杂度达到 O(n*m)当 ids 有几千个、users 有几万个时运行时间立竿见影地拉胯。第二代码里没有类型注解也没说明 users 和 ids 的数据来源与格式几个月后连写它的人自己都要重新猜。第三如果 ids 里存在重复值或者根本不存在的 ID这段代码会要么重复返回要么直接忽略逻辑不够明确。第四一旦 users 列表为空或 id 键不存在还会引发异常看不出代码的作者有防御性编程的意识。我把这段代码放进最初那版“帮我优化一下”的提示词里得到的结果是模型把变量名改顺眼了加了点注释但时间复杂度一点没变。问题出在哪里出在我的提示词没有强调性能目标和边界条件。3.2 实战提示词与 AI 改写过程于是我换成了上面那套五段式模板结合业务场景做了微调。针对这段代码我实际使用的是下面这版提示词。【角色】 你是一名有十年一线开发经验的资深工程师擅长 Python 代码的工业级优化。 【任务】 优化以下函数 get_user_names当前实现使用嵌套循环完成用户 ID 到用户名的映射性能较差且缺少类型标注和异常处理。 【约束】 1. 保持函数签名 get_user_names(ids) 不变 2. 不引入第三方依赖只使用 Python 标准库 3. users 是全局变量列表元素为字典必须兼容缺失 id 或 name 键的情况 4. 返回顺序必须与传入 ids 的顺序一致 5. 如果某个 id 在 users 中不存在应跳过并继续 【示例】 输入: get_user_names([3, 1]) 预期输出: [alice, bob] 【输出】 1. 先用一段话说明原代码的问题 2. 给出完整优化代码 3. 列出你新增的边界测试用例 4. 指出潜在风险点你注意看我加的几条约束保持函数签名不变、只使用标准库、兼容缺失键、保持顺序、跳过不存在 ID。这五条约束让模型的优化方向收敛到了一个明确目标——在不改变对外行为的前提下把嵌套循环换成哈希查找。模型在收到这版提示词后给出的核心优化思路也清晰了先把 users 按 id 建立字典索引把查找复杂度从 O(n) 降到 O(1)再用列表推导式完成顺序映射。这个方案与我手写的优化思路完全一致而且它还顺手加了类型注解和些许注释让代码的自解释性更强。3.3 改写结果对比与要点解析下面就是这版提示词实际生成的代码我做了一些格式整理使它看起来更工整逻辑上则完全保留了模型输出的样子。from typing import Any, Dict, List, Union users: List[Dict[str, Any]] [ {id: 1, name: bob, age: 25}, {id: 2, name: alice, age: 30}, {id: 3, name: carol, age: 35}, ] def get_user_names(ids: List[Union[int, str]]) - List[str]: 根据传入的 id 列表返回对应的用户名列表。 保持输入顺序并在 users 中不存在的 id 时跳过不做异常抛出。 user_map {str(u[id]): u[name] for u in users if id in u and name in u} result [] for i in ids: key str(i) if key in user_map: result.append(user_map[key]) return result print(get_user_names([3, 1])) # [carol, bob] print(get_user_names([99, 2])) # [alice]我建议你实际对比一下新旧代码感受其中差异。性能上改动前嵌套循环最坏要走 n乘以m 次改动后只需要构建一次哈希表然后逐 id 查表时间复杂度接近 O(n m)。如果 users 有十万条ids 有一万条这种提升在数据量大的场景里是肉眼可见的。可读性方面新代码加了类型注解、函数注释和变量命名规范。不要小看这些“表面功夫”在团队协作里类型注解能直接省掉后人大量猜谜时间。健壮性方面代码兼容了缺失键、不在集合中的 ID 和空列表不会因为某个脏数据直接崩溃。可测试性方面新代码用两个 print 用例说明了输入输出行为如果再配合 pytest 就能快速覆盖核心场景。有一个隐藏点你可能没注意到模型在构建 user_map 时用了 if id in u and name in u这个守卫条件是提示词里“兼容缺失 id 或 name 键”的直接产物。如果你不写约束模型通常不会主动处理这类边界因为通用训练数据里少见这种防御性细节。这就是为什么我一直强调约束段决定了 AI 改写代码的下限。4. 迭代提示词的实操技巧与排查记录4.1 提示词失效的四种典型症状与对策就算用了五段式模板我依然会在实践中遇到提示词“失效”的情况。所谓失效不是模型报错而是输出结果达不到预期。下面是我遇到最多的四种症状以及对应的排查方向。症状一模型只是复制原代码几乎没有改动。对策往往是任务段不够具体。你需要补充痛点描述比如“时间复杂度为 O(n²)”“存在数据竞争风险”“逻辑重复度高”。模型需要明确的优化动机。症状二模型过度设计引入不必要的抽象层。这是最常见的翻车现场。原本只要一个函数它非要给你拆成三个类加两个接口。对策是把约束段写死明确说明“禁止引入额外抽象保持代码结构简单”。症状三输出代码没有上下文关联性。比如改了函数名、改了参数顺序、换了返回值形状。根源在于你没有强调“接口兼容”。这时需要在约束段中重复三遍或者直接复制调用方的调用代码作为上下文。症状四格式漂移模型偶尔只给一段代码不附解释也没有测试建议。这时输出段规格要更严格明确要求“先说明问题再贴代码最后列测试”。症状根因对策输出与原代码几乎一样任务段缺少具体痛点描述补充性能指标、运行成本、代码坏味道过度抽象与设计约束段缺少禁止项加入“禁止新增抽象层”等限制接口不兼容调用关系没有被上下文覆盖贴出调用方代码作为只读上下文格式漂移输出段规格太松强制固定输出结构附输出示例4.2 我踩过的坑上下文污染、约束冲突和验证缺失在多次实际调试中有三个坑我反反复复踩有必要单独拿出来讲。第一个坑是上下文污染。有一次我把某模块的十几个函数一次性塞进对话想让模型统一优化。结果是它改出来的代码东拼西凑每个函数都改了一点点但整体风格割裂甚至有的函数之间出现了循环调用的隐患。后来我把任务拆成一次只改一个函数再把相关依赖定义作为上下文效果立刻正常了。记住上下文窗口不是无限的草稿纸它是供模型做精确判断的线索集。第二个坑是约束冲突。有一版提示词我同时要求“保持读秒级别的低延迟”和“不使用任何预计算缓存结构”结果模型逻辑混乱最终给出一版既没性能提升又多了很多冗余判断的代码。这类冲突在提示词里其实很隐蔽因为语言描述不会自动检查逻辑一致性。后来我养成了一个习惯每次写完提示词我会自己先读一遍模拟一下各条约束之间会不会打架。如果约束相互限制你就要主动取舍去掉次要目标。第三个坑是验证缺失。最初我拿到模型改写后的代码看质量还不错直接就合入了分支结果被回归测试打脸。后来我强制要求模型在输出段给出测试建议和边界用例并且自己补一轮基准测试。这步看着小实际上直接决定 AI 辅助开发的可持续性。代码模型不会替你做验证提示词里不写验证要求就等于你主动放弃质量门禁。另外一个与验证相关的习惯是拿到优化代码后先跑旧逻辑的回归用例再补新边界用例最后做一轮基准测试对比。比如上面那个例子我会构造一个一万用户、一万 ID 的数据集对比新旧函数的耗时差距。没有这些数据支撑你很难说服同事“改动值得合入”。毕竟在团队里代码改动是需要可量化收益的。最后再分享一个我的真实体会提示词不是在“命令”模型做事而是在和未来的自己沟通。写提示词时多想想如果你是接手这段代码的同事你需要怎样的信息才能又快又稳地完成任务。想通这一点之后你会发现每次拿到的结果都变得更加可控。上面这套框架我已经用在了好几个历史项目的重构里效率比逐行手改提升了不止一倍而且代码质量稳定在可以直接 review 的水平。你可以先从一段小函数开始试把五段式模板跑通再逐步扩展到更大范围的重构场景。