# LightRAG 性能优化指南 ## 目录 - [问题概述](#问题概述) - [根因分析](#根因分析) - [快速修复](#快速修复) - [详细配置指南](#详细配置指南) - [性能基准测试](#性能基准测试) - [高级优化](#高级优化) - [故障排查](#故障排查) --- ## 问题概述 ### 症状表现 如果您遇到了类似以下的缓慢索引速度: ``` → Processing batch 1/15 (100 chunks) ✓ Batch 1/15 indexed in 1020.6s (0.1 chunks/s) → Processing batch 2/15 (100 chunks) ✓ Batch 2/15 indexed in 1225.9s (0.1 chunks/s) ``` **这不是故意设计的** - 而是由于保守的默认设置导致的。 ### 期望性能 vs 实际性能 | 场景 | 处理速度 | 100个chunks耗时 | 1417个chunks总耗时 | |------|---------|----------------|-------------------| | **默认配置** (MAX_ASYNC=4) | 0.07 chunks/s | ~1500秒 (25分钟) | ~20,000秒 (5.7小时) ❌ | | **优化配置** (MAX_ASYNC=16) | 0.25 chunks/s | ~400秒 (7分钟) | ~5,000秒 (1.4小时) ✅ | | **激进配置** (MAX_ASYNC=32) | 0.5 chunks/s | ~200秒 (3.5分钟) | ~2,500秒 (0.7小时) ✅✅ | --- ## 根因分析 ### 性能瓶颈详解 速度慢的主要原因是**LLM并发限制过低**: ```python # 默认设置 (在 lightrag/constants.py 中) DEFAULT_MAX_ASYNC = 4 # 仅4个并发LLM调用 DEFAULT_MAX_PARALLEL_INSERT = 2 # 仅2个文档并行处理 DEFAULT_EMBEDDING_FUNC_MAX_ASYNC = 8 # Embedding并发数 ``` ### 为什么这么慢? 以100个chunks的批次为例: 1. **串行处理模型** - 100个chunks ÷ 4个并发LLM调用 = **25轮**处理 - 每次LLM调用耗时约40-60秒(网络+处理) - **总耗时:25 × 50秒 = 1250秒** ❌ 2. **瓶颈代码位置** - `lightrag/operate.py:2932` - Chunk级别的实体提取(信号量=4) - `lightrag/lightrag.py:1732` - 文档级别的并行度(信号量=2) 3. **其他影响因素** - Gleaning(额外的精炼LLM调用) - 实体/关系合并(也基于LLM) - 数据库写锁 - LLM API的网络延迟 --- ## 快速修复 ### 方案1:使用预配置的性能模板 ```bash # 复制优化配置文件 cp .env.performance .env # 重启 LightRAG # 如果使用API服务器: pkill -f lightrag_server python -m lightrag.api.lightrag_server # 如果是编程方式: # 直接重启您的应用程序 ``` ### 方案2:手动配置 创建 `.env` 文件并添加以下最小优化配置: ```bash # 核心性能设置 MAX_ASYNC=16 # 4倍提速 MAX_PARALLEL_INSERT=4 # 2倍文档并行 EMBEDDING_FUNC_MAX_ASYNC=16 EMBEDDING_BATCH_NUM=32 # 超时设置 LLM_TIMEOUT=180 EMBEDDING_TIMEOUT=30 ``` ### 方案3:代码中配置 ```python from lightrag import LightRAG rag = LightRAG( working_dir="./your_dir", llm_model_max_async=16, # ← 关键:从默认4提升 max_parallel_insert=4, # ← 从默认2提升 embedding_func_max_async=16, # ← 从默认8提升 embedding_batch_num=32, # ← 从默认10提升 # ... 其他配置 ) ``` --- ## 详细配置指南 ### 1. MAX_ASYNC(最重要!) **控制内容:** 最大并发LLM API调用数 **性能影响:** | MAX_ASYNC | 100个chunks需要轮数 | 每批次耗时 | 提速倍数 | |-----------|-------------------|-----------|---------| | 4 (默认) | 25轮 | ~1500秒 | 1倍 | | 8 | 13轮 | ~750秒 | 2倍 | | 16 | 7轮 | ~400秒 | 4倍 | | 32 | 4轮 | ~200秒 | 8倍 | | 64 | 2轮 | ~100秒 | 16倍 | **推荐设置:** | LLM提供商 | 推荐MAX_ASYNC | 说明 | |----------|--------------|------| | **OpenAI API** | 16-24 | 注意速率限制(RPM/TPM) | | **Azure OpenAI** | 32-64 | 企业版有更高限额 | | **Claude API** | 8-16 | 速率限制较严格 | | **AWS Bedrock** | 24-48 | 因模型和配额而异 | | **Google Gemini** | 16-32 | 检查配额限制 | | **自托管 (Ollama)** | 64-128 | 受GPU/CPU限制 | | **自托管 (vLLM)** | 128-256 | 高吞吐场景 | **设置方法:** ```bash # 在 .env 文件中 MAX_ASYNC=16 # 或作为环境变量 export MAX_ASYNC=16 # 或在代码中 rag = LightRAG(llm_model_max_async=16, ...) ``` ⚠️ **警告:** 设置过高可能触发API速率限制! --- ### 2. MAX_PARALLEL_INSERT **控制内容:** 同时处理的文档数量 **推荐设置:** - **公式:** `MAX_ASYNC / 3` 到 `MAX_ASYNC / 4` - 如果 MAX_ASYNC=16 → 使用 4-5 - 如果 MAX_ASYNC=32 → 使用 8-10 **为什么不能更高?** 设置过高会增加合并阶段的实体/关系命名冲突,反而**降低**整体效率。 **示例:** ```bash MAX_PARALLEL_INSERT=4 # 适合 MAX_ASYNC=16 ``` --- ### 3. EMBEDDING_FUNC_MAX_ASYNC **控制内容:** 并发embedding API调用数 **推荐设置:** | Embedding提供商 | 推荐值 | |----------------|-------| | **OpenAI Embeddings** | 16-32 | | **Azure OpenAI Embeddings** | 32-64 | | **本地 (sentence-transformers)** | 32-64 | | **本地 (BGE/GTE模型)** | 64-128 | **示例:** ```bash EMBEDDING_FUNC_MAX_ASYNC=16 ``` --- ### 4. EMBEDDING_BATCH_NUM **控制内容:** 单次embedding请求处理的文本数量 **影响:** - 默认值10对大多数场景来说太小 - 更大批次 = 更少API调用 = 更快处理 **推荐设置:** - **云端API:** 32-64 - **本地模型:** 100-200 **示例:** ```bash EMBEDDING_BATCH_NUM=32 ``` --- ## 性能基准测试 ### 测试场景 - **数据集:** 1417个chunks分15个批次 - **平均chunk大小:** ~500 tokens - **LLM:** GPT-4-mini - **Embedding:** text-embedding-3-small ### 测试结果 | 配置 | 总耗时 | 处理速度 | 提速倍数 | |-----|-------|---------|---------| | **默认** (MAX_ASYNC=4, INSERT=2) | 20,478秒 (5.7小时) | 0.07 chunks/s | 1倍 | | **基础优化** (MAX_ASYNC=8, INSERT=3) | 10,200秒 (2.8小时) | 0.14 chunks/s | 2倍 | | **推荐配置** (MAX_ASYNC=16, INSERT=4) | 5,100秒 (1.4小时) | 0.28 chunks/s | 4倍 | | **激进配置** (MAX_ASYNC=32, INSERT=8) | 2,550秒 (0.7小时) | 0.56 chunks/s | 8倍 | ### 成本收益分析 | 配置 | 节省时间 | 额外成本* | 建议 | |-----|---------|----------|------| | 基础优化 | 2.9小时 | 无 | ✅ **总是使用** | | 推荐配置 | 4.3小时 | 无 | ✅ **强烈推荐** | | 激进配置 | 5.0小时 | +10-20% (如果超限) | ⚠️ **谨慎使用** | *额外成本仅在超过速率限制需要升级套餐时产生 --- ## 高级优化 ### 1. 使用本地LLM模型 **优势:** 消除网络延迟,无限并发 ```bash # 使用 Ollama LLM_BINDING=ollama LLM_BINDING_HOST=http://localhost:11434 LLM_MODEL_NAME=deepseek-r1:8b MAX_ASYNC=64 # 远高于云端API ``` **推荐模型:** - **DeepSeek-R1** (8B/14B/32B) - 质量好,速度快 - **Qwen2.5** (7B/14B/32B) - 实体提取能力强 - **Llama-3.3** (70B) - 高质量,较慢 ### 2. 使用本地Embedding模型 ```python from sentence_transformers import SentenceTransformer model = SentenceTransformer('BAAI/bge-m3') async def local_embedding_func(texts): return model.encode(texts, normalize_embeddings=True) rag = LightRAG( embedding_func=EmbeddingFunc( embedding_dim=1024, max_token_size=8192, func=local_embedding_func ), embedding_func_max_async=64, # 本地模型可以更高 embedding_batch_num=100, ) ``` ### 3. 禁用Gleaning(如果精度不关键) Gleaning是第二次LLM调用来精炼实体提取。禁用它可以**翻倍**速度: ```python rag = LightRAG( entity_extract_max_gleaning=0, # 默认是1 # ... 其他设置 ) ``` **影响:** - 速度:快2倍 ✅ - 精度:略微降低(~5-10%)⚠️ ### 4. 优化数据库后端 #### 使用更快的图数据库 ```bash # 将 NetworkX/JSON 替换为 Memgraph(内存图数据库) KG_STORAGE=memgraph MEMGRAPH_HOST=localhost MEMGRAPH_PORT=7687 # 或 Neo4j(生产就绪) KG_STORAGE=neo4j NEO4J_URI=bolt://localhost:7687 ``` #### 使用更快的向量数据库 ```bash # 将 NanoVectorDB 替换为 Qdrant 或 Milvus VECTOR_STORAGE=qdrant QDRANT_URL=http://localhost:6333 # 或 Milvus(大规模场景) VECTOR_STORAGE=milvus MILVUS_HOST=localhost MILVUS_PORT=19530 ``` ### 5. 硬件优化 - **使用SSD:** 如果使用JSON/NetworkX存储 - **增加内存:** 用于内存图数据库(NetworkX, Memgraph) - **GPU加速Embedding:** 本地embedding模型(sentence-transformers) --- ## 故障排查 ### 问题1:"Rate limit exceeded"错误 **症状:** ``` openai.RateLimitError: Rate limit exceeded ``` **解决方案:** 1. 降低 MAX_ASYNC: ```bash MAX_ASYNC=8 # 从16降低 ``` 2. 添加延迟(不推荐 - 最好降低MAX_ASYNC): ```python # 在LLM函数包装器中 await asyncio.sleep(0.1) ``` ### 问题2:优化后仍然很慢 **检查项:** 1. **LLM API延迟:** ```bash # 测试LLM端点 time curl -X POST https://api.openai.com/v1/chat/completions \ -H "Authorization: Bearer $OPENAI_API_KEY" \ -d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"test"}]}' ``` - 应该 < 2-3秒 - 如果 > 5秒,说明有网络问题或API端点问题 2. **数据库写入瓶颈:** ```bash # 检查磁盘I/O iostat -x 1 # 如果使用Neo4j,检查查询性能 # 在Neo4j浏览器中: CALL dbms.listQueries() ``` 3. **内存问题:** ```bash # 检查内存使用 free -h htop ``` ### 问题3:内存溢出错误 **症状:** ``` MemoryError: Unable to allocate array ``` **解决方案:** 1. 减少批次大小: ```bash MAX_PARALLEL_INSERT=2 # 从4降低 EMBEDDING_BATCH_NUM=16 # 从32降低 ``` 2. 使用外部数据库而非内存: ```bash # 不使用NetworkX,改用Neo4j KG_STORAGE=neo4j ``` ### 问题4:连接超时错误 **症状:** ``` asyncio.TimeoutError: Task took longer than 180s ``` **解决方案:** ```bash # 增加超时时间 LLM_TIMEOUT=300 # 增加到5分钟 EMBEDDING_TIMEOUT=60 # 增加到1分钟 ``` --- ## 配置模板 ### 模板1:OpenAI云端API(平衡) ```bash # .env MAX_ASYNC=16 MAX_PARALLEL_INSERT=4 EMBEDDING_FUNC_MAX_ASYNC=16 EMBEDDING_BATCH_NUM=32 LLM_TIMEOUT=180 EMBEDDING_TIMEOUT=30 LLM_BINDING=openai LLM_MODEL_NAME=gpt-4o-mini EMBEDDING_BINDING=openai EMBEDDING_MODEL_NAME=text-embedding-3-small ``` ### 模板2:Azure OpenAI(高性能) ```bash # .env MAX_ASYNC=32 MAX_PARALLEL_INSERT=8 EMBEDDING_FUNC_MAX_ASYNC=32 EMBEDDING_BATCH_NUM=64 LLM_TIMEOUT=180 LLM_BINDING=azure_openai AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com/ AZURE_OPENAI_API_KEY=your-key AZURE_OPENAI_DEPLOYMENT=gpt-4o ``` ### 模板3:本地Ollama(最快速度) ```bash # .env MAX_ASYNC=64 MAX_PARALLEL_INSERT=10 EMBEDDING_FUNC_MAX_ASYNC=64 EMBEDDING_BATCH_NUM=100 LLM_TIMEOUT=0 # 本地无需超时 LLM_BINDING=ollama LLM_BINDING_HOST=http://localhost:11434 LLM_MODEL_NAME=deepseek-r1:14b ``` ### 模板4:成本优化(较慢但更便宜) ```bash # .env MAX_ASYNC=8 MAX_PARALLEL_INSERT=2 EMBEDDING_FUNC_MAX_ASYNC=8 EMBEDDING_BATCH_NUM=16 # 使用更小、更便宜的模型 LLM_MODEL_NAME=gpt-4o-mini EMBEDDING_MODEL_NAME=text-embedding-3-small # 禁用gleaning以减少LLM调用 # (在代码中设置:entity_extract_max_gleaning=0) ``` --- ## 性能监控 ### 1. 启用详细日志 ```bash LOG_LEVEL=DEBUG LOG_FILENAME=lightrag_performance.log ``` ### 2. 跟踪关键指标 在日志中查找: ``` ✓ Batch 1/15 indexed in 1020.6s (0.1 chunks/s, track_id: insert_...) ``` **关键指标:** - **Chunks/秒:** 目标 > 0.2(优化后) - **批次耗时:** 目标 < 500秒(100个chunks) - **Track_id:** 用于追踪特定批次 ### 3. 使用性能分析 ```python import time class PerformanceMonitor: def __init__(self): self.start = time.time() def checkpoint(self, label): elapsed = time.time() - self.start print(f"[{label}] {elapsed:.2f}秒") # 在代码中使用: monitor = PerformanceMonitor() await rag.ainsert(text) monitor.checkpoint("插入完成") ``` --- ## 优化检查清单 **快速见效(先做这个!):** - [ ] 复制 `.env.performance` 到 `.env` - [ ] 设置 `MAX_ASYNC=16`(或根据API限制更高) - [ ] 设置 `MAX_PARALLEL_INSERT=4` - [ ] 设置 `EMBEDDING_BATCH_NUM=32` - [ ] 重启 LightRAG 服务 **预期结果:** - 速度提升:**快4-8倍** - 您的1417个chunks:**约1.4小时**而非5.7小时 **如果仍然很慢:** - [ ] 用curl测试检查LLM API延迟 - [ ] 在API控制台监控速率限制 - [ ] 考虑本地模型(Ollama)获得无限速度 - [ ] 切换到更快的数据库后端(Memgraph, Qdrant) --- ## 技术支持 如果优化后仍然遇到性能问题: 1. **检查issues:** https://github.com/HKUDS/LightRAG/issues 2. **提供详细信息:** - 您的 `.env` 配置 - LLM/embedding提供商 - 显示时间的日志片段 - 硬件规格(CPU/内存/磁盘) 3. **加入社区:** - GitHub Discussions - Discord(如果有) --- ## 更新日志 - **2025-11-19:** 初始性能优化指南 - 添加根因分析 - 创建优化配置模板 - 不同配置的基准测试