Zitierungs-Digest (citation-digest)

Gibt zu einer eingegebenen Arbeit alle zitierenden Arbeiten aus, fasst deren Kernfrage („Welches Problem will diese Arbeit lösen?“) zusammen, gruppiert sie nach Kategorien und erzeugt eine Markdown-Datei oder eine Notion-Seite.

Was ist Zitierungs-Digest (citation-digest)?

Dieses Skill verarbeitet eine wissenschaftliche Publikation und erstellt einen strukturierten Überblick über alle Arbeiten, die sie zitieren – angereichert mit der Kernfrage jeder zitierenden Arbeit (basierend auf der Kimi-Zusammenfassung von papers.cool), gruppiert in benutzerdefinierte Kategorien, und ausgegeben als Markdown oder in einer Notion-Seite mit verschachtelten Toggles. Die Pipeline besteht aus fünf aufeinanderfolgenden Skripten: `s2_citations.py` ruft Zitationsdaten von Semantic Scholar ab (mit automatischer Deduplizierung und Priorisierung der Top-20 anhand von Zitationszahlen und Erscheinungsdatum). `kimi_q1.py` extrahiert für jede zitierte Arbeit die originale „Q1“-Antwort („Welches Problem versucht diese Arbeit zu lösen?“) von papers.cool, entweder über arXiv-ID oder über die Venue-Seite für Konferenzbeiträge ohne arXiv-ID. Der Benutzer erstellt dann eine `classify.json`, um die Arbeiten nach vorgegebenen Kriterien (Szenario-Innovation, technische Verbesserung, reiner Survey) zu gruppieren. `build_content.py` setzt alles zu einem Markdown-Dokument zusammen, und `notion_publish.py` veröffentlicht die Struktur als Notion-Seite mit der festen Hierarchie: ein Root-Toggle (benannt nach der ursprünglichen Arbeit) → Beschreibung → Kategorie-Toggles → ein Toggle pro Arbeit (mit Metadaten und Q1-Originaltext). Das Skill behandelt zahlreiche Fallstricke wie Raten-Limits von Semantic Scholar, fehlende Kimi-Zusammenfassungen, Notion-API-Besonderheiten (PATCH statt POST, Zeichenbegrenzung, Tiefenbeschränkung) und stellt sicher, dass keine Arbeit stillschweigend verloren geht.

Funktioniert mit✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/RuijieH/agent-skills/tree/main/skills/citation-digest

Installed? Explore more Produktivität & Zusammenarbeit skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Was macht Zitierungs-Digest (citation-digest)?

Gib eine Arbeit ein, erhalte eine Ausgabe mit „Wer zitiert sie + was will jede zitierende Arbeit lösen + gruppiert nach Kategorien“, als Markdown oder Notion-Seite.

Die Pipeline besteht aus vier Schritten, die Skripte sind bereits fertig – nicht neu erfinden:

s2_citations.py  →  citations.json   Wer zitiert sie (mit Zitationszahl/Datum/DOI/arXiv)
kimi_q1.py       →  kimi.json        Originaltext der Kimi Q1 jeder Arbeit (strukturierte Blöcke)
(Du bestimmst)   →  classify.json    Klassifikationsergebnis
build_content.py →  content.json + digest.md
notion_publish.py→  Notion-Seite

0. Voraussetzungen

  • S2-Key: Bevorzugt $SEMANTIC_SCHOLAR_API_KEY, dann --key, zuletzt ~/.env/semantic-scholar. Ohne Key läuft es auch, aber 429-Fehler häufen sich; das Skript wiederholt automatisch (8× mit 12s Verzögerung).
  • Notion-Token: ~/.notion-token oder $NOTION_TOKEN; die Zielseite muss zuerst mit dieser Integration geteilt werden, sonst findet die Suche sie nicht.

1. Zitate abrufen

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

Das Skript enthält drei Regeln, die du mit Sicherheit selbst übersehen würdest:

  1. Deduplizierung: S2 gibt oft denselben arXiv-Artikel zweimal zurück (z.B. „A Survey on ...“ und „A Summary on ...“, einmal mit ArXiv, einmal nur mit DOI 10.48550/arXiv.xxxx). Es wird nach arXiv-ID → DOI → Titel dedupliziert, wobei der Eintrag mit der höheren Zitationszahl behalten wird.
  2. Bei mehr als 20 Artikeln nur zwei Top-10 behalten: --max-total 20 --top 10 behält die Vereinigung aus „Top-10 nach Zitationszahl“ ∪ „Top-10 nach Datum“. Standardmäßig aktiviert – filtere nicht selbst.
  3. Titelabgleich: Die Suchschnittstelle nimmt das Ergebnis mit der höchsten Token-Ähnlichkeit; bei einem Score <0,55 werden Kandidaten auf stderr aufgelistet, damit der Benutzer bestätigen kann, ob es sich um denselben Artikel handelt.

Sieh dir zuerst citations.json unter source.citationCount an – das ist die zu berichtende „Zitationszahl“.

2. Kimi-Zusammenfassung abrufen

python3 scripts/kimi_q1.py --in citations.json --out kimi.json --sleep 10 --resume
  • Verwendet POST https://papers.cool/arxiv/kimi?paper=<arxiv_id> (genau die zugrundeliegende Implementierung des lokalen papers-cool MCP), muss User-Agent / Origin / Referer-Header setzen, sonst wird der Zugriff blockiert.
  • Gibt HTML-FAQ zurück, nimm nur Q1 „Welches Problem versucht diese Arbeit zu lösen?“ und wandle es strukturiert in Blöcke um: ### → heading_3, - → bulleted_list_item, **bold** → fett. Originaltext 1:1, keine Komprimierung oder Umschreibung.
  • papers.cool nimmt nicht nur arXiv auf, sondern auch Venue-Bereiche: /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. Das Skript geht für Arbeiten ohne arXiv-ID automatisch diesen Weg: /venue/<CODE>.<YEAR>?show=5000 Listenseite → Matche Titel via id="title-<pid>" um die Paper-ID zu erhalten (z.B. 49@2026@IJCAI, die IJCAI-Nummer ist das DOI-Endstück) → POST /venue/kimi?paper=<pid> gibt dasselbe FAQ-HTML zurück. Die Venue-Listenseite zeigt standardmäßig nur 25 Einträge, daher muss ?show= mitgegeben werden.
  • Arbeiten, bei denen beide Wege fehlschlagen (z.B. IEEE MIPR/AIoTC – nicht in papers.cool) landen in missing und fallen auf Abstract oder Titel zurück. In der Seite muss markiert werden „Keine Kimi-Zusammenfassung“ – build_content.py/notion_publish.py fügt bei source != "kimi" automatisch ein ⚠️ hinzu. Trage außerdem in classify.json unter notes den Grund ein.
  • --sleep 10 ist stabiler als 2; bei nicht gecachten Arbeiten berechnet Kimi neu, einzelne können 60–90s dauern. Nach jedem Artikel wird --out geschrieben; bei Unterbrechung mit --resume weitermachen.
  • ⚠️ Nicht pkill -f kimi_q1.py verwenden: Mehrere Claude-Sitzungen, die dieses Skill gleichzeitig ausführen, können sich gegenseitig töten (es wurden bereits 26 fertig abgerufene, aber noch nicht geschriebene Ergebnisse verloren). Wenn du es im Hintergrund laufen lassen willst, kopiere zuerst scripts/kimi_q1.py <scratchpad>/pcfetch_<Sitzungs-ID>.py und verwende einen separaten Prozessnamen.

3. Klassifikation (du machst es, nicht das Skript)

Schreibe classify.json:

{
  "categories": [
    {"name": "🧩 Szenario-Innovation / Problem-Innovation", "desc": "Neue Aufgabe, neuer Benchmark, neue Bewertungsdimension oder ein Phänomen wird als Problem neu definiert",
     "papers": ["2503.14021", "10.1109/CVPR52734.2025.02766", "Exakter Titel"]},
    {"name": "🔧 Technische Verbesserung", "desc": "Problem bekannt, Beitrag liegt in Methode/Trainingsablauf/System/Architektur",
     "papers": ["..."]},
    {"name": "📚 Reiner Survey", "desc": "Keine neue Methode oder Aufgabe, Wert liegt in Zusammenhängen und offenen Fragen",
     "papers": ["..."]}
  ],
  "notes": {"2504.20464": "Dieser Artikel hat bei S2 zwei doppelte Einträge, bereits zusammengeführt"}
}

papers kann arXiv-ID, DOI oder Titel enthalten (exakt oder teilweise übereinstimmend). Nicht abgedeckte Arbeiten landen automatisch in „❓ Nicht klassifiziert“ – werden nicht stillschweigend verloren.

Kriterien (wenn der Benutzer nichts anderes sagt, verwende diese drei):

  • Szenario-Innovation / Problem-Innovation: Neue Aufgabe, neuer Benchmark, neue Bewertungsdimension (z.B. „Nur den Endzustand zu betrachten reicht nicht, man muss den Prozess sehen“) oder ein Phänomen wird als Problem neu definiert (z.B. „Ein Werkzeug fällt aus, wird aber nicht verwendet“).
  • Technische Verbesserung: Problem allgemein anerkannt, Beitrag liegt in Methode, Trainingsablauf, Systemimplementierung, Architektur.
  • Reiner Survey: Überblicksarbeit / Review / Positionspapier, stellt keine experimentell überprüfbare neue Methode vor.
  • Grenzfälle (zählt Benchmark als Problem-Innovation oder eigene Kategorie, wohin mit analytischen Arbeiten) – entscheide nach obigen Kriterien und füge im Antworttext einen kurzen Begründungssatz hinzu, nicht stillschweigend einordnen.

Text-Label: Normale Arbeiten erhalten „Zu lösendes Problem“, Surveys erhalten „Kern-Einsicht“ – da aber der Q1-Originaltext 1:1 übernommen wird, füge normalerweise kein Label hinzu; der Originaltext spricht für sich.

4. Zusammenbau + Ausgabe

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

5. Nach Notion veröffentlichen

python3 scripts/notion_publish.py --content content.json --page-title "topic paper reading"
# oder --page-id xxx; um vorhandene Inhalte zu überschreiben, --replace hinzufügen

Struktur fest vorgegeben: Ein Root-Toggle mit dem Namen der Arbeit → Einleitender Absatz + drei Kategorie-Toggles → Ein Toggle pro Arbeit (erste Zeile graue Metadaten: Veröffentlichungsort · Datum · Zitiert N · arXiv:xxx, klickbar; darunter der Q1-Originaltext als Blöcke).

Fallstricke (alle selbst erlebt)

SymptomUrsache / Lösung
POST /v1/blocks/{id}/children → 400 invalid_request_urlDiese Integration akzeptiert nur PATCH zum Anhängen; notion_publish.py verwendet bereits PATCH
Vorhandene Blöcke „verschieben“Notion hat keine Move-API, nur Neuanlegen: Alten Block lesen → unter neuem Elternteil neu anlegen → alten Block löschen
Block löschen gibt Can't edit block that is archivedDELETE /v1/blocks/{id} verwenden (nach PATCH {archived:true} kann man ihn nicht mehr ändern)
Einzelner rich_text zu langJeder Absatz ≤2000 Zeichen; seg() teilt automatisch bei 1900 Zeichen (lange englische Abstracts ohne Kimi landen hier, getestet mit 2063 Zeichen)
PATCH /blocks/{id}/children → 400 ... start_cursor provided is invalidNotion-Ev.-Konsistenzproblem: Ein gerade erstellter Block kann beim sofortigen Anhängen diesen Fehler werfen – der Schreibvorgang ist oft trotzdem erfolgreich, und ein direktes GET children kann sogar 0 Unterblöcke anzeigen. req() wiederholt bei diesem 400 mit Backoff; bei der Fehlersuche nicht sofort die ganze Seite neu senden, sondern zuerst anhand der Root-Toggles die tatsächliche Struktur prüfen
Vor dem erneuten Senden der gesamten SeiteDas Skript ist nicht idempotent; ein erneuter Durchlauf erzeugt einen zusätzlichen Root-Toggle. Lösche zuerst DELETE /v1/blocks/<vorherige Root-Toggle-ID> (im Log unter root toggle:), dann erneut ausführen
Zu viele Blöcke auf einmal anhängenMaximal 100 Blöcke pro Request (Skript teilt bei 80)
Verschachtelung wird nicht erstelltMaximal zwei Ebenen pro Request: Toggle in Toggle geht, drei oder mehr Ebenen müssen in separaten Appends erstellt werden
S2 gibt ständig 429Normal, Backoff-Wiederholung; parallele Requests erhöhen die Wahrscheinlichkeit, seriell + sleep verwenden

Checkliste vor Fertigstellung

  • citations.json.source.citationCount stimmt mit der tatsächlichen Anzahl der aufgelisteten Arbeiten überein (≤20 alle; >20 Vereinigung der beiden Top-Listen)
  • Jede Arbeit hat eine Metadatenzeile (Zitationszahl Pflicht), bei arXiv-Arbeiten klickbaren Link
  • Arbeiten ohne Kimi-Originaltext sind mit Grund markiert (⚠️ + notes)
  • Notion hat genau einen Root-Toggle auf oberster Ebene (keine Duplikate durch erneutes Senden)
  • Anzahl Kategorien + „Nicht klassifiziert“ = Gesamtzahl der Arbeiten
  • Stichprobe in Notion: Titel → Metadaten → Q1-Originaltext (Untertitel/Liste/Fett vorhanden)

Verwandte Skills