Tutorial: Using Configuration Objects
On this page
Every format has a dedicated config dataclass giving you full control beyond the handful of options exposed as direct constructor kwargs. This tutorial walks through the pattern using CSVLoader as the running example, then shows how it generalizes.
The pattern
from zerda.document_loaders import CSVLoader, CSVLoaderConfig
# Option A: direct kwargs (covers common cases)
loader = CSVLoader("data.csv", content_columns=["title"], max_rows=100)
# Option B: full config object (covers everything)
config = CSVLoaderConfig(
content_columns=["title", "body"],
metadata_columns=["author"],
max_rows=100,
skip_rows=1,
row_joiner=" — ",
)
loader = CSVLoader("data.csv", config=config)
When config= is provided, it takes full precedence — the direct kwargs are only used to build a default config when config is None. See Configuration Reference for the complete field-by-field breakdown of every config dataclass.
Worked example: tuning a CSV load step by step
Start with the raw file:
id,title,body,author,internal_notes
1,Intro to RAG,RAG combines retrieval with generation.,Alice,draft v1
2,Vector DBs,Vector databases store embeddings.,Bob,needs review
Attempt 1 — defaults (every column becomes content):
docs = CSVLoader("articles.csv").load()
print(docs[0].page_content)
# "id: 1\ntitle: Intro to RAG\nbody: RAG combines retrieval with generation.\nauthor: Alice\ninternal_notes: draft v1"
This pulls in internal_notes, which you probably don't want polluting embeddings.
Attempt 2 — scope content to the meaningful fields:
from zerda.document_loaders import CSVLoaderConfig
config = CSVLoaderConfig(content_columns=["title", "body"])
docs = CSVLoader("articles.csv", config=config).load()
print(docs[0].page_content)
# "title: Intro to RAG\nbody: RAG combines retrieval with generation."
Now author and internal_notes are dropped entirely — but you probably want author retrievable as metadata, not lost.
Attempt 3 — route author to metadata explicitly:
config = CSVLoaderConfig(
content_columns=["title", "body"],
metadata_columns=["author"],
)
docs = CSVLoader("articles.csv", config=config).load()
print(docs[0].metadata["author"]) # "Alice"
internal_notes is now excluded from both content and metadata, exactly as intended.
Same pattern, other formats
PDF — page range + password:
from zerda.document_loaders import PDFLoader, PDFLoaderConfig
config = PDFLoaderConfig(start_page=0, end_page=5, password="secret")
docs = PDFLoader("confidential_excerpt.pdf", config=config).load()
HTML — scope extraction to specific tags:
from zerda.document_loaders import HTMLLoader, HTMLLoaderConfig
config = HTMLLoaderConfig(tags_to_extract=["article"], extract_links=True)
docs = HTMLLoader("blog_post.html", config=config).load()
Directory — custom exclusions and concurrency:
from zerda.document_loaders import DirectoryLoader, DirectoryLoaderConfig
config = DirectoryLoaderConfig(
exclude_patterns=["*.tmp", "archive/*"],
max_concurrency=8,
silent_errors=True,
)
docs = DirectoryLoader("./corpus/", config=config).load()
Watch out: GraphLoader and TableLoader behave differently
Unlike every loader above, GraphLoader and TableLoader have specific keyword-only constructor args that always override the matching config= fields:
from zerda.document_loaders import TableLoader, TableLoaderConfig
config = TableLoaderConfig(output_format="json")
# This does NOT get "json" — it gets overwritten back to "markdown"
# because output_format defaults to "markdown" as a direct kwarg:
docs = TableLoader("data.xlsx", config=config).load()
# Correct — pass it directly too:
docs = TableLoader("data.xlsx", config=config, output_format="json").load()
See the warnings on the Graph and Table API pages for full detail.
Next steps
- Configuration Reference — every field, every loader
- Tutorial: Extending the Library