Overview
Quivr is an open-source AI-powered personal knowledge assistant (often called an “AI second brain”) that lets users upload documents, crawl websites, and build a searchable knowledge base they can query conversationally. It supports multiple file formats (PDF, DOCX, TXT, CSV, Markdown, audio, video), integrates with various LLM providers, and provides both a web interface and REST API.
The platform features multi-brain architecture where users can organize knowledge into separate “brains” with different configurations and access controls. Quivr supports custom AI assistants with configurable prompts, tools, and processing workflows, making it suitable for personal knowledge management, team knowledge bases, and domain-specific Q&A systems.
Installation
Docker Compose (Recommended)
git clone https://github.com/QuivrHQ/quivr.git
cd quivr
cp .env.example .env
# Edit .env with your API keys
docker compose up -d
# Frontend at http://localhost:3000
# API at http://localhost:5050
Environment Variables
# .env
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
# Supabase (database)
SUPABASE_URL=http://localhost:54321
SUPABASE_SERVICE_KEY=your-supabase-service-key
# PostgreSQL
PG_DATABASE_URL=postgresql://postgres:postgres@localhost:54321/postgres
# Vector store
VECTOR_STORE=supabase # or qdrant
# LLM defaults
DEFAULT_LLM=gpt-4o
DEFAULT_EMBEDDING_MODEL=text-embedding-3-small
DEFAULT_MAX_TOKENS=2000
Core Concepts
Brain Architecture
| Concept | Description |
|---|
| Brain | Isolated knowledge container with its own config |
| Knowledge | Documents and data within a brain |
| Assistant | AI persona with specific tools and prompts |
| Chat | Conversation session linked to brain(s) |
REST API
# Upload document to brain
curl -X POST http://localhost:5050/upload \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "file=@document.pdf" \
-F "brain_id=BRAIN_UUID"
# Chat with brain
curl -X POST http://localhost:5050/chat/{chat_id}/question \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"question": "What are the main findings?",
"brain_id": "BRAIN_UUID",
"model": "gpt-4o",
"temperature": 0.1,
"max_tokens": 1000
}'
# Create a brain
curl -X POST http://localhost:5050/brains/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Research Papers",
"description": "AI and ML research papers",
"model": "gpt-4o",
"max_tokens": 2000,
"temperature": 0.1
}'
# List brains
curl http://localhost:5050/brains/ \
-H "Authorization: Bearer YOUR_TOKEN"
# Get brain details
curl http://localhost:5050/brains/{brain_id}/ \
-H "Authorization: Bearer YOUR_TOKEN"
# Delete brain
curl -X DELETE http://localhost:5050/brains/{brain_id}/ \
-H "Authorization: Bearer YOUR_TOKEN"
Document Ingestion
| Format | Extensions | Notes |
|---|
| PDF | .pdf | Text and scanned (with OCR) |
| Word | .docx, .doc | Full text extraction |
| Text | .txt, .md, .rst | Plain text |
| Spreadsheet | .csv, .xlsx | Tabular data |
| Web | URL | Crawl and extract |
| Audio | .mp3, .wav | Speech-to-text |
| Video | .mp4 | Extract audio track |
| Code | .py, .js, .ts | Source code |
| Presentation | .pptx | Slide content |
Upload via API
# Single file
curl -X POST http://localhost:5050/upload \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "file=@report.pdf" \
-F "brain_id=BRAIN_UUID"
# URL crawl
curl -X POST http://localhost:5050/crawl \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://docs.example.com",
"brain_id": "BRAIN_UUID",
"depth": 2,
"max_pages": 50
}'
Python SDK
from quivr_core import Brain
# Create brain from files
brain = Brain.from_files(
name="my-brain",
file_paths=["doc1.pdf", "doc2.txt", "doc3.md"]
)
# Ask question
answer = brain.ask("What is the main topic?")
print(answer.answer)
print(f"Sources: {answer.sources}")
# Streaming
for chunk in brain.ask_streaming("Summarize the documents"):
print(chunk, end="")
Configuration
Brain Settings
{
"name": "Technical Docs",
"description": "Engineering documentation",
"model": "gpt-4o",
"max_tokens": 2000,
"temperature": 0.1,
"prompt": {
"title": "Tech Assistant",
"content": "You are a technical documentation assistant. Answer questions based on the provided context. Cite sources when possible."
},
"retrieval_config": {
"search_type": "hybrid",
"top_k": 5,
"score_threshold": 0.5
}
}
Docker Compose Configuration
version: '3.8'
services:
backend:
image: quivr/backend:latest
ports:
- "5050:5050"
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- SUPABASE_URL=${SUPABASE_URL}
- SUPABASE_SERVICE_KEY=${SUPABASE_SERVICE_KEY}
- DEFAULT_LLM=gpt-4o
depends_on:
- supabase
frontend:
image: quivr/frontend:latest
ports:
- "3000:3000"
environment:
- NEXT_PUBLIC_BACKEND_URL=http://localhost:5050
supabase:
image: supabase/postgres:latest
ports:
- "54321:5432"
environment:
- POSTGRES_PASSWORD=postgres
volumes:
- supabase_data:/var/lib/postgresql/data
volumes:
supabase_data:
Advanced Usage
Custom Assistants
from quivr_core import Brain
from quivr_core.assistant import AssistantConfig
config = AssistantConfig(
name="Code Reviewer",
system_prompt="""You are a senior code reviewer.
Analyze code from the knowledge base and provide:
1. Bug identification
2. Performance suggestions
3. Best practice recommendations""",
model="gpt-4o",
temperature=0.2,
tools=["code_analysis", "search"]
)
brain = Brain.from_files(
name="codebase",
file_paths=["src/main.py", "src/utils.py"],
assistant_config=config
)
review = brain.ask("Review the error handling in main.py")
Multi-Brain Queries
# Query across multiple brains
curl -X POST http://localhost:5050/chat/{chat_id}/question \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"question": "Compare the architectures described in both sets of docs",
"brain_ids": ["BRAIN_UUID_1", "BRAIN_UUID_2"],
"model": "gpt-4o"
}'
Webhooks and Integrations
# Set up notification webhook
curl -X POST http://localhost:5050/brains/{brain_id}/webhooks \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhook",
"events": ["document.uploaded", "chat.completed"]
}'
API Key Management
# Generate API key
curl -X POST http://localhost:5050/api-key \
-H "Authorization: Bearer YOUR_TOKEN"
# Use API key
curl -X POST http://localhost:5050/chat/{chat_id}/question \
-H "Authorization: Bearer qvr-API_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{"question": "Hello", "brain_id": "BRAIN_UUID"}'
Troubleshooting
| Issue | Solution |
|---|
| Docker compose fails | Check .env file exists, verify Supabase keys |
| Upload fails | Check file size limits, verify brain ID exists |
| Empty responses | Ensure brain has indexed documents, check model key |
| Slow responses | Use gpt-4o-mini, reduce max_tokens, lower top_k |
| Supabase connection error | Verify SUPABASE_URL and SUPABASE_SERVICE_KEY |
| Frontend not loading | Check NEXT_PUBLIC_BACKEND_URL matches API URL |
| Auth errors | Verify bearer token, check token expiration |
| OCR not working | Ensure Tesseract is installed in Docker image |
# View logs
docker compose logs -f backend
docker compose logs -f frontend
# Health check
curl http://localhost:5050/healthz
# Reset database
docker compose down -v
docker compose up -d
# Rebuild
docker compose build --no-cache
docker compose up -d