Pro edition
Classifier
At a glance
Section titled “At a glance”NextPDF\Pro\Classifier assigns a document type (invoice, contract, report,
and so on) and a detected language using deterministic heuristics over the
document text and structure. It is rule-based, not a machine-learning model.
Availability & licensing
Section titled “Availability & licensing”This capability ships in NextPDF Pro (nextpdf/pro) and activates with a Pro-tier license envelope. A deployment without that entitlement does not load the capability’s classes. Compare editions and get a license.
No runtime capability flag gates this module. The classifier classes are available whenever nextpdf/pro is installed.
Install
Section titled “Install”composer require nextpdf/pro:^3Conceptual overview
Section titled “Conceptual overview”DocumentClassifier orchestrates three collaborators:
StructureAnalyzerinspects the PDF for page count, image and font counts, and form/signature fields, producing aStructureAnalysis.HeuristicClassifier(the defaultClassifierInterface) scores the text against per-type keyword dictionaries and applies structural heuristics (for example, short documents bias away from “report”), yielding aDocumentTypeand a confidence.LanguageDetectoridentifies the language from character-trigram frequency profiles for ten languages, falling back to English below a confidence threshold.
classifyFromText() accepts already-extracted text (with optional raw PDF
bytes for structure); classifyFromFile() accepts raw PDF bytes and extracts
text by parsing the §9.4 text-showing operators directly.
Why it works this way
Section titled “Why it works this way”The load-bearing decision is to classify with deterministic heuristics, not a machine-learning model. A rule-based pipeline is a pure function of its input: identical bytes always yield an identical type, confidence, and language, with no model drift and no network call. That determinism lets the result expose an explicit confidence, an isConfident() gate, and a per-type scores map, so the module shows how it decided rather than hiding the choice behind a model. Callers therefore route low-confidence documents to manual review by contract, and text too short to score falls back to en under the same fixed rule. The trade is deliberate: accuracy is bounded by fixed keyword and trigram profiles, in exchange for reproducibility, inspectability, and a classifier that runs entirely in-process.
Design background: An API that refuses to guess.
Behavior contract
Section titled “Behavior contract”- Input. Extracted text (
classifyFromText) or raw PDF bytes (classifyFromFile). Empty input is valid and yields a low-confidence result, typicallyDocumentType::Other. - Output. A
ClassificationResultwith theDocumentType, a confidence in[0.0, 1.0], detected structural features, an ISO 639-1 language code, and metadata.isConfident(0.7)is the documented threshold helper. - Determinism. Classification and language detection are pure functions of the input — same input, same result, no randomness, no network.
- Scope. Twelve document types and ten language profiles, both fixed in
this release. Custom strategies can be supplied via
ClassifierInterface.
Public API surface
Section titled “Public API surface”| Type | Kind | Key members |
|---|---|---|
NextPDF\Pro\Classifier\DocumentClassifier | final class | static create(): self, classifyFromText(string $text, string $pdfData = ''): ClassificationResult, classifyFromFile(string $pdfData): ClassificationResult |
NextPDF\Pro\Classifier\ClassifierInterface | interface | classify(string $text, StructureAnalysis $structure): ClassificationResult, supports(string $contentType): bool |
NextPDF\Pro\Classifier\HeuristicClassifier | final class | implements ClassifierInterface |
NextPDF\Pro\Classifier\StructureAnalyzer | final class | analyze(string $pdfData): StructureAnalysis |
NextPDF\Pro\Classifier\LanguageDetector | final class | detect(string $text): string |
NextPDF\Pro\Classifier\ClassificationResult | final readonly class | DocumentType $type, float $confidence, array $features, string $language, isConfident(float $threshold = 0.7): bool |
NextPDF\Pro\Classifier\DocumentType | enum | 12 cases (Invoice, Contract, Form, Report, Letter, Receipt, Legal, Medical, Financial, Technical, Academic, Other); label(): string |
Code sample — Quick start
Section titled “Code sample — Quick start”<?php
declare(strict_types=1);
use NextPDF\Pro\Classifier\DocumentClassifier;
$result = DocumentClassifier::create() ->classifyFromText('Invoice #4471 — Amount due: $1,200.00');
printf( "%s (%.0f%% confidence), lang=%s\n", $result->type->label(), $result->confidence * 100, $result->language,);Code sample — Production
Section titled “Code sample — Production”<?php
declare(strict_types=1);
use NextPDF\Pro\Classifier\DocumentClassifier;use NextPDF\Pro\Classifier\DocumentType;
function routeDocument(string $pdfBytes): string{ $result = DocumentClassifier::create()->classifyFromFile($pdfBytes);
if (! $result->isConfident(0.7)) { return 'manual-review'; }
return match ($result->type) { DocumentType::Invoice, DocumentType::Receipt => 'accounts-payable', DocumentType::Contract, DocumentType::Legal => 'legal-intake', default => 'general-inbox', };}Edge cases & gotchas
Section titled “Edge cases & gotchas”- Confidence is heuristic. Treat results below the threshold as “uncertain” and route to manual review, as the production sample does.
- Language detection needs enough text; very short strings fall back to English by design.
classifyFromFile()uses bounded byte-level text extraction; heavily compressed or image-only PDFs reduce the text available to score.- Document-type and language sets are fixed in this release; extend
classification by implementing
ClassifierInterface, not by mutating built-in dictionaries.
Data Residency & PII Mitigations
Section titled “Data Residency & PII Mitigations”Classification runs in-process with no network calls and no storage of the
input. The result includes a DocumentType and language code, not the source
text. If callers persist metadata, review it for incidental PII before
storage.
Safe Telemetry & Log Scrubbing
Section titled “Safe Telemetry & Log Scrubbing”The module emits no telemetry and logs no input. Callers adding logging
should record only the resulting DocumentType and language code, never the
classified text.
Performance
Section titled “Performance”Keyword scoring and trigram counting are linear in text length. Structure
analysis is linear in PDF byte length with a bounded decompression cap. See
performance_budget.
Security notes
Section titled “Security notes”classifyFromFile() parses untrusted PDF bytes with bounded scanning and a
decompression-size cap to resist decompression-bomb input. No embedded
scripts are executed.
Conformance
Section titled “Conformance”| Claim | Spec clause | Status |
|---|---|---|
Text recovered via Tj for file classification | ISO 32000-2:2020 §9.4 | Verified (unit suite) |
Text recovered via TJ for file classification | ISO 32000-2:2020 §9.4 | Verified (unit suite) |
| Machine-learning / model-based classification | — | Not supported (heuristic only) |
Core fallback / alternative
Section titled “Core fallback / alternative”No Core equivalent exists for document classification or language detection.
Enterprise boundary note
Section titled “Enterprise boundary note”This classifier is rule-based and deterministic. It performs no embedding, vector similarity, model inference, or semantic understanding. Those capabilities are not part of this module and are not implied by it.
Publication boundary
Section titled “Publication boundary”This page documents externally observable behavior and the supported public API surface only. Internal namespace paths, helper classes, mechanism tables, runbook filenames, and ticket prefixes are out of scope.
See also
Section titled “See also”- Classifier — Deep Reference — the full public API surface, pipeline order, and failure modes.
- Extraction
- Filter
- Diff