Skip to content

Latest commit

 

History

History
133 lines (90 loc) · 5.28 KB

File metadata and controls

133 lines (90 loc) · 5.28 KB

第 7 阶段:Jupyter Notebook 教程

0. 学习目标

这一阶段的目标是:能用 Notebook 做数据探索、Prompt 实验、Agent 调试和结果分析。

学完后,你应该能:

  • 理解 cell 执行模型和变量状态。
  • 读取 CSV / JSON,展示 pandas DataFrame。
  • 做简单可视化(柱状图)。
  • 把稳定逻辑沉淀到 .py,Notebook 只留探索和展示。

对 Java 程序员:Notebook 最像"一个能保存中间变量、随时重跑某段的 REPL/Scratch 文件"。它不是用来写生产业务逻辑的地方。

1. cell 执行模型(最重要的认知)

  • Notebook 由一个个 cell 组成,可单独执行,执行顺序由你点击决定,不是从上到下。
  • 所有 cell 共享同一个 kernel 的变量状态:cell A 定义的 df,cell B 能直接用。
  • 这带来一个经典坑:乱序执行导致状态不一致。你改了上面的 cell 没重跑,下面却用着旧变量,结果对不上。

黄金习惯:得出结论前,Restart Kernel & Run All(重启内核 + 从头跑一遍),确保结果可从零复现。这等价于"别信增量状态,信一次干净的全量运行"。

2. 适合 / 不适合做什么

适合:快速验证 Prompt、查看中间变量、对比模型输出、分析评估结果、看 DataFrame、一次性实验记录。

不适合:长期维护的核心业务逻辑、复杂服务端工程、大规模并发任务、需要严格代码审查的生产逻辑。

四条原则:

  1. Notebook 用来探索
  2. 稳定逻辑沉淀到 .py(可被 import、可单测、可在服务里复用)。
  3. 评估结论写清楚(Markdown cell 记上下文)。
  4. 重要实验固定随机种子和依赖版本,保证可复现。

3. 本仓库的实践:Notebook 调 .py

参考 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)            # 失败原因分布

4. 展示与可视化

  • 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 节。

5. Markdown cell

把 cell 类型切成 Markdown,用来写标题、记录实验背景、结论。好 Notebook = 代码 + 解释交织,而不是一堆裸代码。

6. Notebook 也能进 CI(可复现保证)

Notebook 最大风险是"在我机器上能跑"。解法是把它当回归测试整本执行

jupyter nbconvert --to notebook --execute notebooks/analyze_eval.ipynb

本仓库用 nbclient 在 pytest 里做了等价的冒烟测试(tests/test_stage7_notebook.py): 读入 notebook、用 python3 kernel 从头执行、断言不报错且生成了 summary CSV。这样 Notebook 一旦因为依赖或函数签名变化跑挂,CI 立刻发现。

7. 可运行验证

交互式打开(手动探索):

.\.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

8. 本阶段掌握标准

  • 能解释 cell 执行模型、共享变量状态,以及乱序执行的坑。
  • 能在 Notebook 里读数据、展示 DataFrame、画一张图。
  • 能把稳定逻辑放进 .py 并在 Notebook 里 import 调用。
  • 知道 Notebook 适合/不适合做什么。
  • 知道怎么用 nbconvert --execute / nbclient 让 Notebook 可复现、进 CI。

9. 练习任务(自己动手)

基于 notebooks/analyze_eval.ipynb 扩展:

  1. 加一个 Markdown cell,写下"哪个模型更好、为什么"的结论。
  2. 把柱状图换成"模型 × prompt 版本"的分组柱状图。
  3. 加一段对比:读入 stage2_eval_results.jsonl,和样本数据并排展示。
  4. 在开头加 import random; random.seed(0),体会"固定随机种子保证可复现"。
  5. 把某个新的探索性分析函数先在 Notebook 里写通,再"沉淀"到 scripts/ 并补一个 pytest。