这一阶段的目标是:能用 Notebook 做数据探索、Prompt 实验、Agent 调试和结果分析。
学完后,你应该能:
- 理解 cell 执行模型和变量状态。
- 读取 CSV / JSON,展示 pandas DataFrame。
- 做简单可视化(柱状图)。
- 把稳定逻辑沉淀到
.py,Notebook 只留探索和展示。
对 Java 程序员:Notebook 最像"一个能保存中间变量、随时重跑某段的 REPL/Scratch 文件"。它不是用来写生产业务逻辑的地方。
- Notebook 由一个个 cell 组成,可单独执行,执行顺序由你点击决定,不是从上到下。
- 所有 cell 共享同一个 kernel 的变量状态:cell A 定义的
df,cell B 能直接用。 - 这带来一个经典坑:乱序执行导致状态不一致。你改了上面的 cell 没重跑,下面却用着旧变量,结果对不上。
黄金习惯:得出结论前,Restart Kernel & Run All(重启内核 + 从头跑一遍),确保结果可从零复现。这等价于"别信增量状态,信一次干净的全量运行"。
适合:快速验证 Prompt、查看中间变量、对比模型输出、分析评估结果、看 DataFrame、一次性实验记录。
不适合:长期维护的核心业务逻辑、复杂服务端工程、大规模并发任务、需要严格代码审查的生产逻辑。
四条原则:
- Notebook 用来探索。
- 稳定逻辑沉淀到
.py(可被 import、可单测、可在服务里复用)。 - 评估结论写清楚(Markdown cell 记上下文)。
- 重要实验固定随机种子和依赖版本,保证可复现。
参考 notebooks/analyze_eval.ipynb 严格贯彻"逻辑在 .py、展示在 Notebook":
# cell:定位项目根并导入已单测的分析模块
from pathlib import Path
import sys
def find_root(start: Path) -> Path:
for p in [start, *start.parents]:
if (p / "requirements.txt").exists():
return p
return start
ROOT = find_root(Path.cwd())
sys.path.append(str(ROOT / "scripts"))
import stage8_pandas_analysis as pdx # 第 8 阶段写好并测过的函数Notebook 里没有
__file__,所以用Path.cwd()向上找requirements.txt来定位项目根——无论从仓库根还是notebooks/启动 Jupyter 都能正确导入。
后续 cell 只是"调函数 + 展示":
results = pdx.load_results(ROOT / "data" / "stage8_eval_results.jsonl")
results.head(10) # cell 最后一个表达式自动渲染成表格
pdx.summarize_by(results, "model") # 按模型汇总
pdx.failure_reason_counts(results) # 失败原因分布- cell 的最后一个表达式会被自动渲染(DataFrame 显示成漂亮表格,不用
print)。 - 画图用 matplotlib:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(5, 3))
ax.bar(by_model["model"], by_model["avg_score"])
ax.set_ylabel("avg_score")
ax.set_title("Average score by model")参考 Notebook 里特意
matplotlib.use("Agg")(无界面后端)并fig.savefig(...), 这样它在无显示环境 / CI 里也能被nbconvert --execute跑通——见第 6 节。
把 cell 类型切成 Markdown,用来写标题、记录实验背景、结论。好 Notebook = 代码 + 解释交织,而不是一堆裸代码。
Notebook 最大风险是"在我机器上能跑"。解法是把它当回归测试整本执行:
jupyter nbconvert --to notebook --execute notebooks/analyze_eval.ipynb本仓库用 nbclient 在 pytest 里做了等价的冒烟测试(tests/test_stage7_notebook.py):
读入 notebook、用 python3 kernel 从头执行、断言不报错且生成了 summary CSV。这样
Notebook 一旦因为依赖或函数签名变化跑挂,CI 立刻发现。
交互式打开(手动探索):
.\.venv\Scripts\python.exe -m jupyter lab
# 或 jupyter notebook,然后打开 notebooks/analyze_eval.ipynb,Run All非交互执行(验证整本可跑):
.\.venv\Scripts\python.exe -m pytest tests\test_stage7_notebook.py- 能解释 cell 执行模型、共享变量状态,以及乱序执行的坑。
- 能在 Notebook 里读数据、展示 DataFrame、画一张图。
- 能把稳定逻辑放进
.py并在 Notebook 里 import 调用。 - 知道 Notebook 适合/不适合做什么。
- 知道怎么用
nbconvert --execute/ nbclient 让 Notebook 可复现、进 CI。
基于 notebooks/analyze_eval.ipynb 扩展:
- 加一个 Markdown cell,写下"哪个模型更好、为什么"的结论。
- 把柱状图换成"模型 × prompt 版本"的分组柱状图。
- 加一段对比:读入
stage2_eval_results.jsonl,和样本数据并排展示。 - 在开头加
import random; random.seed(0),体会"固定随机种子保证可复现"。 - 把某个新的探索性分析函数先在 Notebook 里写通,再"沉淀"到
scripts/并补一个 pytest。