Lewati ke konten

Ikhtisar SDK Python

Software development kit (SDK) Python NextPDF dirancang untuk aplikasi Python yang membutuhkan ekstraksi Portable Document Format (PDF) dengan informasi provenans. SDK ini mengembalikan blok terstruktur beserta jangkar kutipan, termasuk indeks halaman, tingkat keyakinan, bounding box opsional, dan pengidentifikasi node semantik ketika PDF sumber menyediakan struktur tersebut.

Gunakan SDK ini ketika alur kerja Anda perlu menjawab pertanyaan seperti “Dari halaman mana teks ini berasal?”, “Tabel mana yang mendukung nilai ini?”, atau “Apa yang berubah di antara kedua PDF ini?” tanpa memperlakukan ekstraksi PDF sebagai teks biasa tanpa provenans.

  • Klien NextPDF sinkron untuk skrip, pekerjaan batch, dan notebook.
  • Klien AsyncNextPDF asinkron untuk asyncio, FastAPI, dan runtime asinkron lainnya.
  • Antarmuka baris perintah (CLI) nextpdf untuk ekstraksi satu kali dari jalur berkas atau standard input, dengan keluaran ke standard output atau ke sebuah berkas.
  • Server Model Context Protocol (MCP) opsional yang memungkinkan agen artificial intelligence (AI) memanggil alat ekstraksi PDF secara langsung.
  • Backend jarak jauh untuk penggunaan produksi dengan NextPDF Connect.
  • Backend lokal untuk ekstraksi luring khusus library melalui pypdf.

Backend jarak jauh mengirim byte PDF ke server NextPDF Connect. Ini merupakan jalur produksi yang direkomendasikan karena memusatkan perilaku ekstraksi, autentikasi, kuota, dan kendali operasional.

Backend lokal berjalan di dalam proses Python dan membaca PDF melalui pypdf. Backend ini ditujukan untuk pengembangan luring dan pengujian PDF bertag, tetapi tidak dapat menyediakan bounding box yang presisi dan menggunakan ekstraksi heuristik tingkat paragraf untuk PDF tanpa tag. Backend lokal tersedia hanya sebagai library: injeksikan LocalBackend ke dalam AsyncNextPDF untuk menggunakannya. CLI nextpdf dan server MCP tidak dapat menggunakannya. Lihat Matriks pilihan backend untuk perbandingan lengkapnya.

SDK ini tidak melakukan optical character recognition (OCR). PDF hasil pindai atau PDF yang hanya berupa gambar memerlukan proses OCR sebelum NextPDF dapat mengekstrak teks yang tertanam. Tata letak yang rumit, teks yang tumpang tindih, dan pembuat PDF yang tidak lazim juga dapat menurunkan kualitas ekstraksi.

CLI nextpdf hanya bekerja dengan backend jarak jauh dan bukan antarmuka streaming. Setiap perintah membaca seluruh PDF ke dalam memori (dari jalur berkas atau standard input), mengirimkannya ke server NextPDF Connect, membangun hasil lengkap di dalam memori, dan menserialisasikannya dalam sekali penulisan. Anda dapat mengalihkan keluaran tersebut ke sebuah berkas dengan --output (atau -o) atau ke standard output, tetapi hasilnya di-buffer sepenuhnya, bukan dialirkan secara bertahap. CLI tidak dapat menggunakan backend pypdf lokal.

Kedua klien berbagi satu namespace metode ast untuk operasi abstract syntax tree (AST) dan mengembalikan model Pydantic yang sama. Perbedaannya hanya ada pada model konkurensinya.

Konteks AndaGunakanMengapa
Skrip dan pekerjaan batchNextPDF (sinkron)Alur kendali linear; tidak ada event loop yang perlu dikelola.
Notebook JupyterNextPDF (sinkron)run_sync mendeteksi event loop yang sedang berjalan dan mengalihkan eksekusinya ke utas pekerja, sehingga panggilan yang memblokir tetap dapat berjalan di dalam sel.
CLI nextpdfNextPDF (sinkron, internal)CLI membangun klien sinkron untuk Anda.
Layanan asyncioAsyncNextPDFawait native; tanpa penyerahan ke utas.
FastAPI, Starlette, Asynchronous Server Gateway Interface (ASGI)AsyncNextPDFMenggunakan event loop permintaan dan kumpulan koneksi yang sama.
Penyebaran konkurensi tinggiAsyncNextPDFMenjalankan banyak ekstraksi secara konkuren dengan asyncio.gather melalui satu klien dengan connection pool.

NextPDF membungkus AsyncNextPDF internal dan menjalankan setiap panggilan melalui run_sync. Di dalam event loop yang sedang berjalan, seperti di notebook, run_sync mengalihkan coroutine ke satu utas pekerja dengan loop-nya sendiri, sehingga Anda tidak mengalami galat asyncio.run bersarang. Di dalam layanan asyncio atau ASGI, panggil AsyncNextPDF secara langsung agar tidak menanggung overhead penyerahan ke utas tersebut pada setiap panggilan.

Klien asinkron memiliki httpx.AsyncClient sendiri untuk pooling koneksi, jadi gunakan kembali satu instans AsyncNextPDF dan tutup satu kali saja. Klien NextPDF sinkron tidak mengekspos metode close(). Untuk beban kerja asinkron berumur panjang, pilih AsyncNextPDF dan kelola siklus hidupnya secara eksplisit (lihat Model operasional produksi).

Setiap backend mengimplementasikan protokol PdfBackend. Backend jarak jauh (RemoteBackend) dipilih secara otomatis ketika Anda memberikan base_url dan api_key. Anda harus menginjeksikan backend lokal (LocalBackend) secara eksplisit melalui parameter backend= pada AsyncNextPDF; backend ini tidak diekspor dari paket nextpdf tingkat teratas dan tidak dapat diakses dari CLI atau server MCP.

KapabilitasJarak jauh (RemoteBackend)Lokal (LocalBackend)
Dipilih olehbase_url + api_keyAsyncNextPDF(backend=LocalBackend(...))
JaringanNextPDF Connect melalui Hypertext Transfer Protocol Secure (HTTPS)Tidak ada; berjalan di dalam proses
Autentikasi, kuota, pengukuranTerpusat di serverTidak ada
Observabilitas dan kendali operasionalSisi serverTidak ada
Ekstraksi PDF bertag (StructTree)YaYa
Ekstraksi PDF tanpa tagMesin serverPemisahan paragraf heuristik, keyakinan 0.5
Bounding boxYa (ketika server menyediakannya)Tidak (bbox bernilai None)
Ekstraksi tabel pada PDF tanpa tagMesin serverTidak mengembalikan tabel
Dapat digunakan dari CLI / server MCPYaTidak (hanya library)
Direkomendasikan untukProduksiPengembangan luring, pengujian PDF bertag

Gunakan backend jarak jauh untuk produksi karena inilah satu-satunya jalur dengan autentikasi terpusat, penegakan kuota, pengukuran, dan observabilitas. Gunakan backend lokal untuk pengembangan luring dan pengujian terhadap PDF bertag, dengan konsekuensi hasil heuristik, tanpa bounding box, dan tanpa tabel pada masukan tanpa tag.

"""Inject the local backend for offline, library-only extraction."""
from nextpdf import AsyncNextPDF
from nextpdf.backends.local import LocalBackend
async def extract_offline(pdf_bytes: bytes) -> None:
"""Extract cited text without a NextPDF Connect server."""
async with AsyncNextPDF(backend=LocalBackend()) as client:
blocks = await client.ast.extract_cited_text(pdf_bytes)
for block in blocks:
# Heuristic blocks on untagged PDFs report confidence 0.5.
print(block.citation.confidence, block.text)

Di lingkungan produksi, jalankan backend jarak jauh yang terhubung ke NextPDF Connect. Pola di bawah ini mencakup penggunaan ulang klien, penanganan galat, percobaan ulang, penanganan kuota, dan batas waktu. Setiap simbol yang digunakan di sini tersedia di dalam SDK. SDK tidak melakukan percobaan ulang untuk Anda, sehingga perulangan percobaan ulang menjadi tanggung jawab Anda.

Gunakan kembali klien dan manfaatkan pooling koneksi

Bagian berjudul “Gunakan kembali klien dan manfaatkan pooling koneksi”

RemoteBackend mempertahankan satu httpx.AsyncClient yang persisten untuk pooling koneksi. Bangun AsyncNextPDF sekali, bagikan ke seluruh permintaan, dan tutup saat penonaktifan. Jangan membuat klien baru untuk setiap permintaan.

"""Reuse one pooled async client for the lifetime of the process."""
import asyncio
import os
from pathlib import Path
from nextpdf import AsyncNextPDF
async def main() -> None:
"""Run several extractions over a single pooled client."""
base_url = os.environ["NEXTPDF_BASE_URL"]
# Treat the API key as a secret; read it from the environment, never hard-code it.
api_key = os.environ["NEXTPDF_API_KEY"]
async with AsyncNextPDF(base_url=base_url, api_key=api_key) as client:
pdf_paths = (Path("a.pdf"), Path("b.pdf"), Path("c.pdf"))
tasks = [
client.ast.get_document_ast(path.read_bytes())
for path in pdf_paths
]
documents = await asyncio.gather(*tasks)
for document in documents:
print(document.page_count, document.estimated_tokens)
if __name__ == "__main__":
asyncio.run(main())

Pengelola konteks asinkron memanggil close() saat keluar, yang menutup transport yang mendasarinya. Tanpa pengelola konteks, panggil sendiri await client.close().

SDK memunculkan hierarki eksepsi bertipe. Semua galat diturunkan dari NextPDFError; kegagalan tingkat Hypertext Transfer Protocol (HTTP) diturunkan dari NextPDFAPIError dan menyertakan status_code. Tangkap tipe spesifik yang dapat Anda tindaklanjuti, lalu kembali ke tipe dasar sebagai cadangan.

EksepsiDimunculkan ketikaAtribut utama
NextPDFErrorTipe dasar untuk setiap galat SDKstatus_code
NextPDFAPIErrorGalat HTTP apa pun dari serverstatus_code, error_code
NextPDFLicenseErrorHTTP 402; fitur membutuhkan tingkat server yang lebih tinggistatus_code (402)
QuotaExceededErrorHTTP 429; batas laju atau kuota terlampauiretry_after
AstNoStructTreeErrorHTTP 422; PDF tanpa tag dengan mode heuristik nonaktifstatus_code (422)
AstBuildTimeoutErrorHTTP 504; pembangunan AST melampaui batas waktustatus_code (504)
"""Map SDK exceptions to caller-facing outcomes."""
from nextpdf import (
AstBuildTimeoutError,
AstNoStructTreeError,
AsyncNextPDF,
NextPDFAPIError,
NextPDFError,
NextPDFLicenseError,
QuotaExceededError,
)
async def safe_extract(client: AsyncNextPDF, pdf_bytes: bytes) -> str:
"""Extract text, translating known failures into a stable status string."""
try:
blocks = await client.ast.extract_cited_text(pdf_bytes)
except QuotaExceededError as exc:
# exc.retry_after holds the server Retry-After value in seconds, or None.
return f"rate-limited; retry after {exc.retry_after}s"
except NextPDFLicenseError:
return "feature requires a higher server tier"
except AstNoStructTreeError:
return "untagged PDF; enable heuristic mode or use a tagged PDF"
except AstBuildTimeoutError:
return "build timed out; reduce the page range"
except NextPDFAPIError as exc:
return f"server error (status {exc.status_code})"
except NextPDFError:
return "extraction failed"
return "\n".join(block.text for block in blocks)

Coba ulang kegagalan sementara dengan backoff

Bagian berjudul “Coba ulang kegagalan sementara dengan backoff”

SDK tidak melakukan percobaan ulang secara otomatis. Bungkus panggilan dengan perulangan Anda sendiri yang mencoba ulang kegagalan HTTP sementara dan menghormati nilai Retry-After dari server, yang diekspos oleh QuotaExceededError sebagai retry_after (bilangan bulat dalam detik, atau None). Gunakan backoff eksponensial untuk status sementara lainnya, dan jangan mencoba ulang NextPDFLicenseError.

"""Retry transient failures with exponential backoff and Retry-After support."""
import asyncio
from collections.abc import Awaitable, Callable
from typing import TypeVar
from nextpdf import NextPDFAPIError, QuotaExceededError
_RETRYABLE_STATUS = frozenset({500, 502, 503, 504})
_T = TypeVar("_T")
async def with_retry(
coro_factory: Callable[[], Awaitable[_T]],
*,
max_attempts: int = 4,
) -> _T:
"""Call coro_factory() with bounded retries on transient server errors.
Args:
coro_factory: A zero-argument callable returning a fresh awaitable.
max_attempts: Maximum number of attempts before giving up.
Returns:
The awaited result of the first successful attempt.
Raises:
NextPDFAPIError: When all attempts fail or the error is not retryable.
"""
delay = 1.0
for attempt in range(1, max_attempts + 1):
try:
return await coro_factory()
except QuotaExceededError as exc:
if attempt == max_attempts:
raise
await asyncio.sleep(exc.retry_after if exc.retry_after is not None else delay)
delay *= 2.0
except NextPDFAPIError as exc:
if attempt == max_attempts or exc.status_code not in _RETRYABLE_STATUS:
raise
await asyncio.sleep(delay)
delay *= 2.0
raise RuntimeError("unreachable")

Penegakan kuota dan batas laju berada di server. Pada HTTP 429, SDK memunculkan QuotaExceededError dan mengurai header Retry-After ke dalam retry_after. Backend jarak jauh juga menyertakan header X-RateLimit-* pada respons render, sehingga Anda dapat membatasi laju secara proaktif sebelum mencapai batas keras.

Batas waktu permintaan menggunakan nilai standar tetap sebesar 60 detik total dengan batas waktu koneksi 10 detik (httpx.Timeout(60.0, connect=10.0)). Untuk membatasi pembangunan AST yang panjang, persempit pekerjaan dengan page_range_start, page_range_end, atau token_budget alih-alih hanya mengandalkan batas waktu; proses pembangunan yang terlalu panjang mengembalikan AstBuildTimeoutError (HTTP 504).

Pekerja batch membaca PDF, mengekstrak teks yang dikutip, dan menulis keluaran terstruktur. Gunakan kembali satu klien dengan connection pool, batasi konkurensi dengan semaphore, dan terapkan helper percobaan ulang di atas.

"""Batch-extract a directory of PDFs over one pooled async client."""
import asyncio
import os
from pathlib import Path
from nextpdf import AsyncNextPDF
async def run_batch(input_dir: Path, concurrency: int = 8) -> None:
"""Extract cited text for every PDF in input_dir, bounded by concurrency."""
semaphore = asyncio.Semaphore(concurrency)
async def worker(client: AsyncNextPDF, path: Path) -> None:
async with semaphore:
blocks = await client.ast.extract_cited_text(path.read_bytes())
out = path.with_suffix(".txt")
out.write_text("\n".join(b.text for b in blocks), encoding="utf-8")
async with AsyncNextPDF(
base_url=os.environ["NEXTPDF_BASE_URL"],
api_key=os.environ["NEXTPDF_API_KEY"],
) as client:
await asyncio.gather(*(worker(client, p) for p in input_dir.glob("*.pdf")))

Layanan FastAPI berbagi satu AsyncNextPDF di seluruh permintaan selama masa hidup aplikasi, sehingga setiap permintaan menggunakan kembali pool koneksi. Baca kredensial dari lingkungan dan perlakukan kunci API sebagai rahasia.

"""FastAPI service that shares one pooled NextPDF client across requests."""
import os
from contextlib import asynccontextmanager
from fastapi import FastAPI, UploadFile
from nextpdf import AsyncNextPDF
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Create the pooled client on startup and close it on shutdown."""
app.state.client = AsyncNextPDF(
base_url=os.environ["NEXTPDF_BASE_URL"],
api_key=os.environ["NEXTPDF_API_KEY"],
)
try:
yield
finally:
await app.state.client.close()
app = FastAPI(lifespan=lifespan)
@app.post("/extract")
async def extract(file: UploadFile) -> dict[str, list[str]]:
"""Return cited text blocks for an uploaded PDF."""
pdf_bytes = await file.read()
blocks = await app.state.client.ast.extract_cited_text(pdf_bytes)
return {"text": [block.text for block in blocks]}

Untuk agen AI, jalankan server MCP. Server ini mengekspos alat PDF (misalnya nextpdf_extract_text, nextpdf_extract_tables, nextpdf_get_ast, nextpdf_info, nextpdf_search, nextpdf_get_outline, nextpdf_diff, dan nextpdf_health) melalui standard input dan output. Server membaca NEXTPDF_BASE_URL dan NEXTPDF_API_KEY dari lingkungan, sehingga menggunakan backend jarak jauh; seperti CLI, server tidak dapat menggunakan backend lokal. Instal ekstra opsional dan jalankan modulnya.

Terminal window
pip install "nextpdf[mcp]"
python -m nextpdf.mcp

Lihat Server MCP Python untuk panduan integrasi agen, CLI Python untuk penggunaan terminal, dan Referensi API Python untuk seluruh antarmuka klien, model, dan eksepsi.