微软生成式 AI 入门课的 Phi 加载失败:依赖、权重、设备三层排查
generative-ai-for-beginners 的第 19 课讲小语言模型,配套代码在 19-slm/python/ 下。这一课和前面多数课不一样:那些课是拿 endpoint 和 key 调云端接口,这一课的三个 notebook 是真的要把权重加载到本机。于是它也成了整个课程里最容易在第一格代码就卡住的一课。
卡住的位置几乎总是同一行——AutoModelForCausalLM.from_pretrained(...)。但同一行报错,背后可以是三件完全不同的事。下面按依赖、权重来源、设备这三层依次排查,每层都给出判定动作,以及”什么情况说明不是这一层”。
第一层:依赖根本没装
现象
在 19-slm/python/phi35-instruct-demo.ipynb 的第一格就红了:
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
ModuleNotFoundError: No module named 'torch'(或 transformers)。
怎么确认是这个问题
这一层的判定动作很直接:回头看你装的是什么。仓库根目录 00-course-setup/02-setup-local.md 给的本地安装步骤是
python -m venv .venv # make one
source .venv/bin/activate # macOS / Linux
.\.venv\Scripts\activate # Windows PowerShell
pip install -r requirements.txt
然后打开仓库根目录的 requirements.txt 数一下里面有什么:ipywidgets、numpy、matplotlib、pandas、tqdm、python-dotenv、openai、tiktoken、azure-ai-inference、scikit-learn。torch 和 transformers 都不在里面。 pyproject.toml 的 dependencies 同样只有 openai、python-dotenv、requests、azure-ai-inference、tiktoken 这几项。
也就是说,你严格照着安装文档做完,19-slm 这三个本地 notebook 第一格 import 的两个包依然要自己另外补。这不是你漏了哪一步,是这一课的依赖没有被课程级的依赖清单覆盖。19-slm/ 目录下也没有独立的 requirements.txt——这个目录里只有 README.md、img、python 三项。
仓库里给出的处置
真正的安装线索散落在 notebook 自己的单元格里。phi35_moe_demo.ipynb 开头有四格被注释掉的安装命令:
# pip install transformers
# pip install torch torchvision torchaudio -U
# pip install flash-attn --no-build-isolation
# ! pip install flash_attn -U
phi35-vision-demo.ipynb 里则有两格没被注释的:pip install transformers -U 和 pip install jinja2 -U,还有一格 # pip install opencv-python。注意 jinja2 那一格的位置——它排在 processor.tokenizer.apply_chat_template(...) 之前,chat template 的渲染要用到它。
以上命令均原样抄自仓库中对应的 notebook 单元格。该课程持续更新,请以仓库最新内容为准。
处置后怎么验证
在 notebook 里重跑第一格 import,不报错即通过。Windows 侧还有一个额外的坑值得先看一眼:00-course-setup/02-setup-local.md 末尾的故障排查表里,专门列了一行 “pip cannot build wheels (Windows)“,给的处置是 pip install --upgrade pip setuptools wheel 然后重试。flash-attn 这类需要本地编译的包在 Windows 上尤其容易撞到这条,遇到编译期报错先按这条走一遍。
什么情况说明不是这一层
如果 import 全部通过、报错发生在 from_pretrained 这一行,那依赖这层就翻篇了。报错信息里出现了路径、目录名或 repo id,说明问题在下一层。
第二层:权重根本不在那个位置
现象
import 没问题,但 from_pretrained 报路径不存在、或者说找不到 config.json。
怎么确认是这个问题
去看 notebook 里那个字符串到底指向哪。三个 notebook 用的都是本地相对路径,不是 Hugging Face 上的 repo id:
| notebook | 加载路径 |
|---|---|
19-slm/python/phi35-instruct-demo.ipynb | "../phi-3-instruct"(模型与 AutoTokenizer 都用它) |
19-slm/python/phi35-vision-demo.ipynb | model_id = "../Phi3Vision" |
19-slm/python/phi35_moe_demo.ipynb | model_id = "../Phi3MOE" |
notebook 位于 19-slm/python/,../ 上一级就是 19-slm/。所以这三行指的是 19-slm/phi-3-instruct、19-slm/Phi3Vision、19-slm/Phi3MOE。而前面数过了,19-slm/ 下只有 README.md、img、python——这三个目录在仓库里并不存在。
把这三个字符串在整个仓库里搜一遍,命中的只有这三个 notebook 自己,以及 translations/ 下各语言译本里的同名副本,再无别的出现;19-slm/README.md 里也没有给出把权重下载到这几个目录的命令。也就是说,“把权重放到这里”这一步,课程默认你自己完成,但没有写下来。判定动作因此很简单:在 19-slm/ 下看有没有同名目录、目录里有没有 config.json。 没有,就是这一层。
处置
两条路,都在仓库里有依据:
一是自己把对应权重放到 notebook 期望的位置,让 ../phi-3-instruct 这类相对路径成立;二是把字符串改成你自己的路径。Windows 下改路径记得用正斜杠或原始字符串(r"C:\models\..."),否则反斜杠会被当转义符吃掉——这是 Python 的通用写法,不是课程内容。
顺带说两个同属”来源”层的坑。phi35-vision-demo.ipynb 在加载模型之前有一段读图的代码:
images = []
placeholder = ""
for i in range(1,22):
with open("../output/keyframe_"+str(i)+".jpg", "rb") as f:
images.append(Image.open("../output/keyframe_"+str(i)+".jpg"))
placeholder += f"<|image_{i}|>\n"
这些 keyframe_*.jpg 由前面那格被注释掉的 save_keyframes(video_path, output_folder) 函数用 cv2 抽帧生成,调用行 # save_keyframes('../video/copilot.mp4', '../output') 同样是注释掉的。你不先把那两格解注释并准备好视频,这一格就会以 FileNotFoundError 告终,而这个报错看上去和模型毫无关系。
另一个是 trust_remote_code=True——三个 notebook 的 from_pretrained 全都带着它。它的语义是允许执行权重目录里附带的建模代码。所以”权重来源”在这里不只是路径问题:你指过去的那个目录里的代码是会被执行的。核对来源、只用你信得过的权重目录,属于通用安全做法,不是课程正文的内容;安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。
什么情况说明不是这一层
19-slm/ 下确实有对应目录、里面有 config.json,加载过程已经开始往下走(比如已经在读 checkpoint 分片)才失败——那问题在第三层。
第三层:设备参数与你的机器对不上
现象
路径没问题,报错发生在加载过程中,信息里出现 CUDA、device、dtype 这类字眼。
怎么确认是这个问题
把三个 notebook 的设备相关写法并排看一眼,会发现它们并不一致:
# phi35-instruct-demo.ipynb
model = AutoModelForCausalLM.from_pretrained(
"../phi-3-instruct",
device_map="cuda",
torch_dtype="auto",
trust_remote_code=True,
)
# phi35-vision-demo.ipynb
model = AutoModelForCausalLM.from_pretrained(model_id, device_map="cuda", trust_remote_code=True, torch_dtype="auto", _attn_implementation='flash_attention_2')
# phi35_moe_demo.ipynb
model = transformers.AutoModelForCausalLM.from_pretrained(
model_id,
trust_remote_code=True,
torch_dtype=bfloat16,
device_map='auto'
)
三处差异都是硬写死在代码里的:instruct 和 vision 写的是 device_map="cuda",MoE 写的是 device_map='auto';dtype 前两个是 torch_dtype="auto",MoE 是从 torch 导入的 bfloat16;vision 额外带了 _attn_implementation='flash_attention_2',另外两个没有。vision 的推理输入还有一行 .to("cuda:0"):
inputs = processor(prompt, images, return_tensors="pt").to("cuda:0")
判定动作:先确认这些字面量在你机器上成不成立。device_map="cuda" 与 "cuda:0" 是写死的,没有 GPU 或没有对应编号的设备时它们不会自己退化成 CPU。_attn_implementation='flash_attention_2' 要求相应实现可用,而它对应的安装命令在 MoE notebook 里是被注释掉的那两行 flash-attn。
19-slm/README.md 对这条路线的自述是:这是最常用的方法,但需要 GPU 加速;Vision 和 MoE 这类场景计算量大,不量化的话在 CPU 上会很慢。这是仓库文档自述,我们没有跑过,本文不涉及任何速度与资源占用的描述。
处置
改这三个字面量本身:device_map、torch_dtype、_attn_implementation 都是 from_pretrained 的入参,vision 那行的 .to("cuda:0") 也要跟着一起改,否则模型和输入会落在不同设备上。MoE notebook 里还有一格与设备相关的代码,位置在模型已经加载之后、调用 pipe(...) 之前:
import torch
torch.cuda.empty_cache()
import os
os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True "
这一格原样抄自仓库,字符串末尾那个空格也是原文里就有的。仓库没有解释为什么写在这个位置,本文也不替它解释。
以上为按仓库代码中的接口语义组合的示例,未经实测,以仓库最新代码为准。
处置后怎么验证
能走到生成那一步就算过了。三个 notebook 的 generation_args 写法也值得看一眼,instruct 与 MoE 都是:
generation_args = {
"max_new_tokens": 1024,
"return_full_text": False,
"temperature": 0.3,
"do_sample": False,
}
(MoE 那份把 max_new_tokens 写成了 512。以上均为仓库里的示例值,不是推荐配置。)vision 那份是 { "max_new_tokens": 1000, "temperature": 0.0, "do_sample": False, }。这里有个已经被仓库自己记录下来的矛盾:phi35-vision-demo.ipynb 保存的输出里,model.generate(...) 那格留着一条 transformers 的 UserWarning,原文说 do_sample 设为 False 时 temperature 只在采样模式下才起作用,建议设 do_sample=True 或者干脆不传 temperature。同一份文件里,参数和警告就摆在一起。
采样参数还有一层要交代:06-text-generation-apps/README.md 写明,Microsoft Foundry 上当前未废弃的是 reasoning 模型(GPT-5 家族、o 系列),它们不支持 temperature / top_p,也不支持 max_tokens(改用 max_output_tokens),传了会报参数不支持;该文同时写明 temperature / top_p 在 Llama、Mistral、Phi 以及 GPT-4.x 家族上仍然有效。所以本文这套本地 Phi 的写法不能原样搬到 Foundry 的 reasoning 模型上。
什么情况说明不是这一层
改完设备参数还是在同一位置报错,且报错内容始终指向文件或模块,那就回到前两层重查。还有一种情况和这三层都无关:这三个 notebook 的 metadata 里记录的 kernel 都是 “Python 3.8 - AzureML”、language_info.version 都是 3.9.19,而仓库 pyproject.toml 写的是 requires-python = ">=3.10"。这两处对不上是仓库里白纸黑字的事实,至于哪个版本能跑通,仓库没有说明,我们也不推断。
三层都排完还是不行
那就换路线。19-slm/README.md 里给了几条不需要本地加载权重的:ollama run phi3.5;Foundry Local 的 winget install Microsoft.FoundryLocal 加 foundry model run phi-3.5-mini(winget 这条对 Windows 读者正合适),或者 pip install foundry-local-sdk 之后用 FoundryLocalManager("phi-3.5-mini");再就是同目录下的 Phi-3-Vision-Nividia-NIM.ipynb,走 HTTP 调用,里面有一行值得注意的前置检查:
assert len(image_b64) < 180_000, \
"To upload larger images, use the assets API (see docs)"
这条断言是仓库代码里就有的,图片过大时它会先于请求失败。该 notebook 的 headers 里 key 写的是占位串,替换时请用 <YOUR_API_KEY> 这类方式管理,别把真实 key 提交进版本库。
另外提一句路线名称的事:00-course-setup/03-providers.md 逐字写明 GitHub Models 将于 2026 年 7 月底退役,直接替代者是 Microsoft Foundry Models。今天已经过了这个时间点,所以仓库里 githubmodels-* 这个文件名前缀已经和它实际接入的目标脱节,实际要配的是 Microsoft Foundry Models 的 endpoint 与 key。
本文依据 github.com/microsoft/generative-ai-for-beginners 仓库于 2026-08-18 的公开内容整理,
事实来自仓库内的课程正文与代码示例。我们没有跑过文中涉及的代码,
因此不涉及运行结果、耗时与生成质量的任何描述。
该课程持续更新,文中涉及的文件路径、依赖与接口写法随版本变动,请以仓库最新内容为准。
文中涉及的云端服务调用会产生费用并可能上传数据,请自行评估密钥与数据边界。