From f797205dc8705ece7fe2e9219850ab76f0c67939 Mon Sep 17 00:00:00 2001 From: Charles Zhang Date: Thu, 23 Apr 2026 23:42:21 +0800 Subject: [PATCH] add epec md --- OSHWHUB_INGEST_SPEC.md | 274 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 OSHWHUB_INGEST_SPEC.md diff --git a/OSHWHUB_INGEST_SPEC.md b/OSHWHUB_INGEST_SPEC.md new file mode 100644 index 0000000..599ba7c --- /dev/null +++ b/OSHWHUB_INGEST_SPEC.md @@ -0,0 +1,274 @@ +# 立创开源平台抓取 → Forge 接入 spec + +**Date**: 2026-04-23 +**给**: 同学爬 oshwhub.com / 立创开源广场 +**目的**: 爬回来的数据按这份 spec 整理,我们直接批量接入 Forge 的 BoardReference corpus。 + +--- + +## 1. TL;DR — 你交付的目标形态 + +每个项目一个目录,**三件套**: + +``` +/ +├── schematic.kicad_sch # ← 我们主要吃这个:KiCad 7+ S-expression 格式 +├── manifest.json # ← 项目元数据(见 §4) +└── source/ # ← 可选:原 EasyEDA 文件归档(.json / .epro 等) +``` + +**命名**: `project_id` = `oshwhub__`,纯小写下划线。 +例:`oshwhub_1234567_esp32_bluepill_clone`。 + +**交付**: tar.gz 或 git repo 都行。放在我们能访问的路径;我们自己跑批量 migrate。 + +--- + +## 2. 硬性前置条件 —— 任何一条不满足就跳过这个项目 + +### 2.1 License 白名单(关键!) + +**仅抓这些许可的项目**: +- MIT / BSD-2-Clause / BSD-3-Clause / Apache-2.0 +- CC0-1.0 / CC-BY-4.0 / CC-BY-3.0 +- CERN-OHL-P-2.0(permissive 变体) +- Unlicense / public domain + +**必须拒掉的**: +- **CC-BY-SA**(share-alike,会污染我们 corpus——大比例立创项目是这个!务必过滤) +- GPL / LGPL / AGPL 全家 +- "未声明 license" / "All rights reserved" +- CC-BY-NC(禁商用) + +立创项目页面上会显示许可名。你的爬虫要**先读许可、后抓文件**——许可不合格直接跳过,节省带宽。 + +### 2.2 文件格式 + +**必须有 KiCad 7+ 格式的 `.kicad_sch`**: +- 文件首 20 字节包含 `(kicad_sch` +- version 声明 ≥ 20210621(早于这个版本 KiCad 10 加载会 warning 一大堆) + +**如果项目只有 EasyEDA 原文件**: +- 用 [`easyeda2kicad`](https://github.com/uPesy/easyeda2kicad.py) 工具转(`pip install easyeda2kicad`) +- 或者立创 EDA Professional 的"导出 KiCad"功能 +- 转完后**必须验证能被 kicad-cli 加载**(见 §6 自测)——转不出来就跳过、不要硬塞 + +### 2.3 基本质量 + +- 至少 5 个元件(太简单的 breadboard prototype 没参考价值) +- 不超过 300 元件(太大的我们暂时不处理) +- 不是纯 footprint 测试板(没电气连接) + +--- + +## 3. `schematic.kicad_sch` 的要求 + +**原样保留**,不改、不格式化、不重新生成。我们的 corpus 依赖**字节级完整保留**才能做零漂移 byte-copy render。 + +**如果你用 easyeda2kicad 转换**: +- 转一次、存盘、不要后续再处理 +- 多 sheet 项目:把主 sheet 存为 `schematic.kicad_sch`,其它 sheet 存为 `sheets/.kicad_sch` + (我们暂时只消费根 sheet,但不要删其它——留着我们以后升级) + +--- + +## 4. `manifest.json` 格式 + +必填字段: + +```json +{ + "project_id": "oshwhub_1234567_esp32_bluepill_clone", + "source_platform": "oshwhub", + "source_url": "https://oshwhub.com/username/esp32-bluepill-clone", + "source_author": "username", + "title": "ESP32 Blue Pill 克隆", + "description": "一行到三行描述。可以直接从项目页面抓。双语都抓最好(en + zh),至少一个。", + "description_zh": "中文描述 (如果有)", + + "license": "MIT", + "license_source": "https://oshwhub.com/username/esp32-bluepill-clone/license", + "license_verified": true, + + "components_used": ["ESP32-WROOM-32", "AMS1117-3.3", "USB_B_Micro", "C", "R", "LED"], + + "file_checksum_sha256": "abc123...", + "file_size_bytes": 178825, + "kicad_sch_version": "20230121", + + "crawl_timestamp": "2026-04-23T10:00:00Z", + "converted_from": "easyeda", + "conversion_tool": "easyeda2kicad 0.8.2", + + "tags_raw": ["esp32", "dev_board", "usb"] +} +``` + +字段说明: + +- **`source_url`**:立创开源那个 project 的页面 URL。我们保存做 provenance。 +- **`license`**:必须是 §2.1 白名单里的字符串之一。**抓不准就跳过**,宁缺毋滥。 +- **`license_source`**:license 是从哪读到的(页面、LICENSE 文件、README)。方便我们事后验。 +- **`components_used`**:从 sch 里或从 EasyEDA 原 BOM 抓。用于后续 tag 派生——越全越好。 +- **`file_checksum_sha256`**:sha256 of `schematic.kicad_sch`。dedupe 用。 +- **`converted_from` / `conversion_tool`**:原生 KiCad 的项目写 `"converted_from": "native"`;EasyEDA 转来的写具体工具和版本。 +- **`tags_raw`**:立创页面上那个项目自带的标签/分类。原样塞。我们这边有一个 enrich 管线会基于 `components_used` + `description` 再派生更细的 tag(has_mcu / chip_tp4056 / use_portable...),你不用管这一步。 + +可选但有用: +- `source_easyeda_json_path`: 原 EasyEDA 文件的路径(如果你归档到 `source/` 下的话) +- `commit_sha` / `version`: 如果立创项目有版本号 +- `star_count` / `fork_count`: 作为后续 quality 排序参考 + +--- + +## 5. 目录结构示例 + +``` +batch_20260423/ # 你一次交付的批次目录 +├── README.md # 批次元数据(数量、时间、任何 caveat) +├── BATCH_MANIFEST.json # 机器可读的批次清单(见 §5.1) +│ +├── oshwhub_1234567_esp32_bluepill/ +│ ├── schematic.kicad_sch +│ ├── manifest.json +│ └── source/ +│ └── schematic.json # 原 EasyEDA +│ +├── oshwhub_2234568_tp4056_charger_v2/ +│ ├── schematic.kicad_sch +│ ├── manifest.json +│ └── source/ +│ ├── schematic.json +│ └── pcb.json +│ +├── oshwhub_3234569_audio_preamp/ +│ ├── schematic.kicad_sch # 原生 KiCad,无 source/ +│ └── manifest.json +│ +└── ... (N 个项目) +``` + +### 5.1 BATCH_MANIFEST.json + +让我们能一键扫批次: + +```json +{ + "batch_id": "batch_20260423", + "created_at": "2026-04-23T12:00:00Z", + "total_projects": 153, + "by_license": { + "MIT": 87, + "CC-BY-4.0": 34, + "Apache-2.0": 20, + "CC0-1.0": 12 + }, + "projects": [ + "oshwhub_1234567_esp32_bluepill", + "oshwhub_2234568_tp4056_charger_v2", + ... + ] +} +``` + +--- + +## 6. 自测 checklist(你交付前跑一遍) + +对每个 `/` 跑这 4 个检查,任一失败就把这个项目踢出批次: + +```bash +# 1. .kicad_sch 首字节对头 +head -c 20 /schematic.kicad_sch | grep -q "(kicad_sch" || echo FAIL_1 + +# 2. 版本 ≥ 20210621 +grep -oE "version \d{8}" /schematic.kicad_sch | head -1 +# expect 20210621 或更大 + +# 3. 能被 kicad-cli 加载(这一步最关键,catch 掉所有转换失败) +kicad-cli sch export netlist /schematic.kicad_sch \ + -o /tmp/test.net 2>&1 | grep -qi "error\|失败" && echo FAIL_3 + +# 4. manifest.json 合法且必填字段齐 +python3 -c " +import json, sys +m = json.load(open('/manifest.json')) +required = ['project_id', 'source_url', 'license', 'components_used', 'file_checksum_sha256'] +missing = [k for k in required if k not in m or not m[k]] +if missing: + print('FAIL_4 missing:', missing) + sys.exit(1) +" +``` + +把每个项目的检查结果写进 BATCH_MANIFEST 或单独一个 `failed/` 子目录归档。**交付前所有 4 个检查都要过**。 + +--- + +## 7. 已知坑 & 建议 + +### 7.1 立创开源的 license 现实 + +经验数据(不保证准确): +- 立创项目里**可能 50%+ 是 "CC-BY-SA 4.0"**,这是默认选项 → 我们直接拒 +- 大概 20-30% 是 "未声明 license" → 拒 +- 10-15% 是 MIT / Apache / CC0 → 要! +- 少量 GPL → 拒 + +**预期 hit rate**: 你抓 1000 个项目可能只有 150-250 能通过 license 关卡。这是正常的,不要为了数量降低许可标准。 + +### 7.2 EasyEDA → KiCad 转换质量 + +`easyeda2kicad.py` 对大部分项目能用,但: +- 自定义 symbol(立创 SZLCSC 专有库)可能转不过来 → 转完 kicad-cli 加载会 fail → 被 §6 check 3 过滤掉 +- 多 sheet hierarchy 偶尔乱 → 只保根 sheet 也能用 +- footprint 转换常有问题——我们暂时不在乎 footprint(corpus 主要消费 schematic),转不过就空着 + +### 7.3 描述文字 + +立创项目标题和描述常常**中英混杂 + markdown 标记 + emoji**。原样保留没关系,我们的 enrich 管线会 strip markdown。但**别主动翻译或改写** —— 原文有最多信息。 + +### 7.4 同项目多版本 + +立创有的项目带版本(v1 / v2 / Rev.B)。**不同版本视作不同项目**,分别抓、分别起 project_id。不要合并。 + +### 7.5 电气图多页 + +立创项目经常一个 sch 项目分多页(root + mcu_sheet + power_sheet 等)。你遇到时: +- 如果 easyeda2kicad 能转出层级结构 → 主 sheet 存 `schematic.kicad_sch`,子 sheet 存 `sheets/.kicad_sch` +- 如果只导出根 sheet → 根 sheet 存 `schematic.kicad_sch`,在 `manifest.json` 加 `"has_unsaved_subsheets": true` 标记 +- 转不出来 → 跳 + +--- + +## 8. 交付后我们会做什么(你不用担心这部分) + +参考、别去实现: + +1. `batch_migrate_oshwhub.py` 扫整个批次,逐个 `board_ingest_from_file` 入 corpus +2. License 白名单再 double-check 一遍(防你漏过) +3. sha256 dedupe(跨批次) +4. `enrich_tags.py` 跑一遍基于 `components_used` + `description` 生成 chip_* / has_* / use_* tag 家族 +5. 用 kicad-cli 跑 ERC 取 `source_erc_status`,脏的标记一下但仍入库(用户能看到警告) + +--- + +## 9. 测试批次建议 + +**第一次交付先给小批 5-10 个项目**,覆盖: +- 3-5 个 MIT/Apache 原生 KiCad +- 2-3 个 CC0/CC-BY-4.0 从 EasyEDA 转的 +- 1-2 个你不确定的 edge case(多 sheet、异常元件等) + +我们跑一遍 ingest,给你反馈"格式上还要改啥" / "这块数据不够",再开始量产爬。 + +--- + +## 10. 联系点 + +- 这份文档的源头:`hardware_agent_docs/OSHWHUB_INGEST_SPEC.md` +- 我们的 BoardReference schema 定义:`src/facere/references/schema.py` +- 已有的 ingest 入口:`src/facere/references/board_ingest.py` +- 批量 migrate 脚本参考:`benchmarks/corpus_build/migrate_raw_to_board_refs.py` + +有问题直接问我(张大佬)—— 格式细节比速度重要,不清楚的**先对一下再做**。