windlass.rag.builder¶
builder
¶
The fluent RAG builder.
This is the API most people will actually use::
rag = (
Windlass.rag()
.loader("pdf")
.preprocessor()
.chunker("semantic")
.embedding("huggingface")
.vectordb("pinecone")
.retriever("hybrid")
.guardrails()
.observe("langfuse")
)
rag.ingest("./documents")
print(rag.ask("Explain transformers"))
Three properties make it work:
Nothing is constructed until it is needed. Each call records intent; the
pipeline is assembled on the first ingest or ask. So you can reconfigure
freely, and a builder that names Pinecone does not import Pinecone until you use
it.
Cross-component wiring is automatic. The semantic chunker needs the
embedder, the vector retriever needs the embedder and the store, hybrid search
needs a BM25 leg over the same corpus, FAISS needs the embedding
dimensionality. :meth:RAGBuilder.build resolves that graph so you never wire
it by hand.
Every argument accepts three forms. A registry name ("semantic"), a
configured instance (MyChunker(...)), or a factory. That is the whole
extensibility story: your component is indistinguishable from a built-in one.
RAGBuilder
¶
Fluent builder for a :class:~windlass.rag.pipeline.RAGPipeline.
Every configuration method returns self, and the pipeline methods
(:meth:ingest, :meth:ask, :meth:search, ...) are forwarded, so a
builder is a usable pipeline — no explicit .build() required.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
container
|
Container | None
|
Dependency container. Defaults to a child of the process root, so application-wide bindings are inherited. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
container |
The container backing this builder. |
Example
Level 1 — defaults all the way down, no dependencies, no API keys::
rag = Windlass.rag()
rag.ingest_text("Windlass unifies the AI ecosystem.")
print(rag.ask("What does Windlass do?"))
Level 2 — configured::
rag = (Windlass.rag()
.llm("openai", model="gpt-4o-mini", temperature=0)
.embedding("huggingface", model="BAAI/bge-small-en-v1.5")
.chunker("recursive", chunk_size=800, overlap=120)
.vectordb("faiss", persist_path="./index")
.retriever("hybrid", weights=[0.6, 0.4])
.top_k(8))
Level 3 — reach past the abstraction::
index = rag.native_store() # the raw faiss.Index
client = rag.native_llm() # the raw openai.AsyncOpenAI
Source code in src\windlass\rag\builder.py
llm
¶
Choose the generation model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
Any
|
Registry name ( |
None
|
**config
|
Any
|
Provider options — |
{}
|
Returns:
| Type | Description |
|---|---|
Self
|
|
Example
from windlass import Windlass _ = Windlass.rag().llm("fake", responses=["hi"])
Source code in src\windlass\rag\builder.py
embedding
¶
Choose the embedding model.
The same model must embed your corpus and your queries — Windlass uses this one for both, which is why swapping it means re-ingesting.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
Any
|
Registry name ( |
None
|
**config
|
Any
|
Provider options — |
{}
|
Returns:
| Type | Description |
|---|---|
Self
|
|
Source code in src\windlass\rag\builder.py
vectordb
¶
Choose the vector store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
Any
|
Registry name ( |
None
|
**config
|
Any
|
Store options — |
{}
|
Returns:
| Type | Description |
|---|---|
Self
|
|
Source code in src\windlass\rag\builder.py
chunker
¶
Choose the chunking strategy.
The highest-leverage knob in a RAG system: it decides what the retriever can find and what the model gets to read.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
Any
|
Registry name ( |
None
|
**config
|
Any
|
Strategy options — |
{}
|
Returns:
| Type | Description |
|---|---|
Self
|
|
Example
from windlass import Windlass _ = Windlass.rag().chunker("recursive", chunk_size=1000, overlap=200)
Source code in src\windlass\rag\builder.py
retriever
¶
Choose the retrieval strategy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
Any
|
Registry name ( |
None
|
**config
|
Any
|
Strategy options — |
{}
|
Returns:
| Type | Description |
|---|---|
Self
|
|
Note
"hybrid" builds a dense leg plus a BM25 leg over the same corpus
automatically. Pass retrievers=[...] to fuse your own set.
Source code in src\windlass\rag\builder.py
loader
¶
Pin a document loader.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
Any
|
Registry name ( |
None
|
**config
|
Any
|
Loader options. |
{}
|
Returns:
| Type | Description |
|---|---|
Self
|
|
Note
Optional. With no loader configured, Windlass picks one per file from the extension, which is what you want for a mixed corpus.
Source code in src\windlass\rag\builder.py
preprocessor
¶
Add a preprocessing stage.
Called repeatedly, stages compose into a chain in call order.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
Any
|
Registry name ( |
None
|
**config
|
Any
|
Preprocessor options. |
{}
|
Returns:
| Type | Description |
|---|---|
Self
|
|
Example
from windlass import Windlass _ = (Windlass.rag() ... .preprocessor("clean", min_length=50) ... .preprocessor("dedup", threshold=0.95) ... .preprocessor("pii", action="redact"))
Source code in src\windlass\rag\builder.py
memory
¶
Attach conversation memory, making ask multi-turn aware.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
Any
|
Registry name ( |
None
|
**config
|
Any
|
Memory options. |
{}
|
Returns:
| Type | Description |
|---|---|
Self
|
|
Source code in src\windlass\rag\builder.py
guardrails
¶
Enable input and output guardrails.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
Any
|
Registry name ( |
None
|
**config
|
Any
|
Policy options — |
{}
|
Returns:
| Type | Description |
|---|---|
Self
|
|
Example
from windlass import Windlass _ = Windlass.rag().guardrails(pii=True, on_violation="redact")
Source code in src\windlass\rag\builder.py
observe
¶
Enable tracing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
Any
|
Registry name ( |
None
|
**config
|
Any
|
Tracer options — |
{}
|
Returns:
| Type | Description |
|---|---|
Self
|
|
Source code in src\windlass\rag\builder.py
prompt
¶
Override the answer prompt template.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
template
|
str
|
A format string containing |
required |
Returns:
| Type | Description |
|---|---|
Self
|
|
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
When a placeholder is missing. |
Source code in src\windlass\rag\builder.py
top_k
¶
Set how many chunks to retrieve per question.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
k
|
int
|
Number of chunks. Must be positive. |
required |
Returns:
| Type | Description |
|---|---|
Self
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src\windlass\rag\builder.py
max_context_tokens
¶
Cap how much retrieved context reaches the prompt.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tokens
|
int
|
Token ceiling. Lower-ranked chunks are dropped first. |
required |
Returns:
| Type | Description |
|---|---|
Self
|
|
Source code in src\windlass\rag\builder.py
strict
¶
Refuse to answer when retrieval finds nothing.
Removes the model's opportunity to fill an empty context with plausible invention, which is more effective than asking it not to.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
enabled
|
bool
|
True to refuse, False to answer from parametric knowledge. |
True
|
Returns:
| Type | Description |
|---|---|
Self
|
|
Note
Dense retrieval returns the nearest vectors, however far away they
are — so it is almost never empty, and strict mode alone will rarely
fire. Pair it with :meth:min_score to make "found nothing relevant"
mean what you expect:
Source code in src\windlass\rag\builder.py
min_score
¶
Discard retrieval hits scoring below threshold.
This is what turns strict mode into a real relevance gate. Without it,
dense retrieval hands back its k nearest neighbours no matter how
unrelated they are, and the model is asked to answer from noise.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
threshold
|
float | None
|
Minimum score to keep, or |
required |
Returns:
| Type | Description |
|---|---|
Self
|
|
Example
from windlass import Windlass rag = Windlass.rag().retriever("vector").strict().min_score(0.3) rag.ingest_text("Paris is the capital of France.") 1 rag.ask("Explain quantum chromodynamics.").metadata["no_context"] True
Source code in src\windlass\rag\builder.py
batch_size
¶
Set the ingestion batch size.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
size
|
int
|
Chunks embedded and indexed per batch. |
required |
Returns:
| Type | Description |
|---|---|
Self
|
|
bind
¶
Bind an arbitrary dependency into this builder's container.
The escape hatch for wiring something Windlass has no named slot for.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Binding key. |
required |
factory
|
Any
|
A factory callable, or a ready-made instance. |
required |
Returns:
| Type | Description |
|---|---|
Self
|
|
Source code in src\windlass\rag\builder.py
build
¶
Resolve every component and construct the pipeline.
Called automatically on first use. Call it explicitly when you want construction errors (a missing API key, an uninstalled extra) to surface at startup rather than on the first request.
Returns:
| Type | Description |
|---|---|
RAGPipeline
|
The assembled :class: |
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
When a component cannot be constructed. |
MissingDependencyError
|
When a chosen provider's extra is not installed. |
Example
from windlass import Windlass pipeline = Windlass.rag().build() pipeline.top_k 5
Source code in src\windlass\rag\builder.py
ingest
¶
aingest
async
¶
ingest_text
¶
Ingest a raw string. See :meth:~windlass.rag.pipeline.RAGPipeline.ingest_text.
aingest_text
async
¶
ingest_documents
¶
ask
¶
Answer a question. See :meth:~windlass.rag.pipeline.RAGPipeline.ask.
aask
async
¶
stream_ask
¶
Stream an answer. See :meth:~windlass.rag.pipeline.RAGPipeline.stream_ask.
astream_ask
¶
search
¶
search(
query: str, k: int | None = None, *, filters: MetadataFilter | None = None
) -> SearchResult
Retrieve without generating. See :meth:~windlass.rag.pipeline.RAGPipeline.search.
Source code in src\windlass\rag\builder.py
asearch
async
¶
evaluate
¶
Evaluate the pipeline. See :meth:~windlass.rag.pipeline.RAGPipeline.evaluate.