# 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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.clore.ai/guides/rag-and-vector-databases/ragflow.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
