第 0 章:Python 环境与快速入门
本章面向有 JavaScript/TypeScript 经验但不熟悉 Python 的读者。如果你已经能熟练用
pip装包、用conda切环境,扫一眼 0.1 节的双环境策略,然后跳到 0.6 节语法速查就够了。
LLM 生态几乎所有底层工具——PyTorch(Meta 开源的深度学习框架,AI/ML 事实标准,0.4 节会详细讲)、Transformers(HuggingFace 出的加载/运行预训练模型的标准库)、vLLM(UC Berkeley 出的工业级 LLM 推理引擎)、DeepSpeed(微软出的分布式训练加速库)——都是 Python 写的。绕不开。本章用最短篇幅把环境搭好,重点解释为什么这么搭,避免你在工具选型上反复折腾。
几个名字先备案:上一段提到的库后面章节会反复出现,这里先一句话定位,遇到时不至于一头雾水。Transformers 是 HuggingFace(业界的”模型 GitHub”,托管几十万开源模型)开源的 Python 库,几行代码就能加载 BERT、Llama 这类模型。vLLM 是高吞吐 LLM 推理引擎,第 5 章会专门拆。DeepSpeed 是大模型分布式训练库,第 11 章用到。TensorRT-LLM 是 NVIDIA 自家的推理引擎,第 6 章对比时会出现。
0.1 本书的双环境策略:本地 Mac + GPU 服务器
本书的目标读者画像里,绝大多数人手上是这两台机器:
- 一台 Mac(多半是 Apple Silicon,M1/M2/M3/M4 系列)作为日常开发机
- 一台 Linux GPU 服务器(自己的工作站、公司机房,或临时按小时租的阿里云/腾讯云/AutoDL 实例)
两台机器分工很清楚,不要在一台上硬扛所有事:
CUDA 是什么:表格里会反复出现这个词,先一句话讲清楚。CUDA(Compute Unified Device Architecture)是 NVIDIA 在 2006 年推出的 GPU 编程平台,可以理解成 NVIDIA GPU 的”操作系统 API”——PyTorch、vLLM 等 AI 框架通过它调度 GPU 算力,就像 Node.js 通过 libuv 调度 I/O。它是 NVIDIA 专有的,只能跑在 NVIDIA 显卡上。Apple Silicon 的 GPU 用的是另一套叫 MPS(Metal Performance Shaders)的体系,两边互不兼容,所以 vLLM 这类只依赖 CUDA 的工具 Mac 上跑不了。
| 任务 | 推荐环境 | 原因 |
|---|---|---|
| 阅读本书、做笔记 | 本地 Mac | 不需要解释 |
| 第 1-4 章的基础实验(Tokenizer 分词器、Attention 注意力机制拆解、小模型 demo) | 本地 Mac | 7B(70 亿参数,B 是 Billion)以下用 CPU/MPS 能跑,无需开服务器 |
| 跑 vLLM、TensorRT-LLM(第 5、6 章) | GPU 服务器 | vLLM 只支持 NVIDIA CUDA,Mac 跑不了 |
| 量化、推理加速实验(第 7、8 章) | GPU 服务器 | 多数算子需要 CUDA 支持 |
| 微调、RLHF(Reinforcement Learning from Human Feedback,用人类反馈做强化学习对齐)、分布式训练(第 9-11 章) | GPU 服务器 | 显存和算力要求都不是 Mac 能扛的 |
| 生产部署演练(第 12 章) | GPU 服务器 + 容器 | 模拟真实部署环境 |
| 写代码、读源码、做架构图 | 本地 Mac | IDE 体验最好 |
推荐工作模式:在 Mac 上用 IDE 写代码,通过 SSH(Secure Shell,远程登录服务器的加密协议,等价于 JS 工程师常用的命令行那个 ssh)把代码同步到 GPU 服务器上跑。具体怎么搭见 0.5 节。
术语速读:上表的标题列出现了几个高频词,集中先备案一下。Tokenizer(分词器)是把文字切成模型能吃的最小单位(token)的工具,第 2 章会拆。Attention(注意力机制)是 Transformer 架构的核心算子,决定模型怎么”理解上下文”。7B / 13B / 70B 里的 B 指 Billion(十亿),表示模型参数量级。Transformer 是 Google 2017 年论文《Attention Is All You Need》提出的网络架构,是所有现代 LLM 的骨架。
全书约定:后续章节凡是涉及环境相关命令,都会用下面这种格式标注:
Mac 本地:
# 给 Mac 的命令Linux GPU 服务器:
# 给 Linux 的命令
如果某条命令两边一样,就只写一份不重复。
0.2 为什么 Python 工具链看起来这么乱
第一次接触 Python 的 JS 工程师常被这样一个事实劝退:解决”装一个包”这件事,Python 社区给了你十几个工具。
版本管理: pyenv、conda、asdf、官方安装器
虚拟环境: venv、virtualenv、conda env、pipenv
包管理: pip、uv、poetry、pdm、pipenv、conda
项目元数据: requirements.txt、Pipfile、pyproject.toml、setup.py名词卡:上面的工具集中介绍一下,看不懂没关系,本书只会用 conda 和 pip 两个。pip(Python Install Package)是 Python 官方的包管理器,相当于
npm。venv 是 Python 3.3+ 自带的虚拟环境模块,等价于隔离的node_modules。virtualenv 是 venv 出现前的第三方实现,至今还在用。conda 是 Anaconda 公司推出的”环境管理 + 包管理”二合一工具,能管 Python 解释器版本本身。pyenv 是只管 Python 版本的工具,类似nvm。asdf 是跨语言的版本管理器(一个 asdf 能管 Node、Python、Ruby 多种语言)。poetry / pdm / pipenv 是更现代的项目管理工具,类似pnpm + package.json。pyproject.toml 是 PEP 518 引入的新一代项目元数据文件,意图替代老旧的setup.py。
Node 这边对应的只有 nvm + npm/pnpm + package.json 三件套,分工清晰。Python 工具多是历史原因——语言比 npm 早出生十几年,每代工程师都试图修一遍前一代的痛点,但旧工具又没有完全淘汰。
把这些工具按职责分三层:
| 职责 | 是什么 | 类比 Node |
|---|---|---|
| Python 解释器版本管理 | 决定项目用 Python 3.9 还是 3.11 | nvm |
| 虚拟环境隔离 | 让每个项目有独立的依赖目录,互不污染 | node_modules |
| 包安装与依赖管理 | 装第三方库、记录版本 | npm install |
Python 的”乱”主要在于:很多工具同时干多层活,又不互相兼容。
本书选定的组合,三层职责落到 conda 和 pip 两个工具上,关系如下:
conda 负责”装哪版 Python + 隔离环境”,pip 负责”在这个环境里装具体的包”,两者分工不重叠。
我们的选择:Miniconda + pip
本书统一用 Miniconda 管 Python 版本和虚拟环境,用 pip 装包。理由:
- CUDA 兼容性。LLM 训练/推理离不开 CUDA、cuDNN(CUDA Deep Neural Network library,NVIDIA 在 CUDA 之上专门给神经网络做的加速库,卷积、池化这些算子的底层实现)、NCCL(NVIDIA Collective Communications Library,多 GPU 之间高效通信用,第 11 章分布式训练核心依赖)这些 GPU 库。pyenv/venv 装的是纯 Python,遇到 CUDA 版本错位时排查很痛苦。conda 能把 Python 解释器 + CUDA Runtime(运行 CUDA 程序所需的动态链接库,跟显卡驱动里的 CUDA Driver 是两层东西)一起装到环境里,切换干净。
- 生态默认。PyTorch、HuggingFace(业界最大的开源模型托管平台,相当于”模型版 GitHub”)、NVIDIA 的官方安装文档基本都给 conda 命令,社区博客也是。跟着主流走,遇到问题搜得到答案。
- 跨平台一致。Mac 和 Linux 上用同一套命令,本地学到的东西能直接迁移到服务器。
- 学习成本低。一个工具学会就够用,不用先理解
pyenv + pipx + poetry + pyenv-virtualenv这套四件套的协作方式。
什么时候不用 conda?
- 在 Docker 镜像里:用系统 Python + venv 更轻,conda 会让镜像膨胀 1-2 GB。
- 纯 Web 后端(FastAPI 是 Python 主流异步 Web 框架,类似 Node 的 Fastify;Django 是老牌全栈 Web 框架),没 GPU 依赖:用
uv或poetry更现代。 - 你已经有一套熟练的工具链:保持不变,本书命令都能映射过去。
关于
uv:这是 Astral(开发 ruff 的团队,ruff 是 Rust 实现的 Python lint + 格式化工具,相当于 ESLint + Prettier 二合一)2024 年推出的 Rust 实现的包管理器,装包速度比 pip 快 10-100 倍,正在快速取代 pip + venv。如果只做应用层开发非常推荐。但目前 PyTorch GPU wheel(Python 二进制包格式,.whl文件,相当于预编译的.tar.gz)、vLLM 的安装教程还在以 pip/conda 为主,跨工具操作时容易出问题,所以本书先用 pip。等你环境稳定了,可以试试用uv pip install替换pip install,多数情况下完全兼容。
0.3 Node.js 视角下的对照表
下面这张表只列本书会用到的工具,方便建立直觉:
| 你熟悉的 (Node.js) | Python 等价物 | 备注 |
|---|---|---|
nvm use 18 | conda activate llm-infra | 切环境,包含 Python 版本和所有依赖 |
npm install xxx | pip install xxx | 装包到当前激活的环境里 |
package.json | requirements.txt 或 pyproject.toml | 记录依赖;本书用前者 |
package-lock.json | pip freeze > requirements.txt 的输出 | 锁定版本 |
node_modules/ | ~/miniconda3/envs/<name>/lib/python3.10/site-packages/ | 实际包文件放这里 |
npx <cmd> | 激活环境后直接 <cmd> | conda 把可执行文件加到 PATH |
| TypeScript | Type Hints + mypy 检查 | mypy 是 Python 官方推的静态类型检查器;类型注解运行时不强制 |
| ESLint + Prettier | ruff (一个工具搞定 lint + format) | ruff 已在上文出现,是新一代 Python 代码检查/格式化工具 |
| Jest / Vitest | pytest | 测试框架 |
process.env.X | os.environ["X"] 或 os.getenv("X") | 读环境变量 |
0.4 安装步骤
下面的步骤两台机器都要走一遍。命令一样的只写一份,不一样的分 Mac / Linux 两栏并列。
第 1 步:先确认硬件情况
Mac 本地:
# 查芯片型号(确认是 Apple Silicon 还是 Intel)
system_profiler SPDisplaysDataType | grep "Chipset Model"Apple Silicon(M1/M2/M3/M4)会输出 Apple M*,Intel Mac 会显示具体的 Intel/AMD 显卡型号。本书假设你是 Apple Silicon。Intel Mac 把它当成”普通 Linux x86 但没 NVIDIA GPU”处理即可。
Linux GPU 服务器:
# 查 NVIDIA GPU 和驱动
# 输出右上角的 "CUDA Version: 12.x" 是驱动支持的最高 CUDA 版本
nvidia-smi如果 nvidia-smi: command not found,说明你买的机器没有 NVIDIA GPU(可能是 CPU 实例),或者镜像没装驱动。云服务器要换 GPU 镜像;自己的机器装驱动:
# Ubuntu/Debian 装驱动(云镜像通常已经装好了,本地工作站才需要这步)
sudo ubuntu-drivers autoinstall
sudo reboot第 2 步:装 Miniconda
Miniconda 是 Anaconda 的精简版——不带预装的 200 多个数据科学包,只装 conda 工具本身和最小 Python。本书选 Miniconda,不选 Anaconda,因为大包预装会让磁盘膨胀 3 GB+,而我们要装的 PyTorch、vLLM 都自己装更可控。
Mac 本地(Apple Silicon):
# 一定要用 arm64 版本!装错成 x86_64 会走 Rosetta 翻译,性能腰斩
curl -O https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh
bash Miniconda3-latest-MacOSX-arm64.sh如果是 Intel Mac,把 arm64 换成 x86_64。
Linux GPU 服务器:
# 多数云 GPU 实例是 x86_64
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.shARM Linux 实例(比如 AWS Graviton、阿里云倚天,都是基于 ARM 架构的服务器 CPU,区别于 x86 阵营的 Intel/AMD)把 URL 里的 x86_64 换成 aarch64(ARM 64 位指令集的标准名称)。
两边公共的部分:
# 安装过程中:
# 一路按回车看协议 → 输入 yes 接受 → 默认装在 ~/miniconda3
# 最后一步问"是否初始化 conda?" → 选 yes
# 它会往 ~/.bashrc 或 ~/.zshrc 写入初始化代码
# 让 conda 命令立刻可用(不想重开终端的话)
source ~/miniconda3/bin/activate
# 验证:应该输出 conda 24.x 之类
conda --version第 3 步:创建项目专属环境
这一步两边命令完全一样:
# 创建一个名为 llm-infra 的环境,Python 版本固定为 3.10
# -y 表示遇到确认提示直接 yes,省一次回车
conda create -n llm-infra python=3.10 -y
# 激活这个环境
# 激活后终端提示符前面会多一个 (llm-infra) 标识
conda activate llm-infra
# 现在 python、pip 都指向这个环境里的版本
# 验证:路径里应该包含 envs/llm-infra
which python
which pip为什么固定 3.10 这个版本?
- PyTorch / vLLM / Transformers 的稳定兼容版本。3.11、3.12 也支持,但部分第三方包(比如老一点的训练框架)的 wheel 可能还没更新到最新 Python。3.10 是社区文档里最稳的”最大公约数”。
- 不要用 3.9 及以下,类型注解语法(
list[int]而不是List[int])从 3.9 才能用,本书示例需要 3.10+。
环境管理常用命令:
conda activate <环境名> # 切换到某个环境
conda deactivate # 退到 base(conda 的默认环境)
conda env list # 列出所有环境
conda env remove -n <名> # 删除某个环境第 4 步:装 PyTorch
先搞清楚 PyTorch 是什么
PyTorch 是本书最重要的一个依赖——所有模型、训练、推理代码都基于它。装之前先用一段话把它讲清楚,避免后面看代码时一直在心里打问号。
一句话定位:PyTorch 是 Meta(Facebook 母公司)在 2016 年开源的深度学习框架,2026 年的今天是 AI/ML(Artificial Intelligence / Machine Learning,人工智能 / 机器学习)领域事实标准。PyTorch 之于 AI 工程 ≈ Node.js 之于 JS 服务端——你看到的 LLM 模型、训练代码、推理引擎,底层默认都是它。HuggingFace Transformers、vLLM、DeepSpeed、Llama(Meta 开源的 LLM 系列,本书后续会反复拿来当实验对象)系列模型,全是 PyTorch 写的。
它解决的三件事:
- 跨硬件的数值计算。核心数据结构叫 Tensor(张量,可以理解成多维数组:标量是 0 维、向量是 1 维、矩阵是 2 维、再往上就是 n 维 Tensor),可以理解成「numpy(NumPy,Python 数值计算基础库,提供
ndarray多维数组类型)数组 + GPU 加速」。同一份代码不改逻辑就能在 CPU、NVIDIA GPU(CUDA 后端)、Apple Silicon(MPS 后端)、AMD GPU(ROCm 后端,AMD 自家对标 CUDA 的 GPU 计算平台)上跑,差别只在创建 Tensor 时指定device="cuda"还是device="mps" - 自动求导(autograd,automatic differentiation 的简写,深度学习框架的核心特性)。训练神经网络的本质是「定义一个损失函数(loss function,衡量预测值与真实值差距的标量),沿梯度反方向调整参数」。手算梯度对工业级模型完全不现实,PyTorch 在你做运算的同时自动记录计算图,调一次
loss.backward()就把所有参数的梯度算出来 - 神经网络组件库。
torch.nn里有Linear(全连接层)、LayerNorm(层归一化)、MultiheadAttention(多头注意力,Transformer 核心模块)这种现成的层,torch.optim里有 Adam(自适应学习率优化器,最常用的默认选择)、SGD(Stochastic Gradient Descent,随机梯度下降)这些优化器。搭一个 Transformer 不用从矩阵乘法开始写
为什么不是 TensorFlow(Google 2015 年开源的深度学习框架,PyTorch 出现前的主流选择)?早年两家是双雄,PyTorch 因为”写起来像普通 Python、调试用 print 就行”(叫动态图 / Define-by-Run,运行时即时构建计算图;对比 TensorFlow 早期的”静态图 / Define-and-Run”,先编译整个图再喂数据),在研究圈先赢了,工业界跟着迁过来。到 2026 年 TensorFlow 主要还活跃在 Google 内部和部分老项目,新代码基本都是 PyTorch。
JS 工程师视角:你不需要立刻理解”自动求导”具体怎么实现,就像你刚学 Node.js 时不需要先懂 V8(Google 的 JavaScript 引擎,Node.js 的执行核心)。本章你只要知道三件事:PyTorch 是装在 Python 环境里的一个库;它需要根据你的硬件装对应版本(这就是下面这一步的难点);用
torch.cuda.is_available()/torch.backends.mps.is_available()验证 GPU 后端是否可用。深度用法跟着第 2-3 章的实验慢慢长出来。
安装
这一步两边命令完全不同:Mac 用 MPS 后端,Linux 用 CUDA 后端。
Mac 本地(Apple Silicon):
# Apple Silicon 直接装默认版本即可
# PyTorch 自带 MPS 后端,会用 M 系列芯片的 GPU 加速
# 不要加 --index-url,那是给 NVIDIA 装 CUDA 版用的
pip install torchMac 本地(Intel Mac,没 GPU):
# 只能用 CPU 后端
pip install torchLinux GPU 服务器:
选哪个 CUDA 版本不确定?用官方选择器:pytorch.org/get-started/locally,根据 OS、CUDA 版本、包管理器选好后直接复制下面给出的命令。
# 先看第 1 步 nvidia-smi 输出的 CUDA Version
# 装 PyTorch 时选等于或低于这个数字的版本
# 官方目前提供 cu118、cu121、cu124 三档预编译
# CUDA 12.1(最常用,4090/A100 主流驱动都支持)
pip install torch --index-url https://download.pytorch.org/whl/cu121
# CUDA 11.8(老一点的驱动)
pip install torch --index-url https://download.pytorch.org/whl/cu118
# CUDA 12.4(最新驱动)
pip install torch --index-url https://download.pytorch.org/whl/cu124为什么 Linux 必须加 --index-url?
默认 PyPI(Python Package Index,Python 官方包仓库,相当于 npmjs.com)源上的 torch 包不含 CUDA。如果你的项目要用 GPU,必须从 PyTorch 自己的 wheel 仓库下载特定版本,文件名里会带 +cu121 这样的标识。这一步装错后面所有 GPU 代码都会报 CUDA is not available,到时候排查很费时间,第一次就装对很重要。
Mac 上则相反,PyPI 默认的就是带 MPS 的版本,加 --index-url 反而会装错。
国内网络加速:服务器拉取 PyTorch wheel 慢的话,试上交镜像:
pip install torch --index-url https://mirror.sjtu.edu.cn/pytorch-wheels/cu121。Mac 本地用清华源应急:pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple。
顺手装上 numpy
pip install numpyPyTorch 2.x 已经不再把 numpy 当成硬依赖(早期版本会自动一起装上)。但下一步的 verify.py 一跑起来,PyTorch 内部仍会尝试 import numpy,没装就会抛一条 Failed to initialize NumPy 的 warning。本书后续大量做 Tensor ↔ ndarray(numpy 的多维数组类型)互转、读 CSV(Comma-Separated Values,逗号分隔的纯文本表格格式)、可视化,numpy 是绕不开的,现在一行命令装上一劳永逸。
第 5 步:验证安装
下面这段脚本同时支持 CUDA 和 MPS,存成 verify.py 在两台机器上都跑一遍:
import torch
import platform
print(f"OS: {platform.system()} {platform.release()}")
print(f"Python: {platform.python_version()}")
print(f"PyTorch: {torch.__version__}")
# 检测可用的 GPU 后端
# torch.cuda.is_available() → NVIDIA GPU(Linux/Windows)
# torch.backends.mps.is_available() → Apple Silicon GPU
if torch.cuda.is_available():
device = torch.device("cuda")
print(f"Backend: CUDA {torch.version.cuda}")
print(f"GPU: {torch.cuda.get_device_name(0)}")
# total_memory 单位是字节,除两次 1024 拿到 GB
# VRAM = Video RAM,显存,GPU 上的高带宽专用内存,跟系统 RAM 是两套独立空间
vram_gb = torch.cuda.get_device_properties(0).total_memory / 1024**3
print(f"VRAM: {vram_gb:.1f} GB")
elif torch.backends.mps.is_available():
device = torch.device("mps")
print(f"Backend: MPS (Apple Silicon GPU)")
else:
device = torch.device("cpu")
print(f"Backend: CPU only")
# 跑一个最小张量运算,确认计算后端正常
# 张量 (tensor) 是 PyTorch 里的基本数据结构,类似 numpy 数组
x = torch.randn(3, 3, device=device)
print(f"\n{device} 上的张量加法:\n{x + x}")Mac 本地的预期输出:
OS: Darwin 24.x
Python: 3.10.13
PyTorch: 2.4.x
Backend: MPS (Apple Silicon GPU)Linux GPU 服务器的预期输出:
OS: Linux 5.15.0
Python: 3.10.13
PyTorch: 2.3.1+cu121
Backend: CUDA 12.1
GPU: NVIDIA GeForce RTX 4090
VRAM: 23.6 GB如果 Linux 上 CUDA available: False,回到第 4 步检查是否装错了 wheel。
第 6 步:装本书后续会用到的核心库
这一步两边命令一样:
# 一次装齐:数值计算基础 + HuggingFace 全家桶 + 工具
# numpy: 数值计算基础库,跟 Tensor 互转、数据预处理都靠它
# PyTorch 2.x 不再硬依赖 numpy,必须自己装
# transformers: 加载/运行 LLM 的标准库,文档:https://huggingface.co/docs/transformers
# accelerate: HuggingFace 出的多 GPU / 混合精度封装库,几行代码切单机/分布式
# datasets: HuggingFace 出的数据集加载库(微调章节会用,自带流式读取和缓存)
# sentencepiece: Google 出的 subword tokenizer 实现,Llama 等模型用它做分词
# protobuf: Google 出的二进制序列化格式(Protocol Buffers),有些老模型权重用它存
pip install numpy transformers accelerate datasets sentencepiece protobuf
# Jupyter(可选,但强烈推荐)
# Jupyter 是数据科学界事实标准的交互式编程环境
# 起源于 IPython(Interactive Python,加强版的 Python REPL)
# 核心概念:notebook 是 .ipynb 格式的 JSON 文件,按"单元格"组织代码 + Markdown + 输出
# jupyter: notebook 前端(网页 UI + .ipynb 文件格式)
# ipykernel: 执行 Python 代码的后端进程("kernel")
# Jupyter 是前后端分离架构:前端展示,kernel 真正跑代码
pip install jupyter ipykernel
# 把当前 conda 环境注册成一个可选 kernel
# 不跑这一步:notebook 默认用系统 Python,import torch 会报 ModuleNotFoundError
# 跑了之后:在 VS Code / Cursor 打开 .ipynb 时,右上角能选到 "Python (llm-infra)"
python -m ipykernel install --user --name llm-infra --display-name "Python (llm-infra)"给 JS 工程师:一个 kernel ≈ 一个独立的 Python 运行时实例,类似
nvm里的某个 Node 版本。ipykernel install --name xxx类似nvm alias xxx—— 把当前环境登记成 Jupyter 可见的一个选项。以后给每个新建 conda 环境都跑一次这条命令,就能在不同环境之间快速切换,不用反复装包。
Linux GPU 服务器额外推荐:
# nvitop:进程级 GPU 监控工具,类似交互版的 `top` 但专门看 GPU
# 显示每个进程占用多少显存、GPU 使用率、温度
# 项目主页:https://github.com/XuehaiPan/nvitop
pip install nvitop跑训练或推理时,开一个终端执行 nvitop 看着,比反复 watch nvidia-smi 直观得多。
0.5 远程开发:在 Mac 上写代码,在 Linux 上跑
绝大多数读者会用这个工作流:日常坐在 Mac 前面写代码、读源码,但代码实际在 Linux GPU 服务器上跑。下面是几种主流方式,按推荐程度排序。
方式 A:VS Code Remote-SSH / Cursor SSH(首选)
VS Code(微软出的开源跨平台代码编辑器,前端工程师常用)装一个官方扩展 Remote - SSH(Cursor 是基于 VS Code 二次开发的 AI IDE,内置类似功能),就能直接打开远程服务器上的目录,体验和本地几乎没差别——文件树、终端、调试、Jupyter 全部走 SSH 通道,但 IDE 界面跑在本地。
# 1. 在 Mac 本地配置 SSH key(如果还没配)
# ssh-keygen 是生成密钥对的工具,ed25519 是当前最推荐的非对称加密算法(比老的 RSA 更短更快)
ssh-keygen -t ed25519 -C "[email protected]"
# 一路回车,默认存在 ~/.ssh/id_ed25519
# 2. 把公钥拷到 GPU 服务器
ssh-copy-id [email protected]
# 之后 ssh 就不用每次输密码了
# 3. 在 ~/.ssh/config 加一个别名(可选但强烈推荐)
cat >> ~/.ssh/config <<EOF
Host gpu
HostName your-gpu-server.com
User ubuntu
IdentityFile ~/.ssh/id_ed25519
ServerAliveInterval 60
EOF
# 4. 测试连接:以后输 ssh gpu 就够了
ssh gpu在 VS Code/Cursor 里:Cmd+Shift+P → Remote-SSH: Connect to Host → 选 gpu → 新窗口里打开远程目录。所有 pip install、python xxx.py、Jupyter Notebook 都在远程执行。
方式 B:直接 SSH + tmux + vim/nano
最轻量,不需要 IDE。适合临时改个配置、跑个脚本。先解释三个名字:tmux(Terminal Multiplexer)是终端多路复用器,让一个 SSH 连接里跑多个独立会话且断连不丢;vim 是 UNIX 老牌模态编辑器,键位陡峭但极轻量;nano 是更简单的终端编辑器,新手友好。
ssh gpu
tmux new -s work # 创建一个会话,断网也不会丢
# 在 tmux 里干活
# Ctrl+B 然后按 D 退出但保留会话
tmux attach -t work # 下次回来恢复为什么用 tmux?SSH 一断你跑的训练就 GG,tmux 让进程在服务器上一直跑,你随时连进去看进度。
方式 C:Jupyter Notebook 远程访问
适合做可视化实验:
# 在服务器上启动 Jupyter
ssh gpu
conda activate llm-infra
jupyter notebook --no-browser --port=8888
# 在 Mac 本地新开终端,做端口转发
ssh -L 8888:localhost:8888 gpu
# 在 Mac 浏览器打开 http://localhost:8888
# 用服务器输出的 token 登录方式 D:rsync 同步代码(不推荐作为主力)
只在没法用 VS Code Remote 时用。rsync 是 UNIX 经典的增量文件同步工具,只传送变化的部分,比 scp 全量拷贝高效得多:
# 把本地目录同步到服务器
# --exclude 跳过不需要传的大目录
rsync -avz --exclude='.git' --exclude='__pycache__' --exclude='*.pyc' \
./ gpu:~/llm-infra-book/频繁修改时手动 rsync 很烦,远不如 Remote-SSH 流畅。
文件传输小命令
scp(Secure Copy)是基于 SSH 协议的文件拷贝命令,命令行参数和 cp 几乎一致:
# 从本地传到服务器
scp local-file.py gpu:~/
# 从服务器拉回本地
scp gpu:~/results/output.png ./
# 大目录递归
scp -r ./dataset/ gpu:~/data/0.6 给 JS/TS 工程师的 Python 语法速查
只列真正会用到、并且和 JS 差异大的部分。完整教程请参考 Python 官方文档(中文)。
基本类型与运算
# 不需要 const/let/var,直接赋值
x = 42 # int
y = 3.14 # float
name = "递归客" # str(注意:双引号和单引号等价,没有模板字符串那种区分)
ok = True # bool(首字母大写!不是 true)
nothing = None # 等价于 JS 的 null(也不是 undefined)
# f-string(等价于 JS 的模板字符串)
print(f"Hello, {name}! Age: {x + 1}")
# 类型注解(运行时不强制,给 IDE 和 mypy 看)
age: int = 25
names: list[str] = ["Alice", "Bob"]容器:list / dict / tuple
# list ≈ JS Array
fruits = ["apple", "banana", "cherry"]
fruits.append("date") # 类似 push
fruits[0] # 索引访问
fruits[-1] # 负索引:从末尾数(JS 没有,要用 .at(-1))
fruits[1:3] # 切片:返回 ["banana", "cherry"],左闭右开
# dict ≈ JS Object(但 key 可以是任意 hashable 类型,不仅是字符串)
user = {"name": "Alice", "age": 30}
user["name"] # 取值(不能用点号语法)
user.get("email", "N/A") # 带默认值的取值,避免 KeyError
# tuple:不可变的 list,常用于函数返回多个值
point = (1, 2)
x, y = point # 解构,类似 JS 的 [x, y] = arr控制流
# 缩进决定代码块,没有花括号
# 强制 4 空格缩进(PEP 8,Python Enhancement Proposal 第 8 号,社区官方代码风格指南)
if x > 0:
print("positive")
elif x < 0:
print("negative")
else:
print("zero")
# for 永远是 for-of 风格,没有 C 风格的 for(i=0;...)
for fruit in fruits:
print(fruit)
# 要拿索引用 enumerate
for i, fruit in enumerate(fruits):
print(f"{i}: {fruit}")
# 范围循环
for i in range(10): # 0 到 9
print(i)函数
# 定义:def 关键字,参数和返回值类型注解可选
def greet(name: str, age: int = 18) -> str:
return f"Hello {name}, you are {age}"
greet("Alice") # 用默认 age
greet("Bob", age=25) # 命名参数(JS 没有,要靠对象传参模拟)
# Lambda ≈ JS 箭头函数,但只能写一个表达式
square = lambda x: x * x
# 可变参数
def total(*args, **kwargs):
# args 是 tuple,kwargs(keyword arguments,关键字参数)是 dict
# 等价于 JS 的 ...rest 和 ...options
print(args, kwargs)异步
import asyncio
# asyncio 是 Python 标准库里的异步 I/O 框架,对应 Node 的 event loop + Promise
# async def 定义协程(coroutine,可被挂起和恢复的函数对象,await 的实际目标)
async def fetch_data():
await asyncio.sleep(1)
return "data"
# 顶层 await 不能直接用,要 asyncio.run 启动事件循环
# 等价于 Node 早期版本没有顶层 await 的情况
result = asyncio.run(fetch_data())错误处理
try:
risky()
except ValueError as e:
# 类似 JS 的 catch(e),但要指定异常类型
print(f"value error: {e}")
except (KeyError, IndexError) as e:
# 多种异常类型用 tuple 列出
print(f"lookup failed: {e}")
finally:
cleanup()模块导入
# 整体导入
import torch
torch.zeros(3)
# 按需导入(更常用)
# AutoTokenizer / AutoModel 是 transformers 的"工厂类",
# 根据模型名自动选对应实现,免去手动判断模型架构
from transformers import AutoTokenizer, AutoModel
# 改名(处理冲突或简写)
import numpy as np # 社区默认别名容易踩的坑
- 缩进必须一致。混用 tab 和空格会报
IndentationError。VS Code 默认配置就行,不用折腾。 - True / False / None 首字母大写。写成
true直接语法错误。 ==比较值,is比较引用。判断 None 要用if x is None,不要用==。- 可变默认参数是坑。
def f(items=[]):这种写法所有调用共享同一个 list,绝对不要写。要用def f(items=None):+if items is None: items = []。 - 没有
null这个词。所有”空”都是None。
0.7 IDE 推荐
| 工具 | 适合谁 | 备注 |
|---|---|---|
| Cursor | 想要 AI 辅助 | 基于 VS Code,内置 Claude/GPT,写 Python 提速明显,Remote-SSH 内置 |
| VS Code + Python 扩展 | 大部分人 | 最接近 JS 工程师熟悉的体验,免费,社区生态强 |
| PyCharm Community | 重度 Python 项目 | JetBrains 出的 Python IDE 社区免费版,重构和调试体验是行业标杆,启动慢一点 |
| Jupyter Notebook | 实验和数据可视化 | 必备,跑模型时方便看中间结果 |
VS Code / Cursor 推荐扩展(安装后自动启用):
ms-python.python— Python 语言支持ms-python.vscode-pylance— 类型检查和补全(Pylance 是微软出的 Python 语言服务器,基于 Pyright)charliermarsh.ruff— Lint + 格式化(替代老的 black 格式化器 + flake8 lint 工具组合)ms-toolsai.jupyter— 在 IDE 里直接跑 .ipynb 文件ms-vscode-remote.remote-ssh— Remote-SSH(Cursor 已内置)
打开项目目录后,VS Code/Cursor 右下角会让你选 Python Interpreter,选刚才创建的 llm-infra 那个(路径里带 envs/llm-infra/bin/python)。选对之后,所有 import、运行、调试都会用这个环境。
0.8 一份 checklist
两台机器都过一遍,确认下面这些都能跑通,再进入第 1 章:
Mac 本地:
-
conda activate llm-infra能切换到环境 -
which python输出的路径在envs/llm-infra下 -
python -c "import torch; print(torch.__version__)"能输出版本号 -
python -c "import torch; print(torch.backends.mps.is_available())"输出True -
python -c "from transformers import AutoTokenizer"不报错 - Cursor / VS Code 打开 .py 文件能正确识别
llm-infra解释器
Linux GPU 服务器:
-
ssh gpu不用输密码能登上 -
nvidia-smi显示 GPU 信息 -
conda activate llm-infra能切环境 -
python -c "import torch; print(torch.cuda.is_available())"输出True - 从 Mac 用 Remote-SSH 能打开服务器目录、跑 Jupyter Cell
两台机器都过了,环境就绪。下一章我们从一次 LLM API 调用的完整链路讲起,把”应用层 → Infra 层”的整张地图铺开。
本章来自《LLM Infra 从入门到实践》开源版 · 作者「递归客」
在线阅读完整书系:inferloop.dev
源码仓库:github.com/diguike/book-llm-infra
本书资源
- 源码仓库 · github.com/diguike/book-llm-infra
- 在线阅读 · inferloop.dev/llm-infra
- 所有书目 · inferloop.dev
继续阅读 · 同作者其他书
- 《Transformer 工程实战》从注意力机制到生产部署
- 《自己动手写 AI Agent》从 Claude Code 开源架构到你的第一个编程助手
- 《AI 时代的 CLI 工具开发实战》用 TypeScript 构建现代 CLI 工具
- 《Hermes Agent 实战》构建会成长的个人 AI Agent
- 《OpenClaw 源码解析》现代 Agent 系统的架构设计与工程实践
- 《Agent Memory 工程实战》从 claude-mem 源码到企业级记忆平台
- 《AI Token 中转站实战》从 0 搭建企业级 LLM 网关
- 《LangChain.js Agent 开发权威指南》从 1.x 抽象到生产级 Agent
- 《百万级 AI Agent 平台架构》智能客服 SaaS 实战
- 《AI Agent 评测工程实战》从 0 用 TypeScript 构建你的评测平台
- 《源码精读》每章一个开源仓库 · 从架构到品味
- 《Claude Code Skill 指南》
- 《Claude 插件官方指南》