# How to Migrate an Existing RAG Implementation to RAGAnything: A Complete Guide

> Easily migrate your RAG implementation to RAGAnything with this guide. RAGAnything offers multimodal capabilities without data migration. Learn more!

- Repository: [✨Data Intelligence Lab@HKU✨/RAG-Anything](https://github.com/HKUDS/RAG-Anything)
- Tags: migration-guide
- Published: 2026-04-22

---

**RAGAnything is a drop-in wrapper around LightRAG that adds multimodal parsing, processing, and querying without requiring data migration or storage changes.**

If you're already running a RAG system built on LightRAG, migrating to RAGAnything unlocks support for PDFs, images, tables, equations, and mixed-media documents—while preserving your existing vector store, knowledge graph, and retrieval logic. According to the HKUDS/RAG-Anything source code, the migration path is intentionally thin because the core RAG engine remains unchanged.

---

## What RAGAnything Adds to LightRAG

RAGAnything implements three orthogonal layers on top of LightRAG:

| Layer | Purpose | Core File |
|-------|---------|-----------|
| **Parser & Ingestion** | Converts PDFs, Office files, images into a unified `content_list` | [`raganything/parser.py`](https://github.com/HKUDS/RAG-Anything/blob/main/raganything/parser.py) |
| **Multimodal Processors** | Generates textual descriptions and knowledge-graph entities from images, tables, equations | [`raganything/modalprocessors.py`](https://github.com/HKUDS/RAG-Anything/blob/main/raganything/modalprocessors.py) |
| **RAG Engine** | LightRAG-based retrieval with hybrid ranking and optional VLM-enhanced reasoning | [`raganything/raganything.py`](https://github.com/HKUDS/RAG-Anything/blob/main/raganything/raganything.py) |

Because [`raganything/raganything.py`](https://github.com/HKUDS/RAG-Anything/blob/main/raganything/raganything.py) detects pre-initialized LightRAG instances and reuses their storages, no data migration is required.

---

## Step 1: Install RAGAnything

Install with optional extras for full parser support:

```bash
pip install raganything[all]

```

For core functionality only:

```bash
pip install raganything

```

---

## Step 2: Load Your Existing LightRAG Instance

Reuse your working directory and configuration exactly as before. In [`raganything/raganything.py`](https://github.com/HKUDS/RAG-Anything/blob/main/raganything/raganything.py), the `__post_init__` method detects `self.lightrag is not None` and skips re-initialization.

```python
import os
import asyncio
from lightrag import LightRAG
from lightrag.llm.openai import openai_complete_if_cache, openai_embed
from lightrag.utils import EmbeddingFunc

# Load existing LightRAG storage

lightrag = LightRAG(
    working_dir="./my_light_rag",
    llm_model_func=lambda p, **kw: openai_complete_if_cache(
        "gpt-4o-mini", p, api_key=os.getenv("OPENAI_API_KEY"), **kw
    ),
    embedding_func=EmbeddingFunc(
        embedding_dim=3072,
        max_token_size=8192,
        func=lambda texts: openai_embed.func(
            texts, model="text-embedding-3-large", api_key=os.getenv("OPENAI_API_KEY")
        ),
    ),
)

await lightrag.initialize_storages()  # Loads existing KV/graph/vector stores

```

---

## Step 3: Define a Vision Model Function

RAGAnything requires a `vision_model_func` for image captioning and multimodal reasoning. This follows the same pattern as LightRAG's LLM functions but accepts image data:

```python
def vision_model_func(prompt, system_prompt=None, history_messages=[], image_data=None, messages=None, **kw):
    """VLM wrapper for GPT-4o image captioning."""
    if messages:
        return openai_complete_if_cache("gpt-4o", "", messages=messages, **kw)
    
    if image_data:
        return openai_complete_if_cache(
            "gpt-4o",
            "",
            messages=[
                {"role": "system", "content": system_prompt} if system_prompt else None,
                {
                    "role": "user",
                    "content": [
                        {"type": "text", "text": prompt},
                        {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image_data}"}},
                    ],
                },
            ],
            **kw,
        )
    
    # Fallback to text-only LLM

    return lightrag.llm_model_func(prompt, system_prompt, history_messages, **kw)

```

---

## Step 4: Wrap with RAGAnything

Instantiate `RAGAnything` by passing your existing LightRAG instance and vision function:

```python
from raganything import RAGAnything, RAGAnythingConfig

rag = RAGAnything(
    lightrag=lightrag,           # Reuse existing storage

    vision_model_func=vision_model_func,
    # Optional: override LLM/embedding funcs inherited from LightRAG

    # llm_model_func=custom_llm,

    # embedding_func=custom_embed,

)

```

The `RAGAnything` class in [`raganything/raganything.py`](https://github.com/HKUDS/RAG-Anything/blob/main/raganything/raganything.py) wraps the LightRAG engine while adding multimodal processors from [`raganything/modalprocessors.py`](https://github.com/HKUDS/RAG-Anything/blob/main/raganything/modalprocessors.py).

---

## Step 5: Replace Ingestion Calls

### Old LightRAG Pattern

```python

# Legacy LightRAG ingestion

await lightrag.insert_documents(text_chunks)
await lightrag.build_graph()

```

### New RAGAnything Pattern

Use `process_document_complete` for full parsing and ingestion:

```python
await rag.process_document_complete(
    file_path="research_report.pdf",    # PDF, DOCX, images, etc.

    output_dir="./tmp_output",          # Parser temporary files

    parse_method="auto",              # Auto-select: minerU, docling, paddleocr

    # Optional: force specific parser

    # parser="docling"

)

```

Or use `insert_content_list` if you have pre-parsed content:

```python
from raganything.parser import ContentList

my_content_list = ContentList(...)  # Your parsed content

await rag.insert_content_list(
    content_list=my_content_list,
    file_path="my_doc.pdf",
    display_stats=True,
)

```

See [`examples/insert_content_list_example.py`](https://github.com/HKUDS/RAG-Anything/blob/main/examples/insert_content_list_example.py) for a complete working example.

---

## Step 6: Replace Query Calls

### Text-Only Queries

```python

# Old LightRAG

result = await lightrag.query("What are the main findings?", mode="hybrid")

# New RAGAnything

answer = await rag.aquery("What are the main findings?", mode="hybrid")

```

### Multimodal Queries

Use `aquery_with_multimodal` for explicit multimodal payloads:

```python
answer = await rag.aquery_with_multimodal(
    "Compare the performance numbers in the table with the trends shown in Figure 2",
    multimodal_content=[
        {
            "type": "table",
            "table_data": """Method,Accuracy,Latency
            RAG-Anything,95.2%,120ms
            Baseline,87.3%,180ms""",
            "table_caption": "Performance Comparison",
        },
        {
            "type": "image",
            "img_path": "/absolute/path/to/figure2.jpg",
            "image_caption": ["Figure 2: Latency vs Accuracy Plot"],
        },
    ],
    mode="hybrid",
)

```

See [`examples/raganything_example.py`](https://github.com/HKUDS/RAG-Anything/blob/main/examples/raganything_example.py) for the complete multimodal query pattern.

---

## Step 7: Clean Shutdown

Register graceful shutdown to flush caches:

```python
await rag.finalize_storages()

```

`RAGAnything` automatically registers an `atexit` handler, but explicit cleanup is recommended for long-running services (FastAPI, Celery workers, etc.).

---

## Summary

- **RAGAnything wraps LightRAG** without changing the underlying storage or retrieval engine—migration requires no data export/import.
- **Reuse your existing `LightRAG` instance** by passing it to `RAGAnything(lightrag=existing_instance)`.
- **Add a `vision_model_func`** for image captioning and multimodal reasoning.
- **Replace ingestion** with `process_document_complete` or `insert_content_list`.
- **Replace queries** with `aquery` (text) or `aquery_with_multimodal` (mixed media).
- **Call `finalize_storages()`** on shutdown for clean cache flushing.

---

## Frequently Asked Questions

### Can I migrate without re-indexing my existing documents?

Yes. Because `RAGAnything` detects pre-initialized LightRAG instances in [`raganything/raganything.py`](https://github.com/HKUDS/RAG-Anything/blob/main/raganything/raganything.py), your existing vector store, knowledge graph, and KV cache remain intact. Only new documents processed through `process_document_complete` receive multimodal enhancement.

### What parsers does RAGAnything support?

The parser layer in [`raganything/parser.py`](https://github.com/HKUDS/RAG-Anything/blob/main/raganything/parser.py) supports MinerU, Docling, and PaddleOCR through a pluggable factory (`get_parser`). Set `parse_method="auto"` to let the system select based on file type, or specify `parser="docling"` to force a particular engine.

### Do I need a vision model if I only process text documents?

No. The `vision_model_func` parameter is optional. If omitted, RAGAnything operates in text-only mode using the inherited LightRAG configuration. Multimodal processors in [`raganything/modalprocessors.py`](https://github.com/HKUDS/RAG-Anything/blob/main/raganything/modalprocessors.py) automatically skip image captioning when no vision function is provided.

### How do I handle batch document processing?

Use the batch utilities in [`raganything/batch.py`](https://github.com/HKUDS/RAG-Anything/blob/main/raganything/batch.py) for folder-wide ingestion. The `process_directory` function wraps `process_document_complete` with progress callbacks and error handling, enabling efficient migration of large document collections.