Generative AI 入门课程第 4 课:提示工程(Prompt Engineering)基础——提示的设计、构造与优化实战
【免费下载链接】generative-ai-for-beginners21 Lessons, Get Started Building with Generative AI项目地址: https://gitcode.com/GitHub_Trending/ge/generative-ai-for-beginners
本篇为开源课程 generative-ai-for-beginners 第 4 课《Prompt Engineering Fundamentals》的技术讲解(原文见 translations/hi/04-prompt-engineering-fundamentals/README.md,英文原版见 04-prompt-engineering-fundamentals/README.md)。你将系统理解提示工程的核心概念(分词、基础模型、指令微调模型),掌握提示的三种构造方式与"主要内容/辅助内容"设计模式,并跟随仓库自带的 Jupyter Notebook 沙箱完成零样本、少样本、提示线索等真实练习,最终能够针对特定模型与应用目标写出稳定、高质量的提示。
引言:提示已成为生成式 AI 的"编程接口"
生成式 AI 能够根据用户请求生成新的内容(文本、图像、音频、代码等),其底层依赖的是像 OpenAI GPT(Generative Pre-trained Transformer)系列这样针对自然语言与代码训练的大语言模型(LLM)。如今用户无需任何技术背景,就可以用聊天这类熟悉的方式与模型交互:发送一段文本输入(提示,prompt),得到 AI 的回应(补全,completion),并通过多轮对话反复打磨提示,直到结果符合预期。
在这个过程中,"提示"实质上已经成为生成式 AI 应用的主要编程接口(programming interface)——它告诉模型做什么,并直接决定返回结果的质量。而"提示工程"正是围绕提示的设计与优化展开的、快速增长的研究领域,目标是在规模化场景下交付稳定且高质量的回答。
本课的学习目标包括:解释提示工程是什么及为何重要;描述提示的组成要素及其用法;掌握提示工程的最佳实践与技术;并能够使用 OpenAI 端点将这些技术应用到真实示例中。本课的关键术语有三:
- 提示工程(Prompt Engineering):设计并优化输入,以引导 AI 模型产生期望输出的实践。
- 分词(Tokenization):将文本转换为模型可以理解与处理的更小单元(token)的过程。
- 指令微调 LLM(Instruction-Tuned LLMs):通过特定指令进行微调、以提高回答准确性与相关性的 LLM。
学习沙箱:从"艺术"到"直觉"
提示工程目前更多是一门"艺术"而非"科学"。提升直觉最好的方式就是多练习,采用"试错(trial-and-error)"的方法,把应用领域的专业知识与推荐技术、模型特定优化结合起来。
本课配套的 Jupyter Notebook(位于 04-prompt-engineering-fundamentals/python/)提供了一个沙箱环境,你可以边学边练,或在最后的代码挑战中使用。要运行练习,你需要:
- 一个 Azure OpenAI API key(已部署 LLM 的服务端点),或 OpenAI / Microsoft Foundry Models 的端点与密钥;
- 一个 Python 运行时,用于执行 Notebook;
- 本地环境变量——请先完成 本地环境配置 中的步骤。
Notebook 自带入门练习,但课程鼓励你自行添加Markdown(描述)与Code(提示请求)单元,尝试更多示例与想法,逐步建立提示设计的直觉。
图:本课内容的图解路线图——从核心概念与挑战,到对应的提示工程技术及最佳实践。其中"高级技术"部分对应本课程的下一个章节(第 5 课)。
提示工程是什么?
提示工程是**设计并优化文本输入(提示),使其在给定应用目标与模型下交付稳定、高质量的补全(completion)**的过程。可以把这看作两步:
- 针对给定模型与目标,设计初始提示;
- 反复**改进(refine)**提示以提升回答质量。
这本质上是一个需要用户直觉与投入的试错过程。要理解它为什么重要,首先需要理解三个概念:分词(tokenization)=模型如何"看"提示;基础 LLM(base LLM)=基础模型如何处理提示;指令微调 LLM=模型如何"看懂任务"。
分词:模型如何"看"你的提示
LLM 把提示看作一个token 序列,不同模型(或同一模型的不同版本)可能以不同方式对同一提示进行分词。由于 LLM 是在 token(而非原始文本)上训练的,提示的分词方式会直接影响到生成回答的质量。
图:OpenAI Tokenizer 将提示转换为 token 的示例。注意空白字符与标点符号如何被处理;该示例展示的是较老的模型(GPT-3),换用新模型可能得到不同结果。
在仓库配套的 Notebook(oai-assignment.ipynb)中,练习一正是用 OpenAI 的开源分词器tiktoken亲自体验分词过程:先用tiktoken.encoding_for_model("gpt-4o")获取模型对应编码,再用encoding.encode(text)得到整数形式的 token,最后用encoding.decode_single_token_bytes(token)还原成文本片段。把输入换成任意提示,你就能直观地看到同一段文本在不同模型编码下的切分差异。
基础模型(Base LLM / Foundation Model):预测下一个 token
提示完成分词后,基础 LLM 的核心功能就是预测序列中的下一个 token。由于 LLM 在海量文本数据集上训练,它们对 token 之间的统计关系有很好的把握,能够带着一定的置信度做出预测。需要特别注意的是:模型并不理解提示中词语的"含义",它们只看到一个可以通过下一次预测去"补全"的模式,并持续预测直到用户干预或满足某个预设条件。
想直观感受基于提示的补全吗?把上面的提示以默认设置输入 Azure OpenAI 的 Chat Playground,系统把提示视为信息请求,你会看到一条满足该上下文的补全。但假如用户想要的是满足特定标准或任务目标的输出呢?这就轮到指令微调 LLM登场了。
指令微调 LLM(Instruction-Tuned LLM):从"补全"到"执行任务"
指令微调 LLM 以基础模型为起点,用包含清晰指令的示例或输入/输出对(例如多轮"消息")进行微调,AI 的回答会尝试遵循该指令。它使用了诸如基于人类反馈的强化学习(RLHF)等技术,训练模型遵循指令并从反馈中学习,从而产出更适合实际应用、更贴合用户目标的回答。
让我们试试看:回到上面的提示,但把system message改为以下指令:
将提供给你的内容总结给二年级学生。结果限制在一个段落,包含 3-5 个要点。
图:改变系统消息后,回答被"调校"为符合目标受众与格式要求——教师可以直接把这段回答用于课堂幻灯片。
注意系统上下文对补全质量的影响,与用户输入同样显著。在 Notebook 的练习四中,正是用这样的"指令 + 主要内容"结构让模型完成面向特定读者的总结任务。
为什么需要提示工程?
当前 LLM 存在若干挑战,使得不做提示构建与优化就想获得可靠、一致的补全变得更加困难:
- 模型回答是随机的(stochastic)。同一个提示在不同模型或模型版本上很可能产生不同回答,甚至在同一模型的不同时刻也可能结果不同。提示工程技术通过提供更好的护栏(guardrails)帮助我们最小化这些差异。
- 模型会"捏造"回答(fabrication)。模型在庞大但有限的数据集上预训练,缺乏训练范围之外概念的知识,因此可能产出不准确、虚构甚至与已知事实直接矛盾的补全。提示工程技术帮助用户识别并缓解这类捏造,例如要求 AI 给出引用或推理过程。
- 模型能力存在差异。新模型或新一代模型能力更强,但也带来独特的怪癖以及成本与复杂度上的权衡。提示工程帮助我们建立最佳实践与工作流,抽象掉差异,以可扩展、平滑的方式适配模型特定需求。
你可以在 OpenAI 或 Azure OpenAI Playground 中亲自验证:用同一提示访问不同 LLM 部署(如 OpenAI、Azure OpenAI、Hugging Face),观察差异;再对同一个部署重复提交同一提示,观察随机波动。
捏造(Fabrication)示例
本课程用"捏造"(fabrication)一词描述 LLM 因训练局限等原因偶尔生成事实错误信息的现象。你可能在文章或论文中听过"幻觉"(hallucination)这个说法,但课程强烈建议使用"捏造":这样不会把机器驱动的结果误拟人化,也更符合负责任 AI(Responsible AI)在术语上的要求。
怎样感受捏造?想一个不存在的主题(确保不在训练数据集中)让 AI 生成内容。例如这个提示:
提示:为"2076 年火星战争"生成一份教案。
网络搜索只能找到关于火星战争的虚构作品(电视剧、书籍),但没有 2076 年的;常识也告诉我们 2076 年在未来,不可能关联真实事件。那么在三个不同 LLM 提供商上运行这个提示会发生什么?
正如预期,每个模型(或模型版本)都因随机行为与能力差异给出了略有不同的回答——比如一个模型面向八年级受众,另一个则假定是高中生——但三个模型都生成了足以让不知情用户信以为真的回答。本仓库的图片目录中保留了这三份真实截图(OpenAI Playground 响应、Azure OpenAI Playground 响应、Hugging Face Chat 响应),可作为比对参考。
缓解捏造的提示工程技术包括元提示(metaprompting)与温度(temperature)配置;新的提示工程架构也会把新工具与技术无缝融入提示流中,以减轻或降低这些影响。
案例研究:GitHub Copilot
真实世界中提示工程如何被使用?看一个案例:GitHub Copilot——你的"AI 结对程序员",它把文本提示转换为代码补全,并集成到开发环境(如 Visual Studio Code)中提供无缝体验。最早的 Copilot 版本基于 OpenAI Codex 模型,工程师们很快意识到需要对模型进行微调、并发展更好的提示工程技术以提升代码质量。到 2023 年 7 月,GitHub 发布了超越 Codex 的改进 AI 模型,提供更快的建议。
提示的构造(Prompt Construction)
了解了提示工程为什么重要,接下来看提示是如何构造的,以便评估不同技术对提示设计有效性的影响。
基础提示(Basic Prompt)
最基础的提示:不带任何其他上下文直接发送给模型的文本输入。例如把美国国歌的前几个词发给 OpenAI Completion API,它会立即"补全"出后续内容,体现了基本的预测行为:
| 提示(输入) | 补全(输出) |
|---|---|
| Oh say can you see | 听起来你在输入《星条旗》(美国国歌)的歌词。完整歌词如下…… |
复杂提示(Complex Prompt)
现在为基础提示加上上下文与指令。Chat Completion API / Responses API 允许我们把复杂提示构造为多条消息(messages)的集合:
- 反映用户输入与助手回答的输入/输出对;
- 设置助手行为或性格上下文的系统消息(system message)。
请求形式如下,此时分词有效地捕获了上下文与会话信息。修改系统上下文对补全质量的影响,与用户输入同等重要:
response = client.responses.create( model="gpt-4o-mini", input=[ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Who won the world series in 2020?"}, {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."}, {"role": "user", "content": "Where was it played?"} ] )Notebook 的练习五正是让你尝试多轮 system/user/assistant 消息,例如把系统性格改成 "sarcastic assistant",观察回答风格如何随之改变。
指令提示(Instruction Prompt)
上面的用户提示是简单的文本查询,可被理解为"请求信息"。而指令提示用文本更详细地指定任务,为 AI 提供更好指引:
| 提示(输入) | 补全(输出) | 指令类型 |
|---|---|---|
| Write a description of the Civil War | 返回一个简单段落 | 简单 |
| Write a description of the Civil War. Provide key dates and events and describe their significance | 返回一个段落,随后列出带描述的关键事件日期 | 复杂 |
| Write a description of the Civil War in 1 paragraph. Provide 3 bullet points with key dates and their significance. Provide 3 more bullet points with key historical figures and their contributions. Return the output as a JSON file | 以 JSON 格式在文本框中返回更详细的描述,可复制到文件并验证 | 复杂、格式化 |
可以看到:指令越具体(限定长度、要点数量、输出格式),越能约束模型产出可控的结果。
主要内容(Primary Content)
上面这些例子中提示仍然相当开放,LLM 需要自行判断预训练数据集的哪部分相关。采用主要内容设计模式后,输入文本被拆成两部分:
- 指令(动作);
- 相关内容(影响动作的素材)。
例如指令是"用 2 句话总结这段内容":
| 提示(输入) | 补全(输出) |
|---|---|
| Jupiter is the fifth planet from the Sun and the largest in the Solar System. ...(木星介绍长文本)Summarize this in 2 short sentences | Jupiter, the fifth planet from the Sun, is the largest in the Solar System and is known for being one of the brightest objects in the night sky. Named after the Roman god Jupiter, it's a gas giant whose mass is two-and-a-half times that of all other planets in the Solar System combined. |
主要内容片段可用来驱动更有效的指令,常见方式有三种:
- 示例(Examples):不明确告诉模型怎么做,而是给出示例让其推断行为模式;
- 线索(Cues):在指令后给出"线索"来启动补全,引导模型走向更相关的回答;
- 模板(Templates):可重复使用的提示"配方",含占位符(变量),可按具体场景用数据定制。
使用示例:零样本、一样本与少样本提示
用主要内容"喂给"模型期望输出的一些示例,让模型推断期望输出的模式。根据示例数量,可分为零样本(zero-shot)、一样本(one-shot)、少样本(few-shot)提示:
| 学习类型 | 提示(输入) | 补全(输出) |
|---|---|---|
| 零样本 | "The Sun is Shining". Translate to Spanish | "El Sol está brillando". |
| 一样本 | "The Sun is Shining" => "El Sol está brillando". "It's a Cold and Windy Day" => | "Es un día frío y ventoso". |
| 少样本 | The player ran the bases => Baseball The player hit an ace => Tennis The player hit a six => Cricket The player made a slam-dunk => | Basketball |
注意:零样本提示必须给出显式指令("Translate to Spanish"),而一样本中该任务被推断出来;少样本示例表明,增加更多示例能让模型在不增加任何指令的情况下做出更准确的推断。
提示线索(Prompt Cues)
使用主要内容的另一种技术是提供线索而非示例:给模型一个反映期望回答格式的片段作为"开头",模型会"接过线索"顺着这个方向继续:
| 线索数量 | 提示(输入) | 补全(输出) |
|---|---|---|
| 0 | 木星介绍文本 Summarize This | 一段通用的木星总结 |
| 1 | 木星介绍文本 Summarize This What we learned is that Jupiter | 续写为以 "is the fifth planet from the Sun..." 开头的总结 |
| 2 | 木星介绍文本 Summarize This Top 3 Facts We Learned: | 1. ... 2. ... 3. ...(自动编号的三个要点) |
线索越多,输出越贴合你预设的结构。
提示模板(Prompt Templates)
提示模板是预定义的提示"配方",可存储并按需复用,以驱动规模化、一致的用户体验。最简形式是提示示例的集合(提供交互式提示组件与 API 请求格式以支持复用);更复杂的形式(如 LangChain 的 Prompt Templates)包含占位符,可被来自用户输入、系统上下文、外部数据源等的数据动态替换,从而以编程方式在规模化场景下驱动一致的体验。
模板的真正价值在于为垂直应用领域创建并发布提示库(prompt libraries)——模板针对特定领域的上下文或示例做优化,使回答对目标受众更相关、更准确。
辅助内容(Supporting Content)
如果把提示构造看作"指令(任务)+ 目标(主要内容)",那么辅助内容就像额外提供的上下文,用于以某种方式影响输出:可以是调参(tuning parameters)、格式指令、主题分类(taxonomy)等,帮助模型把回答裁剪得符合期望的用户目标。
例如,给定一份带有丰富元数据(名称、描述、级别、元数据标签、讲师等)的课程目录:
- 定义指令"总结 Fall 2023 课程目录";
- 用主要内容提供几个期望输出的示例;
- 用辅助内容指定最受关注的 top 5 "标签"。
这样,模型会按示例展示的格式给出总结;当某个结果带多个标签时,它会优先采用辅助内容中指定的那 5 个标签。
提示的最佳实践(Prompting Best Practices)
知道提示如何构造后,就该思考如何设计它们以体现最佳实践。这可以分为两个部分:正确的心态与正确的技术。
提示工程心态
提示工程是试错过程,牢记三个总体指导因素:
- 领域理解很重要。回答的准确性与相关性取决于应用或用户所处的领域。运用你的直觉与领域专长进一步定制技术:例如在系统提示中定义领域特定人设,在用户提示中使用领域特定模板;提供反映领域上下文的辅助内容,或用领域特定的线索与示例把模型引向熟悉的用法模式。
- 模型理解很重要。模型本质上是随机的,但不同模型在训练数据集(预训练知识)、提供的能力(如通过 API/SDK)以及擅长的内容类型(代码 vs 图像 vs 文本)上也有差异。理解所用模型的优势与局限,并据此为任务排优先级或构建针对模型能力优化的定制模板。
- 迭代与验证很重要。模型演进迅速,提示工程技术亦然。作为领域专家,你的应用可能有社区之外的其他标准。用提示工程工具与技术"启动"提示构建,再用自己的直觉与领域专长迭代、验证结果;记录洞察并建立知识库(如提示库),供他人作为新基线实现更快的迭代。
通用最佳实践
以下是 OpenAI 与 Azure OpenAI 实践者推荐的通用最佳实践:
| 做法 | 为什么 |
|---|---|
| 评估最新模型 | 新一代模型特性与质量更优,但也可能带来更高成本。评估其影响后再做迁移决策。 |
| 分离指令与上下文 | 检查你的模型/提供商是否定义了分隔符来更清晰地区分指令、主要内容与辅助内容。这有助于模型更准确地对 token 分配权重。 |
| 具体而清晰 | 给出关于期望上下文、结果、长度、格式、风格等更多细节,这能同时提升回答的质量与一致性。把配方沉淀为可复用模板。 |
| 描述性表达、善用示例 | 模型对"边说边演示"的方式响应更好。先用zero-shot(给指令但不给示例),再用few-shot作为改进(给出期望输出的少量示例)。善用类比。 |
| 用线索启动补全 | 给一些引导性的词或短语作为回答起点,把模型推向期望结果。 |
| 重复强调 | 有时需要向模型重复:在主要内容前后都放指令,指令与线索并用等。迭代并验证哪种有效。 |
| 顺序很重要 | 信息呈现顺序可能影响输出,即使在示例学习中也有近因偏差(recency bias)。尝试不同顺序找出最优。 |
| 给模型一个"出口" | 给模型一个兜底补全回答,以便它因任何原因无法完成任务时使用。这能降低模型生成错误或捏造回答的概率。 |
与任何最佳实践一样,效果会因模型、任务与领域而异。把这些作为起点,迭代找出最适合你的方式;随着新模型与新工具出现,持续重新评估你的提示工程流程,重点关注流程可扩展性与回答质量。
动手实践:Notebook 作业与代码挑战
恭喜你读完本课正文!现在用真实示例检验这些概念与技术。仓库为第 4 课准备了三个对应不同提供商的 Notebook(内容相同、端点不同):
- oai-assignment.ipynb——使用 OpenAI 端点;
- aoai-assignment.ipynb——使用 Azure OpenAI(Microsoft Foundry)v1 端点;
- githubmodels-assignment.ipynb——使用 Microsoft Foundry Models 的 Azure AI Inference SDK。
第一步:准备运行环境
- (推荐)启动 GitHub Codespaces;
- (备选)把仓库克隆到本地,用 Docker Desktop 运行;
- (备选)在任意你喜欢的 Notebook 运行时中打开 Notebook。
第二步:配置环境变量
把仓库根目录的.env.copy复制为.env,填入AZURE_OPENAI_API_KEY、AZURE_OPENAI_ENDPOINT与AZURE_OPENAI_DEPLOYMENT等值,再回到上文"学习沙箱"了解用法。仓库根目录的 00-course-setup/03-providers.md 给出了完整的变量清单与各提供商的申请说明:
| 变量 | 说明 |
|---|---|
| OPENAI_API_KEY | 非 Azure OpenAI 端点的服务授权密钥 |
| AZURE_OPENAI_API_KEY | Azure OpenAI(Microsoft Foundry)服务的授权密钥 |
| AZURE_OPENAI_ENDPOINT | Azure OpenAI 资源的已部署端点 |
| AZURE_OPENAI_DEPLOYMENT | 文本生成(chat completion)模型部署名,推荐gpt-4o-mini |
| AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT | 文本嵌入模型部署名,推荐text-embedding-3-small |
| AZURE_INFERENCE_ENDPOINT / AZURE_INFERENCE_CREDENTIAL | Microsoft Foundry 项目的端点与 API 密钥 |
仓库还在 shared/python/api_utils.py 提供了create_openai_client()与create_azure_openai_client()两个工厂函数:前者读取OPENAI_API_KEY环境变量;后者把AZURE_OPENAI_ENDPOINT与AZURE_OPENAI_API_KEY组合为<endpoint>/openai/v1/的 v1 端点客户端,无需再传api_version。对应的 tests/test_env_utils.py 则验证了 shared/python/env_utils.py 中get_required_env、validate_env_vars等函数对缺失环境变量的报错行为——这保证了缺失凭据时作业会给出清晰提示,而不是静默失败。
第三步:打开 Notebook 并选择内核
选择运行时内核。若使用选项 1 或 2,直接选择开发容器提供的默认 Python 3.10.x 内核即可。然后依次完成练习:
- 练习一(分词):用
tiktoken观察同一文本在gpt-4o编码下的 token 序列,然后替换成你自己的提示; - 练习二(验证端点):发送基础提示
oh say can you see,预期补全类似 "by the dawn's early light...",用于确认 API 配置正确。oai/aoai 版本使用 Responses API(client.responses.create(model=deployment, input=prompt, temperature=0, max_output_tokens=1024, store=False)),temperature=0表示输出随机性为 0,便于获得可复现结果; - 练习三(捏造):运行"为 2076 年火星战争生成教案"提示,观察模型如何一本正经地"捏造";尝试换提示或换模型看差异;
- 练习四(指令式):用
text变量设置主要内容,用prompt变量提供指令——例如让模型把木星介绍总结给二年级学生; - 练习五(复杂提示):构造 system/user/assistant 多轮消息,把系统人设改成 "sarcastic assistant" 观察风格变化,或尝试不同的人设与消息序列;
- 拓展练习:基于以上模式,用示例、线索等技巧创造你自己的练习。
注意本课没有标准答案——只有通过试错探索选项、建立对"什么模型 + 什么领域下什么有效"的直觉。因此本课不含代码解决方案单元,Notebook 中会提供标题为 "My Solution:" 的 Markdown 单元,展示一个参考示例输出。
知识检查
以下哪个提示遵循了合理的最佳实践?
- 给我看一张红色汽车的图片
- 给我看一张红色汽车的图片,品牌为 Volvo、型号 XC90,停在悬崖边,夕阳西下
- 给我看一张红色汽车的图片,品牌为 Volvo、型号 XC90
答案:2。它是最佳提示:既提供了"是什么"的细节,又落到具体(不只是任何汽车,而是明确的品牌与型号),还描述了整体场景。3 次之,因为它同样包含大量描述。
🚀 挑战:试试用"线索"技术完成句子:"给我看一张红色汽车的图片,品牌为 Volvo 和 ____"。它回答了什么?你会如何改进它?
完成后,你可以继续学习第 5 课 高级提示技术,那里将介绍提示工程中更进阶的方法。
【免费下载链接】generative-ai-for-beginners21 Lessons, Get Started Building with Generative AI项目地址: https://gitcode.com/GitHub_Trending/ge/generative-ai-for-beginners
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考