第 2 讲:提示词工程基础
上课时间:2026 年 10 月 20 日(第 6 周,周二 19:20–20:55)
所属板块:基础方法
这一讲讲两件事:怎么把需求说清楚,怎么把背景材料给对。课上分三部分:提示技术、面向代码任务的提示技巧、上下文工程。
上讲回顾与检查点 1 反馈
25 位同学全部完成了检查点 1,有几个问题比较集中:
- 选题写得太简略,或者直接拿以前的科研项目、旧作品当选题,没有说明这门课准备做什么;
- 关键概念和功能边界不清楚,读者判断不了实际目标;
- 直接粘贴 AI 生成的内容,缺少自己的判断和整理;
- 和 AI 的交互只有一两次,过程记录不够;
- 环境配置、Git 启动这些基础信息没有交代。
一、提示工程在做什么
提示是人机协同的接口。同一个模型、同一个任务,提示不同,结果可能差很多。可以把 AI 当成新同事:任务说清楚,它才做得好。
LLM 会先把提示切成词元(token),再根据这些词元续写。提示里的每个词都会影响输出,包括看起来无关的内容。
Token 是模型处理文本的最小单位。英文单词大约 1 个词元,中文一个汉字平均约 1.2 个词元,具体会有出入。Token 数量影响 API 成本和响应速度,所以上下文不是越多越好。
| 文本 | 约合词元 |
|---|---|
Hello World! |
约 3 个 |
你好世界 |
约 4 个 |
function add(a, b) |
约 7 个 |
二、好提示的四要素
| 要素 | 要写清的内容 |
|---|---|
| 意图 | 要做什么、给谁用、解决什么问题 |
| 约束 | 语言、框架、版本、代码风格、禁止事项 |
| 格式 | 输出成函数、类还是脚本,带不带测试和注释 |
| 上下文 | 相关代码、接口、报错信息 |
三、五种提示技术
Zero-shot:直接描述任务
不给示例,直接说任务、输入输出和要求。适合常见、标准的任务。
用 Python 实现一个二分查找函数:
- 输入:已排序的整数列表 nums、目标值 target
- 输出:目标元素下标;不存在时返回 -1
- 要求:仅用标准库,带类型注解与 docstring
Few-shot:给几个示例
先给 2–5 个“输入 → 输出”示例,再给新输入。适合格式转换、风格统一和项目里的私有约定。示例质量比数量重要。
把错误码统一成项目风格(K=2):
输入:参数缺失 → 输出:E1001 参数缺失:{name}
输入:权限不足 → 输出:E1002 权限不足:{role}
新输入:文件不存在 → 按同样风格输出错误码
Chain-of-Thought:先推理再作答
要求模型先给出推理步骤,再给结论。复杂逻辑任务的正确率会明显提升,简单任务收益有限。
先分析这段代码的问题,再修复,最后给 diff:
1. 逐条列出问题,说明触发条件与影响
2. 说明修复思路,为什么这样改
3. 只输出修改处的 diff,不重写整个文件
Self-consistency:多生成几次再比较
同一个问题多次采样,或者换一种措辞重问,比较答案是否一致。也可以让 AI 给出多个实现方案,交叉比较后择优。
任务:统计日志中每种 ERROR 的出现次数
要求:给出 3 种实现——字典计数 / Counter / pandas
每种说明:性能、可读性、额外依赖
最后:推荐一种,并说明理由
多次结果一致,通常更可信;分歧的地方正好是需要人工检查的地方。
Reflexion:生成后自评再改
流程是生成、自评、修正、再生成。适合代码审查和迭代改进。
第 1 轮:实现 parse_config(path),解析 ini 并返回 dict
第 2 轮:审查你刚生成的代码,指出 3 个潜在问题
第 3 轮:按自评逐条改进,重新输出完整代码
任务越复杂、越不标准,越需要详细的提示技术。
四、代码任务的提示习惯
先写清需求和接口
需求至少包括输入、输出、边界条件和异常处理。可以先把函数签名和数据结构定下来,确认后再实现。
“优化一下”“好看一点”这类说法,AI 只能猜。平时可以积累一些专业词汇,比如 UI/UX、接口、验收、架构,表达越具体,AI 猜的空间越小。
用结构化提示
课上用了医院排队预测的例子。原来的提示是一段混在一起的话:
在医院排队做 CT,估计要等数小时。想做个 HTML 小程序:输入我的号码和当前叫号,
每听到一个号点一下按钮,估算还要等多久。
问题在于信息混杂、边界模糊、没有技术约束。改成结构化的写法后,可用度会明显提高:
# 角色
你是一位资深的前端开发工程师,擅长开发移动端友好的单页应用。
# 背景
我正在医院排队等待检查,需要一个工具来根据当前的叫号速度,预估我还需要等待多久。
这个工具将在手机浏览器上运行。
# 目标
请编写一个单文件的 HTML 小程序(包含 CSS/JS),用于追踪排队进度并预测时间。
# 功能需求
1. 初始化设置:允许用户输入「我的号码」和「当前叫号」
2. 核心交互:提供一个显眼的「过号」按钮,每点击一次,「当前叫号」加 1,并记录当前时间戳
3. 预测逻辑:
- 采用移动平均法:优先计算最近 10 次叫号的平均时间间隔
- 预测「剩余等待时间」= (我的号码 - 当前叫号) * 移动平均时间
- 至少有 3 次点击数据后,才开始显示预测结果
4. 状态显示:实时显示当前叫号、我的号码、预计还需要等待的时长(分钟)、预计叫号时间点
# 技术要求
- 单文件 HTML(内嵌 CSS 和 JS)
- 移动端友好,按钮要大
- 使用 localStorage 保存数据,刷新页面不丢失
# 约束
- 代码简洁,易于理解
- 添加必要的注释
结构化的作用是先把事情想清楚,也让 AI 少猜。常见的分节是角色、背景、目标、功能需求、技术要求、约束。
约束、分步和迭代
写约束时,把语言和版本、命名和注释要求、类型注解、禁止事项都写上。例如“Python 3.12,仅标准库”“不要引入新依赖”“不要修改公共接口”。
先让 AI 讲方案,认可后再写;先搭骨架,再逐个实现。这样错误暴露得早,过程也可控。
结果不符合预期时,具体指出哪里不对。还可以让 AI 用自己的话复述需求,或者让它反过来追问你还没想清楚的地方。需求阶段用后者往往很有效。
五、上下文工程
上下文窗口是模型一次能“看见”的内容上限。项目里的私有约定、接口和错误现场,不会自动出现在它眼前。给的材料质量差,生成结果也不会好。
长会话还会带来几个问题:模型处理更多上下文,响应变慢;需要综合考虑更多上下文,生成质量下降;成本也会增加。
该给什么
- 相关的源码和接口定义,而不是整个仓库;
- 项目约定,比如目录结构、命名规范、技术栈版本;
- 错误现场,包括报错信息和日志;
- 已经试过的方法,避免 AI 重复推荐无效方案。
| 类型 | 示例 |
|---|---|
| 需求描述 | “做一个待办事项应用” |
| 领域知识 | “餐厅点餐系统” |
| 技术约束 | “Python 3.12 + Flask” |
| 代码上下文 | “auth.py 已有认证模块” |
| 业务规则 | “VIP 用户享 8 折” |
| 数据约束 | “用户年龄必须大于 18” |
报错和日志
报错栈一般包含错误类型、消息、位置(文件:行号)和调用链。把完整报错栈和相关代码一起交给 AI,让它解释原因。
日志先做剪裁,按时间窗或 ERROR 级别提取关键片段,不要整屏粘贴。
以下是报错与相关代码,请解释原因并给出修复建议。
给多给少的平衡
上下文太多,关键信息会被稀释,成本上升,注意力也会分散;上下文太少,AI 只能猜接口和约定,容易产生幻觉。
实际做法是按相关性筛选,用 @文件 或索引引用代替全文粘贴。
六、提示模板
常用的提示可以整理成模板,结构是任务、约束、上下文、输出格式、验收标准。
〔任务〕给 students.csv 每行计算平均分并写回
〔约束〕Python 3.12,仅标准库;不修改已有列
〔上下文〕数据格式见样例;复用现有 load_csv()
〔输出格式〕单个函数,带 docstring 与类型注解
〔验收标准〕空数据不报错;平均分保留 1 位小数
把常用的提示存下来,时间长了就是自己的提示库。团队或项目层面可以用 AGENTS.md 这类行为文件,第 5 讲会详细讲。
七、课堂演示:三连对比
任务:给学生成绩表写一个统计脚本。
| 轮次 | 提示 | 结果 |
|---|---|---|
| 第一遍 | “帮我写个统计成绩的脚本” | 字段、规则、格式全凭 AI 猜 |
| 第二遍 | 明确列、规则与输出格式 | 结构可用,细节还要来回改 |
| 第三遍 | 精确提示加上下文,贴数据样例和现有函数 | 接近直接可用,修改轮次最少 |
观察的是输出可用度和修改轮次。
八、课堂实操
下载第 2 讲课堂实操 handout(zip,约 114 KB)。压缩包里有两份练习材料,互不依赖。
| 练习 | 内容 | 入口 |
|---|---|---|
| 练习一:提示策略对比 | 用至少两种提示策略实现一个不依赖标准库 JSON 模块的 JSON parser,再用 JSONTestSuite 评测 | part1-json-parser/ |
| 练习二:构造提问上下文 | 让 AI 回答 billing 代码库的 4 个问题,比较三种上下文构造方式 |
part2-context/ |
练习一
每种提示策略至少运行 3 次,每次生成一个 json_parser.py。提示词保存到 strategy1/、strategy2/ 目录,用 evaluate.py 做正确性评测,最后填两种策略的对比表。
每次尝试用独立的空目录和新会话,不要让后一次看到前一次的结果。如果发现 agent 读到了上一次的产物,清空目录重跑。
练习二
三组做法:
- A 组:在仓库里放开 read / glob,让 agent 自己找;
- B 组:禁用工具,由你挑选相关代码放进提示词;
- C 组:禁用工具,把全部代码放进提示词。
问题在 part2-context/questions.md,答案分别保存为 answer-a.json、answer-b.json、answer-c.json,用 grade_answers.py 按 ground_truth.json 自动批改。
对比正确性、幻觉、提示词规模、工具调用次数和耗时。
A/B/C 三组各用新会话。A 组在 repo/ 里运行,B/C 组在禁工具的 run-tools-off/ 里运行。A 组依赖 repo/.opencode/opencode.json 限制读取范围,不要删除。
需要交的记录
- 两种提示策略的提示词、至少 3 个
json_parser.py,以及evaluate.py的评测输出; - 两种策略的过程和结果对比表;
- 练习二的三组实际使用的提示词、答案 JSON 和对比表;
- 全程的提示词与输出记录。
九、检查点 2
截止 10 月 27 日(周二)23:59。需要提交含 Git 版本历史的代码仓库、用本讲技巧生成的骨架代码,以及提示词和上下文实践记录。
另外,按检查点 2:初始进展的要求,用会话 fork 完成至少一组不同提示词或不同上下文的对比,保留两组完整记录。