[!NOTE]
This is an accelerator to help you get started with multi-modal RAG using ColPali. ColPali was created by the research team at Illuin Technology — this repository provides Azure infrastructure, deployment scripts, and integration patterns to operationalize their work.
[!WARNING]
This code is provided as an accelerator implementation and should be carefully reviewed and adjusted before being used in your environments. This is a demonstration, and is not a production ready solution.
This repository provides a multi-modal RAG (Retrieval-Augmented Generation) solution that processes documents visually using late interaction embedding techniques. Unlike traditional approaches that compress entire documents into single vectors, late interaction methods preserve fine-grained token information—each document page is represented as an image and embedded to produce hundreds of token-level embeddings. This means query tokens can be compared against document tokens directly, capturing layout, charts, tables, and visual elements that OCR pipelines typically lose.
This repository uses ColPali, but any late interaction embedding model can be substituted.
This solution offers an alternative approach to traditional multi-modal RAG implementations by leveraging Vision Language Models (VLMs). Unlike conventional methods that require complex preprocessing pipelines, VLMs process documents holistically as images, significantly reducing system complexity.
Why vision models over traditional text extraction?
Traditional approaches require complex chunking strategies, OCR preprocessing (with its accuracy issues), image verbalization, and separate handling for text, tables, and visual elements. Vision Language Models process documents directly as images, understanding visual layouts and relationships without chunking or OCR. Everything—text, tables, charts, diagrams—is handled uniformly.
ColPali is a multi-modal document understanding model that processes documents as images rather than extracted text. Unlike traditional text-only approaches, ColPali generates embeddings that capture both textual content and visual layout information.
ColPali Architecture - Image source: illuin-tech/colpali repository
Key characteristics:
This implementation ships with TomoroAI/tomoro-colqwen3-embed-4b — a 4B-parameter ColQwen3-based late-interaction embedding model (320-dim per-token vectors). The inference service runs the model behind a vLLM sidecar (/pooling endpoint) so the GPU only does the forward pass while a CPU FastAPI shim handles tokenization, image staging, hierarchical and mean row/column pooling. Any other ColQwen2/ColQwen3 late-interaction checkpoint compatible with vLLM's pooling task can be substituted by changing colpaliInference.modelId in the Helm values.
ColPali was introduced in the paper "ColPali: Efficient Document Retrieval with Vision Language Models" by Manuel Faysse, Hugues Sibille, Tony Wu, et al. (2024).
This is a complete end-to-end deployment for Azure. The main complexity is hosting a model serving layer and building a custom indexing pipeline—both are handled here.
Components:
TomoroAI/tomoro-colqwen3-embed-4b) inference service on AKS — vLLM GPU sidecar + CPU pooling shim, with model weights cached on a shared PVCtomoro-colqwen3-embed-4b (served via vLLM) generates multi-modal embeddings on AKS pods%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#f5f5f5',
'primaryTextColor': '#000000',
'primaryBorderColor': '#333333',
'lineColor': '#666666',
'secondaryColor': '#f8f8f8',
'tertiaryColor': '#fafafa',
'background': '#ffffff',
'mainBkg': '#f5f5f5',
'secondBkg': '#f8f8f8',
'tertiaryBkg': '#fafafa'
}
}}%%
flowchart TB
subgraph INFRA_LAYER ["Azure Infrastructure Layer"]
direction LR
INFRA[Infrastructure Deployment<br/>Bicep Templates] --> AKS[AKS Cluster]
INFRA --> STORAGE[Blob Storage]
INFRA --> EG[Event Grid]
INFRA --> SB[Service Bus]
INFRA --> KV[Key Vault]
INFRA --> ACR[Container Registry]
end
subgraph K8S_LAYER ["AKS Cluster - colpali Namespace"]
direction TB
subgraph MODEL_SETUP ["Model Setup"]
HF[HuggingFace Hub] --> INIT[Init Container<br/>Model Download]
INIT --> PVC[Persistent Volume<br/>Model Cache]
end
subgraph APP_SERVICES ["Application Services"]
COLQWEN[tomoro-colqwen3-embed-4b Inference<br/>StatefulSet (vLLM + shim)]
DOCPROC[Document Processor<br/>Deployment]
QDRANT[Qdrant Vector DB<br/>StatefulSet]
AGENT_API[Agent API<br/>Deployment]
AGENT_UI[Agent UI<br/>Deployment]
INGRESS[NGINX Ingress<br/>External Access]
end
PVC -.->|Mount Model| COLQWEN
end
%% Event-Driven Processing Flow (integrated with existing nodes)
USER[User] -->|1. Upload PDF| STORAGE
STORAGE -->|2. Blob Event| EG
EG -->|3. Route Event| SB
SB -->|4. Queue Message| DOCPROC
DOCPROC -->|5. Read Document| STORAGE
DOCPROC -->|6. Generate Embeddings| COLQWEN
COLQWEN -->|7. Multi-Modal Embeddings| DOCPROC
DOCPROC -->|8. Store Page Images| STORAGE
DOCPROC -->|9. Store Vectors + URLs| QDRANT
subgraph QUERY_LAYER ["Query & Retrieval"]
direction LR
QUERY[User Query] --> INGRESS
INGRESS --> AGENT_UI
AGENT_UI --> AGENT_API
AGENT_API --> QDRANT
QDRANT -->|Vector Search| RESULTS[Relevant Documents]
RESULTS --> AGENT_API
end
%% Infrastructure connections
ACR -.->|Pull Images| COLQWEN
ACR -.->|Pull Images| DOCPROC
ACR -.->|Pull Images| QDRANT
ACR -.->|Pull Images| AGENT_API
ACR -.->|Pull Images| AGENT_UI
KV -.->|Secrets & Config| DOCPROC
KV -.->|Secrets & Config| COLQWEN
KV -.->|Secrets & Config| AGENT_API
%% Node Styling
classDef azure fill:#e8f4f8,stroke:#0078d4,stroke-width:2px
classDef k8s fill:#f0f8ff,stroke:#326ce5,stroke-width:2px
classDef flow fill:#f0fff0,stroke:#28a745,stroke-width:2px
classDef query fill:#f8f0ff,stroke:#6f42c1,stroke-width:2px
class INFRA,AKS,STORAGE,EG,SB,KV,ACR azure
class INIT,PVC,COLQWEN,DOCPROC,QDRANT,AGENT_API,AGENT_UI,INGRESS k8s
class USER,STORAGE,EG,SB,DOCPROC,COLQWEN,QDRANT flow
class QUERY,INGRESS,AGENT_UI,AGENT_API,RESULTS query
For detailed component descriptions, deployment topology, and technical specifications, see the Infrastructure Guide.
For this specific case, AI Search would not have worked for our use case, but it has great applications in other scenarios.
[!NOTE]
AI Search does offer other ways to achieve multi-modal RAG (See Multimodal search in Azure AI Search), but for the use case we explored, ColPali based approaches led to higher retrieval quality, and higher indexing throughput at scale in production based on our benchmarking. Results will vary from use case to use case and should be benchmarked accordingly.
├── modules/
│ ├── agent/ # RAG agent application
│ ├── colpali_inference/ # tomoro-colqwen3-embed-4b inference service (vLLM sidecar + CPU shim)
│ ├── document_processor/ # FastAPI document processing service
│ ├── helm/ # Helm charts for AKS deployment
│ └── infra/ # Bicep infrastructure templates
└── scripts/ # Deployment automation
Two techniques make ColPali embeddings practical at scale:
Hierarchical token pooling (from the ColPali team) reduces embedding dimensions by ~3x while maintaining retrieval quality.
Mean row and column pooling (from Qdrant's PDF retrieval tutorial) compresses embeddings further for fast initial retrieval.
Two-stage retrieval:
Chosen approach: We use row/column mean pooling for L1 and hierarchical pooling for L2 with quantized prefetch (mean_pooling_with_hierarchical_quantized_prefetch_only) based on benchmarking results. We did extensive internal benchmarking, and determined that this combination, has the best latency / retrieval quality trade off for production deployments.
Ready to deploy? See the scripts/README.md for complete deployment instructions and automation scripts.
[!WARNING]
This code is provided as an accelerator implementation and should be carefully reviewed and adjusted before being used in your environments. This is a demonstration, and is not a production ready solution.
We welcome contributions! Please see our Contributing Guide for details on:
Quick start:
pip install pre-commit && pre-commit installMIT License - see LICENSE for details.
Python
79.1%
Bicep
15.1%
PowerShell
3.4%
Dockerfile
1.9%
[!NOTE]
This is an accelerator to help you get started with multi-modal RAG using ColPali. ColPali was created by the research team at Illuin Technology — this repository provides Azure infrastructure, deployment scripts, and integration patterns to operationalize their work.
[!WARNING]
This code is provided as an accelerator implementation and should be carefully reviewed and adjusted before being used in your environments. This is a demonstration, and is not a production ready solution.
This repository provides a multi-modal RAG (Retrieval-Augmented Generation) solution that processes documents visually using late interaction embedding techniques. Unlike traditional approaches that compress entire documents into single vectors, late interaction methods preserve fine-grained token information—each document page is represented as an image and embedded to produce hundreds of token-level embeddings. This means query tokens can be compared against document tokens directly, capturing layout, charts, tables, and visual elements that OCR pipelines typically lose.
This repository uses ColPali, but any late interaction embedding model can be substituted.
This solution offers an alternative approach to traditional multi-modal RAG implementations by leveraging Vision Language Models (VLMs). Unlike conventional methods that require complex preprocessing pipelines, VLMs process documents holistically as images, significantly reducing system complexity.
Why vision models over traditional text extraction?
Traditional approaches require complex chunking strategies, OCR preprocessing (with its accuracy issues), image verbalization, and separate handling for text, tables, and visual elements. Vision Language Models process documents directly as images, understanding visual layouts and relationships without chunking or OCR. Everything—text, tables, charts, diagrams—is handled uniformly.
ColPali is a multi-modal document understanding model that processes documents as images rather than extracted text. Unlike traditional text-only approaches, ColPali generates embeddings that capture both textual content and visual layout information.
ColPali Architecture - Image source: illuin-tech/colpali repository
Key characteristics:
This implementation ships with TomoroAI/tomoro-colqwen3-embed-4b — a 4B-parameter ColQwen3-based late-interaction embedding model (320-dim per-token vectors). The inference service runs the model behind a vLLM sidecar (/pooling endpoint) so the GPU only does the forward pass while a CPU FastAPI shim handles tokenization, image staging, hierarchical and mean row/column pooling. Any other ColQwen2/ColQwen3 late-interaction checkpoint compatible with vLLM's pooling task can be substituted by changing colpaliInference.modelId in the Helm values.
ColPali was introduced in the paper "ColPali: Efficient Document Retrieval with Vision Language Models" by Manuel Faysse, Hugues Sibille, Tony Wu, et al. (2024).
This is a complete end-to-end deployment for Azure. The main complexity is hosting a model serving layer and building a custom indexing pipeline—both are handled here.
Components:
TomoroAI/tomoro-colqwen3-embed-4b) inference service on AKS — vLLM GPU sidecar + CPU pooling shim, with model weights cached on a shared PVCtomoro-colqwen3-embed-4b (served via vLLM) generates multi-modal embeddings on AKS pods%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#f5f5f5',
'primaryTextColor': '#000000',
'primaryBorderColor': '#333333',
'lineColor': '#666666',
'secondaryColor': '#f8f8f8',
'tertiaryColor': '#fafafa',
'background': '#ffffff',
'mainBkg': '#f5f5f5',
'secondBkg': '#f8f8f8',
'tertiaryBkg': '#fafafa'
}
}}%%
flowchart TB
subgraph INFRA_LAYER ["Azure Infrastructure Layer"]
direction LR
INFRA[Infrastructure Deployment<br/>Bicep Templates] --> AKS[AKS Cluster]
INFRA --> STORAGE[Blob Storage]
INFRA --> EG[Event Grid]
INFRA --> SB[Service Bus]
INFRA --> KV[Key Vault]
INFRA --> ACR[Container Registry]
end
subgraph K8S_LAYER ["AKS Cluster - colpali Namespace"]
direction TB
subgraph MODEL_SETUP ["Model Setup"]
HF[HuggingFace Hub] --> INIT[Init Container<br/>Model Download]
INIT --> PVC[Persistent Volume<br/>Model Cache]
end
subgraph APP_SERVICES ["Application Services"]
COLQWEN[tomoro-colqwen3-embed-4b Inference<br/>StatefulSet (vLLM + shim)]
DOCPROC[Document Processor<br/>Deployment]
QDRANT[Qdrant Vector DB<br/>StatefulSet]
AGENT_API[Agent API<br/>Deployment]
AGENT_UI[Agent UI<br/>Deployment]
INGRESS[NGINX Ingress<br/>External Access]
end
PVC -.->|Mount Model| COLQWEN
end
%% Event-Driven Processing Flow (integrated with existing nodes)
USER[User] -->|1. Upload PDF| STORAGE
STORAGE -->|2. Blob Event| EG
EG -->|3. Route Event| SB
SB -->|4. Queue Message| DOCPROC
DOCPROC -->|5. Read Document| STORAGE
DOCPROC -->|6. Generate Embeddings| COLQWEN
COLQWEN -->|7. Multi-Modal Embeddings| DOCPROC
DOCPROC -->|8. Store Page Images| STORAGE
DOCPROC -->|9. Store Vectors + URLs| QDRANT
subgraph QUERY_LAYER ["Query & Retrieval"]
direction LR
QUERY[User Query] --> INGRESS
INGRESS --> AGENT_UI
AGENT_UI --> AGENT_API
AGENT_API --> QDRANT
QDRANT -->|Vector Search| RESULTS[Relevant Documents]
RESULTS --> AGENT_API
end
%% Infrastructure connections
ACR -.->|Pull Images| COLQWEN
ACR -.->|Pull Images| DOCPROC
ACR -.->|Pull Images| QDRANT
ACR -.->|Pull Images| AGENT_API
ACR -.->|Pull Images| AGENT_UI
KV -.->|Secrets & Config| DOCPROC
KV -.->|Secrets & Config| COLQWEN
KV -.->|Secrets & Config| AGENT_API
%% Node Styling
classDef azure fill:#e8f4f8,stroke:#0078d4,stroke-width:2px
classDef k8s fill:#f0f8ff,stroke:#326ce5,stroke-width:2px
classDef flow fill:#f0fff0,stroke:#28a745,stroke-width:2px
classDef query fill:#f8f0ff,stroke:#6f42c1,stroke-width:2px
class INFRA,AKS,STORAGE,EG,SB,KV,ACR azure
class INIT,PVC,COLQWEN,DOCPROC,QDRANT,AGENT_API,AGENT_UI,INGRESS k8s
class USER,STORAGE,EG,SB,DOCPROC,COLQWEN,QDRANT flow
class QUERY,INGRESS,AGENT_UI,AGENT_API,RESULTS query
For detailed component descriptions, deployment topology, and technical specifications, see the Infrastructure Guide.
For this specific case, AI Search would not have worked for our use case, but it has great applications in other scenarios.
[!NOTE]
AI Search does offer other ways to achieve multi-modal RAG (See Multimodal search in Azure AI Search), but for the use case we explored, ColPali based approaches led to higher retrieval quality, and higher indexing throughput at scale in production based on our benchmarking. Results will vary from use case to use case and should be benchmarked accordingly.
├── modules/
│ ├── agent/ # RAG agent application
│ ├── colpali_inference/ # tomoro-colqwen3-embed-4b inference service (vLLM sidecar + CPU shim)
│ ├── document_processor/ # FastAPI document processing service
│ ├── helm/ # Helm charts for AKS deployment
│ └── infra/ # Bicep infrastructure templates
└── scripts/ # Deployment automation
Two techniques make ColPali embeddings practical at scale:
Hierarchical token pooling (from the ColPali team) reduces embedding dimensions by ~3x while maintaining retrieval quality.
Mean row and column pooling (from Qdrant's PDF retrieval tutorial) compresses embeddings further for fast initial retrieval.
Two-stage retrieval:
Chosen approach: We use row/column mean pooling for L1 and hierarchical pooling for L2 with quantized prefetch (mean_pooling_with_hierarchical_quantized_prefetch_only) based on benchmarking results. We did extensive internal benchmarking, and determined that this combination, has the best latency / retrieval quality trade off for production deployments.
Ready to deploy? See the scripts/README.md for complete deployment instructions and automation scripts.
[!WARNING]
This code is provided as an accelerator implementation and should be carefully reviewed and adjusted before being used in your environments. This is a demonstration, and is not a production ready solution.
We welcome contributions! Please see our Contributing Guide for details on:
Quick start:
pip install pre-commit && pre-commit installMIT License - see LICENSE for details.
Python
79.1%
Bicep
15.1%
PowerShell
3.4%
Dockerfile
1.9%