DocumentAnalysisService 

class DocumentAnalysisService
Fully qualified name
\Netresearch\NrLlm\Specialized\Document\DocumentAnalysisService

Stateless "understand this document" primitive (ADR-076).

When the resolved provider implements DocumentCapableInterface (Gemini, Claude), the PDF is ingested natively as a Base64 document block in a single chat call — whole-document reasoning. Otherwise the document is rasterized page-by-page with poppler and each page is read by the vision model; the per-page answers are concatenated with [Page N] markers.

analyzeDocument ( string $pdf, string $prompt, ?ChatOptions $options = null) : DocumentAnalysisResult

Analyze a PDF with a custom prompt.

param string $pdf

Raw PDF bytes (must start with the %PDF- header)

param string $prompt

Analysis prompt, applied to the whole document on the native path and to each page on the fallback

param ChatOptions|null $options

Chat options; provider, model, maxTokens, temperature and the budget attribution fields (beUserUid, plannedCost) are passed through to whichever path runs

throws

UnsupportedFormatException when the bytes are not a PDF

throws

ProviderException when no provider is resolvable (no explicit provider and no active default configuration) — the same error a plain chat() call raises

throws

ServiceUnavailableException when the provider lacks native PDF support and poppler is not installed

throws

PdfRasterizationException when rasterization itself fails

Returns

DocumentAnalysisResult with the answer text, the model/provider that produced it, whether the native document path was used, and the rasterized page count

Usage 

Analyzing a PDF
use Netresearch\NrLlm\Service\Option\ChatOptions;
use Netresearch\NrLlm\Specialized\Document\DocumentAnalysisService;

public function __construct(
    private readonly DocumentAnalysisService $documentAnalysis,
) {}

$result = $this->documentAnalysis->analyzeDocument(
    $pdfBytes,
    'List the key obligations defined in this contract.',
    new ChatOptions(maxTokens: 1024),
);

$result->text;                    // the answer
$result->usedNativeDocumentPath;  // true: one whole-document call
$result->rasterizedPageCount;     // pages read on the fallback path
Copied!

Optional system dependency: poppler 

The rasterization fallback shells out to the poppler binaries pdftoppm and pdfimages (Debian/Ubuntu package poppler-utils; declared in composer.json suggest). They are only needed when the resolved provider has no native PDF support. Without them, the fallback fails with the typed ServiceUnavailableException (code 1784211009) naming both remedies: install poppler-utils or configure a document-capable provider. The native path never touches poppler.

Degradation policy is the caller's: on the fallback path a failed page fails the call — catch and retry (or degrade) in the consumer.

PdfRasterizerInterface 

class PdfRasterizerInterface
Fully qualified name
\Netresearch\NrLlm\Specialized\Document\PdfRasterizerInterface

Rasterizes PDF pages to PNG blobs. The default implementation is the poppler-backed PopplerPdfRenderer; substitute it by aliasing the interface to another class in your Services.yaml.

imagePages ( string $absolutePath) : array

1-based page numbers carrying at least one embedded raster image.

renderPage ( string $absolutePath, int $page) : string

PNG bytes of one rasterized page.

renderDocument ( string $absolutePath) : array

PNG bytes per 1-based page number for the whole document.

isAvailable ( ) : bool

Whether the system binaries are present.