登记AI研究来源边界并列明覆盖缺项

This commit is contained in:
2026-10-30 14:24:12 +08:00
parent 25c5e83d08
commit f27b82b6a5
4 changed files with 310 additions and 0 deletions
+40
View File
@@ -9,10 +9,49 @@ from urllib.parse import urlsplit
ROOT = Path(__file__).resolve().parents[1]
DATA = json.loads((ROOT / 'content/research/ai-companies.seed.json').read_text())
AUDIT = json.loads((ROOT / 'content/research/ai-companies.coverage.json').read_text())
SOURCES = json.loads((ROOT / 'content/research/ai-companies.sources.json').read_text())
TARGET = ROOT / 'content/docs/ai-company-research/02-coverage-and-gaps.md'
BASE = '/docs/other-research/ai-company-research/overview'
def source_register():
sources = SOURCES['sources']
ids = {s['id'] for s in sources}
assert len(ids) == len(sources) and ids == {f'S{i:02}' for i in range(1, 17)}
assert SOURCES['scopeConfirmedAt'] <= DATA['asOf']
host_map = {}
for source in sources:
assert source['status'] in {'candidate-audit', 'targeted', 'pending', 'context', 'access-limited', 'per-company'}
assert source['boundary'] and source['nextCheck']
if source['url']:
assert urlsplit(source['url']).scheme in {'http', 'https'} and urlsplit(source['url']).netloc
for host in source['hosts']:
assert host not in host_map, f'Duplicate source host: {host}'
host_map[host] = source['id']
assigned = {key: [] for key in ids}
for evidence in DATA['evidence']:
owner = host_map.get(urlsplit(evidence['url']).netloc)
if owner is None:
owner = 'S12' if any(word in evidence['kind'] for word in ('官方', '公司自述', '公司披露')) else 'S16'
assigned[owner].append(evidence)
assert sum(len(v) for v in assigned.values()) == len(DATA['evidence'])
statuses = {'candidate-audit': '候选池逐条已读', 'targeted': '定向使用,未穷尽', 'pending': '候选台账待建',
'context': '背景研究', 'access-limited': '访问受限', 'per-company': '随公司逐条核对'}
lines = ['', '## 来源清单与验收边界', '', SOURCES['provenance'], '',
'每条证据在下表只计入一个渠道:先按所列域名归属,再将类型明确标为官方/公司自述/公司披露的剩余项计入S12,其余计入S16。公司可跨渠道出现,所以公司数不可跨行相加。零条证据表示尚未进入研究表,不表示该来源没有相关公司。背景报告不承担公司发现全集的角色。', '',
'| 来源 | 当前状态 | 证据 / 公司 / 观测数 | 已核对范围 | 剩余核查 |', '| --- | --- | --- | --- | --- |']
for source in sources:
evidence = assigned[source['id']]
evidence_ids = {e['id'] for e in evidence}
company_ids = {e['companyId'] for e in evidence if e['companyId']}
observations = sum(o['evidence'] in evidence_ids for o in DATA['observations'])
name = f"[{source['name']}]({source['url']})" if source['url'] else source['name']
lines.append(f"| {source['id']} {name} | {statuses[source['status']]} | {len(evidence)} / {len(company_ids)} / {observations} | {source['boundary']} | {source['nextCheck']} |")
lines += ['', 'Dealroom、Product Hunt、机器之心与36氪入口于2026-10-30重新访问。官网首页可读不证明已取得完整筛选结果;安全检测页面不作为文章内容。候选池之外的来源边界尚需建立可回查条目,完成前不宣布来源清单已全部覆盖。', '']
return lines
def render():
cov = DATA['coverage']
companies = DATA['companies']
@@ -85,6 +124,7 @@ def render():
lines.append(f"| {name} | {len(entries)} | {len({e['url'] for e in entries})} | {note} |")
others = [e for e in DATA['evidence'] if urlsplit(e['url']).netloc not in included]
lines.append(f"| 其他官网、评测及公开资料 | {len(others)} | {len({e['url'] for e in others})} | 按每条来源限制理解,不能统一当作独立证据 |")
lines += source_register()
lines += ['', '## 尚未满足的研究条件', '',
'行业ARR比较仍缺统一业务截止日、币种、经常性定义和业务边界。现有平台MRR可描述已采集产品,不足以代表全部新公司。技术评测只覆盖所列版本与任务,不宜跨领域汇总为统一强弱分数。', '',
'下一轮优先补收入线索的日期及合同定义、非YC和非英文来源、规则初分的人工复核,以及停止服务或被收购案例。这样能减少“只见赢家”和“只见融资公司”的偏差。公开来源池之外的未披露公司仍无法证明已被穷尽。', '',