Skip to content

Component Map

How all modules in the RAGWire package relate to each other: who owns what, who calls whom, and which external libraries each component depends on.


Module Dependency Graph

graph TD
    INIT["ragwire/__init__.py\nPublic API, exports all symbols"]
    INIT --> PIPE

    PIPE["core/pipeline.py\nRAGWire, the main orchestrator"]

    PIPE --> CFG["core/config.py\nConfig"]
    PIPE --> LOAD["loaders/markitdown_loader.py\nMarkItDownLoader"]
    PIPE --> PLOAD["loaders/page_loader.py\nPageLoader (strategy: page)"]
    PLOAD --> LOAD
    PIPE --> SPLIT["processing/splitter.py\nText Splitters + PageSplitter"]
    PIPE --> HASH["processing/hashing.py\nSHA256 Hashing"]
    PIPE --> EXT["metadata/extractor.py\nMetadataExtractor"]
    PIPE --> SCH["metadata/schema.py\nDocumentMetadata"]
    PIPE --> EMB["embeddings/factory.py\nget_embedding"]
    PIPE --> QS["vectorstores/qdrant_store.py\nQdrantStore"]
    PIPE --> HYB["retriever/hybrid.py\nget_retriever / hybrid_search"]
    PIPE --> RRK["retriever/rerank.py\nget_reranker (optional)"]
    PIPE --> GEN["generation/generator.py\nAnswerGenerator"]
    PIPE --> SRC["sources/base.py\nbuild_sources (optional)"]
    PIPE --> LOG["utils/logging.py\nsetup_logging"]

    CLI["cli.py\nthe ragwire command"] --> PIPE
    CLI --> MCP["mcp/server.py\nbuild_server / serve"]
    CLI --> EVAL["eval/runner.py\nevaluate / sweep"]
    MCP --> MTOOL["mcp/tools.py\nsearch_documents, answer_question, ..."]
    MTOOL -.-> PIPE
    EVAL -.-> PIPE

Two of these deliberately do not depend on RAGWire. eval/ calls whatever retrieve it is handed, and mcp/tools.py takes the pipeline as an argument, so both are testable without a vector store and reusable outside the package.

generation/ is the same shape one level down: AnswerGenerator is given documents and returns an Answer, holding no retrieval logic of its own.


External Library Mapping

RAGWire Module Third-Party Libraries Notes
markitdown_loader.py markitdown Document → Markdown conversion
page_loader.py pypdf · python-pptx Page-preserving extraction (PDF pages, PPTX slides) for the page strategy
splitter.py langchain-text-splitters Markdown + recursive splitting; PageSplitter itself needs nothing beyond the stdlib
extractor.py langchain-core (ChatPromptTemplate) Prompt building + LLM chain
schema.py pydantic Metadata schema validation
factory.py (embeddings) langchain-openai · langchain-ollama · langchain-huggingface · langchain-google-genai · openrouter Lazy import; only the configured provider is loaded
qdrant_store.py qdrant-client · langchain-qdrant · fastembed fastembed only needed for hybrid search
hybrid.py langchain-qdrant (QdrantVectorStore) Similarity / MMR / hybrid retrieval
rerank.py sentence-transformers · cohere Optional; lazy import, and the cross-encoder model itself loads only on first use
generator.py langchain-core Grounded answers with citations
eval/ nothing beyond pyyaml Golden sets and metrics are plain arithmetic
sources/s3.py boto3 Optional; local.py needs nothing
mcp/server.py mcp Optional; mcp/tools.py needs nothing
config.py pyyaml · python-dotenv YAML loading + env var resolution
pipeline.py (LLM) langchain-openai · langchain-ollama · langchain-openrouter · langchain-google-genai · langchain-groq · langchain-anthropic Lazy import; only the configured provider is loaded

RAGWire Class: Internal State

classDiagram
    class RAGWire {
        +config: dict
        +loader: MarkItDownLoader or PageLoader
        +splitter: TextSplitter or PageSplitter
        +embedding: EmbeddingModel
        +metadata_extractor: MetadataExtractor
        +vectorstore_wrapper: QdrantStore
        +vectorstore: QdrantVectorStore
        +retriever: Retriever
        +reranker: BaseReranker or None
        +generator: AnswerGenerator
        +sources: List[Source]
        +llm: BaseChatModel
        -_filter_fields: List[str]
        -_stored_values_cache: dict or None
        -_rerank_config: dict

        +ingest_documents(file_paths) dict
        +ingest_directory(directory) dict
        +sync(sources, delete_missing, dry_run) SyncStats
        +retrieve(query, top_k, filters, rerank) List[Document]
        +query(question, top_k, filters, rerank) Answer
        +aquery(question, top_k, filters, rerank) Answer
        +hybrid_search(query, k, filters) List[Document]
        +extract_metadata(text) dict
        +get_field_values(fields, limit) dict
        +filter_fields List[str]
        +discover_metadata_fields() List[str]
        +get_stats() dict

        -_process_document(text, file_path, ...) List[Document]
        -_extract_filters_from_query(query) dict
        -_build_qdrant_filter(filters) Filter
        -_stored_values: dict [property]
        -_initialize_logging()
        -_initialize_loader()
        -_initialize_splitter()
        -_initialize_embeddings()
        -_initialize_llm()
        -_initialize_vectorstore()
        -_initialize_retriever()
    }

    class MetadataExtractor {
        +llm: ChatModel
        +schema_model: BaseModel
        +prompt: ChatPromptTemplate
        +fields: List[str] or None

        +extract(text, stored_values) dict
        +extract_batch(texts, stored_values) List[dict]
        +build_prompt_from_fields(fields)$ str
        +from_yaml(llm, yaml_path)$ MetadataExtractor
        -_parse_json_response(text) dict
    }

    class QdrantStore {
        +client: QdrantClient
        +embedding: EmbeddingModel
        +collection_name: str
        +config: dict

        +set_collection(name)
        +get_store(use_sparse) QdrantVectorStore
        +create_collection(use_sparse)
        +delete_collection()
        +collection_exists() bool
        +file_hash_exists(file_hash) bool
        +get_metadata_keys() List[str]
        +get_field_values(fields, limit) dict
        +create_payload_indexes(fields)
        +get_collection_info() CollectionInfo
    }

    RAGWire --> MetadataExtractor
    RAGWire --> QdrantStore

Data Types Flowing Through the Pipeline

flowchart LR
    F["str\nfile path"] -->|"MarkItDownLoader"| MD["str\nmarkdown text"]
    F -.->|"PageLoader (strategy: page)"| PG["List[dict]\npages: number, label, text"]
    MD -->|"TextSplitter"| CL["List[str]\nchunk texts"]
    PG -.->|"PageSplitter"| CL
    CL -->|"MetadataExtractor + metadata dict"| DL["List[Document]\npage_content + metadata"]
    DL -->|"EmbeddingModel + QdrantStore"| VEC["Qdrant points\nvector + payload"]

    Q["str\nquery"] -->|"EmbeddingModel"| QV["List[float]\nquery vector"]
    QV -->|"Retriever"| RES["List[Document]\nranked results"]