Architecture
On this page
Class hierarchy
All loaders ultimately implement the same abstract contract defined in base_loader.py.
AutoLoader and MultimodalAutoLoader are not subclasses of BaseDocumentLoader — they are dispatcher classes whose load() is a classmethod/instance method that constructs and delegates to one of the concrete loaders above.
Format dispatch flow (AutoLoader)
PDF backend fallback chain
PDFLoader.load() tries three backends in order and returns the result of the first one that succeeds. This is the only loader in the package with a multi-backend fallback strategy.
Directory loading sequence
Dependency graph between modules
graph_loader and table_loader are self-contained: they only depend on base_loader and the Python standard library (plus lazily-imported third-party parsers), and are not wired into EXTENSION_MAP / AutoLoader's dispatch table — they must be used explicitly.
Execution model: eager vs. lazy
Every loader exposes both load() and lazy_load():
load()always returns a fully-materializedList[LoadedDocument].lazy_load()is a generator. The default implementation onBaseDocumentLoaderjust doesyield from self.load()(no real streaming benefit), but several loaders override it for true incremental processing:CSVLoader.lazy_load()— streams rows viacsv.DictReaderwithout loading the whole file into memory as documents up front.JSONLinesLoader.lazy_load()— streams line-by-line.DirectoryLoader.lazy_load()— yields documents as files complete (sequential mode) or as futures complete (concurrent mode).GraphLoader.lazy_load()/TableLoader.lazy_load()— yield nodes/edges or table rows incrementally per parser.
load() in these cases is simply return list(self.lazy_load()).
Concurrency model
Two loaders use thread pools, both via concurrent.futures.ThreadPoolExecutor:
No loader in this package uses asyncio or multiprocessing; "Async Support" and "Multiprocessing-safe" should be read as not implemented wherever they appear in the API reference.
Extension points
The codebase does not define a formal plugin/registration system (no entry-point discovery, no abstract registry). The two practical extension points are:
- Subclass
BaseFileLoaderorBaseDocumentLoaderand implementload(). Your loader is fully compatible withload_and_split()and the rest of the pipeline as long as it returnsLoadedDocumentobjects. - Extend
EXTENSION_MAPinconfig_loader.pyand add a branch inDirectoryLoader._get_loader_for_file()/AutoLoader._create_file_loader()if you want a custom loader to participate in directory scanning and auto-detection.