Communitygithub.com

LPSlv/doc-extract

Agent-Fertigkeit zum korrekten Lesen von PDFs: schnelle lokale Textextraktion plus Vision nur für das, was sie nachweislich übersehen hat – Diagramme, gescannte Seiten und fehlstrukturierte Tabellen.

Was ist doc-extract?

Diese Fertigkeit (Skill) ermöglicht es KI-Agenten, PDFs und Office-Dokumente effizient zu verarbeiten, indem sie zuerst eine schnelle, lokale Textextraktion durchführt und nur bei visuell komplexen Elementen (z. B. Diagramme, gescannte Seiten, nicht strukturierte Tabellen) teure Vision-API-Aufrufe tätigt. Sie unterstützt die Formate PDF, DOCX, XLSX, PPTX und Bilddateien und entscheidet anhand des Inhalts, nicht der Dateierweiterung. Der Skill reduziert die Kosten und Latenz erheblich, indem er nachweislich übersehene Inhalte identifiziert und nur für diese Vision-Aufrufe durchführt. Die Ergebnisse werden als JSON-Objekt ausgegeben, das den Status, den Artifact-Pfad und eine Liste der noch ausstehenden Vision-Items enthält. Der Skill ist deterministisch und zwischengespeichert, sodass wiederholte Verarbeitung derselben Datei keine Kosten verursacht. Er eignet sich besonders für das Extrahieren von Text, das Transkribieren gescannter Seiten, das Erkennen von Tabellen und die Beschreibung von Diagrammen und Bildern in Dokumenten.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add LPSlv/doc-extract

In Ihrer bevorzugten KI fragen

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

Dokumentation

Was macht doc-extract?

Die Textextraktion erledigt die meisten Dokumente von allein. Dieser Skill verwendet dafür schnelle lokale Engines und setzt Vision-Aufrufe nur für das ein, was er nachweislich übersehen hat — Abbildungen, gescannte Seiten und Tabellen, die er nicht strukturieren konnte.

Liest .pdf, .docx, .xlsx, .pptx und Bilddateien. Das Format wird durch den Inhalt bestimmt, nicht durch die Dateierweiterung.

Wann dieser Skill NICHT verwendet werden sollte

  • Zusammenführen, Teilen, Formularausfüllen, Verschlüsselung → anthropics/skills@pdf.
  • Ein Dokument, aus dem Sie nur eine Zahl benötigen und dessen Seite Sie bereits kennen → einfach lesen.

Erfordert uv. Sonst nichts; Abhängigkeiten werden beim ersten Durchlauf aufgelöst.

1. Konvertieren

uv run <skill-verzeichnis>/convert.py DATEI [WEITERE ...]
uv run <skill-verzeichnis>/convert.py DATEI --inline    # Beschreibungen an der Position des Bildes

Ein JSON-Objekt pro Dokument, auf stdout. Alles Deterministische ist nun erledigt: Text extrahiert, Bilder geschrieben, Artifact zwischengespeichert. Der Exit-Code ist ungleich Null, wenn ein Dokument fehlgeschlagen ist.

{"status":"ok","artifact":"/home/…/<sha>-<tag>","cached":false,
 "doc_md":"…/doc.md","pages_dir":"…/pages","manifest":"…/manifest.json",
 "pending":[{"id":"p007-render","page":7,"kind":"page_render",
             "reason":"dense_grid","path":"…/images/p007-render.png"}],
 "dropped":6,"over_scale_guard":false,"scale_guard":15}

Prüfen Sie zuerst status. encrypted, unreadable und unsupported sind endgültig – melden Sie dies und fahren Sie fort; der Batch wird fortgesetzt. Die erneute Ausführung derselben Datei gibt sofort cached: true zurück und verursacht keine Kosten.

Wenn over_scale_guard wahr ist, teilen Sie dem Benutzer mit, wie viele Aufrufe benötigt werden, und holen Sie dessen Zustimmung ein, bevor Sie fortfahren. Ein 84-seitiger Scan sind 84 Aufrufe, und ein 40-bildriger Foliensatz ebenfalls.

2. Jedes ausstehende Element betrachten

pending ist leer → Sie sind fertig, fahren Sie mit Schritt 3 fort.

Andernfalls: Lesen Sie für jeden Eintrag die Datei unter path und schreiben Sie dann, was Sie gesehen haben:

uv run <skill-verzeichnis>/describe.py <artifact> <id> "Ihre Beschreibung"
# oder eine lange per Pipe: … describe.py <artifact> <id> -

Wie die Beschreibung geschrieben wird, hängt von reason ab – siehe reference/describing-visuals.md:

reasonWas zu schreiben ist
standalone_raster, curves, diagonalsBeschreiben Sie die Abbildung: Typ, was sie zeigt, Achsen und Einheiten, bemerkenswerte Werte, aller lesbarer Text.
no_text_layerSeite wörtlich transkribieren. Dies ist der OCR-Pfad; es gibt überhaupt keinen Text.
dense_grid, stroke_gridEine Tabelle, die der Extraktor nicht strukturieren konnte. Geben Sie sie als Markdown-Tabelle wieder.
raster_gridEine Seite mit vielen Bildern – eine zusammengesetzte Abbildung oder ein als Streifen gespeichertes Foto. Beschreiben Sie, was die Panels zusammen zeigen, dann alles Besondere pro Panel.

describe.py kann bedenkenlos erneut ausgeführt werden – es ersetzt statt zu verdoppeln, sodass ein Vision-Durchlauf, der auf halbem Weg abbricht, einfach fortgesetzt werden kann.

Elemente mit kind: "native_chart" erscheinen niemals in pending. Dies sind Tabellenkalkulationsdiagramme, deren Datenreihen aus der Diagrammdefinition ausgelesen wurden, sodass ihre Zahlen exakt sind und nicht aus Pixeln geschätzt werden.

3. Antworten

  • Gesamtes Dokument: doc.md.
  • Eine bestimmte Frage: Durchsuchen Sie die Dateien pro Einheit und lesen Sie nur die, die Sie benötigen.
  • Zitieren Sie nach Einheit oder stellen Sie den Dateinamen mehrerer Dokumente voran ([report.pdf:p12]).
FormatEinheitZitieren alsDatei pro Einheit
LangSeite[p12]pages/p012.md
PowerPointFolie[s07]pages/u007.md
ExcelTabelle[Sheet2]pages/u002.md
WordÜberschrift Ebene 1[Budgetannahmen]pages/u003.md
Bildgesamte Datei[img]pages/u001.md

Office-Einheitendateien sind nummeriert statt benannt, da ein Blatt namens Q1 P&L / draft kein Dateiname ist. manifest.json enthält eine units-Liste, die jeder Datei ihre Bezeichnung in der richtigen Reihenfolge zuordnet.

Die eine Regel

Bearbeiten Sie doc.md niemals von Hand. Alles, was Sie hinzufügen, geht durch describe.py, das es in Trennzeichen einschließt. Dadurch kann der Benchmark die Ergänzungen entfernen und nachweisen, dass der Skill die Textextraktion nicht verschlechtert. Direktes Bearbeiten würde diese Garantie stillschweigend aufheben.

Wo Beschreibungen landen, und das eine, was --inline nicht verspricht

Standardmäßig wird jede Beschreibung als ein Block am Ende von doc.md angefügt, gekennzeichnet mit [s02], [p12] oder [Sheet2]. --inline platziert jeden Block stattdessen an der Position seines Bildes. Übergeben Sie diesen Parameter zur Konvertierungs-Zeit, nicht an describe.py: die Platzierung wird im Artifact (und in dessen Cache-Schlüssel) festgehalten, sodass ein fortgesetzter Vision-Durchlauf die beiden nicht vermischen kann.

FormatWoran --inline verankern kann
PowerPointdie eigene Zeile des Bildes, wenn diese nachweislich die des Bildes ist; andernfalls das Ende der Folie
Worddas Ende des Abschnitts, in dem das Bild sitzt – anydoc rendert ein Bild als seinen Alternativtext, und Word schreibt keinen, es sei denn, der Autor hat einen eingegeben, daher gibt es normalerweise keine Zeile zur Verankerung
Exceldas Ende des Blattes – Bilder und Diagramme stammen aus dem Paket, und anydoc rendert keines von beiden
PDF, Bildnichts. --inline ändert nichts für ein PDF

Der Block wird neben die Zeile der Engine eingefügt, niemals durch sie ersetzt. Deshalb bleibt die Byte-Identität erhalten – eval/gate.py führt beide Platzierungen aus und schlägt bei direkter Bearbeitung fehl.

Was --inline nicht verspricht, ist, dass die Position korrekt ist; die Byte-Identität kann die Platzierung nicht prüfen, da eine Einfügung unabhängig von ihrer Position wiederhergestellt wird. Der Anker ist der Alternativtext von anydoc, der gewöhnlicher Text ist: Eine Folie über eine Datei namens image.png rendert dieselbe Zeile wie ein Bild. Daher wird die eigene Zeile eines Bildes nur verwendet, wenn die Anzahl der Kandidatenzeilen in dieser Einheit der Anzahl der darin enthaltenen Bilder entspricht; andern- falls fällt die Beschreibung auf die Einheitengrenze zurück. Positionen sind entweder nachweislich die des Bildes oder eine Einheitengrenze – niemals eine Vermutung zwischen zwei gleich aussehenden Zeilen.

Warum die Filter genau so sind, wie sie sind

Vereinfachen Sie diese nicht – jeder existiert, weil die offensichtliche Alternative an echten Dokumenten getestet und für unzureichend befunden wurde:

FilterWarum
Bilder auf >50 % der Einheiten, <120px, Seitenverhältnis >8:1 verwerfenEin 14-seitiges Grant-PDF hatte 69 Bildplatzierungen: 7 verschiedene Objekte, sechs davon Logos, Linien und ein Seitenleistenstreifen.
Seiten überspringen, die bereits eine Markdown-Tabelle ergeben habenDer Extraktor ist bei Tabellen, die er parsen kann, besser als Vision. Nur eingreifen, wenn er nichts produziert hat.
Striche in beiden Ausrichtungen erfordernUnterstreichungen und Linien sind nur horizontal. Das Zählen aller achsenparallelen Striche löste bei Bibliographieseiten und Verträgen mit unterstrichenen Überschriften aus.
diagonals von der Flächenuntergrenze ausnehmen4+ diagonale Segmente kommen in Fließtext nicht vor, und die Untergrenze verhinderte Diagramme in einer Seitenecke.
Tintenschwellwert beim dichten GitterzweigTrennt eine schattierte Tabelle, die der Extraktor übersehen hat, von dekorativen Abschnittsbannern.
Seiten mit >6 Rastern zu einem einzigen Render zusammenfassenEin 48-Bild-Inpainting-Vergleich ist eine einzige Abbildung, und ein TI-Paketfoto kommt als 12 Streifen; Einzelaufrufe pro Kachel kosten ~2× die Tokens und verlieren die Komposition. Seiten mit 5–6 Rastern sind manchmal separate Abbildungen, daher liegt die Grenze bei 6.
EMF, WMF und OLE-Payloads verwerfenVon der Text-Engine originalgetreu beibehalten, aber ohne Rasterisierer nicht lesbar – eine Weiterleitung an pending würde ein Element erzeugen, das kein Agent bearbeiten kann. In dropped gezählt, niemals stillschweigend verworfen.

harvest.py ist die einzige Quelle der Wahrheit für das PDF-Routing, und filters.py für die Teile, die für jedes Format gelten. Jede Zahl in der README und im Design-Spezifikationsdokument wird aus ihnen neu generiert; bearbeiten Sie niemals eine Zahl von Hand. Wenn Sie eine Datei nicht ausführen können, ist reference/harvest-block.md eine eigenständige Kopie zum Kopieren und Ausführen.

Das Office-Routing ist bewusst dünner, und das ist ehrlich

Eine PDF-Seite ist ein Programm von Zeichenbefehlen, das seine Abbildungen verbirgt, weshalb harvest.py sie aus der Vektorgeometrie ableitet. OOXML deklariert seine Bilder im Paket, also gibt es nichts abzuleiten. Office- Dokumente erhalten die Einrichtungsfilter, den Zitier- und Cache-Vertrag sowie diese Richtlinie – aber keinen render_reason, kein raster_grid und keinen cost_guard, da es ohne Rendering-Engine keine Folie oder kein Blatt zum Rendern gibt.

Verwandte Skills