windlass.interfaces.preprocessor¶
preprocessor
¶
The preprocessor interface.
Preprocessors sit between loading and chunking. They clean, enrich, filter or redact documents, and they compose: a pipeline runs them in order, each seeing what the previous one produced.
A preprocessor may return zero documents (dropping the input — that is how deduplication and language filtering work), one (the common case), or many (splitting a spreadsheet into per-sheet documents).
Implementers override one coroutine, :meth:Preprocessor.aprocess_one.
Example
from windlass.providers.preprocessors.clean import CleanPreprocessor from windlass.core.types import Document clean = CleanPreprocessor(min_length=0) docs = clean.process([Document(content="a \t b")]) docs[0].content 'a b'
Preprocessor
¶
Bases: Component
Abstract document preprocessor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str | None
|
Component name for traces. |
None
|
**config
|
Any
|
Preprocessor-specific options. |
{}
|
Example
Implementing a preprocessor takes one method::
class Shout(Preprocessor):
provider_name = "shout"
async def aprocess_one(self, document):
return [document.model_copy(
update={"content": document.content.upper()}
)]
Source code in src\windlass\interfaces\base.py
aprocess_one
abstractmethod
async
¶
Transform a single document.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
document
|
Document
|
The document to process. |
required |
Returns:
| Type | Description |
|---|---|
list[Document]
|
Zero, one or many documents. Return |
Raises:
| Type | Description |
|---|---|
IngestionError
|
When the document cannot be processed and dropping it silently would hide a real problem. |
Source code in src\windlass\interfaces\preprocessor.py
aprocess
async
¶
Process a batch of documents concurrently.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
documents
|
Sequence[Document]
|
The documents to process. |
required |
concurrency
|
int | None
|
Maximum simultaneous invocations. Defaults to the
global |
None
|
Returns:
| Type | Description |
|---|---|
list[Document]
|
The flattened output, preserving input order. |
Performance
Order is preserved even though execution is concurrent, so a preprocessor that calls an LLM (metadata extraction, contextual enrichment) still yields a deterministic corpus.
Source code in src\windlass\interfaces\preprocessor.py
process
¶
Blocking :meth:aprocess.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
documents
|
Sequence[Document] | Document
|
One document or a sequence of them. |
required |
Returns:
| Type | Description |
|---|---|
list[Document]
|
The processed documents. |
Source code in src\windlass\interfaces\preprocessor.py
PreprocessorChain
¶
Bases: Preprocessor
Runs several preprocessors in sequence.
Each step sees the full output of the previous one, which matters for corpus-level steps like deduplication that need to compare documents against each other rather than in isolation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
steps
|
Sequence[Preprocessor]
|
The preprocessors to run, in order. |
()
|
name
|
str | None
|
Component name for traces. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
steps |
list[Preprocessor]
|
The configured steps. |
Example
from windlass.providers.preprocessors.clean import CleanPreprocessor chain = PreprocessorChain([CleanPreprocessor(min_length=0)]) from windlass.core.types import Document chain.process([Document(content=" hi ")])[0].content 'hi'
Source code in src\windlass\interfaces\preprocessor.py
add
¶
aprocess_one
async
¶
aprocess
async
¶
Run every step in order over the whole batch.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
documents
|
Sequence[Document]
|
The documents to process. |
required |
concurrency
|
int | None
|
Forwarded to each step. |
None
|
Returns:
| Type | Description |
|---|---|
list[Document]
|
The output of the final step. Short-circuits to |
list[Document]
|
step drops everything. |