深入解析 Skill_Seekers Jupyter 参考文件生成机制:从 `section_s3-s4.md` 看代码单元、Raw 单元与 golden 验证体系
2026/9/23 19:03:06 网站建设 项目流程
  • 人工智能
  • AI 应用
  • AI 技能
  • RAG
  • MCP 服务
  • 网页爬虫

【免费下载链接】Skill_Seekers

Convert documentation websites, GitHub repositories, and PDFs into Claude AI skills with automatic conflict detection

项目地址:https://gitcode.com/gh_mirrors/sk/Skill_Seekers
点击查看免费下载

导读

本文以 Skill_Seekers 仓库中 Jupyter Notebook 转 Skill 流水线的 golden 输出示例tests/golden/phase2/jupyter_kw/references/section_s3-s4.md为切入点,逐行拆解 Skill_Seekers 如何把一个.ipynb中无标题、异常报错、未渲染的"杂项"单元转换为结构化 Markdown 参考文件。读者将掌握参考文件的命名规则、代码单元与 Raw 单元的具体渲染格式、关键词分类与 "Other" 兜底机制,以及 golden 测试如何保证输出字节级稳定。

一、关联文档在产物树中的定位

tests/golden/phase2/jupyter_kw/是 Skill_Seekers 为 Jupyter 抓取器(src/skill_seekers/cli/jupyter_scraper.py)在 Phase 2 重构(迁移到DocumentSkillBuilder)前后输出一致性而提交的 golden 基线树。该目录包含:

  • SKILL.md:生成的主技能入口,含 Section Overview、Dependencies、Code Examples、Notebook Statistics 等汇总;
  • references/index.md:整个 notebook 的分类索引,列出 5 个分类、各类包含的 section 区间、统计信息与导入包列表;
  • references/section_*.md:每个分类对应一个参考文件,section_s3-s4.md正是其中之一。

关联文档section_s3-s4.md属于golden_jupyter_kw构建产物,对应测试 test_jupyter_keyword_categorization_matches_golden 中"Other"分类的输出。它只包含两个单元(Section 3 与 Section 4),恰好覆盖了流水线中最容易被忽略的两种单元类型——抛出异常的代码单元Raw 原始单元,因此是理解整个渲染管线最浓缩的标本。

从 references/index.md 的 Categories 一节可以看到它的归属:

- [Other](https://link.gitcode.com/i/b7f9c2e704a14162f9f90afaeedb8336) (2 sections, Sections 3-4)

index.md的 Statistics 提供了全局口径:5 个 section、2 个 code 单元、2 个 markdown 单元、1 个 raw 单元、1 个 notebook,导入包为numpypandassklearn三个。这些数字与 test_phase2_golden_jupyter.py 中的SECTIONS_extracted_data完全对应。

二、参考文件命名规则:section_s3-s4.md从何而来

参考文件的名字不是随意的,其生成逻辑集中在 src/skill_seekers/cli/scraper_utils.py 的reference_filename()函数中,它是文件写入器、index.mdSKILL.md导航三处共用的"唯一事实来源",以避免链接漂移(代码注释中标记为 DOC-07)。

命名分三种情况:

  1. 分类为空:回退为section_<序号>.md(两位数字补齐),例如空分类的 references/section_04.md;
  2. 只有一个分类:使用源文件 stem 命名(如analysis.md),无 stem 时用main.md
  3. 多分类(当前场景):取分类内最小与最大 section 号拼成区间,格式为<base>_<prefix><min>-<prefix><max>.md

golden_jupyter_kw走第三条路径:其分类来源是测试传入的categories字典(见 test_phase2_golden_jupyter.py),含setupmodelingloadingempty_cat四个显式分类。分类完成后,"Other" 桶收集了未被任何分类命中的 section 3(Magic 单元)与 section 4(Raw 单元),section 号区间为 3–4,因此得到文件名section_s3-s4.md——sprefix参数的默认值,base_stem为空时取"section"。同一逻辑也解释了同目录下section_s1-s1.mdsection_s5-s5.md的命名。

三、代码单元渲染:标题推断、执行计数与错误输出

section_s3-s4.md的第一段完整展示了无执行计数的代码单元是如何被渲染的:

**📄 Source: Section 3** (Code Cell) #### Magic: %timeit ```python %timeit broken()

Errors:

NameError: name 'broken' is not defined Traceback line 1

Tags: raises-exception

逐行对应 [jupyter_scraper.py](https://link.gitcode.com/i/9735c98d6b9f8bb35b679f4aca3d9901) 中的处理: ### 3.1 单元头部与执行计数 渲染入口是 `_write_reference_section()`([jupyter_scraper.py](https://link.gitcode.com/i/9735c98d6b9f8bb35b679f4aca3d9901#L749-L794)):代码单元固定输出 `**📄 Source: Section N** (Code Cell)`,若存在执行计数会追加 `[In N]` 标记(如 `(Code Cell [In 2])`)。本单元 `execution_count` 为 `None`,因此不显示 `[In N]`——这正是 [test_phase2_golden_jupyter.py](https://link.gitcode.com/i/2cbf673e4405cd4929710920525fcf79) 中 section 3 的数据形态。 ### 3.2 Magic 命令的标题推断 代码单元本身没有 Markdown 标题,其标题由 `_infer_code_heading()`([jupyter_scraper.py](https://link.gitcode.com/i/9735c98d6b9f8bb35b679f4aca3d9901#L583-L605))按优先级推断: - 首行是 `# 注释` → 截取注释文本(超过 80 字符截断); - 首行是 `def`/`class`/`async def` → `Define: <名字>`; - 首行是赋值表达式 → `Assign: <变量名>`; - 首行是 **magic 命令(`%` 开头)** → `Magic: <命令>`; - 首行以 `!` 开头 → `Shell: <命令>`; - 兜底 → `Code Cell [<执行计数>]`。 `%timeit broken()` 命中第四支,产出 `Magic: %timeit`。写入时标题层级在 `heading_level`(h3)基础上加一级渲染为 `####`,因此参考文件中出现 `#### Magic: %timeit`。 ### 3.3 错误输出的收集与格式化 异常信息来自 `_parse_code_cell()`([jupyter_scraper.py](https://link.gitcode.com/i/9735c98d6b9f8bb35b679f4aca3d9901#L497-L562))对 `outputs` 中 `output_type == "error"` 的处理:拼接 `ename: evalue`(`NameError: name 'broken' is not defined`)后追加清理过的 traceback 行(剥离 ANSI 颜色码 `\x1b[...m`),得到第二行 `Traceback line 1`。写入时统一放进 `**Errors:**` 代码块([jupyter_scraper.py](https://link.gitcode.com/i/9735c98d6b9f8bb35b679f4aca3d9901#L783-L784))。与之相对,`stream` 输出进 `**Output:**` 块,`execute_result`/`display_data` 的 `text/plain` 进正文文本,`text/html`、`image/png`、`image/svg+xml` 等富输出则折叠为一行 `*Rich output: <mime 列表>*`。 ### 3.4 单元标签 nbformat 中 cell 级 `metadata.tags` 会被保留并渲染为 `*Tags: ...*` 行([jupyter_scraper.py](https://link.gitcode.com/i/9735c98d6b9f8bb35b679f4aca3d9901#L791-L793))。本单元携带 `raises-exception` 标签,在 SKILL 中成为一种语义标注,便于 Agent 检索"会抛异常的示例"。 ## 四、Raw 单元的极简渲染 `section_s3-s4.md` 的第二段是全文件最短的一段: ```markdown **📄 Source: Section 4** (Raw Cell) raw front-matter content

Raw 单元(通常用于存放 front-matter、LaTeX、不可渲染的源文本)由_parse_raw_cell()(jupyter_scraper.py)处理:无标题、无代码样例、无输出,仅保留source.strip()作为正文,写入时头部标记为(Raw Cell)(jupyter_scraper.py)。这段渲染刻意"裸奔",保证 front-matter 类内容不被二次加工破坏,可直接被下游解析器消费。

五、为什么这两个单元会进入 "Other" 分类

"Other" 桶的形成取决于分类策略。categorize_content()(jupyter_scraper.py)按优先级依次处理:

  1. 单文件来源:直接用 notebook 的 stem 作为唯一分类(本 golden 分支未启用,因为测试配置未把notebook_path设为文件);
  2. 显式关键词分类:对每个 section 拼接text + heading + code_section_text(),jupyter_scraper.py),逐个匹配categories字典中的关键词,命中数最多的分类胜出;没有任何命中则落入other
  3. 自动主题分类:无显式分类时使用内置_TOPIC_KEYWORDS(jupyter_scraper.py,涵盖 data_loading、modeling、evaluation 等 8 类主题),得分 ≥2 才入桶,否则进other

test_jupyter_keyword_categorization_matches_golden中,测试传入:

categories={ "setup": ["install", "setup"], "modeling": ["accuracy", "recall", "model"], "loading": ["read_csv"], # 仅能命中代码样例中的 read_csv "empty_cat": ["zzz-no-match"], # 永远不会命中 → 空分类 }

Section 3 的%timeit broken()与 Section 4 的raw front-matter content均不包含任何分类关键词(%timeit不在 modeling 关键词中、brokenraw亦不匹配),于是双双落入other(标题渲染为 "Other")。而 section 1 因含setupinstall命中setup,section 5 因含accuracyrecallmodel命中modeling,section 2 的read_csv命中loading——这正是 index.md 中五个分类数量(1/1/1/0/2)的成因。

六、golden 测试如何保证输出不变

tests/golden/phase2/jupyter_kw/不是随手生成的文档,而是回归测试的字节级基线。tests/phase2_golden_utils.py 定义了校验协议:

  • 重构前用UPDATE_GOLDENS=1 pytest <测试名>从旧代码捕获基线并提交;
  • 重构后测试在比对模式下运行,assert_matches_golden()(tests/phase2_golden_utils.py)会对skill_dir下所有文件做集合与逐字节比对,任何差异(包括空白、换行)都会以 unified diff 形式抛错;
  • 其 docstring 明确警告:UPDATE_GOLDENS=1会重写已提交基线,只能在刻意更新时使用。

因此section_s3-s4.md的每一行都等价于一条约束——只要JupyterToSkillConverter的渲染逻辑有任何行为变化,测试 test_phase2_golden_jupyter.py 就会立即失败。这也是将golden_jupyter_kw归类到"目录来源 + 显式关键词分类 + 空分类 + other 兜底"组合的原因:该分支覆盖了_reference_filename的区间命名、空分类回退(section_04.md)、关键词打分与兜底桶等最易回归的路径。

七、从单文件到整个技能包:参考文件的消费方式

section_s3-s4.md最终通过两条路径被 Agent 消费:

  • SKILL.mdNavigation一节(SKILL.md)列出全部references/*.md及其分类名,链接同样由reference_filename()统一生成,保证不会指向不存在的文件;
  • 顶部 front-matter 的namedescription(如Use when testing the golden_jupyter_kw golden build)供 Agent 在技能选择阶段判断何时加载;description若未显式配置,会由infer_description_from_notebook()(jupyter_scraper.py)依据language_infokernelspec.display_name等 notebook 元数据自动生成。

用户在自己的 notebook 上复现同样的产物,只需安装nbformat后运行(单文件或目录均可,见 jupyter_scraper.py 用法注释):

pip install "skill-seekers[jupyter]" skill-seekers jupyter --notebook analysis.ipynb --name myskill skill-seekers jupyter --notebook ./notebooks/ --name myskill skill-seekers jupyter --from-json notebook_extracted.json

生成的技能目录结构即为本 golden 树所展示的形态:SKILL.md+references/index.md+ 按分类区间命名的references/section_*.md

八、小结

section_s3-s4.md虽只有寥寥数行,却是 Skill_Seekers Jupyter 转 Skill 管线的浓缩横截面:它同时验证了 Magic 标题推断、无执行计数代码单元渲染、ANSI 清理后的错误输出、cell 标签保留、Raw 单元透传、关键词分类的 "Other" 兜底以及多分类区间命名这七项机制。结合 jupyter_scraper.py 的源码与 test_phase2_golden_jupyter.py 的测试数据,可以确认:参考文件不是临时拼凑的摘要,而是由nbformat解析、DocumentSkillBuilder组装、reference_filename()统一命名、golden 测试逐字节守护的规范化产物——这正是 Skill_Seekers 把任意 notebook 变成可被 Agent 引用、检索和复现的知识技能包时的核心保障。

  • 人工智能
  • AI 应用
  • AI 技能
  • RAG
  • MCP 服务
  • 网页爬虫

【免费下载链接】Skill_Seekers

Convert documentation websites, GitHub repositories, and PDFs into Claude AI skills with automatic conflict detection

项目地址:https://gitcode.com/gh_mirrors/sk/Skill_Seekers
点击查看免费下载

相关推荐

上一篇:Karpenter 开发环境搭建与开发者工作流实战指南
下一篇:13ft Ladder技术架构深度剖析:Flask+BeautifulSoup实现

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询