init: edu-content 内容库骨架(L1-L4 四层数据模型 + B类迁移 + lint/CI 工具)
这个提交包含在:
58
tools/index_build.py
普通文件
58
tools/index_build.py
普通文件
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python3
|
||||
"""index_build.py — 生成 INDEX.json(机器可读库全貌)。
|
||||
|
||||
汇总:资源域、各数据集记录数、license 分布、OSS 前缀、红线摘要。
|
||||
注意:本文件由工具生成,勿手改;CI 在 lint 通过后自动重跑。
|
||||
"""
|
||||
import os, glob, json, datetime, collections
|
||||
|
||||
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
def source_summary():
|
||||
import yaml
|
||||
domains, n_sources, lic = {}, 0, collections.Counter()
|
||||
for path in glob.glob(os.path.join(REPO, "sources", "**", "*.yaml"), recursive=True):
|
||||
rel = os.path.relpath(path, os.path.join(REPO, "sources"))
|
||||
domain = os.path.dirname(rel)
|
||||
try: doc = yaml.safe_load(open(path, encoding="utf-8"))
|
||||
except Exception: continue
|
||||
for s in (doc or {}).get("sources", []) or []:
|
||||
n_sources += 1
|
||||
lic[s.get("license")] += 1
|
||||
domains.setdefault(domain, 0)
|
||||
domains[domain] += 1
|
||||
return {"domains": domains, "n_sources": n_sources, "license_breakdown": dict(lic)}
|
||||
|
||||
def structured_summary():
|
||||
datasets, lic = {}, collections.Counter()
|
||||
for path in glob.glob(os.path.join(REPO, "structured", "**", "*.jsonl"), recursive=True):
|
||||
rel = os.path.relpath(path, os.path.join(REPO, "structured"))
|
||||
cnt = 0
|
||||
for line in open(path, encoding="utf-8"):
|
||||
line = line.strip()
|
||||
if not line: continue
|
||||
cnt += 1
|
||||
try: r = json.loads(line)
|
||||
except Exception: continue
|
||||
l = r.get("license")
|
||||
if l: lic[l] += 1
|
||||
datasets[rel] = cnt
|
||||
return {"datasets": datasets, "n_records": sum(datasets.values()), "license_breakdown": dict(lic)}
|
||||
|
||||
def main():
|
||||
idx = {
|
||||
"generated_at": datetime.date.today().isoformat(),
|
||||
"repo": "edu-content",
|
||||
"model": "L1 source registry (git) + L2 raw (OSS edu-raw/) + L3 structured (git)",
|
||||
"oss": {"bucket": "edu-content-hy", "region": "oss-cn-heyuan", "prefixes": ["edu-raw/", "edu-derived/"]},
|
||||
"redline": "restricted / internal-only / unknown 数据永不可进 derived,永不可对外产品使用",
|
||||
"sources": source_summary(),
|
||||
"structured": structured_summary(),
|
||||
"entrypoints": {"human": "README.md", "machine": "INDEX.json", "license": "LICENSES.md", "conventions": "docs/conventions.md"},
|
||||
}
|
||||
out = os.path.join(REPO, "INDEX.json")
|
||||
json.dump(idx, open(out, "w", encoding="utf-8"), ensure_ascii=False, indent=2)
|
||||
print(f"已生成 {out}:{idx['sources']['n_sources']} source,{idx['structured']['n_records']} 结构化记录")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
在新工单中引用
屏蔽一个用户