# RAGFlow

RAGFlow is an open-source **Retrieval-Augmented Generation (RAG) engine** with deep document understanding capabilities. With over **50,000 GitHub stars**, it's one of the most comprehensive RAG platforms available — designed to extract, chunk, and reason over complex documents including PDFs, Word files, spreadsheets, images, and more.

Unlike basic RAG systems that naively split documents into chunks, RAGFlow uses layout-aware parsing to understand document structure, tables, figures, and multi-column layouts. This results in dramatically higher retrieval precision and answer quality.

Key features:

* 📄 **Deep document understanding** — OCR, table extraction, figure recognition
* 🔍 **Multiple chunking strategies** — semantic, layout-aware, fixed-size, Q\&A style
* 🤖 **LLM integration** — works with OpenAI, Ollama, Anthropic, local models
* 🌐 **Full-featured WebUI** — drag-and-drop document management
* 🔌 **REST API** — integrate RAGFlow into any application
* 📊 **Citation tracking** — answers include source document references
* 🏗️ **Multi-tenant** — team workspaces with permission control

{% hint style="success" %}
All examples can be run on GPU servers rented through [CLORE.AI Marketplace](https://clore.ai/marketplace).
{% endhint %}

***

## Server Requirements

| Parameter | Minimum                 | Recommended             |
| --------- | ----------------------- | ----------------------- |
| GPU       | NVIDIA RTX 3080 (10 GB) | NVIDIA RTX 4090 (24 GB) |
| VRAM      | 8 GB                    | 16–24 GB                |
| RAM       | 16 GB                   | 32–64 GB                |
| CPU       | 8 cores                 | 16+ cores               |
| Disk      | 50 GB                   | 100–500 GB              |
| OS        | Ubuntu 20.04+           | Ubuntu 22.04            |
| CUDA      | 11.8+                   | 12.1+                   |
| Ports     | 22, 9380, 80            | 22, 9380, 80            |
| Docker    | Required                | Docker + Docker Compose |

{% hint style="warning" %}
RAGFlow runs multiple services (Elasticsearch, MinIO, MySQL, Redis, Nginx) alongside the main application. Ensure you have sufficient RAM (16 GB minimum, 32 GB recommended) and disk space.
{% endhint %}

***

## Quick Deploy on CLORE.AI

### 1. Find a suitable server

Go to [CLORE.AI Marketplace](https://clore.ai/marketplace) and filter by:

* **VRAM**: ≥ 8 GB
* **RAM**: ≥ 16 GB
* **Disk**: ≥ 50 GB
* **GPU**: RTX 3090, 4090, A100, H100

### 2. Configure your deployment

**Docker Image:**

```
infiniflow/ragflow:latest
```

**Port Mappings:**

```
22   → SSH access
80   → RAGFlow Web UI (HTTP)
9380 → RAGFlow API
```

**Startup Command:**

```bash
bash -c "docker-compose -f docker/docker-compose.yml up -d"
```

### 3. Access the WebUI

```
http://<your-clore-server-ip>:80
```

Default credentials: `admin@ragflow.io` / `admin`

***

## Step-by-Step Setup

### Step 1: SSH into your server

```bash
ssh root@<your-clore-server-ip> -p <ssh-port>
```

### Step 2: Install Docker Compose

```bash
apt-get update && apt-get install -y docker-compose-plugin

# Verify
docker compose version
```

### Step 3: Clone the RAGFlow repository

```bash
cd /workspace
git clone https://github.com/infiniflow/ragflow.git
cd ragflow
```

### Step 4: Configure environment

```bash
# Copy and edit the environment file
cp docker/.env.example docker/.env
nano docker/.env
```

Key settings to configure:

```env
# LLM Configuration
OPENAI_API_KEY=your-openai-api-key

# Or use a local Ollama instance
OLLAMA_BASE_URL=http://localhost:11434

# Storage settings
MINIO_USER=ragflow
MINIO_PASSWORD=infini_rag_flow

# MySQL settings
MYSQL_PASSWORD=infini_rag_flow

# Application port
HTTP_PORT=80
RAGFLOW_API_PORT=9380
```

### Step 5: Choose the right image variant

```bash
# Check available tags
# For CUDA 12.1 (most RTX cards)
docker pull infiniflow/ragflow:latest

# For specific CUDA version
docker pull infiniflow/ragflow:v0.7.0-cuda12.1
```

### Step 6: Start all services

```bash
cd /workspace/ragflow/docker

# Start with GPU support
docker compose -f docker-compose.yml up -d

# Monitor startup (takes 2-5 minutes)
docker compose logs -f
```

Wait for:

```
ragflow-server | INFO: Application startup complete.
```

### Step 7: Create admin account

Open `http://<server-ip>:80` and register the first admin account.

### Step 8: Configure LLM model

1. Go to **Settings → Model Providers**
2. Add your LLM (OpenAI, Ollama, etc.)
3. Set the default chat model and embedding model

***

## Usage Examples

### Example 1: Upload and Query Documents via WebUI

1. Log in to `http://<server-ip>:80`
2. Click **"Knowledge Base"** → **"Create Knowledge Base"**
3. Name it: `"Clore.ai Documentation"`
4. Upload PDF/Word/TXT files using drag-and-drop
5. Wait for parsing (progress shown in UI)
6. Go to **"Chat"** → Create a new assistant linked to your knowledge base
7. Ask questions about your documents

***

### Example 2: API — Create Knowledge Base and Upload Documents

```python
import requests
import json
from pathlib import Path

BASE_URL = "http://<your-clore-server-ip>:9380"
API_KEY = "your-ragflow-api-key"  # Get from Settings → API

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json"
}

# Step 1: Create a knowledge base
kb_payload = {
    "name": "Clore.ai Technical Docs",
    "description": "GPU cloud marketplace documentation and guides",
    "language": "English",
    "embedding_model": "text-embedding-ada-002",
    "chunk_method": "naive",  # or 'qa', 'table', 'paper', 'book'
}

response = requests.post(
    f"{BASE_URL}/api/v1/knowledgebase",
    headers=headers,
    json=kb_payload
)
kb = response.json()
kb_id = kb["data"]["id"]
print(f"Created knowledge base: {kb_id}")

# Step 2: Upload a document
pdf_path = Path("technical_manual.pdf")

with open(pdf_path, "rb") as f:
    files = {"file": (pdf_path.name, f, "application/pdf")}
    upload_response = requests.post(
        f"{BASE_URL}/api/v1/document/upload?kb_id={kb_id}",
        headers={"Authorization": f"Bearer {API_KEY}"},
        files=files
    )

doc = upload_response.json()
doc_id = doc["data"]["id"]
print(f"Uploaded document: {doc_id}")

# Step 3: Start parsing
parse_response = requests.post(
    f"{BASE_URL}/api/v1/document/run",
    headers=headers,
    json={"doc_ids": [doc_id]}
)
print(f"Parsing started: {parse_response.json()}")
```

***

### Example 3: Query Documents via API

```python
import requests
import json

BASE_URL = "http://<your-clore-server-ip>:9380"
API_KEY = "your-ragflow-api-key"
CHAT_ID = "your-chat-assistant-id"  # From WebUI → Chat

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json"
}

def ask_ragflow(question, chat_id, session_id=None):
    """Send a question to RAGFlow and get an answer with citations."""
    payload = {
        "question": question,
        "stream": False
    }

    if session_id:
        payload["session_id"] = session_id

    response = requests.post(
        f"{BASE_URL}/api/v1/chat/{chat_id}/completion",
        headers=headers,
        json=payload
    )

    result = response.json()
    if result.get("code") == 0:
        data = result["data"]
        answer = data.get("answer", "")
        references = data.get("reference", {}).get("chunks", [])
        return answer, references
    else:
        return None, []

# Example queries
questions = [
    "What are the GPU specifications available on Clore.ai?",
    "How do I rent a GPU server on the marketplace?",
    "What is the pricing model for GPU instances?",
    "Which deep learning frameworks are supported?",
]

for question in questions:
    print(f"\n📌 Q: {question}")
    answer, refs = ask_ragflow(question, CHAT_ID)
    print(f"💬 A: {answer}")
    if refs:
        print(f"📚 Sources ({len(refs)} chunks):")
        for ref in refs[:2]:
            print(f"   - {ref.get('docnm_kwd', 'Unknown')}: {ref.get('content_ltks', '')[:100]}...")
```

***

### Example 4: Batch Document Processing Pipeline

```python
import requests
import time
from pathlib import Path

BASE_URL = "http://<your-clore-server-ip>:9380"
API_KEY = "your-ragflow-api-key"

headers = {"Authorization": f"Bearer {API_KEY}"}

def upload_and_parse_documents(kb_id, document_paths):
    """Upload multiple documents and wait for parsing to complete."""
    doc_ids = []

    # Upload all documents
    for doc_path in document_paths:
        path = Path(doc_path)
        with open(path, "rb") as f:
            mime = "application/pdf" if path.suffix == ".pdf" else "text/plain"
            files = {"file": (path.name, f, mime)}
            resp = requests.post(
                f"{BASE_URL}/api/v1/document/upload?kb_id={kb_id}",
                headers=headers,
                files=files
            )
            if resp.status_code == 200:
                doc_id = resp.json()["data"]["id"]
                doc_ids.append(doc_id)
                print(f"✓ Uploaded: {path.name} → {doc_id}")
            else:
                print(f"✗ Failed: {path.name}")

    # Start batch parsing
    if doc_ids:
        requests.post(
            f"{BASE_URL}/api/v1/document/run",
            headers={**headers, "Content-Type": "application/json"},
            json={"doc_ids": doc_ids}
        )
        print(f"\nParsing {len(doc_ids)} documents...")

        # Poll until complete
        while True:
            time.sleep(5)
            status_resp = requests.get(
                f"{BASE_URL}/api/v1/document/list?kb_id={kb_id}",
                headers=headers
            )
            docs = status_resp.json().get("data", {}).get("docs", [])
            pending = [d for d in docs if d.get("status") == "1"]  # 1 = processing
            done = [d for d in docs if d.get("status") == "2"]     # 2 = done

            print(f"  Processing: {len(pending)} | Done: {len(done)}/{len(doc_ids)}")

            if len(pending) == 0:
                break

    print("✓ All documents parsed!")
    return doc_ids

# Usage
docs = ["manual_v1.pdf", "faq.txt", "api_reference.pdf"]
doc_ids = upload_and_parse_documents(kb_id="your-kb-id", document_paths=docs)
```

***

### Example 5: RAGFlow with Local Ollama LLM

```bash
# 1. Install Ollama on the same Clore.ai server
curl -fsSL https://ollama.ai/install.sh | sh

# 2. Pull a local model
ollama pull llama3:8b
ollama pull nomic-embed-text  # For embeddings

# 3. Configure RAGFlow to use Ollama
# In WebUI: Settings → Model Providers → Add Ollama
# Base URL: http://host.docker.internal:11434
# Or if Ollama runs in Docker: http://ollama:11434
```

```python
# Test Ollama integration
import requests

# Verify Ollama is running
resp = requests.get("http://localhost:11434/api/tags")
models = [m["name"] for m in resp.json()["models"]]
print(f"Available Ollama models: {models}")

# Query RAGFlow using local LLM (configured in WebUI)
BASE_URL = "http://localhost:9380"
API_KEY = "your-api-key"
CHAT_ID = "your-chat-id"

response = requests.post(
    f"{BASE_URL}/api/v1/chat/{CHAT_ID}/completion",
    headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
    json={"question": "Explain the RAGFlow architecture", "stream": False}
)
print(response.json()["data"]["answer"])
```

***

## Configuration

### docker-compose.yml Key Services

```yaml
services:
  ragflow:
    image: infiniflow/ragflow:latest
    ports:
      - "9380:9380"
      - "80:80"
    environment:
      - HF_ENDPOINT=https://huggingface.co
      - MACOS=0
    depends_on:
      - mysql
      - minio
      - es01
      - redis

  es01:
    image: elasticsearch:8.11.3
    environment:
      - xpack.security.enabled=false
      - discovery.type=single-node
    volumes:
      - esdata01:/usr/share/elasticsearch/data

  mysql:
    image: mysql:8.0.39
    environment:
      - MYSQL_ROOT_PASSWORD=infini_rag_flow

  minio:
    image: quay.io/minio/minio:RELEASE.2023-12-20T01-00-02Z
    command: server /data --console-address ":9001"

  redis:
    image: redis:7.2.4
```

### Chunking Strategies

| Method   | Best For             | Description                     |
| -------- | -------------------- | ------------------------------- |
| `naive`  | General documents    | Fixed-size chunks with overlap  |
| `qa`     | FAQ/Q\&A documents   | Splits on question-answer pairs |
| `table`  | Spreadsheets, tables | Preserves table structure       |
| `paper`  | Academic papers      | Sections, abstract, references  |
| `book`   | Long books, manuals  | Chapter-aware chunking          |
| `laws`   | Legal documents      | Article-based chunking          |
| `manual` | Technical manuals    | Section hierarchy preservation  |

***

## Performance Tips

### 1. Scale Elasticsearch Memory

```yaml
# In docker-compose.yml
es01:
  environment:
    - ES_JAVA_OPTS=-Xms4g -Xmx4g  # Increase for large document sets
```

### 2. GPU-Accelerated Embedding

Configure RAGFlow to use a GPU-based embedding model:

* In Settings → Model Providers, use a local GPU model via Ollama
* Or point to a dedicated embedding service running on the Clore.ai GPU

### 3. Parallel Document Processing

RAGFlow processes documents in parallel by default. Configure worker count:

```env
# In docker/.env
TASK_WORKER_COUNT=4  # Adjust based on CPU cores
```

### 4. MinIO for Large Document Sets

For deployments with thousands of documents, configure dedicated MinIO storage with larger disk allocation in your CLORE.AI order.

***

## Troubleshooting

### Issue: Services fail to start (memory)

```bash
# Check memory usage
free -h
docker stats

# Reduce Elasticsearch memory
# Edit docker/.env: ES_JAVA_OPTS=-Xms1g -Xmx1g
```

### Issue: Cannot access WebUI on port 80

```bash
# Check nginx is running
docker compose ps

# Check port binding
docker port ragflow-nginx-1

# Verify in CLORE.AI: port 80 must be mapped in your server order
```

### Issue: Document parsing stuck

```bash
# Check task worker logs
docker compose logs ragflow-worker

# Restart worker
docker compose restart ragflow-worker
```

### Issue: Elasticsearch heap out of memory

```bash
# Increase heap in .env
ES_JAVA_OPTS=-Xms2g -Xmx2g
docker compose restart es01
```

### Issue: Embedding model not found

```bash
# Verify HuggingFace model download
docker exec ragflow-server ls /ragflow/models/

# Re-download
docker exec ragflow-server python -c "
from huggingface_hub import snapshot_download
snapshot_download('BAAI/bge-large-en-v1.5')
"
```

***

## Links

* **GitHub**: <https://github.com/infiniflow/ragflow>
* **Official Docs**: <https://ragflow.io/docs>
* **Docker Hub**: <https://hub.docker.com/r/infiniflow/ragflow>
* **API Reference**: <https://ragflow.io/docs/dev/http_api_reference>
* **Discord**: <https://discord.gg/4XxujFgUN7>
* **CLORE.AI Marketplace**: <https://clore.ai/marketplace>

***

## Clore.ai GPU Recommendations

| Use Case                  | Recommended GPU | Est. Cost on Clore.ai |
| ------------------------- | --------------- | --------------------- |
| Development/Testing       | RTX 3090 (24GB) | \~$0.12/gpu/hr        |
| Production RAG            | RTX 3090 (24GB) | \~$0.12/gpu/hr        |
| High-throughput Embedding | RTX 4090 (24GB) | \~$0.70/gpu/hr        |

> 💡 All examples in this guide can be deployed on [Clore.ai](https://clore.ai/marketplace) GPU servers. Browse available GPUs and rent by the hour — no commitments, full root access.
