windlass.providers.preprocessors.enrich¶
enrich
¶
OCR fallback and LLM-driven metadata extraction.
Two preprocessors that reach outside the text they are given:
- :class:
OCRPreprocessorrescues scanned documents.pypdfreturns empty text for an image-only PDF; this notices and re-reads the file with OCR. - :class:
LLMMetadataPreprocessorasks a model for structured metadata — title, summary, topics, entities, document type — which turns a flat corpus into something you can filter and route on.
Example
from windlass.core.types import Document from windlass.providers.llm.fake import FakeLLM llm = FakeLLM(responses=['{"title": "Q3 Report", "topics": ["revenue"]}']) doc = LLMMetadataPreprocessor(llm=llm).process([Document(content="...")])[0] doc.metadata["title"] 'Q3 Report'
OCRPreprocessor
¶
OCRPreprocessor(
*,
min_chars: int = 50,
language: str = "eng",
dpi: int = 300,
max_pages: int = 50,
**config: Any
)
Bases: Preprocessor
OCR fallback for documents whose text layer is missing or unusable.
A scanned PDF is a stack of images. Text extraction returns nothing, and the document silently disappears from your index. This preprocessor detects that and re-reads the source with OCR.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
min_chars
|
int
|
Documents with at least this much text are passed through untouched — OCR is only a fallback, never a replacement. |
50
|
language
|
str
|
Tesseract language code(s). |
'eng'
|
dpi
|
int
|
Rendering resolution for PDF pages. 300 is the usual sweet spot; higher is slower with diminishing returns. |
300
|
max_pages
|
int
|
Ceiling on pages rendered per PDF, to bound the cost of a mistakenly-included 900-page scan. |
50
|
**config
|
Any
|
Forwarded to :class: |
{}
|
Raises:
| Type | Description |
|---|---|
MissingDependencyError
|
When the OCR extras are not installed and a document actually needs OCR. |
Note
PDF rendering needs pdf2image plus Poppler, which Windlass does not
install for you. When rendering is unavailable the document is passed
through unchanged and a warning is logged, rather than failing the run.
Source code in src\windlass\providers\preprocessors\enrich.py
aprocess_one
async
¶
Re-read the document with OCR when its text is missing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
document
|
Document
|
The document to check. |
required |
Returns:
| Type | Description |
|---|---|
list[Document]
|
The original document, or an OCR'd replacement. |
Source code in src\windlass\providers\preprocessors\enrich.py
LLMMetadataPreprocessor
¶
LLMMetadataPreprocessor(
*,
llm: LLM | None = None,
max_input_tokens: int = 1500,
fields: tuple[str, ...] = (
"title",
"summary",
"topics",
"entities",
"document_type",
),
overwrite: bool = False,
**config: Any
)
Bases: Preprocessor
Extracts structured metadata using a language model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
llm
|
LLM | None
|
The model to ask. Use a small, cheap one — this is extraction, not reasoning. |
None
|
max_input_tokens
|
int
|
How much of each document to show the model. The opening of a document usually carries its title and topic. |
1500
|
fields
|
tuple[str, ...]
|
Metadata keys to keep from the model's reply. |
('title', 'summary', 'topics', 'entities', 'document_type')
|
overwrite
|
bool
|
Replace metadata keys that already exist. Off by default, so metadata the loader extracted from the file itself wins. |
False
|
**config
|
Any
|
Forwarded to :class: |
{}
|
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
When no model is supplied. |
Performance
One model call per document, run with the batch concurrency of the preprocessor base class. On a large corpus this is the most expensive preprocessor by a wide margin — measure before enabling it on millions of documents.
Source code in src\windlass\providers\preprocessors\enrich.py
aprocess_one
async
¶
Ask the model for metadata and merge it in.
A failed or unparseable reply leaves the document untouched — metadata enrichment is an improvement, never a gate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
document
|
Document
|
The document to enrich. |
required |
Returns:
| Type | Description |
|---|---|
list[Document]
|
A single-element list. |