feat: add scripts for fetching arXiv papers and generating structured reviews
Sync to site1 / sync (push) Has been cancelled
Sync to site1 / sync (push) Has been cancelled
- Implemented `fetch_crowdroom_papers.py` to scrape arXiv papers related to CrowdRoom with customizable query topics and output options. - Created `gen_review_from_json.py` to render structured markdown reviews from search results JSON, including statistics and insights on papers and GitHub repositories. - Developed `search_info.py` for thematic searches on arXiv and GitHub, supporting HTTP/SOCKS5 proxies and structured output.
This commit is contained in:
@@ -0,0 +1,303 @@
|
||||
"""把 search_results.json 渲染成结构化 markdown 综述。
|
||||
|
||||
用法:
|
||||
python3 research/gen_review_from_json.py \
|
||||
--in research/search_results.json \
|
||||
--out research/zed2i_arxiv_live_review.md
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from collections import Counter
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
# 主题中英文标签 + 项目阶段映射
|
||||
TOPIC_META = {
|
||||
"stereo_matching": {
|
||||
"zh": "A. 双目立体匹配(被动深度)",
|
||||
"stage": "M2-3 / M3-4",
|
||||
"intro": "对应 ZED 双目深度算法的替换/超越路线。关注零样本泛化、Transformer 架构、神经几何编码。",
|
||||
},
|
||||
"visual_inertial_slam": {
|
||||
"zh": "B. 视觉惯性 SLAM / VIO",
|
||||
"stage": "M2-1 / M3-3",
|
||||
"intro": "对标 ZED 内建 VIO 的替代方案。关注 IMU 融合、长时鲁棒、动态环境。",
|
||||
},
|
||||
"gaussian_splatting_slam": {
|
||||
"zh": "C. 3D Gaussian Splatting SLAM(融合建图)",
|
||||
"stage": "M3-5 / M4",
|
||||
"intro": "把 3DGS 作为 SLAM 后端,实现实时定位+建图+渲染一体化。world model 训练的核心视觉表征。",
|
||||
},
|
||||
"monocular_depth_foundation": {
|
||||
"zh": "D. 单目深度基础模型",
|
||||
"stage": "M3-4",
|
||||
"intro": "Depth Anything / Marigold / Metric3D / UniDepth 等通用深度模型,作为双目深度失效的兜底。",
|
||||
},
|
||||
"indoor_rgbd_dataset": {
|
||||
"zh": "E. 室内 RGB-D 数据集与重建",
|
||||
"stage": "M4-1 / M4-2",
|
||||
"intro": "可参考的数据集设计、评测基准、室内几何重建方法。",
|
||||
},
|
||||
"world_model_video": {
|
||||
"zh": "F. 视频世界模型(下游应用)",
|
||||
"stage": "M4-4",
|
||||
"intro": "本项目数据 pipeline 的最终下游:训练能预测未来视频/动作的 world model。",
|
||||
},
|
||||
"zed_camera": {
|
||||
"zh": "G. ZED 相机相关应用工作",
|
||||
"stage": "全周期",
|
||||
"intro": "用 ZED 系列采集数据的应用论文,参考其采集协议、评测方式、参数配置。",
|
||||
},
|
||||
"orbbec_gemini": {
|
||||
"zh": "H. Orbbec / Femto / Azure Kinect 相关工作",
|
||||
"stage": "国产化 / 替代硬件",
|
||||
"intro": "奥比中光、乐视/微视 Femto、微软 Azure Kinect 等 RGB-D 相机的应用论文。",
|
||||
},
|
||||
"rgbd_indoor_reconstruction": {
|
||||
"zh": "I. RGB-D 室内重建",
|
||||
"stage": "M2-2 / M3-5",
|
||||
"intro": "RGB-D 输入下的室内场景重建,与本项目的房间级建图任务高度对齐。",
|
||||
},
|
||||
"neural_stereo_depth": {
|
||||
"zh": "J. 神经立体深度(指定 RAFT/IGEV/Foundation 家族)",
|
||||
"stage": "M3-4",
|
||||
"intro": "针对 RAFT-Stereo / IGEV-Stereo / FoundationStereo 等核心立体匹配方法的衍生与改进。",
|
||||
},
|
||||
}
|
||||
|
||||
CN_KEYWORDS = [
|
||||
# 中国机构关键词(用于粗筛"国产团队"论文)
|
||||
"tsinghua", "peking", "fudan", "shanghai jiao", "zhejiang", "ustc", "huazhong",
|
||||
"harbin", "tianjin", "wuhan", "xi'an jiaotong", "xi'an", "nanjing",
|
||||
"chinese academy", "cas ", "casia",
|
||||
"hkust", "cuhk", "hku", "polyu", "city university of hong kong",
|
||||
"alibaba", "tencent", "bytedance", "baidu", "huawei", "megvii",
|
||||
"sensetime", "ant group", "didi", "meituan", "xiaomi",
|
||||
"damo", "noah", "arc lab", "shanghai ai lab",
|
||||
]
|
||||
|
||||
|
||||
def is_china_team(authors: list[str], summary: str) -> bool:
|
||||
"""粗略判断是否有国产团队作者(依赖摘要中机构提及)。"""
|
||||
lower = (" ".join(authors) + " " + summary).lower()
|
||||
return any(k in lower for k in CN_KEYWORDS)
|
||||
|
||||
|
||||
def fmt_authors(authors: list[str], max_n: int = 4) -> str:
|
||||
if not authors:
|
||||
return "(作者信息缺失)"
|
||||
if len(authors) <= max_n:
|
||||
return ", ".join(authors)
|
||||
return ", ".join(authors[:max_n]) + f" 等 ({len(authors)} 人)"
|
||||
|
||||
|
||||
def render_paper(p: dict, idx: int) -> list[str]:
|
||||
aid = p.get("arxiv_id", "")
|
||||
title = p.get("title", "").strip().rstrip(".")
|
||||
pub = p.get("published", "")[:10]
|
||||
authors = p.get("authors", [])
|
||||
summary = p.get("summary", "")
|
||||
cats = p.get("categories", [])
|
||||
url = p.get("url") or f"https://arxiv.org/abs/{aid}"
|
||||
|
||||
china_tag = " 🇨🇳" if is_china_team(authors, summary) else ""
|
||||
|
||||
lines = [
|
||||
f"#### {idx}. [{aid}]({url}) — {title}{china_tag}",
|
||||
f"- **发表**: {pub} | **分类**: {', '.join(cats[:3]) if cats else '-'}",
|
||||
f"- **作者**: {fmt_authors(authors)}",
|
||||
f"- **摘要**: {summary}",
|
||||
"",
|
||||
]
|
||||
return lines
|
||||
|
||||
|
||||
def render_topic(topic: str, papers: list[dict]) -> list[str]:
|
||||
meta = TOPIC_META.get(topic, {"zh": topic, "stage": "-", "intro": ""})
|
||||
out = [
|
||||
f"## {meta['zh']}",
|
||||
f"**项目阶段**: {meta['stage']} | **论文数**: {len(papers)}",
|
||||
"",
|
||||
meta["intro"],
|
||||
"",
|
||||
]
|
||||
|
||||
# 按时间排序(新到旧)
|
||||
papers_sorted = sorted(papers, key=lambda p: p.get("published", ""), reverse=True)
|
||||
|
||||
for i, p in enumerate(papers_sorted, 1):
|
||||
out.extend(render_paper(p, i))
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def render_github_topic(topic: str, repos: list[dict]) -> list[str]:
|
||||
out = [f"### GitHub: {topic}(按 stars 排序)", ""]
|
||||
for r in repos:
|
||||
out.append(
|
||||
f"- [{r['name']}]({r['url']}) — ⭐ {r['stars']:,} | "
|
||||
f"{r.get('language', '-')} | {r.get('description', '')[:120]}"
|
||||
)
|
||||
out.append("")
|
||||
return out
|
||||
|
||||
|
||||
def main() -> int:
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--in", dest="inp", default="research/data/search_results.json")
|
||||
ap.add_argument("--out", default="research/spatial-memory/zed2i_arxiv_live_review.md")
|
||||
args = ap.parse_args()
|
||||
|
||||
with open(args.inp, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
arxiv = data.get("arxiv", {})
|
||||
github = data.get("github", {})
|
||||
meta = data.get("meta", {})
|
||||
|
||||
# 统计
|
||||
total_papers = sum(len(v) for v in arxiv.values())
|
||||
total_repos = sum(len(v) for v in github.values())
|
||||
|
||||
all_papers = [p for ps in arxiv.values() for p in ps]
|
||||
china_papers = [p for p in all_papers if is_china_team(p.get("authors", []), p.get("summary", ""))]
|
||||
cat_counter: Counter[str] = Counter()
|
||||
for p in all_papers:
|
||||
for c in p.get("categories", [])[:1]:
|
||||
cat_counter[c] += 1
|
||||
|
||||
lines: list[str] = [
|
||||
"# ZED 2i 数据 Pipeline 实时 arXiv 综述(自动生成)",
|
||||
"",
|
||||
f"> **数据来源**:[`research/search_results.json`](search_results.json) 由 [`research/search_info.py`](search_info.py) 通过 HTTP 代理 `127.0.0.1:6984` 拉取自 arxiv.org / api.github.com。",
|
||||
f"> **生成时间**:{meta.get('generated_at', '-')}",
|
||||
f"> **检索代理**:{meta.get('proxy', '-')}",
|
||||
f"> **每主题最多**:{meta.get('max_results_per_topic', '-')} 篇",
|
||||
"",
|
||||
"## 0. 数据概览",
|
||||
"",
|
||||
f"- **arXiv 论文总数**:{total_papers}",
|
||||
f"- **arXiv 主题数**:{len(arxiv)}",
|
||||
f"- **疑似国产团队论文**:{len(china_papers)}(占比 {len(china_papers)*100//max(total_papers,1)}%;🇨🇳 标记,启发式判断)",
|
||||
f"- **GitHub 仓库总数**:{total_repos}",
|
||||
f"- **GitHub 主题数**:{len(github)}",
|
||||
"",
|
||||
"### 0.1 主类目分布(arXiv primary_category)",
|
||||
"",
|
||||
]
|
||||
for cat, n in cat_counter.most_common(10):
|
||||
lines.append(f"- `{cat}`: {n}")
|
||||
lines.append("")
|
||||
|
||||
lines.extend(
|
||||
[
|
||||
"### 0.2 与本项目框架的映射",
|
||||
"",
|
||||
"| 项目阶段 | 主线主题 | 论文数 |",
|
||||
"|---|---|---|",
|
||||
]
|
||||
)
|
||||
for topic, m in TOPIC_META.items():
|
||||
n = len(arxiv.get(topic, []))
|
||||
lines.append(f"| {m['stage']} | {m['zh']} | {n} |")
|
||||
lines.append("")
|
||||
|
||||
lines.extend(
|
||||
[
|
||||
"---",
|
||||
"",
|
||||
"# 第一部分 · arXiv 论文(按主题分组,时间新→旧)",
|
||||
"",
|
||||
]
|
||||
)
|
||||
|
||||
for topic in TOPIC_META.keys():
|
||||
papers = arxiv.get(topic, [])
|
||||
if not papers:
|
||||
continue
|
||||
lines.extend(render_topic(topic, papers))
|
||||
lines.append("---")
|
||||
lines.append("")
|
||||
|
||||
lines.extend(
|
||||
[
|
||||
"# 第二部分 · GitHub 仓库(按 stars 排序)",
|
||||
"",
|
||||
]
|
||||
)
|
||||
for topic, repos in github.items():
|
||||
lines.extend(render_github_topic(topic, repos))
|
||||
|
||||
lines.extend(
|
||||
[
|
||||
"---",
|
||||
"",
|
||||
"# 第三部分 · 关键洞察与项目对接建议",
|
||||
"",
|
||||
"## I.1 最值得关注的新论文(按相关性挑选)",
|
||||
"",
|
||||
"下方挑选每个主题中**与本项目最相关的 3 篇**(基于标题/摘要语义判断):",
|
||||
"",
|
||||
]
|
||||
)
|
||||
|
||||
# 简单挑选每个主题前 3 篇放在洞察区
|
||||
for topic in ["stereo_matching", "visual_inertial_slam", "gaussian_splatting_slam", "monocular_depth_foundation"]:
|
||||
papers = arxiv.get(topic, [])
|
||||
if not papers:
|
||||
continue
|
||||
meta = TOPIC_META[topic]
|
||||
lines.append(f"### {meta['zh']} → {meta['stage']}")
|
||||
for p in sorted(papers, key=lambda x: x.get("published", ""), reverse=True)[:3]:
|
||||
lines.append(f"- **[{p['arxiv_id']}]({p['url']})** {p['title']}({p['published'][:10]})")
|
||||
lines.append("")
|
||||
|
||||
lines.extend(
|
||||
[
|
||||
"## I.2 后续动作清单",
|
||||
"",
|
||||
"- [ ] 把上述每主题的 Top-3 论文加入 [`research/zed2i_stereo_vio_arxiv_review.md`](zed2i_stereo_vio_arxiv_review.md) 第 F 节的论文映射表",
|
||||
"- [ ] 对 🇨🇳 标记的论文重点核查机构归属,更新 G 节国产团队清单",
|
||||
"- [ ] 把 GitHub 仓库中 stars > 5k 的项目加入 [`plans/camera/github_opensource_projects.md`](../plans/camera/github_opensource_projects.md)",
|
||||
"- [ ] 每周重跑 [`research/search_info.py`](search_info.py) 增量更新",
|
||||
"",
|
||||
"## I.3 复现方法",
|
||||
"",
|
||||
"```bash",
|
||||
"# 通过 127.0.0.1:6984 代理拉取最新数据",
|
||||
"HTTPS_PROXY=http://127.0.0.1:6984 HTTP_PROXY=http://127.0.0.1:6984 \\",
|
||||
" python3 research/search_info.py \\",
|
||||
" --proxy http://127.0.0.1:6984 \\",
|
||||
" --max-results 10 --delay 5.0 \\",
|
||||
" --out research/search_results.json",
|
||||
"",
|
||||
"# 渲染为 markdown",
|
||||
"python3 research/gen_review_from_json.py \\",
|
||||
" --in research/search_results.json \\",
|
||||
" --out research/zed2i_arxiv_live_review.md",
|
||||
"```",
|
||||
"",
|
||||
"---",
|
||||
"",
|
||||
"**说明**:",
|
||||
"- 本文档由脚本自动生成,可重复执行覆盖",
|
||||
"- 🇨🇳 标记基于作者/摘要中是否包含中国机构关键词的启发式判断,**仅供参考,需人工复核**",
|
||||
"- 摘要截断到 400 字符以控制文档体积",
|
||||
"- 与 [`zed2i_stereo_vio_arxiv_review.md`](zed2i_stereo_vio_arxiv_review.md)(人工综述)互为补充:人工综述给方法论与映射,本文档给最新原始素材",
|
||||
]
|
||||
)
|
||||
|
||||
with open(args.out, "w", encoding="utf-8") as f:
|
||||
f.write("\n".join(lines))
|
||||
|
||||
print(f"✅ 生成: {args.out}")
|
||||
print(f" arXiv: {total_papers} 篇,国产疑似: {len(china_papers)}")
|
||||
print(f" GitHub: {total_repos} 仓库")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user