同一课的 .ipynb 与 .py 差在哪:微软生成式 AI 入门课第 6 课

2026-08-18

第一次打开 generative-ai-for-beginners 的 06-text-generation-apps/python/ 目录,多半会愣一下:里面既有 oai-app.pyaoai-app-recipe.py 这种单文件脚本,也有 oai-assigment.ipynbaoai-assignment.ipynbgithubmodels-assignment.ipynb 这种 notebook。名字里都带 oai / aoai / githubmodels 前缀,看上去像是同一份东西的两种打包方式。

不是。我把这一课的文件逐个读了一遍,两种形态装的内容不一样,停的位置也不一样,甚至同一段代码在两边写法都有出入。搞清楚这层分工,比纠结「用 Jupyter 还是用编辑器」有用得多。

顺带先说一个会浪费你五分钟的细节:OpenAI 路线那份 notebook 的文件名是 oai-assigment.ipynbassignment 少了一个 n,另外两份 aoai-assignment.ipynbgithubmodels-assignment.ipynb 拼写是完整的。按 oai-assignment 去搜是搜不到的。

notebook 里装的是讲课路径

先看 oai-assigment.ipynb。它绝大多数 cell 是 markdown,真正的代码 cell 屈指可数,依次是:建虚拟环境并装依赖、第一版补全程序、把 prompt 换成菜谱、把菜谱数量和食材改成 input() 读取。

有两个特征值得注意。

第一,每个代码 cell 都是自足的:import osfrom openai import OpenAIload_dotenv()、构造 client、写 prompt、调 client.responses.create(...)print(response.output_text),从头到尾重写一遍。它不是在前一个 cell 的变量上继续搭,而是把整个程序重贴一次、只改中间那一两行。落到阅读上的结果是:每个代码 cell 单独看都是一份完整程序,不需要回头拼上文。

第二,这些 notebook 里没有保存任何执行输出。预期结果不是以 cell 输出的形式存下来的,而是写在紧随其后的 markdown 里的 ```output 代码块中。也就是说,它是一份教学文档,不是一次运行的记录。这一点和仓库自己的说法对得上:00-course-setup/README.md 写明每一课的编码内容都配有 README,让你不运行任何东西也能看到代码和输出。

Windows 侧有一个坑要单独说。建环境那个代码 cell 里写的是 ! python -m venv venv! source venv/bin/activate! pip install openai,是 Unix 形式;Windows 的替代命令 venv\Scripts\activate 只出现在紧跟其后的 markdown NOTE 里,没有进代码 cell。而这个代码 cell 前面那段 markdown 里还有另一条 NOTE,写明如果你在 Codespaces 或 devcontainer 里跑这个 notebook,这一步本来就不需要。两条提示分列代码 cell 前后,只顾着点「运行」很容易两条都错过。

.py 里装的是终态和作业解答

再看同一目录下的脚本。以 OpenAI 路线为例,oai-app.py 对应 notebook 的第一版补全程序,oai-app-recipe.py 对应菜谱生成器,另外还有 oai-history-bot.pyoai-study-buddy.py

后面这两个在 notebook 里根本不存在。它们对应的是章节 README 的 ## Assignment 一节列出的三个可选题目(改进菜谱生成器、做一个 study buddy、做一个 history bot),而 README 的 ## Solution 一节里只给了 prompt 文本,没给完整程序——完整程序在这两个 .py 里。所以 notebook 走到菜谱生成器就停了,脚本目录比它多出整整一段。

菜谱这条线上两边也没停在同一处。notebook 最后一个代码 cell 只做到「数量 + 食材由用户输入」;后续的「加过滤条件」和「用第一次的结果再生成一份购物清单」是写在最后那个 markdown cell 里的片段。而 oai-app-recipe.py 里,这两步是以完整代码的形式落在文件里的:先读 no_recipesingredientsfilter 三个输入拼 prompt,拿到 response.output_text 存进 old_prompt_result,再把它连同 prompt_shopping 拼成 new_prompt 发第二次请求。两次调用都带了 max_output_tokens=600——这是仓库这个文件里当前写着的示例值,不是什么推荐配置。

一句话概括分工:notebook 是「一步一步长出来」的过程,.py 是每一步的终点快照,外加 notebook 没覆盖的作业解答。

两种形态之间已经存在的出入

这才是真正会咬到你的部分。同一课的两种形态并非机械同步,我核到几处白纸黑字的不一致,照着一边改另一边会出问题。

client 的构造方式不同。 notebook 里写的是 OpenAI(api_key = os.environ['OPENAI_API_KEY']),显式把 key 传进去;oai-app.py 里写的是裸的 OpenAI(),靠 SDK 自己去读环境变量。两种都在仓库里,但如果你从 notebook 复制客户端构造、又参考 .py.env 用法,很容易搞不清 key 到底从哪进去的。

采样参数在两边是反的。 githubmodels-assignment.ipynb 的代码 cell 里,模型取自 os.environ.get("AZURE_INFERENCE_CHAT_MODEL", "Llama-3.3-70B-Instruct"),并且实打实往 client.complete(...) 里传了 temperaturemax_tokenstop_p;cell 里的注释解释了原因——temperature/top_p 需要非 reasoning 模型,gpt-5 会拒绝,所以这里用 Llama 模型。而同目录的 githubmodels-app.py 里,model_name 直接写成字符串 "gpt-5-mini"client.complete(...) 的参数列表里一个采样参数都没有,只在末尾留了一行注释,写明 gpt-5 reasoning 模型不接受 temperature/top_p、让它们保持默认。

这不是笔误,是刻意的。章节 README 的「Improve your setup」一节写明:当前 Microsoft Foundry 上未废弃的模型是 reasoning 模型(GPT-5 家族、o 系列),它们不支持 temperaturetop_p,也不支持 max_tokens(要改用 max_output_tokens),给 gpt-5-minitemperature 会拿到「参数不支持」的报错。仓库根目录的 .env.copyAZURE_OPENAI_DEPLOYMENT 下面重复了同一句提醒,并专门留了 AZURE_INFERENCE_CHAT_MODEL 这个变量给「支持采样参数的模型」用。

所以:从 notebook 抄采样参数、往 .py 的模型上套,是这一课最容易踩的一步。 上面提到的模型名与参数值都只是仓库文件里当前写着的示例值,随课程更新会变,别当成推荐配置照搬。

校验函数有两份。 aoai-app-recipe.py 在文件里内联定义了 get_required_envvalidate_number_inputvalidate_text_input 三个函数,同名的实现在 shared/python/env_utils.pyshared/python/input_validation.py 里也有一份,而 tests/ 目录下的 test_env_utils.pytest_input_validation.py 覆盖的是 shared 那一份,不是章节内联的这份。你要把这一课的输入校验搬进自己项目,需要注意这层区别:被测试覆盖的是 shared 那一份,章节内联的那三个函数没有对应测试。tests/test_input_validation.py 就是按 shared.python.input_validation 这个模块路径 import 的,你要复用同一份实现,import 的形态是:

from shared.python.input_validation import validate_text_input

以上为按仓库代码中的接口语义组合的示例,未经实测,以仓库最新代码为准。

注释存在漂移。 oai-app-recipe.pyoai-study-buddy.py 顶部的注释写着 # configure Azure OpenAI service client,但下面构造的其实是普通的 OpenAI(),走的是 OpenAI 路线而不是 Azure。另外,oai-app.py 那个「从前有一条不开心的美人鱼」的补全示例,它的预期输出被以注释形式留在了文件末尾;oai-study-buddy.pyoai-history-bot.py 的末尾也原样带着这两行,可它们的 prompt 早已不是那个补全题了。读的时候按代码为准,别按注释为准。

三条 provider 路线别混着看

这一课的每种形态都按 provider 分了三份,前缀分别是 oai-(OpenAI)、aoai-(Azure OpenAI)、githubmodels-,总说明在 00-course-setup/03-providers.md。前两条的差别很直白:aoai-app.pyAZURE_OPENAI_API_KEYAZURE_OPENAI_ENDPOINT 拼出 .../openai/v1/ 作为 base_url,deployment 名从 AZURE_OPENAI_DEPLOYMENT 读;oai-app.py 什么都不拼。

第三条要特别说明:githubmodels- 这个前缀已经和它实际接入的目标脱节了。仓库在多处逐字写明,GitHub Models 连同它的 GITHUB_TOKEN 变量已于 2026 年 7 月底退役,直接替代者是 Microsoft Foundry Models——00-course-setup/02-setup-local.md00-course-setup/03-providers.md00-course-setup/README.md.env.copy 都写了,githubmodels-app.py 文件头的注释里也写了。这个时间点现在已经过去。所以这条路线现在实际要配的是 Microsoft Foundry Models 的 endpoint 与 key,也就是脚本里读的 AZURE_INFERENCE_ENDPOINTAZURE_INFERENCE_CREDENTIAL,不要再照着 GITHUB_TOKEN 去配。选路线时,第三条应该理解为「Microsoft Foundry Models(原 GitHub Models 路线)」。

顺带一提,githubmodels-assignment.ipynb 的 cell 数比另外两份少,而且中间夹着一个内容为空的代码 cell。这个空 cell 里没有任何代码,仓库里也没有对它的说明,它不影响这条路线两个代码 cell 本身的内容。

从你的处境倒推该点开哪个

  • 第一次学这一课:开 notebook。它的价值在四个代码 cell 之间那些 markdown,程序为什么从这一版变成下一版,只有那里写了。在 Codespaces 或 devcontainer 里,建环境那个 cell 可以跳过;Windows 本地跑,记得用 markdown NOTE 里那条 venv\Scripts\activate,而不是代码 cell 里的 source 那条。
  • 要把成果搬进自己项目:直接读 .py。同一目录下的 requirements.txtopenaipython-dotenv 钉到了具体版本,脚本本身没有叙事、没有中间态,复制过去就是完整程序。校验逻辑记得走 shared/python/ 那份。
  • 做作业或找参考解答:只有 .py 有。oai-history-bot.py / oai-study-buddy.py(以及对应的 aoai- 版)是 README 里 ## Assignment 那三个题目的落地形态,README 的 ## Solution 一节只给 prompt。
  • 要做代码评审或纳入版本控制.ipynb 本身是 JSON 容器,改一行代码在文件里体现为 JSON 结构的变化,而 .py 就是纯文本。这是通用工程做法层面的差别,不是这个课程仓的官方建议。
  • 要试 temperature:先确认你打算调用哪个模型,再决定看哪一份文件。这一点上 notebook 和 .py 给的是两套不同前提:前者预设你换了支持采样参数的模型,后者预设你用的是 reasoning 模型。按 README 的说法,把前者的参数发给后者会拿到「参数不支持」的报错。

有几个维度我没有依据,就不比:两种形态哪种学习效果更好、哪种上手更快、运行表现有无差异——仓库里没有这类结论,我们也没有跑过其中任何一份代码。这篇要说的只有一件事:它们停在不同的位置,装的内容不重合,选之前先知道自己缺的是过程还是终态。


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

本文对照的是同一项目内的两种用法,依据均为上述仓库内容,不对两种用法做优劣排名, 选型结论只在仓库文档写明的能力边界内成立。

安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。

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