微软生成式 AI 入门课第 4 课:提示工程的地基是哪几件事

2026-08-18

翻开 04-prompt-engineering-fundamentals/python/ 这个目录,你会看到三个文件:oai-assignment.ipynbaoai-assignment.ipynbgithubmodels-assignment.ipynb。第一次看到的人容易以为这是三份不同难度的作业,其实不是——把三份文件并排打开,你会发现练习的编号与顺序完全一致,示例文本也是同一段;其中 oai-aoai- 两份连每一格的 markdown 说明都逐字相同,githubmodels- 那份只有 Exercise 2 的说明单元被改过(原因见下文)。真正被换掉的,是客户端怎么建、方法怎么调。

这个安排本身就是这一课要教的东西:同一个提示,换个模型或换个 provider,结果就可能不一样。课程 README 在「Why do we need Prompt Engineering?」那一节把这条列成了第一条挑战(原文说的是响应是随机的、同一提示在不同模型甚至同一模型的不同时刻都可能给出不同结果),然后紧接着让你去 Playground 里做两组对照:一组换 provider 跑同一个提示,一组在同一个部署上重复跑同一个提示。三份 notebook 就是把这组对照搬进代码里的版本。

下面顺着这三份文件走一遍,看看每一格练习到底在测什么。

被钉死的和被换掉的

三份 notebook 都是同一串练习:Exercise 1 tokenization、Exercise 2 验证 key 配置、Exercise 3 fabrications、Exercise 4 instruction based、Exercise 5 complex prompt,最后一格是开放式的 “Explore Your Intuition”。这五格是控制变量里被钉死的那部分。

被换掉的是接线。oai-assignment.ipynb 里直接 client = OpenAI(),然后写死 deployment="gpt-5-mini"(这是仓库示例里的取值),调用走 client.responses.create(...),带 max_output_tokens=1024store=False,取结果用 response.output_text

aoai-assignment.ipynb 的练习正文一个字没改,但客户端换成了:

client = OpenAI(
  api_key=os.environ['AZURE_OPENAI_API_KEY'],
  base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/",
  )

deployment=os.environ['AZURE_OPENAI_DEPLOYMENT']

注意它用的仍然是 openai 这个包的 OpenAI 类,只是把 base_url 拼到了 Azure 资源的 /openai/v1/ 路径上——单元注释里写明这是「OpenAI client against the Azure OpenAI (Microsoft Foundry) v1 endpoint with the Responses API」。所以从 oai 切到 aoai,函数体一行都不用动,这也是课程把三份文件做成同构的用意所在。

第三份就是那个名字已经名不副实的 githubmodels-assignment.ipynb。文件名前缀还留着 githubmodels,但里面 Exercise 2 的 markdown 单元逐字写明:GitHub Models 将于 2026 年 7 月底退役,这个练习改用 Microsoft Foundry Models。00-course-setup/03-providers.md 在讲「文件名里的 provider 标签」那份清单里,githubmodels 这一条写的也是「requires Microsoft Foundry Models endpoint, key」,后面同样跟着退役说明。今天这个时间点已经过去了,所以如果你照着前缀名去找 GitHub Models 的 token,方向就错了;实际要配的两个变量是 AZURE_INFERENCE_ENDPOINTAZURE_INFERENCE_CREDENTIAL,值取自 Foundry 项目 Overview 页上的 endpoint 与 API key。这条路线的客户端也换了 SDK:

from azure.ai.inference import ChatCompletionsClient
from azure.core.credentials import AzureKeyCredential

client = ChatCompletionsClient(
    endpoint=endpoint,
    credential=AzureKeyCredential(token),
)

调用走 client.complete(...),取结果是 response.choices[0].message.content,跟前两份的 output_text 不是一回事。写作业时这一处最容易串。

两个探针:一个有已知答案,一个刻意没有答案

Exercise 2 和 Exercise 3 表面上都是「发一句话看模型回什么」,设计意图完全相反。

Exercise 2 的提示词是 oh say can you see,markdown 单元里给了判定标准:输出应当 “along the lines of by the dawn's early light..”。这句是美国国歌的开头,属于任何一个语言模型都大概率见过的高频文本——换句话说,这一格根本不是在考提示词,而是拿一个已知答案的探针验证你的 endpoint、key、部署名三件事配对了没有。它失败你就知道是环境问题,不是提示词问题。这个先后顺序值得抄:先用确定性最高的输入把链路验通,再去调那些没有标准答案的东西。

Exercise 3 反过来,提示词是 generate a lesson plan on the Martian War of 2076.。README 里作者交代了这个题目是怎么选出来的:检索后发现有虚构作品写过火星战争,但没有 2076 年这一场,而且 2076 本身在未来,因此不可能对应真实事件。这是一个被刻意造出来、保证落在训练数据之外的空洞。课程还专门交代了用词:它统一用 fabrication 而不是 hallucination,仓库自述的理由是不想用拟人化的词去描述机器行为。

顺带一个文件层面的细节:githubmodels-assignment.ipynb 在仓库里保存了几格历史输出,另外两份没有保存输出。这些输出是别人某次执行后留在文件里的,按这一课自己说的随机性,它不构成你现在跑会得到什么的依据。

Exercise 1 为什么排在最前

Exercise 1 是唯一一格不调用云端 API 的练习:

import tiktoken
encoding = tiktoken.encoding_for_model("gpt-4o")
tokens = encoding.encode(text)

后面用 encoding.decode_single_token_bytes(token) 把整数逐个解回字节看。用的示例文本是那段关于木星的英文段落,README 正文里的 primary content 例子用的也是它——同一段文本贯穿了 tokenization、摘要、cue 三处,你改一处就能对照着看另外两处的变化。

把它放在第一格,配合 README 里那句「LLM 是按 token 序列看提示的,不同模型对同一段文本的切法可能不同」,指向很明确:后面所有关于「换个模型结果不一样」的观察,第一层解释在这里。这一格的依赖是 tiktoken,已经写在仓库根的 requirements.txt 里,同一个文件里还有 python-dotenvopenaiazure-ai-inference

采样参数那条已经移过位的线

三份 notebook 的 get_completion 签名不一样,这不是随手写的。oaiaoai 两份只传 max_output_tokensstoregithubmodels 那份多了三个参数:

def get_completion(prompt, client, model_name, temperature=1.0, max_tokens=1000, top_p=1.0):

上面这几个是仓库当前代码里的默认值,随版本可能变动。而紧挨着这段的注释直接说明了为什么只有这份有:temperature/top_p 需要非 reasoning 模型,gpt-5 会拒绝,所以这里用 Llama 模型。它取的模型名是 os.environ.get("AZURE_INFERENCE_CHAT_MODEL", "Llama-3.3-70B-Instruct"),这个 fallback 值同样只是仓库里的示例取值。

这层在 06-text-generation-apps/README.md 里讲得更完整:当前 Microsoft Foundry 上未废弃的是 reasoning 模型(GPT-5 家族、o 系列),它们不支持 temperaturetop_p,也不支持 max_tokens(改用 max_output_tokens,传了会收到参数不支持的报错;temperature/top_p 在 Llama、Mistral、Phi 以及 GPT-4.x 家族上仍然有效,而该文档同时标明 GPT-4.x 正在废弃过程中。.env.copy 里也在 AZURE_OPENAI_DEPLOYMENT 下面留了同样的提醒,并单独加了一个 AZURE_INFERENCE_CHAT_MODEL 变量,专门用来指一个支持采样控制的部署。

所以如果你看过老版本的提示工程教程、习惯上手就调 temperature,这一课的默认路线上其实没有这个旋钮可拧。

课程给基础技法留下的判定标准

这一课讲的技法本身不复杂:zero-shot / one-shot / few-shot、cue、template、primary content 与 supporting content 的分工。真正有价值的是它把「怎么算写好了」写成了可对照的东西。

一处是 README 末尾的 Knowledge check,它给了三个候选提示词并直接公布了排序:写明「红色 Volvo XC90 停在悬崖边、夕阳西下」的那条最好,判据是既说清了「what」又给了具体的品牌型号,还描述了整体场景;只给品牌型号的那条次之。这是全课唯一一处把好坏判据落成明文的地方。

另一处是 Best Practices 那张表。里面有两条特别容易被跳过:一条是 Give the model an “out”——给模型一个「做不到时可以这样答」的兜底回复,表里写明这能降低编造的概率;另一条是 Separate instructions & context,先确认你用的模型或 provider 有没有定义分隔符,用它把指令、primary content、secondary content 划开。回头看 notebook 里那个反复出现的写法:

prompt = f"""
Summarize content you are provided with for a second-grade student.
```{text}```
"""

指令在上、被处理的内容用三个反引号围起来——这就是上面那条 best practice 在代码里的样子,不是随便加的格式。

上手前置

作业那一节写的路径是:fork 仓库,然后三选一——推荐用 GitHub Codespaces,或者克隆到本地配合 Docker Desktop,或者用你自己的 notebook 运行时打开。接着把仓库根的 .env.copy 复制成 .env,填 AZURE_OPENAI_API_KEYAZURE_OPENAI_ENDPOINTAZURE_OPENAI_DEPLOYMENT。用前两种方式的话,kernel 选 dev container 自带的那个默认 Python kernel 即可(README 里写了具体的小版本号,随镜像更新,以仓库最新内容为准)。

复制文件那一步仓库给的是 cp .env.copy .env,这是 bash 写法;Windows 上如果直接用 PowerShell 而不是 WSL 或 Git Bash,仓库里我们没有找到对应的命令写法,得自己换成 PowerShell 的复制命令。另外如果你不想连云端,00-course-setup/03-providers.md 给了离线路线,Windows 侧的安装命令写的是 winget install Microsoft.FoundryLocal,macOS 侧是 brew install microsoft/foundrylocal/foundrylocal。要注意 .env 是被 gitignore 的,别把它提交上去。

最后提一句这一课自己的态度:作业说明里写明这些练习没有对错答案,所以整课不提供 Code Solution,只在 notebook 里放标题为 “My Solution:” 的 markdown 单元给一个参考输出。你把练习跑出跟示例不一样的结果,不代表你做错了。

以上代码片段均原样引自仓库文件,未经实测,以仓库最新代码为准。


本文依据 github.com/microsoft/generative-ai-for-beginners 仓库于 2026-08-18 的公开内容整理, 事实来自仓库内的课程正文与代码示例。我们没有跑过文中涉及的代码, 因此不涉及运行结果、耗时与生成质量的任何描述。 该课程持续更新,文中涉及的文件路径、依赖与接口写法随版本变动,请以仓库最新内容为准。 文中涉及的云端服务调用会产生费用并可能上传数据,请自行评估密钥与数据边界。 安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。