Prompt 基础
什么是 Prompt Engineering
Prompt Engineering(提示词工程)是指通过精心设计输入给大语言模型(LLM)的文本提示,来引导模型生成高质量、符合预期输出的技术。它不需要修改模型本身的参数,而是通过优化"问法"来获得更好的"答案"。
对于开发者而言,掌握 Prompt Engineering 意味着:
- 降低开发成本:无需微调模型即可完成多数任务
- 提升输出质量:结构化的提示词能显著改善生成结果
- 增强可控性:精确控制模型的行为边界和输出格式
- 加速迭代:快速调整提示词比重新训练模型高效得多
Prompt 的基本结构
一个高质量的 Prompt 通常包含以下四个核心组成部分:
| 组成部分 | 说明 | 是否必需 |
|---|---|---|
| 指令(Instruction) | 告诉模型要做什么 | 必需 |
| 上下文(Context) | 提供背景信息和约束条件 | 推荐 |
| 输入数据(Input Data) | 需要模型处理的具体内容 | 视情况 |
| 输出格式(Output Format) | 指定期望的输出结构 | 推荐 |
指令(Instruction)
指令是 Prompt 的核心,明确告诉模型需要执行的任务。好的指令应该清晰、具体、无歧义。
# 模糊的指令
帮我写点关于 Go 的东西。
# 清晰的指令
请为 Go 语言初学者编写一篇介绍 goroutine 并发编程的教程,包含 3 个由浅入深的代码示例。
上下文(Context)
上下文为模型提供执行任务所需的背景信息,帮助模型理解你的具体需求场景。
你正在为一个面向后端开发者的技术博客撰写内容。读者具备基本的编程经验,
但对 Go 语言了解有限。文章风格应当专业但通俗易懂。
请编写一篇关于 Go 接口(interface)的入门教程。
输入数据(Input Data)
输入数据是你需要模型处理的具体内容,比如一段代码、一篇文章、一组数据等。
请分析以下 Go 代码中的潜在问题并给出优化建议:
func fetchData(urls []string) []string {
var results []string
for _, url := range urls {
resp, err := http.Get(url)
if err != nil {
continue
}
body, _ := io.ReadAll(resp.Body)
results = append(results, string(body))
}
return results
}
输出格式(Output Format)
明确指定输出格式可以让模型生成结构化、可预测的结果,这对于程序化处理尤为重要。
请分析以下错误日志,以 JSON 格式返回结果,包含以下字段:
- error_type: 错误类型
- root_cause: 根本原因
- severity: 严重程度(high/medium/low)
- suggestion: 修复建议
角色设定(System Prompt)
角色设定是通过 System Prompt 为模型赋予特定身份和行为规范的技术。它是 Prompt Engineering 中最强大的工具之一。
基本角色设定
你是一位拥有 10 年经验的 Go 语言架构师,擅长设计高并发微服务系统。
你的回答风格简洁专业,善于用代码示例说明问题。
当遇到不确定的问题时,你会明确指出而不是猜测。
结构化 System Prompt
在实际应用开发中,System Prompt 通常需要更加结构化:
## 角色
你是 CoderMast 技术文档助手,负责帮助开发者解答技术问题。
## 能力范围
- Go 语言开发(核心语法、标准库、常用框架)
- 云原生技术(Docker、Kubernetes)
- 数据库(MySQL、Redis)
## 行为规范
1. 始终提供可运行的代码示例
2. 代码示例使用 Go 1.21+ 语法
3. 涉及安全相关问题时,优先推荐安全实践
4. 不了解的问题如实告知,不编造信息
## 输出格式
- 使用 Markdown 格式
- 代码块标注语言类型
- 关键概念用粗体标注
Zero-shot vs Few-shot
这是 Prompt Engineering 中两种最基础的策略,区别在于是否提供示例。
Zero-shot(零样本)
直接描述任务,不提供任何示例。适用于简单、明确的任务。
将以下英文技术术语翻译为中文,保留原文在括号中:
goroutine, channel, interface, struct, slice
输出:
协程(goroutine)、通道(channel)、接口(interface)、结构体(struct)、切片(slice)
Few-shot(少样本)
提供几个输入-输出示例,让模型学习期望的模式。适用于复杂任务或需要特定格式的场景。
请按照以下格式为 Go 标准库函数生成中文文档:
示例 1:
函数:strings.Contains(s, substr string) bool
文档:判断字符串 s 是否包含子串 substr。若包含返回 true,否则返回 false。
场景:用于字符串搜索、内容过滤等场景。
示例 2:
函数:strings.Replace(s, old, new string, n int) string
文档:将字符串 s 中的 old 替换为 new,n 为替换次数(-1 表示全部替换)。返回替换后的新字符串。
场景:用于文本处理、模板渲染、数据清洗等场景。
请为以下函数生成文档:
函数:strings.Split(s, sep string) []string
对比与选择
| 特性 | Zero-shot | Few-shot |
|---|---|---|
| Token 消耗 | 低 | 较高 |
| 适用场景 | 简单明确的任务 | 复杂格式、特定风格 |
| 准确度 | 取决于任务复杂度 | 通常更高 |
| 灵活性 | 高 | 受示例约束 |
输出格式控制
控制输出格式是 Prompt Engineering 在开发中最实用的技能之一。
JSON 格式输出
分析以下 Go 代码的复杂度,以 JSON 格式返回结果:
代码:
func BubbleSort(arr []int) []int { ... }
请严格按照以下 JSON Schema 返回:
{
"function_name": "函数名",
"time_complexity": "时间复杂度(大 O 表示法)",
"space_complexity": "空间复杂度(大 O 表示法)",
"is_stable": true/false,
"optimization_suggestions": ["建议1", "建议2"]
}
Markdown 格式输出
请为 sync.WaitGroup 编写使用说明,格式要求:
- 使用二级标题 (##) 分隔各部分
- 包含"概述"、"核心方法"、"使用示例"、"注意事项"四个部分
- 核心方法用表格展示(列:方法名、参数、说明)
- 代码示例使用 Go 代码块
结构化列表输出
列出 Go 语言中常见的 5 种并发模式,按以下格式输出:
**模式名称**
- 简介:一句话描述
- 适用场景:列举 2-3 个场景
- 代码骨架:关键代码片段
- 注意事项:1-2 个常见陷阱
---
使用分隔符控制边界
使用明确的分隔符帮助模型区分不同部分的内容:
请翻译 <text> 标签中的内容为中文,并对 <review> 标签中的内容进行代码审查。
<text>
Goroutines are lightweight threads managed by the Go runtime.
</text>
<review>
func main() {
go func() {
fmt.Println("hello")
}
}
</review>
常见误区与最佳实践
误区一:指令过于模糊
# 不好的写法
帮我优化这段代码。
# 好的写法
请从以下三个方面优化这段 Go 代码:
1. 性能:减少不必要的内存分配
2. 可读性:改善变量命名和代码结构
3. 错误处理:补充缺失的错误检查
请逐一给出优化后的代码和修改说明。
误区二:一次性要求过多
将复杂任务拆分为多个步骤,效果远好于一个巨大的 Prompt。
# 不好的写法
帮我设计一个完整的微服务架构,包含所有代码、部署配置和文档。
# 好的写法(分步骤)
第一步:请先帮我梳理这个电商系统需要拆分为哪些微服务,以及它们之间的依赖关系。
第二步:(基于第一步的结果)请为"订单服务"设计 API 接口。
第三步:(基于前两步)请实现订单服务的核心业务逻辑。
误区三:忽略否定指令的效果
# 不好的写法
不要使用全局变量,不要忽略错误,不要写过长的函数。
# 好的写法
请遵循以下编码规范:
- 使用依赖注入传递依赖,避免全局状态
- 所有错误必须显式处理(检查或返回)
- 单个函数不超过 50 行,超出则拆分为子函数
误区四:缺少输出约束
没有约束的 Prompt 容易产生冗长、偏离主题的回答。
# 不好的写法
解释一下 Go 的 GC。
# 好的写法
用 3-5 句话概括 Go 垃圾回收(GC)的核心机制,重点说明三色标记法的工作原理。
面向有 Java GC 基础的开发者,可以对比说明。
实战综合示例
下面是一个结合以上所有技巧的完整 Prompt 示例:
## 角色
你是一位 Go 语言技术专家和技术写作者。
## 任务
为初学者编写 Go 错误处理的最佳实践指南。
## 上下文
目标读者是有其他语言(Java/Python)经验但刚接触 Go 的开发者。
他们习惯了 try-catch 模式,需要理解 Go 的错误处理哲学。
## 要求
1. 解释 Go 为什么选择返回值而非异常
2. 展示 3 个逐步进阶的错误处理模式:
- 基础:简单的 if err != nil
- 中级:自定义错误类型 + errors.Is/As
- 高级:错误包装链 + sentinel errors
3. 每个模式提供可运行的完整代码示例
## 输出格式
- Markdown 格式
- 代码使用 go 代码块
- 每个模式以二级标题分隔
- 在每个模式末尾用 > 引用块总结要点
## 约束
- 总长度控制在 800-1200 字
- 代码示例使用 Go 1.21+ 语法
- 不要涉及 panic/recover(这是另一个主题)
小结
Prompt Engineering 的核心原则可以归纳为:
- 明确性:清晰描述你想要什么,而不是让模型猜测
- 结构化:使用分隔符、标签、格式要求组织 Prompt
- 具体性:提供上下文、示例和约束条件
- 迭代性:Prompt 很少一次就完美,需要不断调优
掌握这些基础之后,你可以进一步学习更高级的提示词技巧,如 Chain-of-Thought 推理、ReAct 模式等,来处理更复杂的任务场景。