Community생산성 & 협업github.com

citation-digest (引用文献速览)

给定一篇论文,抓取其引用列表(来自 Semantic Scholar,含被引数),为每篇论文抓取 papers.cool 上 Kimi 的总结(仅保留“试图解决什么问题”原文),按指定类别归类,并输出为 Markdown 或发布到 Notion(论文根 toggle → 分类 toggle → 每篇一个 toggle)。适用于用户请求“引用/被引/citing papers/literature digest”并希望按主题分类或写入 Notion 的场景。

citation-digest (引用文献速览)란 무엇인가요?

该技能(citation-digest)是一个为 AI 编程助手(如 Claude Code、Cursor 等)设计的自动化文献引用摘要工具。它能够接收一篇输入论文,自动从 Semantic Scholar 获取其被引论文列表(包括被引数、日期、DOI 和 arXiv ID),进而通过 papers.cool 的 Kimi 接口抓取每篇被引论文的“试图解决什么问题”这一关键段落的原文,最后按用户定义的类别(如场景创新、技术改进、综述)对引用文献进行分组,并生成结构化的 Markdown 文件或直接发布到 Notion 页面。该工具的主要价值在于大幅节省了研究人员手动整理文献、提炼问题和分类的精力,尤其适合需要快速了解某篇论文的学术影响、梳理相关研究趋势或构建文献笔记的场景。内部流程由多个 Python 脚本串联组成,包括去重、限流、错误重试和 Notion API 适配等工程化细节,用户只需调用几个命令即可完成从抓取到输出的全过程。支持通过 arXiv ID、论文标题或 Semantic Scholar ID 指定输入论文。

지원 대상✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/RuijieH/agent-skills/tree/main/skills/citation-digest

Installed? Explore more 생산성 & 협업 skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

引用文献速览(citation-digest)

입력된 논문을 바탕으로, "누가 인용했는지 + 각 논문이 어떤 문제를 해결하려는지 + 주제별 그룹화" 결과를 markdown 또는 Notion 페이지로 출력합니다.

파이프라인은 네 단계로 구성되며, 스크립트가 이미 캡슐화되어 있으므로 새로 만들지 마십시오:

s2_citations.py  →  citations.json    누가 인용했는지 (인용 수/날짜/DOI/arXiv 포함)
kimi_q1.py       →  kimi.json         각 논문의 Kimi Q1 원문 (구조화된 블록)
(직접 판단)      →  classify.json     분류 결과
build_content.py →  content.json + digest.md
notion_publish.py→  Notion 페이지

0. 사전 준비

  • S2 키: 우선순위는 $SEMANTIC_SCHOLAR_API_KEY, 그 다음 --key, 마지막으로 ~/.env/semantic-scholar. 키가 없어도 실행은 가능하지만 429 오류가 많이 발생하며, 스크립트가 자동으로 재시도합니다 (8회 × 12초).
  • Notion 토큰: ~/.notion-token 또는 $NOTION_TOKEN; 대상 페이지는 반드시 이 integration과 먼저 공유되어야 검색이 가능합니다.

1. 인용 정보 가져오기

python3 scripts/s2_citations.py --title "MP-GUI: Modality Perception with MLLMs for GUI Understanding" --out citations.json
# 또는 --arxiv 2503.14021 / --paper-id 0e931ba8...

스크립트에는 여러분이 반드시 겪게 될 세 가지 규칙이 내장되어 있습니다:

  1. 중복 제거: S2는 동일한 arXiv 논문을 두 개의 레코드로 반환하는 경우가 잦습니다 (예: "A Survey on ..."과 "A Summary on ...", 하나는 ArXiv ID, 다른 하나는 DOI 10.48550/arXiv.xxxx만 있음). arXiv id → DOI → 제목 순으로 중복을 제거하고, 인용 수가 높은 레코드를 유지합니다.
  2. 20편 초과 시 상위 10개만 유지: --max-total 20 --top 10을 통해, 인용 수 상위 10개 ∪ 날짜 상위 10개를 유지합니다. 기본적으로 활성화되어 있으므로 별도로 필터링하지 마십시오.
  3. 제목 매칭: 검색 인터페이스는 토큰 중복도가 가장 높은 결과를 선택합니다; 점수가 <0.55인 경우 stderr에 후보 목록을 출력하여 사용자에게 동일 논문인지 확인을 요청합니다.

먼저 citations.json의 source.citationCount를 확인하세요. 이 값이 보고할 "인용 수"입니다.

2. Kimi 요약 가져오기

python3 scripts/kimi_q1.py --in citations.json --out kimi.json --sleep 10 --resume
  • POST https://papers.cool/arxiv/kimi?paper=<arxiv_id> 엔드포인트를 사용합니다 (로컬 papers-cool MCP의 하부 구현과 동일). 반드시 User-Agent / Origin / Referer 헤더를 포함해야 하며, 그렇지 않으면 차단됩니다.
  • HTML FAQ 형식의 응답이 반환되며, 오직 Q1, "이 논문은 어떤 문제를 해결하려는가?" 부분만 추출하여 구조화된 블록으로 변환합니다: ### → heading_3, - → bulleted_list_item, **bold** → 굵게. 원문을 그대로 가져오며, 압축하거나 수정하지 않습니다.
  • papers.cool은 arXiv 외에도 venue 섹션을 지원합니다: /venue/<CODE>.<YEAR>. CODE는 다음과 같습니다: AAAI/ACL/COLM/COLT/CoRL/CVPR/ECCV/EMNLP/ICCV/ICLR/ICML/IJCAI/INTERSPEECH/IWSLT/MICCAI/MLSYS/NAACL/NDSS/NeurIPS/OSDI/UAI. 스크립트는 arXiv ID가 없는 논문에 대해 자동으로 이 우회 경로를 사용합니다: /venue/<CODE>.<YEAR>?show=5000 리스트 페이지에서 id="title-<pid>"로 제목을 매칭하여 paper id를 얻은 후 (형식: 49@2026@IJCAI; IJCAI의 시퀀스 번호는 DOI의 끝자리와 같습니다), POST /venue/kimi?paper=<pid>를 호출하여 동일한 FAQ HTML을 반환받습니다. venue 리스트 페이지는 기본적으로 25개만 제공하므로 ?show= 파라미터를 반드시 포함해야 합니다.
  • 두 경로 모두 실패하는 경우 (IEEE MIPR, AIoTC 등 papers.cool이 수집하지 않는 학술지), missing 목록에 추가되고 요약문이나 제목으로 대체됩니다. 반드시 페이지에 "Kimi 요약 아님"을 표시해야 합니다 — build_content.py / notion_publish.py는 source != "kimi"인 경우 자동으로 ⚠️ 표시를 추가하며, classify.json의 notes에 사유를 명시해야 합니다.
  • --sleep 10은 2보다 안정적입니다; 캐시되지 않은 논문의 경우 Kimi가 실시간으로 계산해야 하므로 단일 논문에 60-90초가 소요될 수 있습니다. 각 논문을 가져올 때마다 --out 파일에 기록하며, 중단된 경우 --resume 플래그를 사용하여 재개할 수 있습니다.
  • ⚠️ pkill -f kimi_q1.py를 사용하지 마십시오: 여러 Claude 세션이 동시에 이 스킬을 실행할 때 서로를 잘못 종료할 수 있습니다 (실제로 26편의 가져온 결과가 디스크에 기록되기 전에 손실된 사례가 있습니다). 백그라운드에서 실행해야 한다면 먼저 cp scripts/kimi_q1.py <scratchpad>/pcfetch_<세션ID>.py로 복사하여 독립적인 프로세스 이름을 사용하십시오.

3. 분류 (직접 수행, 스크립트가 하지 않음)

classify.json 파일을 작성하십시오:

{
  "categories": [
    {"name": "🧩 시나리오 혁신 / 문제 혁신", "desc": "새로운 작업, 새로운 벤치마크, 새로운 평가 차원, 또는 문제를 재정의한 경우",
     "papers": ["2503.14021", "10.1109/CVPR52734.2025.02766", "Exact Title"]},
    {"name": "🔧 기술 개선", "desc": "문제는 알려져 있고, 기여는 방법/훈련 절차/시스템/아키텍처에 있음",
     "papers": ["..."]},
    {"name": "📚 리뷰에 한정", "desc": "새로운 방법이나 작업을 제안하지 않으며, 가치는 맥락과 미해결 문제 정리에 있음",
     "papers": ["..."]}
  ],
  "notes": {"2504.20464": "이 논문은 S2에 중복 레코드가 두 개 있으며, 병합 완료"}
}

papers에는 arXiv id, DOI, 제목 중 하나를 사용할 수 있습니다 (정확히 일치 또는 포함 매칭). 분류되지 않은 논문은 자동으로 "❓ 미분류"에 포함되며, 조용히 사라지지 않습니다.

판단 기준 (사용자가 별도로 지정하지 않은 경우 다음 세 가지를 사용):

  • 시나리오 혁신 / 문제 혁신: 새로운 작업, 새로운 벤치마크, 새로운 평가 차원을 제안 (예: "최종 상태만 보는 것이 아니라 과정을 봐야 함"), 또는 어떤 현상을 문제로 재정의 (예: "도구가 고장났는데 사용하지 않음").
  • 기술 개선: 문제가 이미 인정되었으며, 기여는 방법, 훈련 절차, 시스템 구현, 아키텍처에 있음.
  • 리뷰에 한정: Survey / Review / Position 논문이며, 실험 가능한 새로운 방법을 제안하지 않음.
  • 경계 사례 (벤치마크를 문제 혁신으로 볼지 별도 분류로 볼지, 분석형 논문의 분류) — 위 기준에 따라 우선 판단한 후, 응답에 판단 근거를 한 문장으로 설명하고 단순히 조용히 분류하지 마십시오.

본문 레이블: 일반 논문은 "해결하려는 문제", 리뷰 논문은 "핵심 통찰"을 사용 — 그러나 Q1 원문을 그대로 가져오므로 일반적으로 레이블을 추가하지 않고, 원문이 스스로 말하도록 합니다.

4. 조립 + 출력

python3 scripts/build_content.py --citations citations.json --kimi kimi.json \
    --classify classify.json --out content.json --md digest.md

5. Notion에 게시

python3 scripts/notion_publish.py --content content.json --page-title "topic论文阅读"
# 또는 --page-id xxx; 기존 내용을 덮어쓰려면 --replace 추가

구조는 다음과 같이 고정됩니다: 논문 제목으로 명명된 최상위 toggle → 설명 단락 + 세 개의 분류 toggle → 각 논문당 하나의 toggle (첫 번째 줄은 회색 메타 정보: 발행처 · 날짜 · 인용 N회 · arXiv:xxx, 클릭 가능; 아래는 Q1 원문 블록).

문제점 (모두 실제로 겪은 사례)

증상원인 / 해결 방법
POST /v1/blocks/{id}/children → 400 invalid_request_url이 Integration은 PATCH 추가만 허용; notion_publish.py는 이미 PATCH를 사용합니다.
기존 블록을 "이동"하고 싶을 때Notion에는 move API가 없습니다. 재구성해야 함: 이전 블록 읽기 → 새 부모에 재구성 → 이전 블록 삭제.
블록 삭제 시 Can't edit block that is archived 오류DELETE /v1/blocks/{id} 사용 (일단 PATCH {archived:true}를 하면 더 이상 수정할 수 없습니다).
단일 rich_text가 너무 김각 단락은 ≤2000자; seg()가 자동으로 1900자 단위로 분할합니다 (긴 영문 초록에서 자주 발생, 실제로 2063자 사례 있었음).
PATCH /blocks/{id}/children → 400 ... start_cursor provided is invalidNotion 최종 일관성 문제: 방금 생성한 블록에 바로 내용을 추가하면 발생 가능. 쓰기는 대개 성공. 바로 GET children을 해도 0개의 자식 블록이 반환될 수 있음. req()에 이 400에 대한 백오프 재시도가 구현되어 있음. 문제 해결 시 서둘러 전체 페이지를 재전송하지 말고, 우선 최상위 toggle을 순회하며 실제 구조를 확인하십시오.
전체 페이지 재전송 전스크립트는 멱등적이지 않으므로, 그냥 다시 실행하면 최상위 toggle이 하나 더 추가됩니다. 먼저 DELETE /v1/blocks/<이전 최상위 toggle id> (로그의 root toggle: 행 참조)를 실행한 후 재실행하십시오.
한 번에 너무 많이 추가각 요청은 ≤100 블록 (스크립트는 80개 단위로 분할).
중첩이 생성되지 않음단일 요청은 최대 두 단계까지: toggle의 children 안에 toggle을 넣는 것은 가능하지만, 세 단계 이상은 여러 번 append해야 합니다.
S2가 계속 429 반환정상입니다. 백오프 재시도; 병렬 요청은 더 쉽게 걸리므로, 직렬 + sleep 사용.

마무리 전 자가 점검

  • citations.json.source.citationCount와 실제 나열된 논문 수가 일치 (<=20이면 전체 나열; >20이면 두 목록의 합집합).
  • 각 논문에 메타 정보 행이 있음 (인용 수 필수), arXiv가 있는 경우 클릭 가능한 링크.
  • Kimi 원문이 없는 논문은 모두 사유가 표시됨 (⚠️ 표시 + notes).
  • Notion 최상위에는 하나의 toggle만 존재 (재전송으로 인한 중복 없음).
  • 분류된 항목 수 + 미분류 수 = 총 논문 수.
  • Notion에서 임의의 toggle 하나를 확인: 제목 → 메타 정보 → Q1 원문 (소제목/목록/굵은 글씨 모두 정상).

관련 스킬