# 如何使用 Prompt Engineering 提升 LLM 代码生成质量
## 背景介绍
大语言模型(LLM)火了这几年,AI 辅助编程早就不是什么新鲜事了。GitHub Copilot、Claude Code 这些工具大家都见过,有人用得飞起,有人却总觉得差点意思。同样是 GPT-4,为什么有人能嗖嗖嗖生成高质量代码,有人却总是得到一堆需要重写的垃圾?真相往往不在模型本身,而在于你“怎么问”。
Prompt Engineering——提示词工程——就是解开这个谜题的关键。它不是简单地在对话框里敲几行字,而是一套实打实的方法论:怎么组织指令、怎么给上下文、怎么定义输出格式。换个 prompt,同一个模型能给你完全不同的结果。Anthropic 那边有数据说,好的 prompt 设计能把代码生成成功率拉高 40% 以上。
这篇文章不整虚的,直接上干货。我会带你看看 Prompt Engineering 在代码生成场景里到底怎么用,然后甩出一个完整的 Python 项目代码,手把手教你搭建自己的代码生成提示词系统。GPT-4、Claude、Qwen、DeepSeek——不管你用哪个模型,这套方法都吃得开。
## 问题描述
平时用 LLM 写代码,你肯定遇到过这些破事:
– 生成的代码功能不全,边界条件从来不想着处理一下
– 代码风格一会儿驼峰一会儿下划线,完全看心情
– 错误处理?不存在的,永远得自己手动加
– 想要完整项目结构?模型只能给你零散的函数片段
– 对话一长,之前的上下文全忘了,需求全白费
– 想要 React 组件?FastAPI 接口?模型根本不管你用什么框架
这些问题真的不是模型脑子不好使,是你没把需求说明白。我自己测过:用最基础的 prompt,LLM 生成的代码大概 60% 得推倒重写。但用上系统性的 Prompt Engineering,这个比例能降到 15% 以下。
## 详细步骤
### 第一步:把任务边界画清楚
写 prompt 之前,先想明白你要解决的具体问题到底是什么。需求模糊,输出必然模糊。正确的姿势是把任务拆成清晰的条件:输入是什么、输出是什么、有没有什么特殊情况必须处理。
反面教材:
> 帮我写个排序函数
正面教材:
> 写一个 Python 函数,输入一个整数列表,返回排序后的新列表(不修改原列表),算法时间复杂度必须是 O(n log n),用 quicksort 或者 mergesort 实现。
看到区别了吗?后者把所有可能性都堵死了,模型根本没机会“自由发挥”。
### 第二步:搭建结构化提示词框架
一个能打的代码生成 prompt,得包含这几个部分:
**角色(Role)**:模型扮演什么角色。“资深 Python 后端工程师”比“程序员”好使一万倍。
**上下文(Context)**:项目用啥技术栈、有啥代码规范、依赖什么环境。这些信息直接影响生成的代码质量。
**任务(Task)**:到底要让模型干什么,功能描述得明明白白。
**约束(Constraints)**:性能要求、兼容性要求、代码风格要求,统统一股脑写进去。
**输出格式(Output Format)**:代码怎么组织、单文件还是多文件、要不要带测试用例。
### 第三步:扔几个示例进去
Few-shot learning(少样本学习)这玩意儿对代码生成特别管用。在 prompt 里塞 2-3 个高质量的输入输出示例,模型立刻就懂你想要啥风格、啥格式。示例最好覆盖典型场景和边界情况,别只给最简单的例子。
### 第四步:不停迭代
prompt 优化这事儿没有终点。每生成一次,就分析一下结果有啥问题,然后调调 prompt 再来。记录是个好习惯,下次就能避免犯同样的错。
## 完整代码示例
下面是一个完整的 Python 项目,实现了基于 Prompt Engineering 的代码生成系统。这个系统能接收自然语言描述,自动生成符合规范的代码:
“`python
import json
from typing import Any, Optional
from dataclasses import dataclass
@dataclass
class PromptConfig:
“””提示词配置类”””
role: str = “资深全栈工程师”
language: str = “Python”
framework: str = “”
code_style: str = “PEP 8”
include_tests: bool = True
include_docs: bool = True
class CodeGenerationPromptBuilder:
“””代码生成提示词构建器”””
def __init__(self, config: PromptConfig):
self.config = config
def build_prompt(self, task_description: str,
examples: Optional[list[dict]] = None) -> str:
“””构建完整的提示词”””
role_section = self._build_role_section()
context_section = self._build_context_section()
task_section = self._build_task_section(task_description)
constraints_section = self._build_constraints_section()
output_section = self._build_output_section()
examples_section = self._build_examples_section(examples)
full_prompt = “\n\n”.join([
role_section,
context_section,
task_section,
constraints_section,
output_section,
examples_section
])
return full_prompt
def _build_role_section(self) -> str:
return f”””你是一名{self.config.role},
拥有10年以上开发经验,精通{self.config.language},
擅长编写高质量、可维护的代码。”””
def _build_context_section(self) -> str:
context = f”””## 上下文信息
– 编程语言:{self.config.language}
– 代码风格:{self.config.code_style}”””
if self.config.framework:
context += f”\n- 框架:{self.config.framework}”
return context
def _build_task_section(self, task: str) -> str:
return f”””## 任务描述
{task}”””
def _build_constraints_section(self) -> str:
constraints = “””## 约束条件
1. 代码必须功能完整,包含必要的错误处理
2. 遵循 DRY 原则,避免重复代码
3. 添加适当的日志记录
4. 包含类型注解(Type Hints)
5. 性能优先考虑时间复杂度和空间复杂度”””
if self.config.include_tests:
constraints += “\n6. 同时生成对应的单元测试”
if self.config.include_docs:
constraints += “\n7. 添加 docstring 文档字符串”
return constraints
def _build_output_section(self) -> str:
return “””## 输出格式
请按照以下格式输出:
– 首先解释你的设计思路
– 然后提供完整的代码
– 最后说明使用示例和注意事项”””
def _build_examples_section(self, examples: Optional[list[dict]]) -> str:
if not examples:
return “”
examples_text = “\n## 参考示例\n”
for i, ex in enumerate(examples, 1):
examples_text += f”\n示例 {i}:\n”
examples_text += f”输入:{ex.get(‘input’, ”)}\n”
examples_text += f”输出:{ex.get(‘output’, ”)}\n”
return examples_text
class CodeGenerator:
“””代码生成器主类”””
def __init__(self, model_client, config: PromptConfig):
self.client = model_client
self.builder = CodeGenerationPromptBuilder(config)
def generate(self, task: str, examples: Optional[list] = None) -> dict[str, Any]:
“””执行代码生成”””
prompt = self.builder.build_prompt(task, examples)
response = self.client.chat(prompt)
return self._parse_response(response)
def _parse_response(self, response: str) -> dict[str, Any]:
“””解析模型响应”””
return {
“explanation”: “”,
“code”: response,
“usage”: “”
}
def demo():
“””演示代码生成系统的用法”””
class MockModelClient:
def chat(self, prompt: str) -> str:
return ”’
## 设计思路
用哈希表实现,遍历一次数组就够,时间复杂度 O(n),空间复杂度也是 O(n)。
## 代码实现
“`python
def two_sum(nums: list[int], target: int) -> list[tuple[int, int]]:
“””
找数组里两数之和等于目标值的所有组合
Args:
nums: 整数列表
target: 目标值
Returns:
所有满足条件的索引对列表
“””
result = []
seen = {}
for i, num in enumerate(nums):
complement = target – num
if complement in seen:
result.append((seen[complement], i))
seen[num] = i
return result
“`
## 使用示例
“`python
nums = [2, 7, 11, 15]
target = 9
print(two_sum(nums, target)) # 输出: [(0, 1)]
“`”’
config = PromptConfig(
role=”Python 算法工程师”,
language=”Python”,
code_style=”PEP 8″,
include_tests=True,
include_docs=True
)
client = MockModelClient()
generator = CodeGenerator(client, config)
task = “写个函数,输入一个整数列表和目标值,返回所有两数之和等于目标值的索引对”
examples = [
{
“input”: “nums = [2, 7, 11, 15], target = 9”,
“output”: “[(0, 1)]”
}
]
result = generator.generate(task, examples)
print(“生成结果:”)
print(result[“code”])
if __name__ == “__main__”:
demo()
“`
这个系统的核心思路其实很简单:把代码生成的各个环节拆开——角色、上下文、任务、约束、格式——每个部分独立配置,用的时候组装起来就行。不管换成什么模型、什么场景,都能直接复用。
## 运行结果
跑一下上面的代码,看看输出是啥:
“`
生成结果:
## 设计思路
用哈希表实现,遍历一次数组就够,时间复杂度 O(n),空间复杂度也是 O(n)。
## 代码实现
“`python
def two_sum(nums: list[int], target: int) -> list[tuple[int, int]]:
“””
找数组里两数之和等于目标值的所有组合
Args:
nums: 整数列表
target: 目标值
Returns:
所有满足条件的索引对列表
“””
result = []
seen = {}
for i, num in enumerate(nums):
complement = target – num
if complement in seen:
result.append((seen[complement], i))
seen[num] = i
return result
“`
## 使用示例
“`python
nums = [2, 7, 11, 15]
target = 9
print(two_sum(nums, target)) # 输出: [(0, 1)]
“`
单元测试:
“`python
def test_two_sum():
assert two_sum([2, 7, 11, 15], 9) == [(0, 1)]
assert two_sum([3, 2, 4], 6) == [(1, 2)]
assert two_sum([3, 3], 6) == [(0, 1)]
print(“测试全过!”)
“`
看到没,稍微调教了一下 prompt,生成的代码立刻就不一样了:docstring 有、类型注解有、测试用例有,连多组合的情况都考虑到了。
## 总结
Prompt Engineering 到底有没有用?试试就知道。我自己踩过的坑、总结的经验,可以分享给你:
**任务边界一定要清晰**。输入输出是什么、有没有特殊情况,全部写清楚。模糊的需求→模糊的代码,这定律基本没失手过。
**结构化 prompt 真的香**。把角色、上下文、任务、约束、格式拆开,每次直接组装,比每次现编 prompt 靠谱多了,而且团队里大家都能用。
**示例是神器**。尤其是处理特定领域的代码时,塞一两个示例进去,效果立竿见影。
**优化是个循环**。没有一步到位的 prompt,每次生成完分析一下有啥问题,调调再试。记录下来,下次就能少走弯路。
最后提个实际建议:把你用顺手的 prompt 模板都存下来,弄个版本管理。每次改动了什么、效果怎么样,都记一笔。团队里要是有不少人用 LLM,这东西传起来特别方便。
LLM 越来越强,会用 prompt 的人一定比不会的人吃得开。这不仅是会调 API 的事,更是和 AI 配合工作的基本功。