File size: 4,384 Bytes
c4ef1cf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9513cca
c4ef1cf
 
 
9513cca
c4ef1cf
 
 
 
9513cca
c4ef1cf
 
 
 
 
 
 
2e67ce5
 
de13ab3
c4ef1cf
2e67ce5
 
 
 
de13ab3
2e67ce5
 
 
de13ab3
2e67ce5
 
 
 
 
 
 
de13ab3
2e67ce5
 
 
 
 
de13ab3
2e67ce5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c4ef1cf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
de13ab3
 
9513cca
c4ef1cf
de13ab3
 
 
 
 
 
c4ef1cf
 
 
 
 
 
 
 
 
 
 
 
9513cca
c4ef1cf
 
 
 
2e67ce5
 
c4ef1cf
de13ab3
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
"""
Visual RAG Toolkit - End-to-end visual document retrieval with two-stage pooling.

A modular toolkit for building visual document retrieval systems:

Components:
-----------
- embedding: Visual and text embedding generation (ColPali, etc.)
- indexing: PDF processing, Qdrant indexing, Cloudinary uploads
- retrieval: Single-stage and two-stage retrieval with MaxSim
- visualization: Saliency maps and attention visualization
- cli: Command-line interface

Quick Start:
------------
>>> from visual_rag import VisualEmbedder, PDFProcessor, TwoStageRetriever
>>>
>>> # Process PDFs
>>> processor = PDFProcessor(dpi=140)
>>> images, texts = processor.process_pdf("report.pdf")
>>>
>>> # Generate embeddings
>>> embedder = VisualEmbedder()
>>> embeddings = embedder.embed_images(images)
>>> query_emb = embedder.embed_query("What is the budget?")
>>>
>>> # Search with two-stage retrieval
>>> retriever = TwoStageRetriever(qdrant_client, "my_collection")
>>> results = retriever.search(query_emb, top_k=10)

Each component works independently - use only what you need.
"""

import logging

__version__ = "0.1.4"


def setup_logging(level: str = "INFO", format: str = None) -> None:
    """
    Configure logging for visual_rag package.

    Args:
        level: Log level ("DEBUG", "INFO", "WARNING", "ERROR")
        format: Custom format string. Default shows time, level, and message.

    Example:
        >>> import visual_rag
        >>> visual_rag.setup_logging("INFO")
        >>> # Now you'll see processing logs
    """
    if format is None:
        format = "[%(asctime)s] %(levelname)s - %(message)s"

    logging.basicConfig(
        level=getattr(logging, level.upper(), logging.INFO),
        format=format,
        datefmt="%H:%M:%S",
    )

    # Also set the visual_rag logger specifically
    logger = logging.getLogger("visual_rag")
    logger.setLevel(getattr(logging, level.upper(), logging.INFO))


# Enable INFO logging by default for visual_rag package and all submodules
# This ensures logs like "Processing PDF...", "Embedding pages..." are visible
_logger = logging.getLogger("visual_rag")
if not _logger.handlers:
    _handler = logging.StreamHandler()
    _handler.setFormatter(logging.Formatter("[%(asctime)s] %(message)s", datefmt="%H:%M:%S"))
    _logger.addHandler(_handler)
_logger.setLevel(logging.INFO)
_logger.propagate = False  # Don't duplicate to root logger

# Import main classes at package level for convenience
# These are optional - if dependencies aren't installed, we catch the error

try:
    from visual_rag.embedding.visual_embedder import VisualEmbedder
except ImportError:
    VisualEmbedder = None

try:
    from visual_rag.indexing.pdf_processor import PDFProcessor
except ImportError:
    PDFProcessor = None

try:
    from visual_rag.indexing.qdrant_indexer import QdrantIndexer
except ImportError:
    QdrantIndexer = None

try:
    from visual_rag.indexing.cloudinary_uploader import CloudinaryUploader
except ImportError:
    CloudinaryUploader = None

try:
    from visual_rag.retrieval.two_stage import TwoStageRetriever
except ImportError:
    TwoStageRetriever = None

try:
    from visual_rag.retrieval.multi_vector import MultiVectorRetriever
except ImportError:
    MultiVectorRetriever = None

try:
    from visual_rag.qdrant_admin import QdrantAdmin
except ImportError:
    QdrantAdmin = None

# demo is lazily imported to avoid RuntimeWarning when running as __main__
# Access via visual_rag.demo() which triggers __getattr__

# Config utilities (always available)
try:
    from visual_rag.config import get, get_section, load_config
except ImportError:
    get = None
    get_section = None
    load_config = None

__all__ = [
    # Version
    "__version__",
    # Main classes
    "VisualEmbedder",
    "PDFProcessor",
    "QdrantIndexer",
    "CloudinaryUploader",
    "TwoStageRetriever",
    "MultiVectorRetriever",
    "QdrantAdmin",
    "demo",
    # Config utilities
    "load_config",
    "get",
    "get_section",
    # Logging
    "setup_logging",
]


def __getattr__(name: str):
    """Lazy import for demo to avoid RuntimeWarning when running as __main__."""
    if name == "demo":
        try:
            from visual_rag.demo_runner import demo

            return demo
        except ImportError:
            return None
    raise AttributeError(f"module 'visual_rag' has no attribute {name!r}")