微软生成式 AI 入门课的 Phi 加载失败:依赖、权重、设备三层排查

2026-08-18
站内工具 AI 编程工具报错分诊器 → 把报错原文贴进去,先分清是网络、额度、配置还是上游故障,再决定往哪个方向查。

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 数一下里面有什么:ipywidgetsnumpymatplotlibpandastqdmpython-dotenvopenaitiktokenazure-ai-inferencescikit-learntorchtransformers 都不在里面。 pyproject.tomldependencies 同样只有 openaipython-dotenvrequestsazure-ai-inferencetiktoken 这几项。

也就是说,你严格照着安装文档做完,19-slm 这三个本地 notebook 第一格 import 的两个包依然要自己另外补。这不是你漏了哪一步,是这一课的依赖没有被课程级的依赖清单覆盖。19-slm/ 目录下也没有独立的 requirements.txt——这个目录里只有 README.mdimgpython 三项。

仓库里给出的处置

真正的安装线索散落在 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 -Upip 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.ipynbmodel_id = "../Phi3Vision"
19-slm/python/phi35_moe_demo.ipynbmodel_id = "../Phi3MOE"

notebook 位于 19-slm/python/../ 上一级就是 19-slm/。所以这三行指的是 19-slm/phi-3-instruct19-slm/Phi3Vision19-slm/Phi3MOE。而前面数过了,19-slm/ 下只有 README.mdimgpython——这三个目录在仓库里并不存在

把这三个字符串在整个仓库里搜一遍,命中的只有这三个 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_maptorch_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 设为 Falsetemperature 只在采样模式下才起作用,建议设 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.FoundryLocalfoundry model run phi-3.5-miniwinget 这条对 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 的公开内容整理, 事实来自仓库内的课程正文与代码示例。我们没有跑过文中涉及的代码, 因此不涉及运行结果、耗时与生成质量的任何描述。 该课程持续更新,文中涉及的文件路径、依赖与接口写法随版本变动,请以仓库最新内容为准。 文中涉及的云端服务调用会产生费用并可能上传数据,请自行评估密钥与数据边界。

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