agentsclimarketplace

Pdf metadata filler

Skill eUmeda/pdf-metadata-filler

論文PDFの Title/Author/DOI を自動補完する。「PDFのメタデータを埋めたい」「論文PDFにメタデータがない」「PDFのメタデータ補完」「PDF走査して補完」「/pdf-meta」「/pdf-metadata」で使用。ファイル名DOI→本文DOI→OpenAlex→CrossRef→CiNii(和文紀要)→OCR→LLM(Gemini/Groq)の多段で書誌を取得し pypdf/exiftool で書込。From its SKILL.md

Install
npx -y skills add eUmeda/pdf-metadata-filler

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

5.8 KB, ~2.1k tokens by cl100k_base, as published. Nobody here has run it

PDF Metadata Filler

PDF ディレクトリの Title/Author/DOI 欠損を多段フォールバックで補完する。 エンジンは OpenAlex/CrossRef/CiNii + OCR + LLM(Gemini/Groq, REST 直叩き)。 (earlier private tooling を統合・置換した公開版, 2026-06)

取得チェーン(fill_pdf_metadata.py

ファイル名DOI → 本文DOI → OpenAlex(DOI) → CrossRef(DOI)
            → OpenAlex(title) → CrossRef(title) → CiNii(title=和文紀要に強い)
            → (スキャンPDF) OCR(eng+jpn) → LLM テキスト提案(Groq→Gemini)
  • 書込: 本体は pypdf(アトミック書込: .pdf.tmpos.replace。元 PDF は失敗時も無傷)。 helper の upgrade_matched.py / fuzzy_fill.py は exiftool 書込。
  • バックアップ契約(全書込スクリプト共通): 変更前に <name>.pdf.bak未存在時のみ作成。 既存 .bak は原本なので再実行でも決して上書きしない。バックアップ失敗時はそのファイルを書き込まない。
  • DOI は /Subject に格納(dedup キー)。title 類似度ゲート(0.6) で誤一致抑止。 LLM は本文に無ければ doi 空(捏造禁止)。

スクリプト(scripts/

script役割
fill_pdf_metadata.py本体。<dir> [--dry-run] [--only-list FILE] [--redo] [--keys PATH]
verify_proposals.pyLLM提案(done_groq_proposal)のタイトルを OpenAlex/CrossRef/CiNii 照合 → matched/unmatched/no_title/error(read-only。error=API一時障害、再実行で再照合)
upgrade_matched.pymatched を実 DOI/著者で格上げ(exiftool) → status done
fuzzy_fill.pyno-title を 強制OCR(eng+jpn)+ファイル名で LLM ファジー全埋め → done_fuzzy(LLM 必須・キー未設定は設定エラーで即終了)
  • helper 3 スクリプトは対象 dir を第1引数(または環境変数 PAPERS_DIR)で受け取る。未指定は明示エラー。
  • --keys PATH は全スクリプト共通。既定の解決順: --keys → リポジトリ直下(scripts/ の親)の api_keys.json →(fill_pdf_metadata.py のみ)走査対象 dir
  • 書込対象パスは対象 dir 内に限定(containment チェック。../ 等で外の PDF は書き換えない)。
  • helper は exiftool / tesseract を起動時に確認し、無ければ LLM トークン消費前に終了する。

標準運用: ①fill_pdf_metadata.py <dir> --dry-run で件数確認 → ②本実行(in-place, .bak退避) → ③verifyupgrade→(必要なら)fuzzy

無料枠ガード(オーバーフロー防止)

プロバイダ別日次トークン予算 + RPM スロットル + プロンプト縮小 + 429/5xx の Retry-After 尊重バックオフ。 予算超過・走行中 429 は失敗でなく deferred_quota(翌日 resume で継続)。 書誌 API の一時障害(429/5xx/接続断)は deferred_api で保留し、未検証の LLM 提案にフォールバックしない。 モデル不存在(404)等の恒久エラーは当該プロバイダを無効化(誤って翌日に保留しない)。 LLM 優先 Groq→Gemini。使用量は対象 dir の _llm_usage.json に永続化。 --only-list FILE が空のときは「対象0件」(全走査にフォールバックしない安全策)。

status 規約(信頼度)

done=API検証済(高信頼) / done_ocr_fallback=ヒューリスティックOCR(未検証) / done_groq_proposal=LLM提案(未検証) / done_fuzzy=OCR+ファイル名のLLMファジー(未検証) / deferred_quota=LLM無料枠待ち / deferred_api=書誌API一時障害(再実行で継続) / failed

書込フィールド

/Title=論文タイトル, /Author=第一著者(複数は "First et al."), /Subject=DOI: … | 誌名 | 年, /Keywords=DOI。

鍵・依存

  • api_keys.json(雛形 api_keys.example.json): openalex.emailopenalex.api_keycinii.appidgemini.api_key/modelgroq.api_key/model実鍵は commit/同期しない(gitignore)。
  • OpenAlex は 2026-02-13 以降 API キー必須(無料)。未設定なら警告のうえテスト枠で試行、 401/403/409 で OpenAlex 段をスキップ。CiNii は appid 必須(NII 開発者登録・無料)、未設定なら CiNii 段スキップ。
  • メールが空/プレースホルダ(example.com / your-email 等)のとき mailto は一切送信しない(匿名 User-Agent)。
  • Gemini 無料枠は送信テキストが Google の製品改善(人手レビュー含む)に使われうる。機密 PDF は有料枠か Groq を使う。
  • 依存: pypdf requests pypdfium2 pytesseract Pillow + tesseract(eng+jpn) + exiftool(helper 書込用)。 LLM SDK(groq / google-generativeai)は不要(requests による REST 直叩き)。
  • 実行時 state(pdf_metadata_status.json / _llm_usage.json / _proposals_verified.csv)は すべて対象 papers ディレクトリ側に置く。壊れた state は *.corrupt-<時刻> に退避して保全。
  • 自動再開(launchd/cron)・creds 管理・大規模運用は各自の環境に合わせて構成すること。

CiNii(和文紀要) 対応を内蔵。OCR/LLM 経路で scan PDF にも対応。 dedup / quarantine スクリプトは本 repo の範囲外(Roadmap 参照)。

What ships with it: 10 files

121.1 KB alongside SKILL.md, 4 of them executable

scripts/

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.