Knowledge Base RAG System Generator
Build a production-grade knowledge base — similar to Microsoft Copilot Studio's
"Knowledge" feature — where users add files, URLs, and text, and an AI agent uses
all of it as grounded context.
This skill supports two output modes:
- n8n Mode → Generates importable n8n workflow JSONs + SQL schema
- Code Mode → Generates application code (TypeScript or Python) + SQL schema
Both modes share the same RAG theory, database schema, and architectural principles.
The difference is in the implementation layer.
When to Use This Skill
Use this skill when the user wants to:
- Build a knowledge base where users upload documents and an AI answers from them
- Implement RAG (Retrieval-Augmented Generation) in any application
- Create a document Q&A system, FAQ bot, or support assistant grounded in custom data
- Add semantic search or vector search to an existing project
- Build something like Copilot Studio's Knowledge feature with their own stack
- Set up a document ingestion pipeline with chunking, embedding, and indexing
- Integrate hybrid search (vector + keyword) into their AI agent or chatbot
This skill covers the full lifecycle: ingestion, chunking, embedding, storage, retrieval, reranking, and context formatting — for both n8n workflow and application code approaches.
Core Components Overview
Before diving into references, here's what a complete RAG system needs:
| Component |
Options |
Default |
| Vector Database |
pgvector (PostgreSQL), Pinecone, Weaviate, Chroma, Qdrant |
pgvector |
| Embedding Model |
OpenAI text-embedding-3-small/large, Voyage AI voyage-3-large, BGE, E5 |
text-embedding-3-small |
| Chunking Strategy |
Recursive character, Token-based, Semantic, Markdown header |
Recursive character |
| Search Method |
Vector-only, BM25-only, Hybrid (vector + BM25) |
Hybrid |
| Reranking |
Cohere Rerank, Cross-encoder (sentence-transformers), Jina Reranker |
Optional (Cohere) |
| Framework |
Custom code, LangChain, LlamaIndex |
Custom code |
Quick Reference: What to Read and When
| File |
When to read |
references/rag-theory.md |
Always read first. Core RAG concepts, techniques, and decision framework |
references/sql-schema.md |
Always. Database schema (same for both modes) |
references/workflow-ingestion.md |
n8n Mode: ingestion workflows |
references/workflow-rag-query.md |
n8n Mode: AI agent query tool workflow |
references/n8n-patterns.md |
n8n Mode: n8n JSON structure and node configs |
references/code-ingestion.md |
Code Mode: ingestion service/API implementation |
references/code-rag-query.md |
Code Mode: RAG query service implementation |
references/code-patterns.md |
Code Mode: project structure, libraries, best practices |
references/vector-stores.md |
When user needs non-pgvector stores (Pinecone, Weaviate, Chroma, Qdrant) |
What This System Does
Users can add three types of knowledge sources:
- Files — PDF, DOCX, TXT, MD
- URLs — Websites scraped and indexed
- Text — Plain text or HTML pasted directly
All content is processed through the same pipeline:
Source → Extract Text → Contextual Chunking → Hybrid Indexing → Ready for AI
↓ ↓
(context-enriched chunks) (vector + BM25 indexes)
The AI queries this knowledge base using:
Question → Query Expansion → Hybrid Search (vector + BM25)
→ Rerank Results → Format Context → AI Response
Step-by-Step Generation Process
Step 1: Determine Output Mode
This is the first and most important question. Ask the user:
"How do you want to build this system? I can generate:
A) n8n Workflows — Importable JSON workflows for n8n. Best if you're building
automations with n8n and want to plug RAG into your AI Agent nodes.
B) Application Code — TypeScript or Python services/APIs. Best if you're building
a custom application (Next.js, Express, FastAPI, etc.) and want to integrate RAG
directly into your codebase.
Which approach fits your project?"
How to infer the mode if not explicitly stated:
- User mentions n8n, workflows, AI Agent node, webhooks → n8n Mode
- User mentions Next.js, Express, FastAPI, React, API routes, their app → Code Mode
- User is building a SaaS product → likely Code Mode
- User wants quick automation / chatbot → likely n8n Mode
- If ambiguous → ask
Step 2: Gather Requirements
Ask (skip already answered):
Common to both modes:
- Database — Supabase Cloud or self-hosted PostgreSQL?
- Source types — Files / URLs / Text? Default: all three
- File types — PDF, DOCX, TXT/MD? Default: all
- Multi-tenant — Multiple clients/tenants? Default: no
- Embedding model — Default: OpenAI
text-embedding-3-small (1536d)
- RAG level — Basic (vector-only) or Advanced (hybrid + contextual)? Default: Advanced
- Content language — For BM25 config. Default: Portuguese
n8n Mode specific:
8. n8n environment — Self-hosted or cloud?
9. Trigger type — Webhook only, or also scheduled/event-driven?
Code Mode specific:
8. Language — TypeScript or Python?
9. Framework — Express, Next.js API Routes, FastAPI, NestJS, etc.?
10. Existing project — Adding to existing codebase or greenfield?
11. ORM/DB client — Prisma, Drizzle, Knex, pg, asyncpg, SQLAlchemy, etc.?
Step 3: Read Theory
Always read references/rag-theory.md first, regardless of mode. This ensures
the system uses modern RAG techniques. Key concepts covered:
- Naive RAG → Advanced RAG → Modern RAG evolution
- Contextual chunking (Anthropic's technique, 49-67% retrieval improvement)
- Hybrid search (vector + BM25)
- Reranking with cross-encoders
- Query expansion and HyDE
- Common failure modes and fixes
- Decision framework: prototype vs production vs mission-critical
Step 4: Generate SQL Schema
Same for both modes. Read references/sql-schema.md, then generate:
knowledge_sources table (unified for files, URLs, text)
document_chunks table (embedding + tsvector for hybrid search)
match_documents() and hybrid_search() PostgreSQL functions
- HNSW + GIN indexes
- Optional: RLS, multi-tenant variant
Step 5: Generate Implementation (mode-dependent)
If n8n Mode:
Read these references:
references/workflow-ingestion.md
references/workflow-rag-query.md
references/n8n-patterns.md
Generate:
schema.sql — Database setup
workflow-file-upload.json — File ingestion
workflow-url-scrape.json — URL ingestion
workflow-text-input.json — Text ingestion
workflow-rag-query.json — AI agent query tool
If Code Mode:
Read these references:
references/code-ingestion.md
references/code-rag-query.md
references/code-patterns.md
Generate project files based on user's stack. Typical output:
TypeScript (Express/Next.js):
schema.sql
src/
lib/
db.ts — Database connection
embeddings.ts — OpenAI embedding client
chunker.ts — Text chunking with sentence boundaries
contextualizer.ts — Contextual chunking via LLM
text-extractors.ts — PDF/DOCX/TXT extraction
url-scraper.ts — URL content extraction
services/
ingestion.service.ts — Unified ingestion pipeline
rag-query.service.ts — Hybrid search + formatting
routes/
knowledge.routes.ts — REST API endpoints
types/
knowledge.types.ts — TypeScript interfaces
Python (FastAPI):
schema.sql
app/
core/
database.py — Database connection
embeddings.py — OpenAI embedding client
chunker.py — Text chunking
contextualizer.py — Contextual chunking via LLM
extractors.py — PDF/DOCX/TXT extraction
scraper.py — URL content extraction
services/
ingestion.py — Unified ingestion pipeline
rag_query.py — Hybrid search + formatting
routes/
knowledge.py — FastAPI route handlers
models/
schemas.py — Pydantic models
Adapt to the user's existing project structure. If they already have a src/lib
folder, follow their conventions. If they use Prisma, generate a Prisma schema
alongside the raw SQL. Match their patterns.
Step 6: Deliver
Present the generated files with a brief setup guide.
n8n Mode setup:
- Run
schema.sql in Supabase SQL Editor / psql
- Import workflow JSONs into n8n
- Update credential IDs in all nodes
- Test with sample upload
Code Mode setup:
- Run
schema.sql
- Install dependencies (list them)
- Set environment variables (DB URL, OpenAI key)
- Integrate routes/services into existing app
- Test with sample upload
Customization Parameters (both modes)
| Parameter |
Default |
Notes |
| Embedding model |
text-embedding-3-small |
1536d. Alternatives: text-embedding-3-large (3072d), Voyage AI voyage-3-large (1024d), bge-large-en-v1.5 (1024d) |
| Chunk size |
800 tokens (~3200 chars) |
Smaller = more precise |
| Chunk overlap |
200 tokens (~800 chars) |
Prevents splitting ideas |
| Contextual chunking |
Enabled |
LLM enriches each chunk |
| Hybrid search |
Enabled |
Vector + BM25 combined |
| Reranking |
Optional |
Max precision, adds latency |
| Similarity threshold |
0.70 |
Tune per use case |
| Max results |
10 retrieve → 5 return |
Broad retrieval, precise return |
| Max file size |
10MB |
Configurable |
| BM25 language |
'portuguese' |
Match content language |
| Multi-tenant |
Disabled |
Adds tenant_id isolation |
Architecture (both modes share this)
┌─────────────────────────────────────────────────────┐
│ INGESTION LAYER │
│ │
│ n8n Mode: Webhook workflows (JSON) │
│ Code Mode: REST API endpoints (Express/FastAPI) │
│ │
│ ┌─────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Files │ │ URLs │ │ Text │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ └──────────────┼─────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────┐ │
│ │ Shared Processing Pipeline │ │
│ │ Extract → Chunk → Contextualize│ │
│ │ → Embed → Store │ │
│ └──────────────────────────────────┘ │
└──────────────────┬──────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ STORAGE LAYER (PostgreSQL + pgvector) │
│ (identical for both modes) │
│ │
│ knowledge_sources → source metadata + status │
│ document_chunks → text + embedding + tsvector │
│ hybrid_search() → vector + BM25 combined │
└──────────────────┬──────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ QUERY LAYER │
│ │
│ n8n Mode: Tool Workflow for AI Agent node │
│ Code Mode: Service function / API endpoint │
│ │
│ Query → Embed → Hybrid Search → Rerank → Context │
└─────────────────────────────────────────────────────┘
Best Practices
- Always use hybrid search in production — Vector-only search misses exact keywords (product codes, acronyms, IDs). Combining vector + BM25 consistently outperforms either alone.
- Enable contextual chunking for any serious use case — The one-time ingestion cost pays for itself with 49-67% fewer retrieval failures (Anthropic research).
- Keep chunks between 500-1000 tokens — Too large dilutes embeddings, too small loses context. 800 tokens with 200 overlap is a solid default.
- Use the same embedding model for ingestion AND querying — Mixing models produces incompatible vector spaces. This is the #1 silent failure mode.
- Retrieve broadly, return precisely — Fetch 10-20 candidates, then rerank or filter down to the top 5 for the LLM. This dramatically improves answer quality.
- Match BM25 language config to your content — PostgreSQL text search needs the correct language configuration (
'portuguese', 'english', etc.) for proper stemming.
- Process ingestion asynchronously for large files — Return immediately with a status endpoint. Use background processing or a job queue for files > 5MB.
- Add evaluation early — Track retrieval precision with test queries before going to production. A simple "expected answer in top-5 results" test catches most issues.
Common Issues & Solutions
| Issue |
Cause |
Fix |
| AI can't find information that's clearly in the documents |
Chunks too large, embedding diluted |
Reduce chunk size, enable contextual chunking, add BM25 |
| Search works for some queries but not others |
Vector-only misses exact terms |
Enable hybrid search with BM25 |
| AI returns irrelevant information |
Threshold too low, no reranking |
Increase threshold (0.70→0.80), add reranking, reduce max results |
| Processing documents takes too long |
Large model for contextualization, no batching |
Use fast model (Haiku/4o-mini), batch embedding calls |
| AI hallucinates despite having right context |
Too much context confuses LLM |
Return fewer, higher-quality chunks (5 max), use reranking |
| Documents in different languages get mixed up |
BM25 config doesn't match language |
Set correct PostgreSQL text search configuration |
1---2name: knowledge-base-rag3description: Build complete knowledge base systems where users can add files (PDF, DOCX, TXT/MD), website URLs, and plain text — and an AI agent searches all of it via advanced RAG. Think of it as building Copilot Studio's "Knowledge" feature. Can generate EITHER n8n workflow JSONs OR application code (TypeScript/Python) depending on how the user is building their project. Applies state-of-the-art RAG techniques including contextual chunking, hybrid search (vector + BM25), reranking, and metadata filtering. Trigger this skill whenever the user mentions: knowledge base, RAG system, document ingestion, file upload for AI, vector search, AI agent with custom data, "like Copilot Studio Knowledge", embedding pipeline, semantic search, or any system where content is ingested and queried by an AI. Also trigger when the user is building an application that needs RAG capabilities, regardless of the tech stack.4---56# Knowledge Base RAG System Generator78Build a production-grade knowledge base — similar to Microsoft Copilot Studio's9"Knowledge" feature — where users add files, URLs, and text, and an AI agent uses10all of it as grounded context.1112This skill supports **two output modes**:1314- **n8n Mode** → Generates importable n8n workflow JSONs + SQL schema15- **Code Mode** → Generates application code (TypeScript or Python) + SQL schema1617Both modes share the same RAG theory, database schema, and architectural principles.18The difference is in the implementation layer.1920## When to Use This Skill2122Use this skill when the user wants to:2324- Build a **knowledge base** where users upload documents and an AI answers from them25- Implement **RAG** (Retrieval-Augmented Generation) in any application26- Create a **document Q&A** system, FAQ bot, or support assistant grounded in custom data27- Add **semantic search** or **vector search** to an existing project28- Build something **like Copilot Studio's Knowledge** feature with their own stack29- Set up a **document ingestion pipeline** with chunking, embedding, and indexing30- Integrate **hybrid search** (vector + keyword) into their AI agent or chatbot3132This skill covers the full lifecycle: ingestion, chunking, embedding, storage, retrieval, reranking, and context formatting — for both n8n workflow and application code approaches.3334## Core Components Overview3536Before diving into references, here's what a complete RAG system needs:3738| Component | Options | Default |39|-----------|---------|---------|40| **Vector Database** | pgvector (PostgreSQL), Pinecone, Weaviate, Chroma, Qdrant | pgvector |41| **Embedding Model** | OpenAI text-embedding-3-small/large, Voyage AI voyage-3-large, BGE, E5 | text-embedding-3-small |42| **Chunking Strategy** | Recursive character, Token-based, Semantic, Markdown header | Recursive character |43| **Search Method** | Vector-only, BM25-only, Hybrid (vector + BM25) | Hybrid |44| **Reranking** | Cohere Rerank, Cross-encoder (sentence-transformers), Jina Reranker | Optional (Cohere) |45| **Framework** | Custom code, LangChain, LlamaIndex | Custom code |4647## Quick Reference: What to Read and When4849| File | When to read |50|------|-------------|51| `references/rag-theory.md` | **Always read first.** Core RAG concepts, techniques, and decision framework |52| `references/sql-schema.md` | **Always.** Database schema (same for both modes) |53| `references/workflow-ingestion.md` | n8n Mode: ingestion workflows |54| `references/workflow-rag-query.md` | n8n Mode: AI agent query tool workflow |55| `references/n8n-patterns.md` | n8n Mode: n8n JSON structure and node configs |56| `references/code-ingestion.md` | Code Mode: ingestion service/API implementation |57| `references/code-rag-query.md` | Code Mode: RAG query service implementation |58| `references/code-patterns.md` | Code Mode: project structure, libraries, best practices |59| `references/vector-stores.md` | When user needs non-pgvector stores (Pinecone, Weaviate, Chroma, Qdrant) |6061## What This System Does6263Users can add three types of knowledge sources:64651. **Files** — PDF, DOCX, TXT, MD662. **URLs** — Websites scraped and indexed673. **Text** — Plain text or HTML pasted directly6869All content is processed through the same pipeline:7071```72Source → Extract Text → Contextual Chunking → Hybrid Indexing → Ready for AI73 ↓ ↓74 (context-enriched chunks) (vector + BM25 indexes)75```7677The AI queries this knowledge base using:7879```80Question → Query Expansion → Hybrid Search (vector + BM25)81 → Rerank Results → Format Context → AI Response82```8384## Step-by-Step Generation Process8586### Step 1: Determine Output Mode8788**This is the first and most important question.** Ask the user:8990> "How do you want to build this system? I can generate:91>92> **A) n8n Workflows** — Importable JSON workflows for n8n. Best if you're building93> automations with n8n and want to plug RAG into your AI Agent nodes.94>95> **B) Application Code** — TypeScript or Python services/APIs. Best if you're building96> a custom application (Next.js, Express, FastAPI, etc.) and want to integrate RAG97> directly into your codebase.98>99> Which approach fits your project?"100101**How to infer the mode if not explicitly stated:**102- User mentions n8n, workflows, AI Agent node, webhooks → **n8n Mode**103- User mentions Next.js, Express, FastAPI, React, API routes, their app → **Code Mode**104- User is building a SaaS product → likely **Code Mode**105- User wants quick automation / chatbot → likely **n8n Mode**106- If ambiguous → **ask**107108### Step 2: Gather Requirements109110Ask (skip already answered):111112**Common to both modes:**1131. **Database** — Supabase Cloud or self-hosted PostgreSQL?1142. **Source types** — Files / URLs / Text? Default: all three1153. **File types** — PDF, DOCX, TXT/MD? Default: all1164. **Multi-tenant** — Multiple clients/tenants? Default: no1175. **Embedding model** — Default: OpenAI `text-embedding-3-small` (1536d)1186. **RAG level** — Basic (vector-only) or Advanced (hybrid + contextual)? Default: Advanced1197. **Content language** — For BM25 config. Default: Portuguese120121**n8n Mode specific:**1228. **n8n environment** — Self-hosted or cloud?1239. **Trigger type** — Webhook only, or also scheduled/event-driven?124125**Code Mode specific:**1268. **Language** — TypeScript or Python?1279. **Framework** — Express, Next.js API Routes, FastAPI, NestJS, etc.?12810. **Existing project** — Adding to existing codebase or greenfield?12911. **ORM/DB client** — Prisma, Drizzle, Knex, pg, asyncpg, SQLAlchemy, etc.?130131### Step 3: Read Theory132133**Always read `references/rag-theory.md` first**, regardless of mode. This ensures134the system uses modern RAG techniques. Key concepts covered:135136- Naive RAG → Advanced RAG → Modern RAG evolution137- Contextual chunking (Anthropic's technique, 49-67% retrieval improvement)138- Hybrid search (vector + BM25)139- Reranking with cross-encoders140- Query expansion and HyDE141- Common failure modes and fixes142- Decision framework: prototype vs production vs mission-critical143144### Step 4: Generate SQL Schema145146**Same for both modes.** Read `references/sql-schema.md`, then generate:147148- `knowledge_sources` table (unified for files, URLs, text)149- `document_chunks` table (embedding + tsvector for hybrid search)150- `match_documents()` and `hybrid_search()` PostgreSQL functions151- HNSW + GIN indexes152- Optional: RLS, multi-tenant variant153154### Step 5: Generate Implementation (mode-dependent)155156#### If n8n Mode:157158Read these references:159- `references/workflow-ingestion.md`160- `references/workflow-rag-query.md`161- `references/n8n-patterns.md`162163Generate:1641. `schema.sql` — Database setup1652. `workflow-file-upload.json` — File ingestion1663. `workflow-url-scrape.json` — URL ingestion1674. `workflow-text-input.json` — Text ingestion1685. `workflow-rag-query.json` — AI agent query tool169170#### If Code Mode:171172Read these references:173- `references/code-ingestion.md`174- `references/code-rag-query.md`175- `references/code-patterns.md`176177Generate project files based on user's stack. Typical output:178179**TypeScript (Express/Next.js):**180```181schema.sql182src/183 lib/184 db.ts — Database connection185 embeddings.ts — OpenAI embedding client186 chunker.ts — Text chunking with sentence boundaries187 contextualizer.ts — Contextual chunking via LLM188 text-extractors.ts — PDF/DOCX/TXT extraction189 url-scraper.ts — URL content extraction190 services/191 ingestion.service.ts — Unified ingestion pipeline192 rag-query.service.ts — Hybrid search + formatting193 routes/194 knowledge.routes.ts — REST API endpoints195 types/196 knowledge.types.ts — TypeScript interfaces197```198199**Python (FastAPI):**200```201schema.sql202app/203 core/204 database.py — Database connection205 embeddings.py — OpenAI embedding client206 chunker.py — Text chunking207 contextualizer.py — Contextual chunking via LLM208 extractors.py — PDF/DOCX/TXT extraction209 scraper.py — URL content extraction210 services/211 ingestion.py — Unified ingestion pipeline212 rag_query.py — Hybrid search + formatting213 routes/214 knowledge.py — FastAPI route handlers215 models/216 schemas.py — Pydantic models217```218219**Adapt to the user's existing project structure.** If they already have a `src/lib`220folder, follow their conventions. If they use Prisma, generate a Prisma schema221alongside the raw SQL. Match their patterns.222223### Step 6: Deliver224225Present the generated files with a brief setup guide.226227**n8n Mode setup:**2281. Run `schema.sql` in Supabase SQL Editor / psql2292. Import workflow JSONs into n8n2303. Update credential IDs in all nodes2314. Test with sample upload232233**Code Mode setup:**2341. Run `schema.sql`2352. Install dependencies (list them)2363. Set environment variables (DB URL, OpenAI key)2374. Integrate routes/services into existing app2385. Test with sample upload239240## Customization Parameters (both modes)241242| Parameter | Default | Notes |243|-----------|---------|-------|244| Embedding model | `text-embedding-3-small` | 1536d. Alternatives: `text-embedding-3-large` (3072d), Voyage AI `voyage-3-large` (1024d), `bge-large-en-v1.5` (1024d) |245| Chunk size | 800 tokens (~3200 chars) | Smaller = more precise |246| Chunk overlap | 200 tokens (~800 chars) | Prevents splitting ideas |247| Contextual chunking | Enabled | LLM enriches each chunk |248| Hybrid search | Enabled | Vector + BM25 combined |249| Reranking | Optional | Max precision, adds latency |250| Similarity threshold | 0.70 | Tune per use case |251| Max results | 10 retrieve → 5 return | Broad retrieval, precise return |252| Max file size | 10MB | Configurable |253| BM25 language | 'portuguese' | Match content language |254| Multi-tenant | Disabled | Adds tenant_id isolation |255256## Architecture (both modes share this)257258```259┌─────────────────────────────────────────────────────┐260│ INGESTION LAYER │261│ │262│ n8n Mode: Webhook workflows (JSON) │263│ Code Mode: REST API endpoints (Express/FastAPI) │264│ │265│ ┌─────────┐ ┌──────────┐ ┌──────────┐ │266│ │ Files │ │ URLs │ │ Text │ │267│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │268│ └──────────────┼─────────────┘ │269│ ↓ │270│ ┌──────────────────────────────────┐ │271│ │ Shared Processing Pipeline │ │272│ │ Extract → Chunk → Contextualize│ │273│ │ → Embed → Store │ │274│ └──────────────────────────────────┘ │275└──────────────────┬──────────────────────────────────┘276 ↓277┌─────────────────────────────────────────────────────┐278│ STORAGE LAYER (PostgreSQL + pgvector) │279│ (identical for both modes) │280│ │281│ knowledge_sources → source metadata + status │282│ document_chunks → text + embedding + tsvector │283│ hybrid_search() → vector + BM25 combined │284└──────────────────┬──────────────────────────────────┘285 ↓286┌─────────────────────────────────────────────────────┐287│ QUERY LAYER │288│ │289│ n8n Mode: Tool Workflow for AI Agent node │290│ Code Mode: Service function / API endpoint │291│ │292│ Query → Embed → Hybrid Search → Rerank → Context │293└─────────────────────────────────────────────────────┘294```295296## Best Practices2972981. **Always use hybrid search in production** — Vector-only search misses exact keywords (product codes, acronyms, IDs). Combining vector + BM25 consistently outperforms either alone.2992. **Enable contextual chunking for any serious use case** — The one-time ingestion cost pays for itself with 49-67% fewer retrieval failures (Anthropic research).3003. **Keep chunks between 500-1000 tokens** — Too large dilutes embeddings, too small loses context. 800 tokens with 200 overlap is a solid default.3014. **Use the same embedding model for ingestion AND querying** — Mixing models produces incompatible vector spaces. This is the #1 silent failure mode.3025. **Retrieve broadly, return precisely** — Fetch 10-20 candidates, then rerank or filter down to the top 5 for the LLM. This dramatically improves answer quality.3036. **Match BM25 language config to your content** — PostgreSQL text search needs the correct language configuration (`'portuguese'`, `'english'`, etc.) for proper stemming.3047. **Process ingestion asynchronously for large files** — Return immediately with a status endpoint. Use background processing or a job queue for files > 5MB.3058. **Add evaluation early** — Track retrieval precision with test queries before going to production. A simple "expected answer in top-5 results" test catches most issues.306307## Common Issues & Solutions308309| Issue | Cause | Fix |310|-------|-------|-----|311| AI can't find information that's clearly in the documents | Chunks too large, embedding diluted | Reduce chunk size, enable contextual chunking, add BM25 |312| Search works for some queries but not others | Vector-only misses exact terms | Enable hybrid search with BM25 |313| AI returns irrelevant information | Threshold too low, no reranking | Increase threshold (0.70→0.80), add reranking, reduce max results |314| Processing documents takes too long | Large model for contextualization, no batching | Use fast model (Haiku/4o-mini), batch embedding calls |315| AI hallucinates despite having right context | Too much context confuses LLM | Return fewer, higher-quality chunks (5 max), use reranking |316| Documents in different languages get mixed up | BM25 config doesn't match language | Set correct PostgreSQL text search configuration |