Showing preview only (6,598K chars total). Download the full file or copy to clipboard to get everything.
Repository: HKUDS/LightRAG
Branch: main
Commit: 3131c0e90514
Files: 378
Total size: 6.2 MB
Directory structure:
gitextract_rq0j1lje/
├── .clinerules/
│ └── 01-basic.md
├── .dockerignore
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.yml
│ │ ├── config.yml
│ │ ├── feature_request.yml
│ │ └── question.yml
│ ├── dependabot.yml
│ ├── pull_request_template.md
│ └── workflows/
│ ├── claude.yml
│ ├── copilot-setup-steps.yml
│ ├── docker-build-lite.yml
│ ├── docker-build-manual.yml
│ ├── docker-publish.yml
│ ├── linting.yaml
│ ├── pypi-publish.yml
│ ├── stale.yaml
│ └── tests.yml
├── .gitignore
├── .pre-commit-config.yaml
├── AGENTS.md
├── Dockerfile
├── Dockerfile.lite
├── LICENSE
├── MANIFEST.in
├── Makefile
├── README-zh.md
├── README.md
├── SECURITY.md
├── config.ini.example
├── docker-build-push.sh
├── docker-compose-full.yml
├── docker-compose.yml
├── docs/
│ ├── Algorithm.md
│ ├── DockerDeployment.md
│ ├── FrontendBuildGuide.md
│ ├── InteractiveSetup.md
│ ├── LightRAG_concurrent_explain.md
│ ├── MilvusConfigurationGuide.md
│ ├── OfflineDeployment.md
│ └── UV_LOCK_GUIDE.md
├── env.example
├── examples/
│ ├── generate_query.py
│ ├── graph_visual_with_html.py
│ ├── graph_visual_with_neo4j.py
│ ├── graph_visual_with_opensearch.py
│ ├── insert_custom_kg.py
│ ├── lightrag_azure_openai_demo.py
│ ├── lightrag_gemini_demo.py
│ ├── lightrag_gemini_postgres_demo.py
│ ├── lightrag_gemini_workspace_demo.py
│ ├── lightrag_ollama_demo.py
│ ├── lightrag_openai_compatible_demo.py
│ ├── lightrag_openai_demo.py
│ ├── lightrag_openai_mongodb_graph_demo.py
│ ├── lightrag_openai_opensearch_graph_demo.py
│ ├── lightrag_vllm_demo.py
│ ├── milvus_kwargs_configuration_demo.py
│ ├── modalprocessors_example.py
│ ├── opensearch_storage_demo.py
│ ├── raganything_example.py
│ ├── rerank_example.py
│ └── unofficial-sample/
│ ├── copy_llm_cache_to_another_storage.py
│ ├── lightrag_bedrock_demo.py
│ ├── lightrag_cloudflare_demo.py
│ ├── lightrag_hf_demo.py
│ ├── lightrag_llamaindex_direct_demo.py
│ ├── lightrag_llamaindex_litellm_demo.py
│ ├── lightrag_llamaindex_litellm_opik_demo.py
│ ├── lightrag_lmdeploy_demo.py
│ ├── lightrag_nvidia_demo.py
│ └── lightrag_openai_neo4j_milvus_redis_demo.py
├── k8s-deploy/
│ ├── README-zh.md
│ ├── README.md
│ ├── databases/
│ │ ├── 00-config.sh
│ │ ├── 01-prepare.sh
│ │ ├── 02-install-database.sh
│ │ ├── 03-uninstall-database.sh
│ │ ├── 04-cleanup.sh
│ │ ├── README.md
│ │ ├── elasticsearch/
│ │ │ └── values.yaml
│ │ ├── install-kubeblocks.sh
│ │ ├── mongodb/
│ │ │ └── values.yaml
│ │ ├── neo4j/
│ │ │ └── values.yaml
│ │ ├── postgresql/
│ │ │ └── values.yaml
│ │ ├── qdrant/
│ │ │ └── values.yaml
│ │ ├── redis/
│ │ │ └── values.yaml
│ │ ├── scripts/
│ │ │ └── common.sh
│ │ └── uninstall-kubeblocks.sh
│ ├── install_lightrag.sh
│ ├── install_lightrag_dev.sh
│ ├── lightrag/
│ │ ├── .helmignore
│ │ ├── Chart.yaml
│ │ ├── templates/
│ │ │ ├── NOTES.txt
│ │ │ ├── _helpers.tpl
│ │ │ ├── deployment.yaml
│ │ │ ├── pvc.yaml
│ │ │ ├── secret.yaml
│ │ │ └── service.yaml
│ │ └── values.yaml
│ ├── uninstall_lightrag.sh
│ └── uninstall_lightrag_dev.sh
├── lightrag/
│ ├── __init__.py
│ ├── api/
│ │ ├── .gitignore
│ │ ├── README-zh.md
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── auth.py
│ │ ├── config.py
│ │ ├── gunicorn_config.py
│ │ ├── lightrag_server.py
│ │ ├── routers/
│ │ │ ├── __init__.py
│ │ │ ├── document_routes.py
│ │ │ ├── graph_routes.py
│ │ │ ├── ollama_api.py
│ │ │ └── query_routes.py
│ │ ├── run_with_gunicorn.py
│ │ ├── runtime_validation.py
│ │ ├── static/
│ │ │ └── swagger-ui/
│ │ │ ├── swagger-ui-bundle.js
│ │ │ └── swagger-ui.css
│ │ └── utils_api.py
│ ├── base.py
│ ├── constants.py
│ ├── evaluation/
│ │ ├── README_EVALUASTION_RAGAS.md
│ │ ├── __init__.py
│ │ ├── eval_rag_quality.py
│ │ ├── sample_dataset.json
│ │ └── sample_documents/
│ │ ├── 01_lightrag_overview.md
│ │ ├── 02_rag_architecture.md
│ │ ├── 03_lightrag_improvements.md
│ │ ├── 04_supported_databases.md
│ │ ├── 05_evaluation_and_deployment.md
│ │ └── README.md
│ ├── exceptions.py
│ ├── kg/
│ │ ├── __init__.py
│ │ ├── deprecated/
│ │ │ └── chroma_impl.py
│ │ ├── faiss_impl.py
│ │ ├── json_doc_status_impl.py
│ │ ├── json_kv_impl.py
│ │ ├── memgraph_impl.py
│ │ ├── milvus_impl.py
│ │ ├── mongo_impl.py
│ │ ├── nano_vector_db_impl.py
│ │ ├── neo4j_impl.py
│ │ ├── networkx_impl.py
│ │ ├── opensearch_impl.py
│ │ ├── postgres_impl.py
│ │ ├── qdrant_impl.py
│ │ ├── redis_impl.py
│ │ └── shared_storage.py
│ ├── lightrag.py
│ ├── llm/
│ │ ├── __init__.py
│ │ ├── anthropic.py
│ │ ├── azure_openai.py
│ │ ├── bedrock.py
│ │ ├── binding_options.py
│ │ ├── deprecated/
│ │ │ └── siliconcloud.py
│ │ ├── gemini.py
│ │ ├── hf.py
│ │ ├── jina.py
│ │ ├── llama_index_impl.py
│ │ ├── lmdeploy.py
│ │ ├── lollms.py
│ │ ├── nvidia_openai.py
│ │ ├── ollama.py
│ │ ├── openai.py
│ │ └── zhipu.py
│ ├── namespace.py
│ ├── operate.py
│ ├── prompt.py
│ ├── rerank.py
│ ├── tools/
│ │ ├── README_CLEAN_LLM_QUERY_CACHE.md
│ │ ├── README_MIGRATE_LLM_CACHE.md
│ │ ├── __init__.py
│ │ ├── check_initialization.py
│ │ ├── clean_llm_query_cache.py
│ │ ├── download_cache.py
│ │ ├── lightrag_visualizer/
│ │ │ ├── README-zh.md
│ │ │ ├── README.md
│ │ │ ├── __init__.py
│ │ │ ├── assets/
│ │ │ │ ├── LICENSE - Geist.txt
│ │ │ │ ├── LICENSE - SmileySans.txt
│ │ │ │ └── place_font_here
│ │ │ ├── graph_visualizer.py
│ │ │ └── requirements.txt
│ │ ├── migrate_llm_cache.py
│ │ └── prepare_qdrant_legacy_data.py
│ ├── types.py
│ ├── utils.py
│ └── utils_graph.py
├── lightrag.service.example
├── lightrag_webui/
│ ├── .gitignore
│ ├── .prettierrc.json
│ ├── README.md
│ ├── components.json
│ ├── env.development.smaple
│ ├── env.local.sample
│ ├── eslint.config.js
│ ├── index.html
│ ├── package.json
│ ├── src/
│ │ ├── App.tsx
│ │ ├── AppRouter.tsx
│ │ ├── api/
│ │ │ └── lightrag.ts
│ │ ├── components/
│ │ │ ├── ApiKeyAlert.tsx
│ │ │ ├── AppSettings.tsx
│ │ │ ├── LanguageToggle.tsx
│ │ │ ├── Root.tsx
│ │ │ ├── ThemeProvider.tsx
│ │ │ ├── ThemeToggle.tsx
│ │ │ ├── documents/
│ │ │ │ ├── ClearDocumentsDialog.tsx
│ │ │ │ ├── DeleteDocumentsDialog.tsx
│ │ │ │ ├── PipelineStatusDialog.tsx
│ │ │ │ └── UploadDocumentsDialog.tsx
│ │ │ ├── graph/
│ │ │ │ ├── EditablePropertyRow.tsx
│ │ │ │ ├── FocusOnNode.tsx
│ │ │ │ ├── FullScreenControl.tsx
│ │ │ │ ├── GraphControl.tsx
│ │ │ │ ├── GraphLabels.tsx
│ │ │ │ ├── GraphSearch.tsx
│ │ │ │ ├── LayoutsControl.tsx
│ │ │ │ ├── Legend.tsx
│ │ │ │ ├── LegendButton.tsx
│ │ │ │ ├── MergeDialog.tsx
│ │ │ │ ├── PropertiesView.tsx
│ │ │ │ ├── PropertyEditDialog.tsx
│ │ │ │ ├── PropertyRowComponents.tsx
│ │ │ │ ├── Settings.tsx
│ │ │ │ ├── SettingsDisplay.tsx
│ │ │ │ └── ZoomControl.tsx
│ │ │ ├── retrieval/
│ │ │ │ ├── ChatMessage.tsx
│ │ │ │ └── QuerySettings.tsx
│ │ │ ├── status/
│ │ │ │ ├── StatusCard.tsx
│ │ │ │ ├── StatusDialog.tsx
│ │ │ │ └── StatusIndicator.tsx
│ │ │ └── ui/
│ │ │ ├── Alert.tsx
│ │ │ ├── AlertDialog.tsx
│ │ │ ├── AsyncSearch.tsx
│ │ │ ├── AsyncSelect.tsx
│ │ │ ├── Badge.tsx
│ │ │ ├── Button.tsx
│ │ │ ├── Card.tsx
│ │ │ ├── Checkbox.tsx
│ │ │ ├── Command.tsx
│ │ │ ├── DataTable.tsx
│ │ │ ├── Dialog.tsx
│ │ │ ├── EmptyCard.tsx
│ │ │ ├── FileUploader.tsx
│ │ │ ├── Input.tsx
│ │ │ ├── NumberInput.tsx
│ │ │ ├── PaginationControls.tsx
│ │ │ ├── Popover.tsx
│ │ │ ├── Progress.tsx
│ │ │ ├── ScrollArea.tsx
│ │ │ ├── Select.tsx
│ │ │ ├── Separator.tsx
│ │ │ ├── TabContent.tsx
│ │ │ ├── Table.tsx
│ │ │ ├── Tabs.tsx
│ │ │ ├── Text.tsx
│ │ │ ├── Textarea.tsx
│ │ │ ├── Tooltip.tsx
│ │ │ └── UserPromptInputWithHistory.tsx
│ │ ├── contexts/
│ │ │ ├── TabVisibilityProvider.tsx
│ │ │ ├── context.ts
│ │ │ ├── types.ts
│ │ │ └── useTabVisibility.ts
│ │ ├── features/
│ │ │ ├── ApiSite.tsx
│ │ │ ├── DocumentManager.tsx
│ │ │ ├── GraphViewer.tsx
│ │ │ ├── LoginPage.tsx
│ │ │ ├── RetrievalTesting.tsx
│ │ │ └── SiteHeader.tsx
│ │ ├── hooks/
│ │ │ ├── useDebounce.tsx
│ │ │ ├── useLightragGraph.tsx
│ │ │ ├── useRandomGraph.tsx
│ │ │ └── useTheme.tsx
│ │ ├── i18n.ts
│ │ ├── index.css
│ │ ├── lib/
│ │ │ ├── constants.ts
│ │ │ ├── extensions.ts
│ │ │ └── utils.ts
│ │ ├── locales/
│ │ │ ├── ar.json
│ │ │ ├── de.json
│ │ │ ├── en.json
│ │ │ ├── fr.json
│ │ │ ├── ja.json
│ │ │ ├── ko.json
│ │ │ ├── ru.json
│ │ │ ├── uk.json
│ │ │ ├── vi.json
│ │ │ ├── zh.json
│ │ │ └── zh_TW.json
│ │ ├── main.tsx
│ │ ├── services/
│ │ │ └── navigation.ts
│ │ ├── stores/
│ │ │ ├── graph.ts
│ │ │ ├── settings.ts
│ │ │ └── state.ts
│ │ ├── types/
│ │ │ └── katex.d.ts
│ │ ├── utils/
│ │ │ ├── SearchHistoryManager.ts
│ │ │ ├── clipboard.ts
│ │ │ ├── graphColor.ts
│ │ │ └── remarkFootnotes.ts
│ │ └── vite-env.d.ts
│ ├── tailwind.config.js
│ ├── tsconfig.json
│ └── vite.config.ts
├── pyproject.toml
├── reproduce/
│ ├── Step_0.py
│ ├── Step_1.py
│ ├── Step_1_openai_compatible.py
│ ├── Step_2.py
│ ├── Step_3.py
│ ├── Step_3_openai_compatible.py
│ └── batch_eval.py
├── requirements-offline-llm.txt
├── requirements-offline-storage.txt
├── requirements-offline.txt
├── scripts/
│ ├── setup/
│ │ ├── lib/
│ │ │ ├── file_ops.sh
│ │ │ ├── presets.sh
│ │ │ ├── prompts.sh
│ │ │ ├── storage_requirements.sh
│ │ │ └── validation.sh
│ │ ├── setup.sh
│ │ └── templates/
│ │ ├── memgraph.yml
│ │ ├── milvus-gpu.yml
│ │ ├── milvus.yml
│ │ ├── mongodb.yml
│ │ ├── neo4j.yml
│ │ ├── opensearch.yml
│ │ ├── postgres.yml
│ │ ├── qdrant-gpu.yml
│ │ ├── qdrant.yml
│ │ ├── redis.conf.template
│ │ ├── redis.yml
│ │ ├── vllm-embed-gpu.yml
│ │ ├── vllm-embed.yml
│ │ ├── vllm-rerank-gpu.yml
│ │ └── vllm-rerank.yml
│ └── test.sh
├── setup.py
└── tests/
├── README_WORKSPACE_ISOLATION_TESTS.md
├── conftest.py
├── test_aquery_data_endpoint.py
├── test_batch_embeddings.py
├── test_chunking.py
├── test_curl_aquery_data.sh
├── test_description_api_validation.py
├── test_dimension_mismatch.py
├── test_doc_status_chunk_preservation.py
├── test_document_file_path_normalization.py
├── test_extract_entities.py
├── test_faiss_meta_inconsistency.py
├── test_graph_storage.py
├── test_interactive_setup_outputs.py
├── test_lightrag_ollama_chat.py
├── test_llm_cache_tools_opensearch.py
├── test_milvus_index_config.py
├── test_milvus_index_creation.py
├── test_milvus_kwargs_bridge.py
├── test_neo4j_fulltext_index.py
├── test_no_model_suffix_safety.py
├── test_opensearch_storage.py
├── test_overlap_validation.py
├── test_postgres_index_name.py
├── test_postgres_migration.py
├── test_postgres_retry_integration.py
├── test_postgres_upsert.py
├── test_qdrant_migration.py
├── test_qdrant_upsert_batching.py
├── test_rerank_chunking.py
├── test_runtime_target_validation.py
├── test_token_auto_renewal.py
├── test_unified_lock_safety.py
├── test_workspace_isolation.py
├── test_workspace_migration_isolation.py
├── test_workspace_sanitization.py
├── test_write_json_optimization.py
└── test_zhipu_llm.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .clinerules/01-basic.md
================================================
# LightRAG Project Intelligence (.clinerules)
## Project Overview
LightRAG is a mature, production-ready Retrieval-Augmented Generation (RAG) system with comprehensive knowledge graph capabilities. The system has evolved from experimental to production-ready status with extensive functionality across all major components.
## Current System State (August 15, 2025)
- **Status**: Production Ready - Stable and Mature
- **Configuration**: Gemini 2.5 Flash + BAAI/bge-m3 embeddings via custom endpoints
- **Storage**: Default in-memory with file persistence (JsonKVStorage, NetworkXStorage, NanoVectorDBStorage)
- **Language**: Chinese for summaries
- **Workspace**: `space1` for data isolation
- **Authentication**: JWT-based with admin/user accounts
## Critical Implementation Patterns
### 1. Embedding Format Compatibility (CRITICAL)
**Pattern**: Always handle both base64 and raw array embedding formats
**Location**: `lightrag/llm/openai.py` - `openai_embed` function
**Issue**: Custom OpenAI-compatible endpoints return embeddings as raw arrays, not base64 strings
**Solution**:
```python
np.array(dp.embedding, dtype=np.float32) if isinstance(dp.embedding, list)
else np.frombuffer(base64.b64decode(dp.embedding), dtype=np.float32)
```
**Impact**: Document processing fails completely without this dual format support
### 2. Async Pattern Consistency (CRITICAL)
**Pattern**: Always await coroutines before calling methods on the result
**Common Error**: `coroutine.method()` instead of `(await coroutine).method()`
**Locations**: MongoDB implementations, Neo4j operations
**Example**: `await self._data.list_indexes()` then `await cursor.to_list()`
### 3. Storage Layer Data Compatibility (CRITICAL)
**Pattern**: Always filter deprecated/incompatible fields during deserialization
**Common Fields to Remove**: `content`, `_id` (MongoDB), database-specific fields
**Implementation**: `data.pop('field_name', None)` before creating dataclass objects
**Locations**: All storage implementations (JSON, Redis, MongoDB, PostgreSQL)
### 4. Lock Key Generation (CRITICAL)
**Pattern**: Always sort relationship pairs for consistent lock keys
**Implementation**: `sorted_key_parts = sorted([src, tgt])` then `f"{sorted_key_parts[0]}-{sorted_key_parts[1]}"`
**Impact**: Prevents deadlocks in concurrent relationship processing
### 5. Event Loop Management (CRITICAL)
**Pattern**: Handle event loop mismatches during shutdown gracefully
**Implementation**: Timeout + specific RuntimeError handling for "attached to a different loop"
**Location**: Neo4j storage finalization
**Impact**: Prevents application shutdown failures
### 6. Async Generator Lock Management (CRITICAL)
**Pattern**: Never hold locks across async generator yields - create snapshots instead
**Issue**: Holding locks while yielding causes deadlock when consumers need the same lock
**Location**: `lightrag/tools/migrate_llm_cache.py` - `stream_default_caches_json`
**Solution**: Create snapshot of data while holding lock, release lock, then iterate over snapshot
```python
# WRONG - Deadlock prone:
async with storage._storage_lock:
for key, value in storage._data.items():
batch[key] = value
if len(batch) >= batch_size:
yield batch # Lock still held!
# CORRECT - Snapshot approach:
async with storage._storage_lock:
matching_items = [(k, v) for k, v in storage._data.items() if condition]
# Lock released here
for key, value in matching_items:
batch[key] = value
if len(batch) >= batch_size:
yield batch # No lock held
```
**Impact**: Prevents deadlocks in Json→Json migrations and similar scenarios where source/target share locks
**Applicable To**: Any async generator that needs to access shared resources while yielding
## Architecture Patterns
### 1. Dependency Injection
**Pattern**: Pass configuration through object constructors, not direct imports
**Example**: OllamaAPI receives configuration through LightRAG object
**Benefit**: Better testability and modularity
### 2. Memory Bank Documentation
**Pattern**: Maintain comprehensive memory bank for development continuity
**Structure**: Core files (projectbrief.md, activeContext.md, progress.md, etc.)
**Purpose**: Essential for context preservation across development sessions
### 3. Configuration Management
**Pattern**: Centralize defaults in constants.py, use environment variables for runtime config
**Implementation**: Default values in constants, override via .env file
**Benefit**: Consistent configuration across components
## Development Workflow Patterns
### 1. Frontend Development (CRITICAL)
**Package Manager**: **ALWAYS USE BUN** - Never use npm or yarn unless Bun is unavailable
**Commands**:
- `bun install` - Install dependencies
- `bun run dev` - Start development server
- `bun run build` - Build for production
- `bun run lint` - Run linting
- `bun test` - Run tests
- `bun run preview` - Preview production build
**Pattern**: All frontend operations must use Bun commands
**Fallback**: Only use npm/yarn if Bun installation fails
**Testing**: Use `bun test` for all frontend testing
### 2. Bug Fix Approach
1. **Identify root cause** - Don't just fix symptoms
2. **Implement robust solution** - Handle edge cases and format variations
3. **Maintain backward compatibility** - Preserve existing functionality
4. **Add comprehensive error handling** - Graceful degradation
5. **Document the fix** - Update memory bank with technical details
### 3. Feature Implementation
1. **Follow existing patterns** - Maintain architectural consistency
2. **Use dependency injection** - Avoid direct imports between modules
3. **Implement comprehensive error handling** - Handle all failure modes
4. **Add proper logging** - Debug and warning messages
5. **Update documentation** - Memory bank and code comments
6. **Comment Language** - Use English for comments and documentation
### 4. Performance Optimization
1. **Profile before optimizing** - Identify actual bottlenecks
2. **Maintain algorithmic correctness** - Don't sacrifice functionality for speed
3. **Use appropriate data structures** - Match structure to access patterns
4. **Implement caching strategically** - Cache expensive operations
5. **Monitor memory usage** - Prevent memory leaks
### 5. Testing Workflow (CRITICAL)
**Pattern**: All tests must use pytest markers for proper CI/CD execution
**Test Categories**:
- **Offline Tests**: Use `@pytest.mark.offline` - No external dependencies (runs in CI)
- **Integration Tests**: Use `@pytest.mark.integration` - Requires databases/APIs (skipped by default)
**Commands**:
- `pytest tests/ -m offline -v` - CI default (~3 seconds for 21 tests)
- `pytest tests/ --run-integration -v` - Full test suite (all 46 tests)
**Best Practices**:
1. **Prefer offline tests** - Use mocks for LLM, embeddings, databases
2. **Mock external dependencies** - AsyncMock for async functions
3. **Test isolation** - Each test should be independent
4. **Documentation** - Add docstrings explaining purpose and scope
**Configuration**:
- `tests/pytest.ini` - Marker definitions and test discovery
- `tests/conftest.py` - Fixtures and custom options
- `.github/workflows/tests.yml` - CI/CD workflow (Python 3.10/3.11/3.12)
**Documentation**: See `memory-bank/testing-guidelines.md` for complete testing guidelines
**Impact**: Ensures all tests run reliably in CI without external services while maintaining comprehensive integration test coverage for local development
## Technology Stack Intelligence
### 1. LLM Integration
- **Primary**: Gemini 2.5 Flash via custom endpoint
- **Embedding**: BAAI/bge-m3 via custom endpoint
- **Reranking**: BAAI/bge-reranker-v2-m3
- **Pattern**: Always handle multiple provider formats
### 2. Storage Backends
- **Default**: In-memory with file persistence
- **Production Options**: PostgreSQL, MongoDB, Redis, Neo4j
- **Pattern**: Abstract storage interface with multiple implementations
### 3. API Architecture
- **Framework**: FastAPI with Gunicorn for production
- **Authentication**: JWT-based with role support
- **Compatibility**: Ollama-compatible endpoints for easy integration
### 4. Frontend
- **Framework**: React with TypeScript
- **Package Manager**: **BUN (REQUIRED)** - Always use Bun for all frontend operations
- **Build Tool**: Vite with Bun runtime
- **Visualization**: Sigma.js for graph rendering
- **State Management**: React hooks with context
- **Internationalization**: i18next for multi-language support
## Common Pitfalls and Solutions
### 1. Embedding Format Issues
**Pitfall**: Assuming all endpoints return base64-encoded embeddings
**Solution**: Always check format and handle both base64 and raw arrays
### 2. Async/Await Patterns
**Pitfall**: Calling methods on coroutines instead of awaited results
**Solution**: Always await coroutines before accessing their methods
### 3. Data Model Evolution
**Pitfall**: Breaking changes when removing fields from dataclasses
**Solution**: Filter deprecated fields during deserialization, don't break storage
### 4. Concurrency Issues
**Pitfall**: Inconsistent lock key generation causing deadlocks
**Solution**: Always sort keys for deterministic lock ordering
### 5. Event Loop Management
**Pitfall**: Event loop mismatches during shutdown
**Solution**: Implement timeout and specific error handling for loop issues
## Performance Considerations
### 1. Query Context Building
- **Algorithm**: Linear gradient weighted polling for fair resource allocation
- **Optimization**: Round-robin merging to eliminate mode bias
- **Pattern**: Smart chunk selection based on cross-entity occurrence
### 2. Graph Operations
- **Optimization**: Batch operations where possible
- **Pattern**: Use appropriate indexing for large datasets
- **Consideration**: Memory usage with large graphs
### 3. LLM Request Management
- **Pattern**: Priority-based queue for request ordering
- **Optimization**: Connection pooling and retry mechanisms
- **Consideration**: Rate limiting and cost management
## Security Patterns
### 1. Authentication
- **Implementation**: JWT tokens with role-based access
- **Pattern**: Stateless authentication with configurable expiration
- **Security**: Proper token validation and refresh mechanisms
### 2. API Security
- **Pattern**: Input validation and sanitization
- **Implementation**: FastAPI dependency injection for auth
- **Consideration**: Rate limiting and abuse prevention
## Maintenance Guidelines
### 1. Memory Bank Updates
- **Trigger**: After significant changes or bug fixes
- **Pattern**: Update activeContext.md and progress.md
- **Purpose**: Maintain development continuity
### 2. Configuration Management
- **Pattern**: Environment-based configuration with sensible defaults
- **Implementation**: .env files with example templates
- **Consideration**: Security for production deployments
### 3. Error Handling
- **Pattern**: Comprehensive logging with appropriate levels
- **Implementation**: Graceful degradation where possible
- **Consideration**: User-friendly error messages
## Project Evolution Notes
The project has evolved from experimental to production-ready status. Key milestones:
- **Early 2025**: Basic RAG implementation
- **Mid 2025**: Multiple storage backends and LLM providers
- **July 2025**: Major query optimization and algorithm improvements
- **August 2025**: Production-ready stable state
The system now supports enterprise-level deployments with comprehensive functionality across all components.
================================================
FILE: .dockerignore
================================================
# Python-related files and directories
__pycache__
.cache
# Virtual environment directories
*.venv
# Env
env/
*.env*
.env_example
# Distribution / build files
site
dist/
build/
.eggs/
*.egg-info/
*.tgz
*.tar.gz
# Exclude siles and folders
*.yml
.dockerignore
Dockerfile
Makefile
# Exclude other projects
/tests
/scripts
/data
/dickens
/reproduce
/output_complete
/rag_storage
/inputs
# Python version manager file
.python-version
# Reports
*.coverage/
*.log
log/
*.logfire
# Cache
.cache/
.mypy_cache
.pytest_cache
.ruff_cache
.gradio
.logfire
temp/
# MacOS-related files
.DS_Store
# VS Code settings (local configuration files)
.vscode
# file
TODO.md
# Exclude Git-related files
.git
.github
.gitignore
.pre-commit-config.yaml
================================================
FILE: .gitattributes
================================================
lightrag/api/webui/** binary
lightrag/api/webui/** linguist-generated
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: Bug Report
description: File a bug report
title: "[Bug]:"
labels: ["bug", "triage"]
body:
- type: checkboxes
id: existingcheck
attributes:
label: Do you need to file an issue?
description: Please help us manage our time by avoiding duplicates and common bugs with the steps below.
options:
- label: I have searched the existing issues and this bug is not already filed.
- label: I believe this is a legitimate bug, not just a question or feature request.
- type: textarea
id: description
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is.
placeholder: What went wrong?
- type: textarea
id: reproduce
attributes:
label: Steps to reproduce
description: Steps to reproduce the behavior.
placeholder: How can we replicate the issue?
- type: textarea
id: expected_behavior
attributes:
label: Expected Behavior
description: A clear and concise description of what you expected to happen.
placeholder: What should have happened?
- type: textarea
id: configused
attributes:
label: LightRAG Config Used
description: The LightRAG configuration used for the run.
placeholder: The settings content or LightRAG configuration
value: |
# Paste your config here
- type: textarea
id: screenshotslogs
attributes:
label: Logs and screenshots
description: If applicable, add screenshots and logs to help explain your problem.
placeholder: Add logs and screenshots here
- type: textarea
id: additional_information
attributes:
label: Additional Information
description: |
- LightRAG Version: e.g., v0.1.1
- Operating System: e.g., Windows 10, Ubuntu 20.04
- Python Version: e.g., 3.8
- Related Issues: e.g., #1
- Any other relevant information.
value: |
- LightRAG Version:
- Operating System:
- Python Version:
- Related Issues:
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
name: Feature Request
description: File a feature request
labels: ["enhancement"]
title: "[Feature Request]:"
body:
- type: checkboxes
id: existingcheck
attributes:
label: Do you need to file a feature request?
description: Please help us manage our time by avoiding duplicates and common feature request with the steps below.
options:
- label: I have searched the existing feature request and this feature request is not already filed.
- label: I believe this is a legitimate feature request, not just a question or bug.
- type: textarea
id: feature_request_description
attributes:
label: Feature Request Description
description: A clear and concise description of the feature request you would like.
placeholder: What this feature request add more or improve?
- type: textarea
id: additional_context
attributes:
label: Additional Context
description: Add any other context or screenshots about the feature request here.
placeholder: Any additional information
================================================
FILE: .github/ISSUE_TEMPLATE/question.yml
================================================
name: Question
description: Ask a general question
labels: ["question"]
title: "[Question]:"
body:
- type: checkboxes
id: existingcheck
attributes:
label: Do you need to ask a question?
description: Please help us manage our time by avoiding duplicates and common questions with the steps below.
options:
- label: I have searched the existing question and discussions and this question is not already answered.
- label: I believe this is a legitimate question, not just a bug or feature request.
- type: textarea
id: question
attributes:
label: Your Question
description: A clear and concise description of your question.
placeholder: What is your question?
- type: textarea
id: context
attributes:
label: Additional Context
description: Provide any additional context or details that might help us understand your question better.
placeholder: Add any relevant information here
================================================
FILE: .github/dependabot.yml
================================================
# Keep GitHub Actions up to date with GitHub's Dependabot...
# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem
version: 2
updates:
# ============================================================
# GitHub Actions
# PR Strategy:
# - All updates (major/minor/patch): Grouped into a single PR
# ============================================================
- package-ecosystem: github-actions
directory: /
groups:
github-actions:
patterns:
- "*" # Group all Actions updates into a single larger pull request
schedule:
interval: weekly
day: monday
time: "02:00"
timezone: "Asia/Shanghai"
labels:
- "dependencies"
- "github-actions"
open-pull-requests-limit: 2
# ============================================================
# Python (pip) Dependencies
# PR Strategy:
# - Major updates: Individual PR per package (except numpy which is ignored)
# - Minor updates: Grouped by category (llm-providers, storage, etc.)
# - Patch updates: Grouped by category
# ============================================================
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
day: "wednesday"
time: "02:00"
timezone: "Asia/Shanghai"
cooldown:
default-days: 5
semver-major-days: 30
semver-minor-days: 7
semver-patch-days: 3
groups:
# Core dependencies - LLM providers and embeddings
llm-providers:
patterns:
- "openai"
- "anthropic"
- "google-*"
- "boto3"
- "botocore"
- "ollama"
update-types:
- "minor"
- "patch"
# Storage backends
storage:
patterns:
- "neo4j"
- "pymongo"
- "redis"
- "psycopg*"
- "asyncpg"
- "milvus*"
- "qdrant*"
update-types:
- "minor"
- "patch"
# Data processing and ML
data-processing:
patterns:
- "numpy"
- "scipy"
- "pandas"
- "tiktoken"
- "transformers"
- "torch*"
update-types:
- "minor"
- "patch"
# Web framework and API
web-framework:
patterns:
- "fastapi"
- "uvicorn"
- "gunicorn"
- "starlette"
- "pydantic*"
update-types:
- "minor"
- "patch"
# Development and testing tools
dev-tools:
patterns:
- "pytest*"
- "ruff"
- "pre-commit"
- "black"
- "mypy"
update-types:
- "minor"
- "patch"
# Minor and patch updates for everything else
python-minor-patch:
patterns:
- "*"
update-types:
- "minor"
- "patch"
ignore:
- dependency-name: "numpy"
update-types:
- "version-update:semver-major"
labels:
- "dependencies"
- "python"
open-pull-requests-limit: 5
# ============================================================
# Frontend (bun) Dependencies
# PR Strategy:
# - Major updates: Individual PR per package
# - Minor updates: Grouped by category (react, ui-components, etc.)
# - Patch updates: Grouped by category
# ============================================================
- package-ecosystem: "bun"
directory: "/lightrag_webui"
schedule:
interval: "weekly"
day: "friday"
time: "02:00"
timezone: "Asia/Shanghai"
cooldown:
default-days: 5
semver-major-days: 30
semver-minor-days: 7
semver-patch-days: 3
groups:
# React ecosystem
react:
patterns:
- "react"
- "react-dom"
- "react-router*"
- "@types/react*"
update-types:
- "minor"
- "patch"
# UI components and styling
ui-components:
patterns:
- "@radix-ui/*"
- "tailwind*"
- "@tailwindcss/*"
- "lucide-react"
- "class-variance-authority"
- "clsx"
update-types:
- "minor"
- "patch"
# Graph visualization
graph-viz:
patterns:
- "sigma"
- "@sigma/*"
- "graphology*"
update-types:
- "minor"
- "patch"
# Build tools and dev dependencies
build-tools:
patterns:
- "vite"
- "@vitejs/*"
- "typescript"
- "eslint*"
- "@eslint/*"
- "typescript-eslint"
- "prettier"
- "prettier-*"
- "@types/bun"
update-types:
- "minor"
- "patch"
# Content rendering libraries (math, diagrams, etc.)
content-rendering:
patterns:
- "katex"
- "mermaid"
update-types:
- "minor"
- "patch"
# All other minor and patch updates
frontend-minor-patch:
patterns:
- "*"
update-types:
- "minor"
- "patch"
labels:
- "dependencies"
- "frontend"
open-pull-requests-limit: 5
================================================
FILE: .github/pull_request_template.md
================================================
<!--
Thanks for contributing to LightRAG!
Please ensure your pull request is ready for review before submitting.
About this template
This template helps contributors provide a clear and concise description of their changes. Feel free to adjust it as needed.
-->
## Description
[Briefly describe the changes made in this pull request.]
## Related Issues
[Reference any related issues or tasks addressed by this pull request.]
## Changes Made
[List the specific changes made in this pull request.]
## Checklist
- [ ] Changes tested locally
- [ ] Code reviewed
- [ ] Documentation updated (if necessary)
- [ ] Unit tests added (if applicable)
## Additional Notes
[Add any additional notes or context for the reviewer(s).]
================================================
FILE: .github/workflows/claude.yml
================================================
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]
jobs:
claude:
if: |
(
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
) && (
github.event.comment.author_association == 'OWNER' ||
github.event.comment.author_association == 'MEMBER' ||
github.event.comment.author_association == 'COLLABORATOR' ||
github.event.review.author_association == 'OWNER' ||
github.event.review.author_association == 'MEMBER' ||
github.event.review.author_association == 'COLLABORATOR' ||
github.event.issue.author_association == 'OWNER' ||
github.event.issue.author_association == 'MEMBER' ||
github.event.issue.author_association == 'COLLABORATOR'
)
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Get PR details for checkout
if: github.event.issue.pull_request || github.event_name == 'pull_request_review_comment' || github.event_name == 'pull_request_review'
id: pr_details
env:
GH_TOKEN: ${{ github.token }}
run: |
# Get PR number from the event
if [ "${{ github.event_name }}" == "issue_comment" ]; then
PR_NUMBER=${{ github.event.issue.number }}
elif [ "${{ github.event_name }}" == "pull_request_review_comment" ]; then
PR_NUMBER=${{ github.event.pull_request.number }}
elif [ "${{ github.event_name }}" == "pull_request_review" ]; then
PR_NUMBER=${{ github.event.pull_request.number }}
fi
if [ -n "$PR_NUMBER" ]; then
echo "Fetching PR #$PR_NUMBER details"
PR_DATA=$(gh pr view $PR_NUMBER -R ${{ github.repository }} --json headRefName,headRepository,headRepositoryOwner)
HEAD_REF=$(echo "$PR_DATA" | jq -r '.headRefName')
HEAD_REPO=$(echo "$PR_DATA" | jq -r '.headRepository.name')
HEAD_OWNER=$(echo "$PR_DATA" | jq -r '.headRepositoryOwner.login')
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
echo "head_ref=$HEAD_REF" >> $GITHUB_OUTPUT
echo "head_repo=$HEAD_REPO" >> $GITHUB_OUTPUT
echo "head_owner=$HEAD_OWNER" >> $GITHUB_OUTPUT
echo "repository=$HEAD_OWNER/$HEAD_REPO" >> $GITHUB_OUTPUT
fi
- name: Checkout repository
uses: actions/checkout@v6
with:
repository: ${{ steps.pr_details.outputs.repository || github.repository }}
ref: ${{ steps.pr_details.outputs.head_ref || github.ref }}
fetch-depth: 0
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# This is an optional setting that allows Claude to read CI results on PRs
additional_permissions: |
actions: read
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
# prompt: 'Update the pull request description to include a summary of changes.'
# Optional: Add claude_args to customize behavior and configuration
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options
# claude_args: '--allowed-tools Bash(gh pr:*)'
================================================
FILE: .github/workflows/copilot-setup-steps.yml
================================================
name: "Copilot Setup Steps"
# Automatically run the setup steps when they are changed to allow for easy validation, and
# allow manual testing through the repository's "Actions" tab
on:
workflow_dispatch:
push:
paths:
- .github/workflows/copilot-setup-steps.yml
pull_request:
paths:
- .github/workflows/copilot-setup-steps.yml
jobs:
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
copilot-setup-steps:
runs-on: ubuntu-latest
# Timeout after 30 minutes (maximum is 59)
timeout-minutes: 30
# You can define any steps you want, and they will run before the agent starts.
# If you do not check out your code, Copilot will do this for you.
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up Python 3.11
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Cache pip packages
uses: actions/cache@v5
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-copilot-${{ hashFiles('**/pyproject.toml') }}
restore-keys: |
${{ runner.os }}-pip-copilot-
${{ runner.os }}-pip-
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[api]"
pip install pytest pytest-asyncio httpx
- name: Create minimal frontend stub for Copilot agent
run: |
mkdir -p lightrag/api/webui
echo '<!DOCTYPE html><html><head><title>LightRAG - Copilot Agent</title></head><body><h1>Copilot Agent Mode</h1></body></html>' > lightrag/api/webui/index.html
echo "Created minimal frontend stub for Copilot agent environment"
- name: Verify installation
run: |
python --version
pip list | grep lightrag
lightrag-server --help || echo "Note: Server requires .env configuration to run"
================================================
FILE: .github/workflows/docker-build-lite.yml
================================================
name: Build Lite Docker Image
on:
workflow_dispatch:
inputs:
_notes_:
description: '⚠️ Create lite Docker images only after non-trivial version releases.'
required: false
type: boolean
default: false
permissions:
contents: read
packages: write
jobs:
build-and-push-lite:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Get latest tag
id: get_tag
run: |
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$LATEST_TAG" ]; then
LATEST_TAG="sha-$(git rev-parse --short HEAD)"
echo "No tags found, using commit SHA: $LATEST_TAG"
else
echo "Latest tag found: $LATEST_TAG"
fi
echo "tag=$LATEST_TAG" >> $GITHUB_OUTPUT
- name: Prepare lite tag
id: lite_tag
run: |
LITE_TAG="${{ steps.get_tag.outputs.tag }}-lite"
echo "Lite image tag: $LITE_TAG"
echo "lite_tag=$LITE_TAG" >> $GITHUB_OUTPUT
- name: Update version in __init__.py
run: |
sed -i "s/__version__ = \".*\"/__version__ = \"${{ steps.get_tag.outputs.tag }}\"/" lightrag/__init__.py
cat lightrag/__init__.py | grep __version__
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v6
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=raw,value=${{ steps.lite_tag.outputs.lite_tag }}
type=raw,value=lite
- name: Build and push lite Docker image
uses: docker/build-push-action@v7
with:
context: .
file: ./Dockerfile.lite
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=min
- name: Output image details
run: |
echo "Lite Docker image built and pushed successfully!"
echo "Image tag: ghcr.io/${{ github.repository }}:${{ steps.lite_tag.outputs.lite_tag }}"
echo "Base Git tag used: ${{ steps.get_tag.outputs.tag }}"
================================================
FILE: .github/workflows/docker-build-manual.yml
================================================
name: Build Test Docker Image manually
on:
workflow_dispatch:
inputs:
_notes_:
description: '⚠️ Please create a new git tag before building the docker image.'
required: false
type: boolean
default: false
permissions:
contents: read
packages: write
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0 # Fetch all history for tags
- name: Get latest tag
id: get_tag
run: |
# Get the latest tag, fallback to commit SHA if no tags exist
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$LATEST_TAG" ]; then
LATEST_TAG="sha-$(git rev-parse --short HEAD)"
echo "No tags found, using commit SHA: $LATEST_TAG"
else
echo "Latest tag found: $LATEST_TAG"
fi
echo "tag=$LATEST_TAG" >> $GITHUB_OUTPUT
echo "image_tag=$LATEST_TAG" >> $GITHUB_OUTPUT
- name: Update version in __init__.py
run: |
sed -i "s/__version__ = \".*\"/__version__ = \"${{ steps.get_tag.outputs.tag }}\"/" lightrag/__init__.py
echo "Updated __init__.py with version ${{ steps.get_tag.outputs.tag }}"
cat lightrag/__init__.py | grep __version__
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v6
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=raw,value=${{ steps.get_tag.outputs.tag }}
- name: Build and push Docker image
uses: docker/build-push-action@v7
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Output image details
run: |
echo "Docker image built and pushed successfully!"
echo "Image tags:"
echo " - ghcr.io/${{ github.repository }}:${{ steps.get_tag.outputs.tag }}"
echo "Latest Git tag used: ${{ steps.get_tag.outputs.tag }}"
================================================
FILE: .github/workflows/docker-publish.yml
================================================
name: Build Latest Docker Image on Release
on:
release:
types: [published]
workflow_dispatch:
permissions:
contents: read
packages: write
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0 # Fetch all history for tags
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Get latest tag
id: get_tag
run: |
TAG=$(git describe --tags --abbrev=0)
echo "Found tag: $TAG"
echo "tag=$TAG" >> $GITHUB_OUTPUT
- name: Check if pre-release
id: check_prerelease
run: |
TAG="${{ steps.get_tag.outputs.tag }}"
if [[ "$TAG" == *"rc"* ]] || [[ "$TAG" == *"dev"* ]]; then
echo "is_prerelease=true" >> $GITHUB_OUTPUT
echo "This is a pre-release version: $TAG"
else
echo "is_prerelease=false" >> $GITHUB_OUTPUT
echo "This is a stable release: $TAG"
fi
- name: Update version in __init__.py
run: |
sed -i "s/__version__ = \".*\"/__version__ = \"${{ steps.get_tag.outputs.tag }}\"/" lightrag/__init__.py
echo "Updated __init__.py with version ${{ steps.get_tag.outputs.tag }}"
cat lightrag/__init__.py | grep __version__
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v6
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=raw,value=${{ steps.get_tag.outputs.tag }}
type=raw,value=latest,enable=${{ steps.check_prerelease.outputs.is_prerelease == 'false' }}
- name: Build and push Docker image
uses: docker/build-push-action@v7
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
================================================
FILE: .github/workflows/linting.yaml
================================================
name: Linting and Formatting
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
lint-and-format:
name: Linting and Formatting
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pre-commit
- name: Run pre-commit
run: pre-commit run --all-files --show-diff-on-failure
================================================
FILE: .github/workflows/pypi-publish.yml
================================================
name: Upload LightRAG-hku Package
on:
release:
types: [published]
workflow_dispatch:
permissions:
contents: read
jobs:
release-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # Fetch all history for tags
# Build frontend WebUI
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Build Frontend WebUI
run: |
cd lightrag_webui
bun install --frozen-lockfile
bun run build
cd ..
- name: Verify Frontend Build
run: |
if [ ! -f "lightrag/api/webui/index.html" ]; then
echo "❌ Error: Frontend build failed - index.html not found"
exit 1
fi
echo "✅ Frontend build verified"
echo "Frontend files:"
ls -lh lightrag/api/webui/ | head -10
- uses: actions/setup-python@v6
with:
python-version: "3.x"
- name: Get version from tag
id: get_version
run: |
TAG=$(git describe --tags --abbrev=0)
echo "Found tag: $TAG"
echo "Extracted version: $TAG"
echo "version=$TAG" >> $GITHUB_OUTPUT
- name: Update version in __init__.py
run: |
sed -i "s/__version__ = \".*\"/__version__ = \"${{ steps.get_version.outputs.version }}\"/" lightrag/__init__.py
echo "Updated __init__.py with version ${{ steps.get_version.outputs.version }}"
cat lightrag/__init__.py | grep __version__
- name: Build release distributions
run: |
python -m pip install build
python -m build
- name: Upload distributions
uses: actions/upload-artifact@v7
with:
name: release-dists
path: dist/
pypi-publish:
runs-on: ubuntu-latest
needs:
- release-build
permissions:
id-token: write
environment:
name: pypi
steps:
- name: Retrieve release distributions
uses: actions/download-artifact@v8
with:
name: release-dists
path: dist/
- name: Publish release distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist/
================================================
FILE: .github/workflows/stale.yaml
================================================
# .github/workflows/stale.yml
name: Mark stale issues and pull requests
on:
schedule:
- cron: '30 22 * * *' # run at 22:30+08 every day
permissions:
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v10
with:
days-before-stale: 90 # 90 days
days-before-close: 7 # 7 days after marked as stale
stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.'
close-issue-message: 'This issue has been automatically closed because it has not had recent activity. Please open a new issue if you still have this problem.'
stale-pr-message: 'This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.'
close-pr-message: 'This pull request has been automatically closed because it has not had recent activity.'
# If there are specific labels, exempt them from being marked as stale, for example:
exempt-issue-labels: 'enhancement,tracked'
# exempt-pr-labels: 'bug,enhancement,help wanted'
repo-token: ${{ secrets.GITHUB_TOKEN }} # token provided by GitHub
================================================
FILE: .github/workflows/tests.yml
================================================
name: Offline Unit Tests
on:
push:
branches: [ main, dev ]
pull_request:
branches: [ main, dev ]
jobs:
offline-tests:
name: Offline Tests
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.12', '3.14']
steps:
- uses: actions/checkout@v6
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Cache pip packages
uses: actions/cache@v5
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt', '**/pyproject.toml') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[api]"
pip install pytest pytest-asyncio
- name: Run offline tests
run: |
# Run only tests marked as 'offline' (no external dependencies)
# Integration tests requiring databases/APIs are skipped by default
pytest tests/ -m offline -v --tb=short
- name: Upload test results
if: always()
uses: actions/upload-artifact@v7
with:
name: test-results-py${{ matrix.python-version }}
path: |
.pytest_cache/
test-results.xml
retention-days: 7
================================================
FILE: .gitignore
================================================
# Python-related files
__pycache__/
*.py[cod]
*.egg-info/
.eggs/
*.tgz
*.tar.gz
*.ini
# Virtual Environment
.venv/
venv/
# Enviroment Variable Files
.env
.env.backup.*
# Generated Docker Compose files (output of setup wizard)
docker-compose.*.yml
# Build / Distribution
dist/
build/
site/
# Logs / Reports
*.log
*.log.*
*.logfire
*.coverage/
log/
# Caches
.cache/
.mypy_cache/
.pytest_cache/
.ruff_cache/
.gradio/
.history/
temp/
# IDE / Editor Files
.idea/
.vscode/
.vscode/settings.json
# Framework-specific files
local_neo4jWorkDir/
neo4jWorkDir/
# Data & Storage
inputs/
output/
rag_storage/
data/
# Evaluation results
lightrag/evaluation/results/
# Miscellaneous
.DS_Store
TODO.md
ignore_this.txt
*.ignore.*
# Project-specific files
/dickens*/
/book.txt
download_models_hf.py
# Frontend build output (built during PyPI release)
/lightrag/api/webui/
# temporary test files in project root
/test_*
# Cline files
memory-bank
.claude/CLAUDE.md
.claude/
# Claude Code
CLAUDE.md
================================================
FILE: .pre-commit-config.yaml
================================================
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
exclude: ^lightrag/api/webui/
- id: end-of-file-fixer
exclude: ^lightrag/api/webui/
- id: requirements-txt-fixer
exclude: ^lightrag/api/webui/
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.4
hooks:
- id: ruff-format
exclude: ^lightrag/api/webui/
- id: ruff
args: [--fix, --ignore=E402]
exclude: ^lightrag/api/webui/
- repo: https://github.com/mgedmin/check-manifest
rev: "0.49"
hooks:
- id: check-manifest
stages: [manual]
exclude: ^lightrag/api/webui/
================================================
FILE: AGENTS.md
================================================
# Repository Guidelines
LightRAG is an advanced Retrieval-Augmented Generation (RAG) framework designed to enhance information retrieval and generation through graph-based knowledge representation.
## Project Structure & Module Organization
- `lightrag/`: Core Python package with orchestrators (`lightrag/lightrag.py`), storage adapters in `kg/`, LLM bindings in `llm/`, and helpers such as `operate.py` and `utils_*.py`.
- `lightrag-api/`: FastAPI service (`lightrag_server.py`) with routers under `routers/` and Gunicorn launcher `run_with_gunicorn.py`.
- `lightrag_webui/`: React 19 + TypeScript client driven by Bun + Vite; UI components live in `src/`.
- `scripts/setup/`: Interactive environment setup wizard. `setup.sh` orchestrates staged `--base` / `--storage` / `--server` / validation flows, `lib/` holds prompt/validation/file helpers, and `templates/*.yml` contains compose fragments for bundled services.
- Tests live in `tests/` and root-level `test_*.py`. Working datasets stay in `inputs/`, `rag_storage/`, `temp/`; deployment collateral lives in `docs/`, `k8s-deploy/`, and `docker-compose.yml`.
- `Makefile`: Canonical entry point for the setup wizard and local developer shortcuts; prefer documented targets over invoking ad hoc shell snippets.
## Build, Test, and Development Commands
- `python -m venv .venv && source .venv/bin/activate`: set up the Python runtime.
- `pip install -e .` / `pip install -e .[api]`: install the package and API extras in editable mode.
- `make env-base`: first-run interactive setup for LLM, embedding, and reranker configuration; writes `.env` and may generate `docker-compose.final.yml`.
- `make env-storage`, `make env-server`: optional follow-up wizard stages for storage backends and server/security/SSL settings; both reuse the existing `.env`.
- `make env-validate`, `make env-security-check`, `make env-backup`: validate, audit, or back up the current `.env` via the setup wizard.
- `lightrag-server` or `uvicorn lightrag.api.lightrag_server:app --reload`: start the API locally; ensure `.env` is present.
- `python -m pytest tests` (offline markers apply by default) or `python -m pytest tests --run-integration` / `python test_graph_storage.py`: run the full suite, opt into integration coverage, or target an individual script.
- `ruff check .`: lint Python sources before committing.
- `bun install`, `bun run dev`, `bun run build`, `bun test`: manage the web UI workflow (Bun is mandatory).
## Coding Style & Naming Conventions
- Backend code follow PEP 8 with four-space indentation, annotate functions, and reach for dataclasses when modelling state.
- Use `lightrag.utils.logger` instead of `print`; respect logger configuration flags.
- Extend storage or pipeline abstractions via `lightrag.base` and keep reusable helpers in the existing `utils_*.py`.
- Python modules remain lowercase with underscores; React components use `PascalCase.tsx` and hooks-first patterns.
- Front-end code should remain in TypeScript with two-space indentation, rely on functional React components with hooks, and follow Tailwind utility style.
## Testing Guidelines
- Keep pytest additions close to the code you touch (`tests/` mirrors feature folders and there are root-level `test_*.py` helpers); functions must start with `test_`.
- Follow `tests/pytest.ini`: markers include `offline`, `integration`, `requires_db`, and `requires_api`, and the suite runs with `-m "not integration"` by default—pass `--run-integration` (or set `LIGHTRAG_RUN_INTEGRATION=true`) when external services are available.
- Use the custom CLI toggles from `tests/conftest.py`: `--keep-artifacts`/`LIGHTRAG_KEEP_ARTIFACTS=true`, `--stress-test`/`LIGHTRAG_STRESS_TEST=true`, and `--test-workers N`/`LIGHTRAG_TEST_WORKERS` to dial up workloads or preserve temp files during investigations.
- Export other required `LIGHTRAG_*` environment variables before running integration or storage tests so adapters can reach configured backends.
- For UI updates, pair changes with Vitest specs and run `bun test`.
## Commit & Pull Request Guidelines
- Use concise, imperative commit subjects (e.g., `Fix lock key normalization`) and add body context only when necessary.
- PRs should include a summary, operational impact, linked issues, and screenshots or API samples for user-facing work.
- Verify `ruff check .`, `python -m pytest`, and affected Bun commands succeed before requesting review; note the runs in the PR text.
- This repo is a fork of `HKUDS/LightRAG`. Always target **`HKUDS/LightRAG:main`** (upstream) when creating PRs, not the fork's own main.
## Security & Configuration Tips
- Copy `.env.example` and `config.ini.example`; never commit secrets or real connection strings.
- Configure storage backends through `LIGHTRAG_*` variables and validate them with `docker-compose` services when needed.
- Treat `lightrag.log*` as local artefacts; purge sensitive information before sharing logs or outputs.
## Automation & Agent Workflow
- Use repo-relative `workdir` arguments for every shell command and prefer `rg`/`rg --files` for searches since they are faster under the CLI harness.
- Default edits to ASCII, rely on `apply_patch` for single-file changes, and only add concise comments that aid comprehension of complex logic.
- Honor existing local modifications; never revert or discard user changes (especially via `git reset --hard`) unless explicitly asked.
- Follow the planning tool guidance: skip it for trivial fixes, but provide multi-step plans for non-trivial work and keep the plan updated as steps progress.
- Validate changes by running the relevant `ruff`/`pytest`/`bun test` commands whenever feasible, and describe any unrun checks with follow-up guidance.
- For Codex and other fresh-shell automation, prefer `./scripts/test.sh` instead of bare `pytest`; the script falls back through `PYTHON`, the active virtualenv, `uv`, `.venv`, and `venv` before trying `python` or `python3`.
- For setup workflow changes, prefer `make env-*` targets over calling `scripts/setup/setup.sh` directly; the `Makefile` resolves a Bash 4+ interpreter for macOS/Linux compatibility.
- When editing setup logic, keep `.env` host-usable and treat `docker-compose.final.yml` as generated output assembled from `scripts/setup/templates/*.yml`; compose-only overrides belong in the wizard-managed compose layer rather than being persisted back into `.env`.
================================================
FILE: Dockerfile
================================================
# syntax=docker/dockerfile:1
# Frontend build stage
# Build frontend assets on the native build platform to avoid
# cross-architecture emulation issues during multi-platform builds.
FROM --platform=$BUILDPLATFORM oven/bun:1 AS frontend-builder
WORKDIR /app
# Copy frontend source code
COPY lightrag_webui/ ./lightrag_webui/
# Build frontend assets for inclusion in the API package
RUN --mount=type=cache,target=/root/.bun/install/cache \
cd lightrag_webui \
&& bun install --frozen-lockfile \
&& bun run build
# Python build stage - using uv for faster package installation
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS builder
ENV DEBIAN_FRONTEND=noninteractive
ENV UV_SYSTEM_PYTHON=1
ENV UV_COMPILE_BYTECODE=1
WORKDIR /app
# Install system deps (Rust is required by some wheels)
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
curl \
build-essential \
pkg-config \
&& rm -rf /var/lib/apt/lists/* \
&& curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
ENV PATH="/root/.cargo/bin:/root/.local/bin:${PATH}"
# Ensure shared data directory exists for uv caches
RUN mkdir -p /root/.local/share/uv
# Copy project metadata and sources
COPY pyproject.toml .
COPY setup.py .
COPY uv.lock .
# Install base, API, and offline extras without the project to improve caching
RUN --mount=type=cache,target=/root/.local/share/uv \
uv sync --frozen --no-dev --extra api --extra offline --no-install-project --no-editable
# Copy project sources after dependency layer
COPY lightrag/ ./lightrag/
# Include pre-built frontend assets from the previous stage
COPY --from=frontend-builder /app/lightrag/api/webui ./lightrag/api/webui
# Sync project in non-editable mode and ensure pip is available for runtime installs
RUN --mount=type=cache,target=/root/.local/share/uv \
uv sync --frozen --no-dev --extra api --extra offline --no-editable \
&& /app/.venv/bin/python -m ensurepip --upgrade
# Prepare offline cache directory and pre-populate tiktoken data
# Use uv run to execute commands from the virtual environment
RUN mkdir -p /app/data/tiktoken \
&& uv run lightrag-download-cache --cache-dir /app/data/tiktoken || status=$?; \
if [ -n "${status:-}" ] && [ "$status" -ne 0 ] && [ "$status" -ne 2 ]; then exit "$status"; fi
# Final stage
FROM python:3.12-slim
WORKDIR /app
# Install uv for package management
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
ENV UV_SYSTEM_PYTHON=1
# Copy installed packages and application code
COPY --from=builder /root/.local /root/.local
COPY --from=builder /app/.venv /app/.venv
COPY --from=builder /app/lightrag ./lightrag
COPY pyproject.toml .
COPY setup.py .
COPY uv.lock .
# Ensure the installed scripts are on PATH
ENV PATH=/app/.venv/bin:/root/.local/bin:$PATH
# Install dependencies with uv sync (uses locked versions from uv.lock)
# And ensure pip is available for runtime installs
RUN --mount=type=cache,target=/root/.local/share/uv \
uv sync --frozen --no-dev --extra api --extra offline --no-editable \
&& /app/.venv/bin/python -m ensurepip --upgrade
# Create persistent data directories AFTER package installation
RUN mkdir -p /app/data/rag_storage /app/data/inputs /app/data/tiktoken
# Copy offline cache into the newly created directory
COPY --from=builder /app/data/tiktoken /app/data/tiktoken
# Point to the prepared cache
ENV TIKTOKEN_CACHE_DIR=/app/data/tiktoken
ENV WORKING_DIR=/app/data/rag_storage
ENV INPUT_DIR=/app/data/inputs
# Expose API port
EXPOSE 9621
ENTRYPOINT ["python", "-m", "lightrag.api.lightrag_server"]
================================================
FILE: Dockerfile.lite
================================================
# syntax=docker/dockerfile:1
# Frontend build stage
# Build frontend assets on the native build platform to avoid
# cross-architecture emulation issues during multi-platform builds.
FROM --platform=$BUILDPLATFORM oven/bun:1 AS frontend-builder
WORKDIR /app
# Copy frontend source code
COPY lightrag_webui/ ./lightrag_webui/
# Build frontend assets for inclusion in the API package
RUN --mount=type=cache,target=/root/.bun/install/cache \
cd lightrag_webui \
&& bun install --frozen-lockfile \
&& bun run build
# Python build stage - using uv for package installation
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS builder
ENV DEBIAN_FRONTEND=noninteractive
ENV UV_SYSTEM_PYTHON=1
ENV UV_COMPILE_BYTECODE=1
WORKDIR /app
# Install system dependencies required by some wheels
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
curl \
build-essential \
pkg-config \
&& rm -rf /var/lib/apt/lists/* \
&& curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
ENV PATH="/root/.cargo/bin:/root/.local/bin:${PATH}"
# Ensure shared data directory exists for uv caches
RUN mkdir -p /root/.local/share/uv
# Copy project metadata and sources
COPY pyproject.toml .
COPY setup.py .
COPY uv.lock .
# Install project dependencies (base + API extras) without the project to improve caching
RUN --mount=type=cache,target=/root/.local/share/uv \
uv sync --frozen --no-dev --extra api --no-install-project --no-editable
# Copy project sources after dependency layer
COPY lightrag/ ./lightrag/
# Include pre-built frontend assets from the previous stage
COPY --from=frontend-builder /app/lightrag/api/webui ./lightrag/api/webui
# Sync project in non-editable mode and ensure pip is available for runtime installs
RUN --mount=type=cache,target=/root/.local/share/uv \
uv sync --frozen --no-dev --extra api --no-editable \
&& /app/.venv/bin/python -m ensurepip --upgrade
# Prepare tiktoken cache directory and pre-populate tokenizer data
# Ignore exit code 2 which indicates assets already cached
RUN mkdir -p /app/data/tiktoken \
&& uv run lightrag-download-cache --cache-dir /app/data/tiktoken || status=$?; \
if [ -n "${status:-}" ] && [ "$status" -ne 0 ] && [ "$status" -ne 2 ]; then exit "$status"; fi
# Final stage
FROM python:3.12-slim
WORKDIR /app
# Install uv for package management
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
ENV UV_SYSTEM_PYTHON=1
# Copy installed packages and application code
COPY --from=builder /root/.local /root/.local
COPY --from=builder /app/.venv /app/.venv
COPY --from=builder /app/lightrag ./lightrag
COPY pyproject.toml .
COPY setup.py .
COPY uv.lock .
# Ensure the installed scripts are on PATH
ENV PATH=/app/.venv/bin:/root/.local/bin:$PATH
# Sync dependencies inside the final image using uv
# And ensure pip is available for runtime installs
RUN --mount=type=cache,target=/root/.local/share/uv \
uv sync --frozen --no-dev --extra api --no-editable \
&& /app/.venv/bin/python -m ensurepip --upgrade
# Create persistent data directories
RUN mkdir -p /app/data/rag_storage /app/data/inputs /app/data/tiktoken
# Copy cached tokenizer assets prepared in the builder stage
COPY --from=builder /app/data/tiktoken /app/data/tiktoken
# Docker data directories
ENV TIKTOKEN_CACHE_DIR=/app/data/tiktoken
ENV WORKING_DIR=/app/data/rag_storage
ENV INPUT_DIR=/app/data/inputs
# Expose API port
EXPOSE 9621
# Set entrypoint
ENTRYPOINT ["python", "-m", "lightrag.api.lightrag_server"]
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2025 LightRAG Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: MANIFEST.in
================================================
include requirements.txt
include lightrag/api/requirements.txt
recursive-include lightrag/api/webui *
recursive-include lightrag/api/static *
================================================
FILE: Makefile
================================================
SHELL := /bin/bash
SETUP_SCRIPT := scripts/setup/setup.sh
SETUP_BASH ?= $(or $(firstword $(wildcard /opt/homebrew/bin/bash /usr/local/bin/bash /opt/local/bin/bash)),$(shell command -v bash 2>/dev/null),bash)
SETUP_OPTS ?=
COLOR_RESET := \033[0m
COLOR_BOLD := \033[1m
COLOR_BLUE := \033[34m
COLOR_GREEN := \033[32m
COLOR_YELLOW := \033[33m
ifeq ($(NO_COLOR),1)
COLOR_RESET :=
COLOR_BOLD :=
COLOR_BLUE :=
COLOR_GREEN :=
COLOR_YELLOW :=
endif
.PHONY: help configure env-base env-storage env-server env-validate env-backup env-security-check env-base-rewrite env-storage-rewrite env base storage server validate backup security security-check base-rewrite storage-rewrite
help:
@printf "$(COLOR_BOLD)Interactive setup targets$(COLOR_RESET)\n"
@printf " $(COLOR_GREEN)make env-base$(COLOR_RESET) Configure LLM, embedding, and reranker (run first)\n"
@printf " $(COLOR_GREEN)make env-storage$(COLOR_RESET) Configure storage backends and databases\n"
@printf " $(COLOR_GREEN)make env-server$(COLOR_RESET) Configure server, security, and SSL\n"
@printf " $(COLOR_GREEN)make env-validate$(COLOR_RESET) Validate existing .env\n"
@printf " $(COLOR_GREEN)make env-security-check$(COLOR_RESET) Audit existing .env for security risks\n"
@printf " $(COLOR_GREEN)make env-backup$(COLOR_RESET) Backup current .env\n"
@printf " $(COLOR_GREEN)make env-base-rewrite$(COLOR_RESET) Force-regenerate wizard-managed compose services during base setup\n"
@printf " $(COLOR_GREEN)make env-storage-rewrite$(COLOR_RESET) Force-regenerate wizard-managed compose services during storage setup\n"
@printf " $(COLOR_GREEN)make base$(COLOR_RESET) Short form of make env-base (all env prefix can be stripped)\n"
@printf "\n"
@printf "$(COLOR_BOLD)Typical workflow$(COLOR_RESET)\n"
@printf " 1. make env-base # set LLM/embedding/reranker\n"
@printf " 2. make env-storage # set storage backends (optional)\n"
@printf " 3. make env-server # set port/security/SSL (optional)\n\n"
@printf "$(COLOR_BOLD)Examples$(COLOR_RESET)\n"
@printf " make env-base\n"
@printf " make env-storage SETUP_OPTS=--debug\n"
@printf " make env-server\n\n"
@printf " make env-storage-rewrite\n\n"
@printf " make env-security-check\n\n"
@printf "$(COLOR_BOLD)Compose Output$(COLOR_RESET)\n"
@printf " Bundled service images are defined in scripts/setup/templates/*.yml.\n"
@printf " Compose file output: docker-compose.final.yml\n"
env-base env base configure:
@$(SETUP_BASH) $(SETUP_SCRIPT) --base $(SETUP_OPTS)
env-storage storage:
@$(SETUP_BASH) $(SETUP_SCRIPT) --storage $(SETUP_OPTS)
env-base-rewrite base-rewrite:
@$(SETUP_BASH) $(SETUP_SCRIPT) --base --rewrite-compose $(SETUP_OPTS)
env-storage-rewrite storage-rewrite:
@$(SETUP_BASH) $(SETUP_SCRIPT) --storage --rewrite-compose $(SETUP_OPTS)
env-server server:
@$(SETUP_BASH) $(SETUP_SCRIPT) --server $(SETUP_OPTS)
env-validate validate:
@$(SETUP_BASH) $(SETUP_SCRIPT) --validate $(SETUP_OPTS)
env-security-check security security-check:
@$(SETUP_BASH) $(SETUP_SCRIPT) --security-check $(SETUP_OPTS)
env-backup backup:
@$(SETUP_BASH) $(SETUP_SCRIPT) --backup $(SETUP_OPTS)
================================================
FILE: README-zh.md
================================================
<div align="center">
<div style="margin: 20px 0;">
<img src="./assets/logo.png" width="120" height="120" alt="LightRAG Logo" style="border-radius: 20px; box-shadow: 0 8px 32px rgba(0, 217, 255, 0.3);">
</div>
# 🚀 LightRAG: 简单且快速的检索增强生成(RAG)框架
<div align="center">
<a href="https://trendshift.io/repositories/13043" target="_blank"><img src="https://trendshift.io/api/badge/repositories/13043" alt="HKUDS%2FLightRAG | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
</div>
<div align="center">
<div style="width: 100%; height: 2px; margin: 20px 0; background: linear-gradient(90deg, transparent, #00d9ff, transparent);"></div>
</div>
<div align="center">
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; padding: 25px; text-align: center;">
<p>
<a href='https://github.com/HKUDS/LightRAG'><img src='https://img.shields.io/badge/🔥项目-主页-00d9ff?style=for-the-badge&logo=github&logoColor=white&labelColor=1a1a2e'></a>
<a href='https://arxiv.org/abs/2410.05779'><img src='https://img.shields.io/badge/📄arXiv-2410.05779-ff6b6b?style=for-the-badge&logo=arxiv&logoColor=white&labelColor=1a1a2e'></a>
<a href="https://github.com/HKUDS/LightRAG/stargazers"><img src='https://img.shields.io/github/stars/HKUDS/LightRAG?color=00d9ff&style=for-the-badge&logo=star&logoColor=white&labelColor=1a1a2e' /></a>
</p>
<p>
<img src="https://img.shields.io/badge/🐍Python-3.10-4ecdc4?style=for-the-badge&logo=python&logoColor=white&labelColor=1a1a2e">
<a href="https://pypi.org/project/lightrag-hku/"><img src="https://img.shields.io/pypi/v/lightrag-hku.svg?style=for-the-badge&logo=pypi&logoColor=white&labelColor=1a1a2e&color=ff6b6b"></a>
</p>
<p>
<a href="https://discord.gg/yF2MmDJyGJ"><img src="https://img.shields.io/badge/💬Discord-社区-7289da?style=for-the-badge&logo=discord&logoColor=white&labelColor=1a1a2e"></a>
<a href="https://github.com/HKUDS/LightRAG/issues/285"><img src="https://img.shields.io/badge/💬微信群-交流-07c160?style=for-the-badge&logo=wechat&logoColor=white&labelColor=1a1a2e"></a>
</p>
<p>
<a href="README-zh.md"><img src="https://img.shields.io/badge/🇨🇳中文版-1a1a2e?style=for-the-badge"></a>
<a href="README.md"><img src="https://img.shields.io/badge/🇺🇸English-1a1a2e?style=for-the-badge"></a>
</p>
<p>
<a href="https://pepy.tech/projects/lightrag-hku"><img src="https://static.pepy.tech/personalized-badge/lightrag-hku?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads"></a>
</p>
</div>
</div>
</div>
<div align="center" style="margin: 30px 0;">
<img src="https://user-images.githubusercontent.com/74038190/212284100-561aa473-3905-4a80-b561-0d28506553ee.gif" width="800">
</div>
<div align="center" style="margin: 30px 0;">
<img src="./README.assets/b2aaf634151b4706892693ffb43d9093.png" width="800" alt="LightRAG Diagram">
</div>
---
<div align="center">
<table>
<tr>
<td style="vertical-align: middle;">
<img src="./assets/LiteWrite.png"
width="56"
height="56"
alt="LiteWrite"
style="border-radius: 12px;" />
</td>
<td style="vertical-align: middle; padding-left: 12px;">
<a href="https://litewrite.ai">
<img src="https://img.shields.io/badge/🚀%20LiteWrite-AI%20原生%20LaTeX%20编辑器-ff6b6b?style=for-the-badge&logoColor=white&labelColor=1a1a2e">
</a>
</td>
</tr>
</table>
</div>
---
## 🎉 新闻
- [2025.11]🎯[新功能]: 集成了 **RAGAS 评估**和 **Langfuse 追踪**。更新了 API 以在查询结果中返回召回上下文,支持上下文精度指标。
- [2025.10]🎯[可扩展性增强]: 消除了处理瓶颈,以高效支持**大规模数据集**。
- [2025.09]🎯[新功能]: 显著提升了 Qwen3-30B-A3B 等**开源 LLM** 的知识图谱提取准确性。
- [2025.08]🎯[新功能]: 现已支持 **Reranker**,显著提升混合查询性能(已设为默认查询模式)。
- [2025.08]🎯[新功能]: 添加了**文档删除**功能,并支持自动重新生成知识图谱,以确保最佳查询性能。
- [2025.06]🎯[新发布]: 我们的团队发布了 [RAG-Anything](https://github.com/HKUDS/RAG-Anything) —— 一个用于无缝处理文本、图像、表格和方程式的**全功能多模态 RAG** 系统。
- [2025.06]🎯[新功能]: LightRAG 现已集成 [RAG-Anything](https://github.com/HKUDS/RAG-Anything),支持全面的多模态数据处理,实现对 PDF、图像、Office 文档、表格和公式等多种格式的无缝文档解析和 RAG 能力。详见[多模态文档处理部分](https://github.com/HKUDS/LightRAG/?tab=readme-ov-file#multimodal-document-processing-rag-anything-integration)。
- [2025.03]🎯[新功能]: LightRAG 现已支持引用功能,实现了准确的源归因和增强的文档可追溯性。
- [2025.02]🎯[新功能]: 现在您可以使用 MongoDB 作为一体化存储解决方案,实现统一的数据管理。
- [2025.02]🎯[新发布]: 我们的团队发布了 [VideoRAG](https://github.com/HKUDS/VideoRAG) —— 一个用于理解超长上下文视频的 RAG 系统。
- [2025.01]🎯[新发布]: 我们的团队发布了 [MiniRAG](https://github.com/HKUDS/MiniRAG),使用小型模型简化 RAG。
- [2025.01]🎯现在您可以使用 PostgreSQL 作为一体化存储解决方案进行数据管理。
- [2024.11]🎯[新资源]: LightRAG 的综合指南现已在 [LearnOpenCV](https://learnopencv.com/lightrag) 上发布 —— 探索深入的教程和最佳实践。非常感谢博客作者的杰出贡献!
- [2024.11]🎯[新功能]: 推出 LightRAG WebUI —— 一个允许您通过直观的 Web 界面插入、查询和可视化 LightRAG 知识的仪表板。
- [2024.11]🎯[新功能]: 现在您可以[使用 Neo4J 进行存储](https://github.com/HKUDS/LightRAG?tab=readme-ov-file#using-neo4j-for-storage) —— 开启图数据库支持。
- [2024.10]🎯[新功能]: 我们添加了 [LightRAG 介绍视频](https://youtu.be/oageL-1I0GE) 的链接 —— 演示 LightRAG 的各项功能。感谢作者的杰出贡献!
- [2024.10]🎯[新频道]: 我们创建了一个 [Discord 频道](https://discord.gg/yF2MmDJyGJ)!💬 欢迎加入我们的社区进行分享、讨论和协作! 🎉🎉
- [2024.10]🎯[新功能]: LightRAG 现在支持 [Ollama 模型](https://github.com/HKUDS/LightRAG?tab=readme-ov-file#quick-start)!
<details>
<summary style="font-size: 1.4em; font-weight: bold; cursor: pointer; display: list-item;">
算法流程图
</summary>

*图1:LightRAG索引流程图 - 图片来源:[Source](https://learnopencv.com/lightrag/)*

*图2:LightRAG检索和查询流程图 - 图片来源:[Source](https://learnopencv.com/lightrag/)*
</details>
## 安装
> **💡 使用 uv 进行包管理**: 本项目使用 [uv](https://docs.astral.sh/uv/) 进行快速可靠的 Python 包管理。
> 首先安装 uv: `curl -LsSf https://astral.sh/uv/install.sh | sh` (Unix/macOS) 或 `powershell -c "irm https://astral.sh/uv/install.ps1 | iex"` (Windows)
>
> **注意**:如果您愿意,也可以使用 pip,但为了获得更好的性能 and 更可靠的依赖管理,建议使用 uv。
>
> **📦 离线部署**: 对于离线或隔离环境,请参阅[离线部署指南](./docs/OfflineDeployment.md),了解预安装所有依赖项和缓存文件的说明。
### 安装LightRAG服务器
LightRAG服务器旨在提供Web UI和API支持。Web UI便于文档索引、知识图谱探索和简单的RAG查询界面。LightRAG服务器还提供兼容Ollama的接口,旨在将LightRAG模拟为Ollama聊天模型。这使得AI聊天机器人(如Open WebUI)可以轻松访问LightRAG。
* 从PyPI安装
```bash
### 使用 uv 安装 LightRAG 服务器(作为工具,推荐)
uv tool install "lightrag-hku[api]"
### 或使用 pip
# python -m venv .venv
# source .venv/bin/activate # Windows: .venv\Scripts\activate
# pip install "lightrag-hku[api]"
### 构建前端代码
cd lightrag_webui
bun install --frozen-lockfile
bun run build
cd ..
# 配置 env 文件
# 从 GitHub 仓库的根目录上下载 env.example 文件
# 或从本地检出的源代码中获取 env.example 文件
cp env.example .env # 使用你的LLM和Embedding模型访问参数更新.env文件
# 启动API-WebUI服务
lightrag-server
```
* 从源代码安装
```bash
git clone https://github.com/HKUDS/LightRAG.git
cd LightRAG
# 使用 uv (推荐)
# 注意: uv sync 会自动在 .venv/ 目录创建虚拟环境
uv sync --extra api
source .venv/bin/activate # 激活虚拟环境 (Linux/macOS)
# Windows 系统: .venv\Scripts\activate
### 或使用 pip 和虚拟环境
# python -m venv .venv
# source .venv/bin/activate # Windows: .venv\Scripts\activate
# pip install -e ".[api]"
# 构建前端代码
cd lightrag_webui
bun install --frozen-lockfile
bun run build
cd ..
# 配置 env 文件
cp env.example .env # 使用你的LLM和Embedding模型访问参数更新.env文件
# 启动API-WebUI服务
lightrag-server
```
* 使用 Docker Compose 启动 LightRAG 服务器
```bash
git clone https://github.com/HKUDS/LightRAG.git
cd LightRAG
cp env.example .env # 使用你的LLM和Embedding模型访问参数更新.env文件
# modify LLM and Embedding settings in .env
docker compose up
```
> 在此获取LightRAG docker镜像历史版本: [LightRAG Docker Images]( https://github.com/HKUDS/LightRAG/pkgs/container/lightrag)
### 使用 Setup 工具创建 .env 文件
除了手动编辑 `env.example` 之外,您还可以使用交互式向导生成配置好的 `.env`,并在需要时生成 `docker-compose.final.yml`:
```bash
make env-base # 必跑第一步:配置 LLM、Embedding、Reranker
make env-storage # 可选:配置存储后端和数据库服务
make env-server # 可选:配置服务端口、鉴权和 SSL
make env-base-rewrite # 可选:强制重建向导托管的 compose 服务块
make env-storage-rewrite # 可选:强制重建向导托管的 compose 服务块
make env-security-check # 可选:审计当前 .env 中的安全风险
```
每个目标的详细说明请参阅 [docs/InteractiveSetup.md](./docs/InteractiveSetup.md)。
这些 setup 向导只负责更新配置;如需在部署前审计当前 `.env` 的安全风险,请额外运行
`make env-security-check`。
默认情况下,重新运行 setup 会保留未变化的向导托管 compose 服务块;只有在需要按模板强制重建这些托管块时,才使用
`*-rewrite` 目标。
### 安装LightRAG Core
* 从源代码安装(推荐)
```bash
cd LightRAG
# 注意: uv sync 会自动在 .venv/ 目录创建虚拟环境
uv sync
source .venv/bin/activate # 激活虚拟环境 (Linux/macOS)
# Windows 系统: .venv\Scripts\activate
# 或: pip install -e .
```
* 从PyPI安装
```bash
uv pip install lightrag-hku
# 或: pip install lightrag-hku
```
## 快速开始
### LightRAG的LLM及配套技术栈要求
LightRAG对大型语言模型(LLM)的能力要求远高于传统RAG,因为它需要LLM执行文档中的实体关系抽取任务。配置合适的Embedding和Reranker模型对提高查询表现也至关重要。
- **LLM选型**:
- 推荐选用参数量至少为32B的LLM。
- 上下文长度至少为32KB,推荐达到64KB。
- 在文档索引阶段不建议选择推理模型。
- 在查询阶段建议选择比索引阶段能力更强的模型,以达到更高的查询效果。
- **Embedding模型**:
- 高性能的Embedding模型对RAG至关重要。
- 推荐使用主流的多语言Embedding模型,例如:BAAI/bge-m3 和 text-embedding-3-large。
- **重要提示**:在文档索引前必须确定使用的Embedding模型,且在文档查询阶段必须沿用与索引阶段相同的模型。有些存储(例如PostgreSQL)在首次建立数表的时候需要确定向量维度,因此更换Embedding模型后需要删除向量相关库表,以便让LightRAG重建新的库表。
- **Reranker模型配置**:
- 配置Reranker模型能够显著提升LightRAG的检索效果。
- 启用Reranker模型后,推荐将“mix模式”设为默认查询模式。
- 推荐选用主流的Reranker模型,例如:BAAI/bge-reranker-v2-m3 或 Jina 等服务商提供的模型。
### 使用LightRAG服务器
**有关LightRAG服务器的更多信息,请参阅[LightRAG服务器](./lightrag/api/README.md)。**
### 使用LightRAG Core
LightRAG核心功能的示例代码请参见`examples`目录。您还可参照[视频](https://www.youtube.com/watch?v=g21royNJ4fw)视频完成环境配置。若已持有OpenAI API密钥,可以通过以下命令运行演示代码:
```bash
### you should run the demo code with project folder
cd LightRAG
### provide your API-KEY for OpenAI
export OPENAI_API_KEY="sk-...your_opeai_key..."
### download the demo document of "A Christmas Carol" by Charles Dickens
curl https://raw.githubusercontent.com/gusye1234/nano-graphrag/main/tests/mock_data.txt > ./book.txt
### run the demo code
python examples/lightrag_openai_demo.py
```
如需流式响应示例的实现代码,请参阅 `examples/lightrag_openai_compatible_demo.py`。运行前,请确保根据需求修改示例代码中的LLM及嵌入模型配置。
**注意1**:在运行demo程序的时候需要注意,不同的测试程序可能使用的是不同的embedding模型,更换不同的embeding模型的时候需要把清空数据目录(`./dickens`),否则层序执行会出错。如果你想保留LLM缓存,可以在清除数据目录时保留`kv_store_llm_response_cache.json`文件。
**注意2**:官方支持的示例代码仅为 `lightrag_openai_demo.py` 和 `lightrag_openai_compatible_demo.py` 两个文件。其他示例文件均为社区贡献内容,尚未经过完整测试与优化。
## 使用LightRAG Core进行编程
> ⚠️ **如果您希望将LightRAG集成到您的项目中,建议您使用LightRAG Server提供的REST API**。LightRAG Core通常用于嵌入式应用,或供希望进行研究与评估的学者使用。
### ⚠️ 重要:初始化要求
LightRAG 在使用前需要显式初始化。 创建 LightRAG 实例后,您必须调用 await rag.initialize_storages(),否则将出现错误。
### 一个简单程序
以下Python代码片段演示了如何初始化LightRAG、插入文本并进行查询:
```python
import os
import asyncio
from lightrag import LightRAG, QueryParam
from lightrag.llm.openai import gpt_4o_mini_complete, gpt_4o_complete, openai_embed
from lightrag.utils import setup_logger
setup_logger("lightrag", level="INFO")
WORKING_DIR = "./rag_storage"
if not os.path.exists(WORKING_DIR):
os.mkdir(WORKING_DIR)
async def initialize_rag():
rag = LightRAG(
working_dir=WORKING_DIR,
embedding_func=openai_embed,
llm_model_func=gpt_4o_mini_complete,
)
# IMPORTANT: Both initialization calls are required!
await rag.initialize_storages() # Initialize storage backends
return rag
async def main():
try:
# 初始化RAG实例
rag = await initialize_rag()
await rag.ainsert("Your text")
# 执行混合检索
mode = "hybrid"
print(
await rag.aquery(
"What are the top themes in this story?",
param=QueryParam(mode=mode)
)
)
except Exception as e:
print(f"发生错误: {e}")
finally:
if rag:
await rag.finalize_storages()
if __name__ == "__main__":
asyncio.run(main())
```
重要说明:
- 运行脚本前请先导出你的OPENAI_API_KEY环境变量。
- 该程序使用LightRAG的默认存储设置,所有数据将持久化在WORKING_DIR/rag_storage目录下。
- 该示例仅展示了初始化LightRAG对象的最简单方式:注入embedding和LLM函数,并在创建LightRAG对象后初始化存储和管道状态。
### LightRAG初始化参数
以下是完整的LightRAG对象初始化参数清单:
<details>
<summary> 参数 </summary>
| **参数** | **类型** | **说明** | **默认值** |
| -------------- | ---------- | ----------------- | ------------- |
| **working_dir** | `str` | 存储缓存的目录 | `lightrag_cache+timestamp` |
| **workspace** | str | 用于不同 LightRAG 实例之间数据隔离的工作区名称 | |
| **kv_storage** | `str` | Storage type for documents and text chunks. Supported types: `JsonKVStorage`,`PGKVStorage`,`RedisKVStorage`,`MongoKVStorage`,`OpenSearchKVStorage` | `JsonKVStorage` |
| **vector_storage** | `str` | Storage type for embedding vectors. Supported types: `NanoVectorDBStorage`,`PGVectorStorage`,`MilvusVectorDBStorage`,`ChromaVectorDBStorage`,`FaissVectorDBStorage`,`MongoVectorDBStorage`,`QdrantVectorDBStorage`,`OpenSearchVectorDBStorage` | `NanoVectorDBStorage` |
| **graph_storage** | `str` | Storage type for graph edges and nodes. Supported types: `NetworkXStorage`,`Neo4JStorage`,`PGGraphStorage`,`AGEStorage`,`OpenSearchGraphStorage` | `NetworkXStorage` |
| **doc_status_storage** | `str` | Storage type for documents process status. Supported types: `JsonDocStatusStorage`,`PGDocStatusStorage`,`MongoDocStatusStorage`,`OpenSearchDocStatusStorage` | `JsonDocStatusStorage` |
| **chunk_token_size** | `int` | 拆分文档时每个块的最大令牌大小 | `1200` |
| **chunk_overlap_token_size** | `int` | 拆分文档时两个块之间的重叠令牌大小 | `100` |
| **tokenizer** | `Tokenizer` | 用于将文本转换为 tokens(数字)以及使用遵循 TokenizerInterface 协议的 .encode() 和 .decode() 函数将 tokens 转换回文本的函数。 如果您不指定,它将使用默认的 Tiktoken tokenizer。 | `TiktokenTokenizer` |
| **tiktoken_model_name** | `str` | 如果您使用的是默认的 Tiktoken tokenizer,那么这是要使用的特定 Tiktoken 模型的名称。如果您提供自己的 tokenizer,则忽略此设置。 | `gpt-4o-mini` |
| **entity_extract_max_gleaning** | `int` | 实体提取过程中的循环次数,附加历史消息 | `1` |
| **node_embedding_algorithm** | `str` | 节点嵌入算法(当前未使用) | `node2vec` |
| **node2vec_params** | `dict` | 节点嵌入的参数 | `{"dimensions": 1536,"num_walks": 10,"walk_length": 40,"window_size": 2,"iterations": 3,"random_seed": 3,}` |
| **embedding_func** | `EmbeddingFunc` | 从文本生成嵌入向量的函数 | `openai_embed` |
| **embedding_batch_num** | `int` | 嵌入过程的最大批量大小(每批发送多个文本) | `32` |
| **embedding_func_max_async** | `int` | 最大并发异步嵌入进程数 | `16` |
| **llm_model_func** | `callable` | LLM生成的函数 | `gpt_4o_mini_complete` |
| **llm_model_name** | `str` | 用于生成的LLM模型名称 | `meta-llama/Llama-3.2-1B-Instruct` |
| **summary_context_size** | `int` | 合并实体关系摘要时送给LLM的最大令牌数 | `10000`(由环境变量 SUMMARY_MAX_CONTEXT 设置) |
| **summary_max_tokens** | `int` | 合并实体关系描述的最大令牌数长度 | `500`(由环境变量 SUMMARY_MAX_TOKENS 设置) |
| **llm_model_max_async** | `int` | 最大并发异步LLM进程数 | `4`(默认值由环境变量MAX_ASYNC更改) |
| **llm_model_kwargs** | `dict` | LLM生成的附加参数 | |
| **vector_db_storage_cls_kwargs** | `dict` | 向量数据库的附加参数,如设置节点和关系检索的阈值 | cosine_better_than_threshold: 0.2(默认值由环境变量COSINE_THRESHOLD更改) |
| **enable_llm_cache** | `bool` | 如果为`TRUE`,将LLM结果存储在缓存中;重复的提示返回缓存的响应 | `TRUE` |
| **enable_llm_cache_for_entity_extract** | `bool` | 如果为`TRUE`,将实体提取的LLM结果存储在缓存中;适合初学者调试应用程序 | `TRUE` |
| **addon_params** | `dict` | 附加参数,例如`{"language": "Simplified Chinese", "entity_types": ["organization", "person", "location", "event"]}`:设置示例限制、输出语言和文档处理的批量大小 | language: English` |
| **embedding_cache_config** | `dict` | 问答缓存的配置。包含三个参数:`enabled`:布尔值,启用/禁用缓存查找功能。启用时,系统将在生成新答案之前检查缓存的响应。`similarity_threshold`:浮点值(0-1),相似度阈值。当新问题与缓存问题的相似度超过此阈值时,将直接返回缓存的答案而不调用LLM。`use_llm_check`:布尔值,启用/禁用LLM相似度验证。启用时,在返回缓存答案之前,将使用LLM作为二次检查来验证问题之间的相似度。 | 默认:`{"enabled": False, "similarity_threshold": 0.95, "use_llm_check": False}` |
</details>
### 查询参数
使用QueryParam控制你的查询行为:
```python
class QueryParam:
"""Configuration parameters for query execution in LightRAG."""
mode: Literal["local", "global", "hybrid", "naive", "mix", "bypass"] = "global"
"""Specifies the retrieval mode:
- "local": Focuses on context-dependent information.
- "global": Utilizes global knowledge.
- "hybrid": Combines local and global retrieval methods.
- "naive": Performs a basic search without advanced techniques.
- "mix": Integrates knowledge graph and vector retrieval.
"""
only_need_context: bool = False
"""If True, only returns the retrieved context without generating a response."""
only_need_prompt: bool = False
"""If True, only returns the generated prompt without producing a response."""
response_type: str = "Multiple Paragraphs"
"""Defines the response format. Examples: 'Multiple Paragraphs', 'Single Paragraph', 'Bullet Points'."""
stream: bool = False
"""If True, enables streaming output for real-time responses."""
top_k: int = int(os.getenv("TOP_K", "60"))
"""Number of top items to retrieve. Represents entities in 'local' mode and relationships in 'global' mode."""
chunk_top_k: int = int(os.getenv("CHUNK_TOP_K", "20"))
"""Number of text chunks to retrieve initially from vector search and keep after reranking.
If None, defaults to top_k value.
"""
max_entity_tokens: int = int(os.getenv("MAX_ENTITY_TOKENS", "6000"))
"""Maximum number of tokens allocated for entity context in unified token control system."""
max_relation_tokens: int = int(os.getenv("MAX_RELATION_TOKENS", "8000"))
"""Maximum number of tokens allocated for relationship context in unified token control system."""
max_total_tokens: int = int(os.getenv("MAX_TOTAL_TOKENS", "30000"))
"""Maximum total tokens budget for the entire query context (entities + relations + chunks + system prompt)."""
# History messages are only sent to LLM for context, not used for retrieval
conversation_history: list[dict[str, str]] = field(default_factory=list)
"""Stores past conversation history to maintain context.
Format: [{"role": "user/assistant", "content": "message"}].
"""
# Deprecated (ids filter lead to potential hallucination effects)
ids: list[str] | None = None
"""List of ids to filter the results."""
model_func: Callable[..., object] | None = None
"""Optional override for the LLM model function to use for this specific query.
If provided, this will be used instead of the global model function.
This allows using different models for different query modes.
"""
user_prompt: str | None = None
"""User-provided prompt for the query.
Addition instructions for LLM. If provided, this will be inject into the prompt template.
It's purpose is the let user customize the way LLM generate the response.
"""
enable_rerank: bool = True
"""Enable reranking for retrieved text chunks. If True but no rerank model is configured, a warning will be issued.
Default is True to enable reranking when rerank model is available.
"""
```
> top_k的默认值可以通过环境变量TOP_K更改。
### LLM and Embedding注入
LightRAG 需要利用LLM和Embeding模型来完成文档索引和知识库查询工作。在初始化LightRAG的时候需要把阶段,需要把LLM和Embedding的操作函数注入到对象中:
<details>
<summary> <b>使用类OpenAI的API</b> </summary>
* LightRAG还支持类OpenAI的聊天/嵌入API:
```python
import os
import numpy as np
from lightrag.utils import wrap_embedding_func_with_attrs
from lightrag.llm.openai import openai_complete_if_cache, openai_embed
async def llm_model_func(
prompt, system_prompt=None, history_messages=[], keyword_extraction=False, **kwargs
) -> str:
return await openai_complete_if_cache(
"solar-mini",
prompt,
system_prompt=system_prompt,
history_messages=history_messages,
api_key=os.getenv("UPSTAGE_API_KEY"),
base_url="https://api.upstage.ai/v1/solar",
**kwargs
)
@wrap_embedding_func_with_attrs(embedding_dim=4096, max_token_size=8192, model_name="solar-embedding-1-large-query")
async def embedding_func(texts: list[str]) -> np.ndarray:
return await openai_embed.func(
texts,
model="solar-embedding-1-large-query",
api_key=os.getenv("UPSTAGE_API_KEY"),
base_url="https://api.upstage.ai/v1/solar"
)
async def initialize_rag():
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=llm_model_func,
embedding_func=embedding_func # 直接传入装饰后的函数
)
await rag.initialize_storages()
return rag
```
> **关于嵌入函数封装的重要说明:**
>
> `EmbeddingFunc` 不能嵌套封装。已经被 `@wrap_embedding_func_with_attrs` 装饰过的嵌入函数(如 `openai_embed`、`ollama_embed` 等)不能再次使用 `EmbeddingFunc()` 封装。这就是为什么在创建自定义嵌入函数时,我们调用 `xxx_embed.func`(底层未封装的函数)而不是直接调用 `xxx_embed`。
</details>
<details>
<summary> <b>使用 Hugging Face 模型</b> </summary>
* 如果您想使用 Hugging Face 模型,只需要按如下方式设置 LightRAG:
参见 `lightrag_hf_demo.py`
```python
from functools import partial
from transformers import AutoTokenizer, AutoModel
# Pre-load tokenizer and model
tokenizer = AutoTokenizer.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")
embed_model = AutoModel.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")
# 使用 Hugging Face 模型初始化 LightRAG
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=hf_model_complete, # 使用 Hugging Face 模型进行文本生成
llm_model_name='meta-llama/Llama-3.1-8B-Instruct', # Hugging Face 的模型名称
# 使用 Hugging Face 嵌入函数
embedding_func=EmbeddingFunc(
embedding_dim=384,
max_token_size=2048,
model_name="sentence-transformers/all-MiniLM-L6-v2",
func=partial(
hf_embed.func, # 使用 .func 访问底层未封装的函数
tokenizer=tokenizer,
embed_model=embed_model
)
),
)
```
</details>
<details>
<summary> <b>使用Ollama模型</b> </summary>
**综述**
如果您想使用Ollama模型,您需要拉取计划使用的模型和嵌入模型,例如`nomic-embed-text`。
然后您只需要按如下方式设置LightRAG:
```python
import numpy as np
from lightrag.utils import wrap_embedding_func_with_attrs
from lightrag.llm.ollama import ollama_model_complete, ollama_embed
@wrap_embedding_func_with_attrs(embedding_dim=768, max_token_size=8192, model_name="nomic-embed-text")
async def embedding_func(texts: list[str]) -> np.ndarray:
return await ollama_embed.func(texts, embed_model="nomic-embed-text")
# Initialize LightRAG with Ollama model
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=ollama_model_complete, # Use Ollama model for text generation
llm_model_name='your_model_name', # Your model name
embedding_func=embedding_func, # Pass the decorated function directly
)
```
* **增加上下文大小**
为了使 LightRAG 正常工作,上下文大小至少需要 32k tokens。默认情况下,Ollama 模型的上下文大小为 8k。您可以通过以下两种方式之一来实现:
* **在 Modelfile 中增加 `num_ctx` 参数**
1. 拉取模型:
```bash
ollama pull qwen2
```
2. 显示模型文件:
```bash
ollama show --modelfile qwen2 > Modelfile
```
3. 编辑 Modelfile,添加以下行:
```bash
PARAMETER num_ctx 32768
```
4. 创建修改后的模型:
```bash
ollama create -f Modelfile qwen2m
```
* **通过 Ollama API 设置 `num_ctx`**
您可以使用 `llm_model_kwargs` 参数来配置 Ollama:
```python
import numpy as np
from lightrag.utils import wrap_embedding_func_with_attrs
from lightrag.llm.ollama import ollama_model_complete, ollama_embed
@wrap_embedding_func_with_attrs(embedding_dim=768, max_token_size=8192, model_name="nomic-embed-text")
async def embedding_func(texts: list[str]) -> np.ndarray:
return await ollama_embed.func(texts, embed_model="nomic-embed-text")
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=ollama_model_complete, # 使用 Ollama 模型进行文本生成
llm_model_name='your_model_name', # 您的模型名称
llm_model_kwargs={"options": {"num_ctx": 32768}},
embedding_func=embedding_func, # 直接传入装饰后的函数
)
```
> **关于嵌入函数封装的重要说明:**
>
> `EmbeddingFunc` 不能嵌套封装。已经被 `@wrap_embedding_func_with_attrs` 装饰过的嵌入函数(如 `openai_embed`、`ollama_embed` 等)不能再次使用 `EmbeddingFunc()` 封装。这就是为什么在创建自定义嵌入函数时,我们调用 `xxx_embed.func`(底层未封装的函数)而不是直接调用 `xxx_embed`。
* **低显存 GPU**
如果要在低显存 GPU 上运行此实验,您应该选择较小的模型并调整上下文窗口(增加上下文会增加内存消耗)。例如,在一块改装的 6GB 显存的挖矿 GPU 上运行此 Ollama 示例,需要在使用 `gemma2:2b` 时将上下文大小设置为 26k。它能够在 `book.txt` 中找到 197 个实体和 19 个关系。
</details>
<details>
<summary> <b>LlamaIndex</b> </summary>
LightRAG 支持与 LlamaIndex 集成(`llm/llama_index_impl.py`):
- 通过 LlamaIndex 与 OpenAI 和其他提供商集成
- 详细设置请参阅 [LlamaIndex 文档](https://developers.llamaindex.ai/python/framework/) 或 [示例](examples/unofficial-sample/)
**示例用法**
```python
# 使用 LlamaIndex 直接访问 OpenAI
import asyncio
from lightrag import LightRAG
from lightrag.llm.llama_index_impl import llama_index_complete_if_cache, llama_index_embed
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI
from lightrag.utils import setup_logger
# 为 LightRAG 设置日志处理器
setup_logger("lightrag", level="INFO")
async def initialize_rag():
rag = LightRAG(
working_dir="your/path",
llm_model_func=llama_index_complete_if_cache, # 与 LlamaIndex 兼容的补全函数
embedding_func=EmbeddingFunc( # 与 LlamaIndex 兼容的嵌入函数
embedding_dim=1536,
max_token_size=2048,
model_name=embed_model,
func=partial(llama_index_embed.func, embed_model=embed_model) # 使用 .func 访问未封装的原始函数
),
)
await rag.initialize_storages()
return rag
def main():
# 初始化 RAG 实例
rag = asyncio.run(initialize_rag())
with open("./book.txt", "r", encoding="utf-8") as f:
rag.insert(f.read())
# 执行朴素搜索
print(
rag.query("What are the top themes in this story?", param=QueryParam(mode="naive"))
)
# 执行本地搜索
print(
rag.query("What are the top themes in this story?", param=QueryParam(mode="local"))
)
# 执行全局搜索
print(
rag.query("What are the top themes in this story?", param=QueryParam(mode="global"))
)
# 执行混合搜索
print(
rag.query("What are the top themes in this story?", param=QueryParam(mode="hybrid"))
)
if __name__ == "__main__":
main()
```
**详细文档和示例请参阅:**
- [LlamaIndex 文档](https://developers.llamaindex.ai/python/framework/)
- [直接使用 OpenAI 示例](examples/unofficial-sample/lightrag_llamaindex_direct_demo.py)
- [LiteLLM 代理示例](examples/unofficial-sample/lightrag_llamaindex_litellm_demo.py)
- [LiteLLM 代理与 Opik 集成示例](examples/unofficial-sample/lightrag_llamaindex_litellm_opik_demo.py)
</details>
<details>
<summary> <b>使用 Azure OpenAI 模型</b> </summary>
如果您想使用 Azure OpenAI 模型,您只需要按如下方式设置 LightRAG:
```python
import os
import numpy as np
from lightrag.utils import wrap_embedding_func_with_attrs
from lightrag.llm.azure_openai import azure_openai_complete_if_cache, azure_openai_embed
# 配置生成模型
async def llm_model_func(
prompt, system_prompt=None, history_messages=[], keyword_extraction=False, **kwargs
) -> str:
return await azure_openai_complete_if_cache(
prompt,
system_prompt=system_prompt,
history_messages=history_messages,
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
api_version=os.getenv("AZURE_OPENAI_API_VERSION"),
deployment_name=os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME"),
**kwargs
)
# 配置嵌入模型
@wrap_embedding_func_with_attrs(
embedding_dim=1536,
max_token_size=8192,
model_name=os.getenv("AZURE_OPENAI_EMBEDDING_MODEL")
)
async def embedding_func(texts: list[str]) -> np.ndarray:
return await azure_openai_embed.func(
texts,
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
api_version=os.getenv("AZURE_OPENAI_API_VERSION"),
deployment_name=os.getenv("AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME")
)
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=llm_model_func,
embedding_func=embedding_func
)
```
</details>
<details>
<summary> <b>使用 Google Gemini 模型</b> </summary>
如果您想使用 Google Gemini 模型,您只需要按如下方式设置 LightRAG:
```python
import os
import numpy as np
from lightrag.utils import wrap_embedding_func_with_attrs
from lightrag.llm.gemini import gemini_complete, gemini_embed
# 配置生成模型
async def llm_model_func(
prompt, system_prompt=None, history_messages=[], keyword_extraction=False, **kwargs
) -> str:
return await gemini_complete(
prompt,
system_prompt=system_prompt,
history_messages=history_messages,
api_key=os.getenv("GEMINI_API_KEY"),
model="gemini-1.5-flash",
**kwargs
)
# 配置嵌入模型
@wrap_embedding_func_with_attrs(
embedding_dim=768,
max_token_size=2048,
model_name="models/text-embedding-004"
)
async def embedding_func(texts: list[str]) -> np.ndarray:
return await gemini_embed.func(
texts,
api_key=os.getenv("GEMINI_API_KEY"),
model="models/text-embedding-004"
)
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=llm_model_func,
llm_model_name="gemini-2.0-flash",
embedding_func=embedding_func
)
```
</details>
### Rerank 函数注入
为了提升检索质量,可以基于更有效的相关性评分模型对文档进行重新排序。`rerank.py` 文件提供了三个 Reranker 服务商的驱动函数:
* **Cohere / vLLM**: `cohere_rerank`
* **Jina AI**: `jina_rerank`
* **阿里云**: `ali_rerank`
您可以将其中一个函数注入到 LightRAG 对象的 `rerank_model_func` 属性中。这将使 LightRAG 的查询函数能够使用注入的函数对检索到的文本块进行重新排序。详细用法请参考 `examples/rerank_example.py` 文件。
### User Prompt 与 Query 的区别
使用 LightRAG 进行内容查询时,应避免将搜索过程与不相关的输出处理混合在一起,因为这会显著影响查询效果。QueryParam 中的 `user_prompt` 参数专门用于解决此问题 - 它不参与 RAG 检索阶段,而是在查询完成后指导 LLM 如何处理检索到的结果。使用方法如下:
```python
# 创建查询参数
query_param = QueryParam(
mode = "hybrid", # 其他模式:local, global, hybrid, mix, naive
user_prompt = "对于图表,使用 mermaid 格式,节点名称使用英文或拼音,显示标签使用中文",
)
# 查询并处理
response_default = rag.query(
"请为斯克鲁奇绘制人物关系图",
param=query_param
)
print(response_default)
```
### 插入
<details>
<summary> <b> 基本插入 </b></summary>
```python
# 基本插入
rag.insert("文本")
```
</details>
<details>
<summary> <b> 批量插入 </b></summary>
```python
# 基本批量插入:一次插入多个文本
rag.insert(["文本1", "文本2",...])
# 自定义批量大小配置的批量插入
rag = LightRAG(
...
working_dir=WORKING_DIR,
max_parallel_insert = 4
)
rag.insert(["文本1", "文本2", "文本3", ...]) # 文档将以每批 4 个的方式处理
```
`max_parallel_insert` 参数决定了文档索引管道中并发处理的文档数量。如果未指定,默认值为 **2**。我们建议将此设置保持在 **10 以下**,因为性能瓶颈通常在于大语言模型(LLM)的处理能力。
</details>
<details>
<summary> <b> 带 ID 插入 </b></summary>
如果您想为文档提供自定义 ID,文档数量和 ID 数量必须相同。
```python
# 插入单个文本,并为其提供 ID
rag.insert("文本1", ids=["文本1的ID"])
# 插入多个文本,并为它们提供 ID
rag.insert(["文本1", "文本2",...], ids=["文本1的ID", "文本2的ID"])
```
</details>
<details>
<summary><b>使用管道插入</b></summary>
`apipeline_enqueue_documents` 和 `apipeline_process_enqueue_documents` 函数允许您将文档增量插入到图中。这对于希望在后台处理文档同时允许主线程继续执行的场景非常有用。
```python
rag = LightRAG(..)
await rag.apipeline_enqueue_documents(input)
# 在循环中的例程
await rag.apipeline_process_enqueue_documents(input)
```
</details>
<details>
<summary><b>多文件类型支持插入</b></summary>
`textract` 支持读取 TXT、DOCX、PPTX、CSV 和 PDF 等文件类型。
```python
import textract
file_path = 'TEXT.pdf'
text_content = textract.process(file_path)
rag.insert(text_content.decode('utf-8'))
```
</details>
<details>
<summary><b>引用功能</b></summary>
通过提供文件路径,系统可以确保来源可以追溯到原始文档。
```python
# 定义文档及其文件路径
documents = ["文档内容 1", "文档内容 2"]
file_paths = ["path/to/doc1.txt", "path/to/doc2.txt"]
# 带文件路径插入文档
rag.insert(documents, file_paths=file_paths)
```
</details>
### 存储方案
LightRAG 使用 4 种类型的存储来满足不同用途:
* KV_STORAGE:LLM 响应缓存、文本块、文档信息
* VECTOR_STORAGE:实体向量、关系向量、文本块向量
* GRAPH_STORAGE:实体关系图
* DOC_STATUS_STORAGE:文档索引状态
每种存储类型都有多种实现:
* KV_STORAGE 支持的实现:
```
JsonKVStorage JsonFile(默认)
PGKVStorage Postgres
RedisKVStorage Redis
MongoKVStorage MongoDB
OpenSearchKVStorage OpenSearch
```
* GRAPH_STORAGE 支持的实现:
```
NetworkXStorage NetworkX(默认)
Neo4JStorage Neo4J
PGGraphStorage PostgreSQL with AGE 插件
MemgraphStorage Memgraph
OpenSearchGraphStorage OpenSearch
```
> 测试表明,Neo4J 在生产环境中的性能优于带有 AGE 插件的 PostgreSQL。
* VECTOR_STORAGE 支持的实现:
```
NanoVectorDBStorage NanoVector(默认)
PGVectorStorage Postgres
MilvusVectorDBStorage Milvus
FaissVectorDBStorage Faiss
QdrantVectorDBStorage Qdrant
MongoVectorDBStorage MongoDB
OpenSearchVectorDBStorage OpenSearch
```
* DOC_STATUS_STORAGE 支持的实现:
```
JsonDocStatusStorage JsonFile(默认)
PGDocStatusStorage Postgres
MongoDocStatusStorage MongoDB
OpenSearchDocStatusStorage OpenSearch
```
各存储类型的示例连接配置可在仓库中的 `env.example` 文件里找到。连接字符串中的数据库实例需要您预先在数据库服务器上创建。LightRAG 仅负责在数据库实例中创建表,不负责创建数据库实例本身。如果使用 Redis 作为存储,请记住配置 Redis 的自动数据持久化规则,否则 Redis 服务重启后数据将会丢失。如果使用 PostgreSQL,建议使用 16.6 或更高版本。
<details>
<summary> <b>使用 Neo4J 存储</b> </summary>
* 对于生产级场景,您很可能需要使用企业级解决方案
* 用于知识图谱存储。推荐在 Docker 中运行 Neo4J 进行无缝本地测试。
* 参见:https://hub.docker.com/_/neo4j
```python
export NEO4J_URI="neo4j://localhost:7687"
export NEO4J_USERNAME="neo4j"
export NEO4J_PASSWORD="password"
export NEO4J_DATABASE="neo4j" #<----------- 使用 neo4j 社区版 docker 镜像时数据库实例必须为neo4j
# 为 LightRAG 设置日志
setup_logger("lightrag", level="INFO")
# 启动项目时,请确保通过指定 graph_storage="Neo4JStorage" 来覆盖默认的 KG: NetworkX。
# 使用 Neo4J 实现初始化 LightRAG。
async def initialize_rag():
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=gpt_4o_mini_complete, # 使用 gpt_4o_mini_complete LLM 模型
graph_storage="Neo4JStorage", #<-----------覆盖 KG 默认值
)
# 初始化数据库连接
await rag.initialize_storages()
# 初始化文档处理的管道状态
return rag
```
参见 test_neo4j.py 获取可运行的示例。
</details>
<details>
<summary> <b>使用 PostgreSQL 存储</b> </summary>
对于生产级场景,您很可能需要使用企业级解决方案。PostgreSQL 可以为您提供一站式解决方案,作为 KV 存储、VectorDB(pgvector)和 GraphDB(apache AGE)。支持 PostgreSQL 16.6 或更高版本。
* PostgreSQL 很轻量,包含所有必要插件的完整二进制发行版可以压缩到 40MB:参考 [Windows Release](https://github.com/ShanGor/apache-age-windows/releases/tag/PG17%2Fv1.5.0-rc0),Linux/Mac 也很容易安装。
* 如果您喜欢 docker,建议初学者使用此镜像以避免出现问题(默认用户密码:rag/rag):https://hub.docker.com/r/gzdaniel/postgres-for-rag
* 如何开始?参考:[examples/lightrag_gemini_postgres_demo.py](https://github.com/HKUDS/LightRAG/blob/main/examples/lightrag_gemini_postgres_demo.py)
* 对于高性能图数据库需求,推荐使用 Neo4j,因为 Apache AGE 的性能不够理想。
</details>
<details>
<summary> <b>使用 Faiss 存储</b> </summary>
在使用 Faiss 向量数据库之前,您必须手动安装 `faiss-cpu` 或 `faiss-gpu`。
- 安装所需依赖:
```
pip install faiss-cpu
```
如果您有 GPU 支持,也可以安装 `faiss-gpu`。
- 这里我们使用 `sentence-transformers`,但您也可以使用 `3072` 维度的 `OpenAIEmbedding` 模型。
```python
async def embedding_func(texts: list[str]) -> np.ndarray:
model = SentenceTransformer('all-MiniLM-L6-v2')
embeddings = model.encode(texts, convert_to_numpy=True)
return embeddings
# 使用 LLM 模型函数和嵌入函数初始化 LightRAG
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=llm_model_func,
embedding_func=EmbeddingFunc(
embedding_dim=384,
max_token_size=2048,
model_name="all-MiniLM-L6-v2",
func=embedding_func,
),
vector_storage="FaissVectorDBStorage",
vector_db_storage_cls_kwargs={
"cosine_better_than_threshold": 0.3 # 您期望的阈值
}
)
```
</details>
<details>
<summary> <b>使用 Memgraph 存储</b> </summary>
* Memgraph 是一个高性能的内存图数据库,兼容 Neo4j Bolt 协议。
* 您可以使用 Docker 在本地运行 Memgraph 进行简单测试:
* 参见:https://memgraph.com/download
```python
export MEMGRAPH_URI="bolt://localhost:7687"
# 为 LightRAG 设置日志
setup_logger("lightrag", level="INFO")
# 启动项目时,通过指定 kg="MemgraphStorage" 来覆盖默认的 KG: NetworkX。
# 注意:默认设置使用 NetworkX
# 使用 Memgraph 实现初始化 LightRAG。
async def initialize_rag():
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=gpt_4o_mini_complete, # 使用 gpt_4o_mini_complete LLM 模型
graph_storage="MemgraphStorage", #<-----------覆盖 KG 默认值
)
# 初始化数据库连接
await rag.initialize_storages()
# 初始化文档处理的管道状态
return rag
```
</details>
<details>
<summary> <b>使用 Milvus 作为向量存储</b> </summary>
Milvus 是一个高性能、可扩展的向量数据库,适用于生产环境的向量存储。LightRAG 提供了三种配置 Milvus 的方式,并支持可配置的索引类型,以优化性能和内存使用。
### 支持的索引类型
- `AUTOINDEX`(默认):Milvus 自动选择最佳索引
- `HNSW`:层次可导航小世界图,适用于高召回率
- `HNSW_SQ`:使用标量量化技术的 HNSW,可节省内存(需 Milvus 2.6.8+)
- `HNSW_PQ`、`HNSW_PRQ`:使用乘积量化/残差乘积量化技术的 HNSW
- `IVF_FLAT`、`IVF_SQ8`、`IVF_PQ`:倒排文件族索引
- `DISKANN`:基于磁盘的近似最近邻索引
- `SCANN`:可扩展的最近邻索引
### 支持的度量类型
`COSINE` (默认), `L2`, `IP`
---
### 配置方法1 — 环境变量 (`.env` file)
适用于: **LightRAG Server 部署和 Docker/k8s 设置**.
```bash
# Connection
MILVUS_URI=http://localhost:19530
MILVUS_DB_NAME=lightrag
# MILVUS_USER=root
# MILVUS_PASSWORD=your_password
# MILVUS_TOKEN=your_token
# Storage selection
LIGHTRAG_VECTOR_STORAGE=MilvusVectorDBStorage
# Index configuration (all optional — sensible defaults apply)
MILVUS_INDEX_TYPE=HNSW # Default: AUTOINDEX
MILVUS_METRIC_TYPE=COSINE # Default: COSINE
MILVUS_HNSW_M=16 # Default: 16, range [2-2048]
MILVUS_HNSW_EF_CONSTRUCTION=360 # Default: 360
MILVUS_HNSW_EF=200 # Default: 200
# HNSW_SQ options (requires Milvus 2.6.8+)
# MILVUS_INDEX_TYPE=HNSW_SQ
# MILVUS_HNSW_SQ_TYPE=SQ8 # SQ4U, SQ6, SQ8, BF16, FP16
# MILVUS_HNSW_SQ_REFINE=false # Enable refinement
# MILVUS_HNSW_SQ_REFINE_TYPE=FP32 # Refinement precision
# MILVUS_HNSW_SQ_REFINE_K=10 # Refinement expansion factor
# IVF options
# MILVUS_IVF_NLIST=1024
# MILVUS_IVF_NPROBE=16
```
然后再Python代码中:
```python
from lightrag import LightRAG
async def initialize_rag():
rag = LightRAG(
working_dir="./rag_storage",
llm_model_func=...,
embedding_func=...,
vector_storage="MilvusVectorDBStorage",
)
await rag.initialize_storages()
return rag
```
### 配置方案2 — `vector_db_storage_cls_kwargs` (Python SDK)
适用于: **Python SDK / framework integration** (使用代码进行配置)
```python
from lightrag import LightRAG
async def initialize_rag():
rag = LightRAG(
working_dir="./rag_storage",
llm_model_func=...,
embedding_func=...,
vector_storage="MilvusVectorDBStorage",
vector_db_storage_cls_kwargs={
"milvus_uri": "http://localhost:19530",
"milvus_db_name": "lightrag",
"index_type": "HNSW",
"metric_type": "COSINE",
"hnsw_m": 16,
"hnsw_ef_construction": 360,
"hnsw_ef": 200,
"cosine_better_than_threshold": 0.2,
},
)
await rag.initialize_storages()
return rag
```
### 配置方案3 — `config.ini` (遗留方案)
仅适用于连接参数配资;索引方式配资依然需要使用环境变量或kwargs.
```ini
[milvus]
uri = http://localhost:19530
db_name = lightrag
# user = root
# password = your_password
# token = your_token
```
### 配置优先级
| 配置 | 1st (highest) | 2nd | 3rd (lowest) |
|---|---|---|---|
| 连接方式 (`uri`, …) | `vector_db_storage_cls_kwargs` | Environment variables | `config.ini` |
| 索引方法 (`index_type`, …) | `vector_db_storage_cls_kwargs` | Environment variables | defaults |
### HNSW_SQ 压缩的权衡
| SQ Type | Compression | Precision | Notes |
|---|---|---|---|
| `SQ4U` | ~8× | Lower | Best memory savings |
| `SQ6` | ~5.3× | Balanced | Good trade-off |
| `SQ8` | ~4× | Good | **Recommended** |
| `BF16` / `FP16` | ~2× | High | Near-lossless |
**版本要求:**
- HNSW_SQ 缩影方式要求 **Milvus 2.6.8 或更高版本**
- LightRAG 将自动检查服务的版本并在不符合要求的时候抛出错误
- 其它缩影方式要求Milvus 2.0+
**向后兼容性:**
- 现有数据集合不受影响;索引配置仅适用于新创建的集合
- 有关完整的配置选项,请参阅 env.example 和 docs/MilvusConfigurationGuide.md。
完整的配资选项请参考 `env.example` 和 `docs/MilvusConfigurationGuide.md`.
</details>
<details>
<summary> <b>使用 MongoDB 存储</b> </summary>
MongoDB 为 LightRAG 提供了一站式存储解决方案。MongoDB 提供原生的 KV 存储和向量存储。LightRAG 使用 MongoDB 集合来实现简单的图存储。`MongoVectorDBStorage` 需要目标 MongoDB 部署具备 Atlas Search / Vector Search 能力,例如 MongoDB Atlas 或 Atlas local。交互式 setup 向导内置的本地 Docker MongoDB 服务是 MongoDB Community Edition,因此它可以用于 KV / 图 / 文档状态存储,但不能作为 `MongoVectorDBStorage` 的后端。
</details>
<details>
<summary> <b>使用 Redis 存储</b> </summary>
LightRAG 支持使用 Redis 作为 KV 存储。使用 Redis 存储时,需要注意持久化配置和内存使用配置。以下是推荐的 Redis 配置:
```
save 900 1
save 300 10
save 60 1000
stop-writes-on-bgsave-error yes
maxmemory 4gb
maxmemory-policy noeviction
maxclients 500
```
当交互式 setup 管理本地 Redis 容器时,它会在 `./data/config/redis.conf` 生成一个可直接修改的配置文件,并将其挂载到容器内。后续重新运行 setup 时会保留该文件,避免覆盖用户的手工调整。
</details>
<details>
<summary> <b>使用 OpenSearch 存储</b> </summary>
OpenSearch 为 LightRAG 的全部四种存储类型(KV、向量、图、文档状态)提供了统一的存储解决方案。它提供原生 k-NN 向量搜索、全文搜索和水平扩展能力,且无云服务限制。
* **环境要求**:OpenSearch 3.x 或更高版本,需启用 k-NN 插件。
使用 Docker 安装 (不含插件):
```bash
docker run -d -p 9200:9200 -e "discovery.type=single-node" \
-e "OPENSEARCH_INITIAL_ADMIN_PASSWORD=<custom-admin-password>" \
opensearchproject/opensearch:latest
```
使用 Docker Compose 安装 (推荐,含插件):
```bash
curl -O https://raw.githubusercontent.com/opensearch-project/opensearch-build/main/docker/release/dockercomposefiles/docker-compose-3.x.yml
# 启动 OpenSearch 集群
OPENSEARCH_INITIAL_ADMIN_PASSWORD=<custom-admin-password> docker-compose -f docker-compose-3.x.yml up -d
```
* **配置**:设置环境变量(完整列表请参见 `env.example`):
```bash
export OPENSEARCH_HOSTS=localhost:9200
export OPENSEARCH_USER=admin
export OPENSEARCH_PASSWORD=<custom-admin-password>
export OPENSEARCH_USE_SSL=true
export OPENSEARCH_VERIFY_CERTS=false
```
* **使用方式**:
```python
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=your_llm_func,
embedding_func=your_embed_func,
kv_storage="OpenSearchKVStorage",
doc_status_storage="OpenSearchDocStatusStorage",
graph_storage="OpenSearchGraphStorage",
vector_storage="OpenSearchVectorDBStorage",
)
```
* **图遍历**:当 OpenSearch SQL 插件支持 PPL 时,图查询会使用 `graphlookup` 命令进行服务端 BFS 遍历以获得最佳性能。否则,将回退到客户端批量 BFS。此功能在启动时自动检测,也可通过 `OPENSEARCH_USE_PPL_GRAPHLOOKUP=true|false` 强制设置。
* **集成测试**:针对实际运行的 OpenSearch 集群进行集成测试:
1. 使用 Docker Compose 启动 OpenSearch(下载 [`docker-compose-3.x.yml`](https://raw.githubusercontent.com/opensearch-project/opensearch-build/main/docker/release/dockercomposefiles/docker-compose-3.x.yml)):
```bash
OPENSEARCH_INITIAL_ADMIN_PASSWORD=<custom-admin-password> docker-compose -f docker-compose-3.x.yml up -d
```
2. 验证集群是否正常运行:
```bash
curl -sk -u admin:<custom-admin-password> https://localhost:9200
curl -sk -u admin:<custom-admin-password> https://localhost:9200/_cat/plugins?v
```
3. 运行单元测试(无需 OpenSearch 实例,使用 mock):
```bash
python -m pytest tests/test_opensearch_storage.py -v
```
4. 使用实际集群以OpenSearch作为存储的演示:
```bash
export OPENSEARCH_HOSTS=localhost:9200
export OPENSEARCH_USER=admin
export OPENSEARCH_PASSWORD=<custom-admin-password>
export OPENSEARCH_USE_SSL=true
export OPENSEARCH_VERIFY_CERTS=false
python examples/opensearch_storage_demo.py
```
5. 运行完整的 OpenAI + OpenSearch 示例(需要 `OPENAI_API_KEY`):
```bash
export OPENAI_API_KEY=your-api-key
python examples/lightrag_openai_opensearch_graph_demo.py
```
6. 通过 LightRAG WebUI 或独立 HTML 文件可视化知识图谱:
启动 LightRAG 服务器之前,需要[构建前端组建](https://github.com/HKUDS/LightRAG/blob/main/lightrag/api/README.md).
```bash
# 带上 OpenSearch 存储的配置,启动 LightRAG 服务器
LIGHTRAG_KV_STORAGE=OpenSearchKVStorage \
LIGHTRAG_DOC_STATUS_STORAGE=OpenSearchDocStatusStorage \
LIGHTRAG_GRAPH_STORAGE=OpenSearchGraphStorage \
LIGHTRAG_VECTOR_STORAGE=OpenSearchVectorDBStorage \
LLM_BINDING=openai \
EMBEDDING_BINDING=openai \
EMBEDDING_MODEL=text-embedding-3-large \
EMBEDDING_DIM=3072 \
OPENAI_API_KEY=your-api-key \
lightrag-server
# 执行该脚本读取 OpenSearch 存储的数据,生成知识图谱
python examples/graph_visual_with_opensearch.py
# 打开 http://localhost:9621/webui/ -> 知识图谱标签
# 或执行该脚本生成独立 HTML 文件
python examples/graph_visual_with_opensearch.py --html
```
</details>
### LightRAG 实例之间的数据隔离
`workspace` 参数确保不同 LightRAG 实例之间的数据隔离。一旦初始化,`workspace` 是不可变的,无法更改。以下是不同类型存储实现工作区的方式:
- **对于基于本地文件的数据库,通过工作区子目录实现数据隔离**:`JsonKVStorage`、`JsonDocStatusStorage`、`NetworkXStorage`、`NanoVectorDBStorage`、`FaissVectorDBStorage`。
- **对于以集合方式存储数据的数据库,通过在集合名称前添加工作区前缀来实现**:`RedisKVStorage`、`RedisDocStatusStorage`、`MilvusVectorDBStorage`、`MongoKVStorage`、`MongoDocStatusStorage`、`MongoVectorDBStorage`、`MongoGraphStorage`、`PGGraphStorage`。
- **对于 Qdrant 向量数据库,通过基于 payload 的分区实现数据隔离(Qdrant 推荐的多租户方法)**:`QdrantVectorDBStorage` 使用带有 payload 过滤的共享集合,实现无限的工作区可扩展性。
- **对于关系型数据库,通过在表中添加 `workspace` 字段实现逻辑数据分离**:`PGKVStorage`、`PGVectorStorage`、`PGDocStatusStorage`。
- **对于 Neo4j 图数据库,通过标签实现逻辑数据隔离**:`Neo4JStorage`
- **对于 OpenSearch,通过索引名称前缀实现数据隔离**:`OpenSearchKVStorage`、`OpenSearchDocStatusStorage`、`OpenSearchGraphStorage`、`OpenSearchVectorDBStorage`
为了保持与旧数据的兼容性,当未配置工作区时,PostgreSQL 非图存储的默认工作区为 `default`,PostgreSQL AGE 图存储的默认工作区为 null,Neo4j 图存储的默认工作区为 `base`。对于所有外部存储,系统提供专用的工作区环境变量来覆盖通用的 `WORKSPACE` 环境变量配置。这些存储特定的工作区环境变量包括:`REDIS_WORKSPACE`、`MILVUS_WORKSPACE`、`QDRANT_WORKSPACE`、`MONGODB_WORKSPACE`、`POSTGRES_WORKSPACE`、`NEO4J_WORKSPACE`、`OPENSEARCH_WORKSPACE`。
**使用示例:**
有关在单个应用程序中管理多个隔离知识库(例如,将"书籍"内容与"人力资源政策"分开)的实际演示,请参阅 [Workspace Demo](examples/lightrag_gemini_workspace_demo.py)。
### AGENTS.md -- 指导编码代理
AGENTS.md 是一种简单、开放的格式,用于指导编码代理(https://agents.md/)。它是一个专门的、可预测的地方,用于提供上下文和指令,帮助 AI 编码代理在 LightRAG 项目上工作。不同的 AI 编码器不应单独维护各自的指导文件。如果任何 AI 编码器无法自动识别 AGENTS.md,可以使用符号链接作为解决方案。建立符号链接后,可以通过配置本地的 `.gitignore_global` 来防止它们被提交到 Git 仓库。
## 编辑实体和关系
LightRAG 现在支持全面的知识图谱管理功能,允许您在知识图谱中创建、编辑和删除实体和关系。
<details>
<summary> <b> 创建实体和关系 </b></summary>
```python
# 创建新实体
entity = rag.create_entity("Google", {
"description": "Google 是一家专注于互联网相关服务和产品的跨国科技公司。",
"entity_type": "company"
})
# 创建另一个实体
product = rag.create_entity("Gmail", {
"description": "Gmail 是 Google 开发的电子邮件服务。",
"entity_type": "product"
})
# 创建实体之间的关系
relation = rag.create_relation("Google", "Gmail", {
"description": "Google 开发和运营 Gmail。",
"keywords": "develops operates service",
"weight": 2.0
})
```
</details>
<details>
<summary> <b> 手动修改实体与关系 </b></summary>
```python
# Edit an existing entity
updated_entity = rag.edit_entity("Google", {
"description": "Google is a subsidiary of Alphabet Inc., founded in 1998.",
"entity_type": "tech_company"
})
# Rename an entity (with all its relationships properly migrated)
renamed_entity = rag.edit_entity("Gmail", {
"entity_name": "Google Mail",
"description": "Google Mail (formerly Gmail) is an email service."
})
# Edit a relation between entities
updated_relation = rag.edit_relation("Google", "Google Mail", {
"description": "Google created and maintains Google Mail service.",
"keywords": "creates maintains email service",
"weight": 3.0
})
```
所有操作均提供同步和异步两个版本。异步版本带有 "a" 前缀(例如:`acreate_entity`、`aedit_relation`)。
</details>
<details>
<summary> <b> 插入自定义知识图谱 </b></summary>
```python
custom_kg = {
"chunks": [
{
"content": "Alice and Bob are collaborating on quantum computing research.",
"source_id": "doc-1",
"file_path": "test_file",
}
],
"entities": [
{
"entity_name": "Alice",
"entity_type": "person",
"description": "Alice is a researcher specializing in quantum physics.",
"source_id": "doc-1",
"file_path": "test_file"
},
{
"entity_name": "Bob",
"entity_type": "person",
"description": "Bob is a mathematician.",
"source_id": "doc-1",
"file_path": "test_file"
},
{
"entity_name": "Quantum Computing",
"entity_type": "technology",
"description": "Quantum computing utilizes quantum mechanical phenomena for computation.",
"source_id": "doc-1",
"file_path": "test_file"
}
],
"relationships": [
{
"src_id": "Alice",
"tgt_id": "Bob",
"description": "Alice and Bob are research partners.",
"keywords": "collaboration research",
"weight": 1.0,
"source_id": "doc-1",
"file_path": "test_file"
},
{
"src_id": "Alice",
"tgt_id": "Quantum Computing",
"description": "Alice conducts research on quantum computing.",
"keywords": "research expertise",
"weight": 1.0,
"source_id": "doc-1",
"file_path": "test_file"
},
{
"src_id": "Bob",
"tgt_id": "Quantum Computing",
"description": "Bob researches quantum computing.",
"keywords": "research application",
"weight": 1.0,
"source_id": "doc-1",
"file_path": "test_file"
}
]
}
rag.insert_custom_kg(custom_kg)
```
</details>
<details>
<summary> <b>其它实体与关系操作</b></summary>
- **create_entity**:创建具有指定属性的新实体
- **edit_entity**:更新现有实体的属性或重命名它
- **create_relation**:在现有实体之间创建新关系
- **edit_relation**:更新现有关系的属性
这些操作在图数据库和向量数据库组件之间保持数据一致性,确保您的知识图谱保持连贯。
</details>
## 删除功能
LightRAG 提供了全面的删除能力,允许您删除文档、实体和关系。
<details>
<summary> <b>删除实体</b> </summary>
您可以通过实体名称删除实体及其所有关联关系:
```python
# 删除实体及其所有关系(同步版本)
rag.delete_by_entity("Google")
# 异步版本
await rag.adelete_by_entity("Google")
```
删除实体时:
- 从知识图谱中移除该实体节点
- 删除所有关联的关系
- 从向量数据库中移除相关的嵌入向量
- 保持知识图谱的完整性
</details>
<details>
<summary> <b>删除关系</b> </summary>
您可以删除两个特定实体之间的关系:
```python
# 删除两个实体之间的关系(同步版本)
rag.delete_by_relation("Google", "Gmail")
# 异步版本
await rag.adelete_by_relation("Google", "Gmail")
```
删除关系时:
- 移除指定的关系边
- 从向量数据库中删除该关系的嵌入向量
- 保留实体节点及其它关系
</details>
<details>
<summary> <b>通过文档 ID 删除</b> </summary>
您可以通过文档 ID 删除整个文档及其所有相关的知识:
```python
# 通过文档 ID 删除(异步版本)
await rag.adelete_by_doc_id("doc-12345")
```
通过文档 ID 删除时的优化处理:
- **智能清理**:自动识别并删除仅属于该文档的实体和关系
- **保留共享知识**:如果实体或关系在其他文档中也存在,则会保留并重新构建其描述
- **缓存优化**:清理相关的 LLM 缓存以减少存储开销
- **增量重建**:从剩余文档中重新构建受影响的实体和关系描述
删除过程包括:
1. 删除与该文档相关的所有文本块
2. 识别并删除仅属于该文档的实体和关系
3. 重新构建在其他文档中仍存在的实体和关系
4. 更新所有相关的向量索引
5. 清理文档状态记录
注意:由于涉及复杂的知识图谱重构过程,通过文档 ID 删除是一个异步操作。
</details>
**重要提醒:**
1. **不可逆操作**:所有删除操作都是不可逆的,请谨慎使用
2. **性能考虑**:删除大量数据可能需要一些时间,特别是通过文档 ID 删除
3. **数据一致性**:删除操作会自动维护知识图谱与向量数据库之间的一致性
4. **备份建议**:在执行重要删除操作前,请考虑备份数据
**批量删除建议:**
- 对于批量删除操作,建议使用异步方法以获得更好的性能
- 对于大规模删除,建议分批处理以避免系统负载过高
## 实体合并
<details>
<summary> <b>合并实体及其关系</b> </summary>
LightRAG 现在支持将多个实体合并为单个实体,并自动处理所有关系:
```python
# 基础实体合并
rag.merge_entities(
source_entities=["Artificial Intelligence", "AI", "Machine Intelligence"],
target_entity="AI Technology"
)
```
使用自定义合并策略:
```python
# 为不同字段定义自定义合并策略
rag.merge_entities(
source_entities=["John Smith", "Dr. Smith", "J. Smith"],
target_entity="John Smith",
merge_strategy={
"description": "concatenate", # 合并所有描述
"entity_type": "keep_first", # 保留第一个实体的类型
"source_id": "join_unique" # 合并所有唯一的源 ID
}
)
```
使用自定义目标实体数据:
```python
# 为合并后的实体指定精确值
rag.merge_entities(
source_entities=["New York", "NYC", "Big Apple"],
target_entity="New York City",
target_entity_data={
"entity_type": "LOCATION",
"description": "New York City is the most populous city in the United States.",
}
)
```
结合上述两种方式的高级用法:
```python
# 合并公司实体,同时使用策略和自定义数据
rag.merge_entities(
source_entities=["Microsoft Corp", "Microsoft Corporation", "MSFT"],
target_entity="Microsoft",
merge_strategy={
"description": "concatenate", # 合并所有描述
"source_id": "join_unique" # 合并源 ID
},
target_entity_data={
"entity_type": "ORGANIZATION",
}
)
```
合并实体时:
* 所有来自源实体的关系都会重定向到目标实体
* 重复的关系会被智能合并
* 防止出现自我指向的关系(自环)
* 合并完成后源实体会被移除
* 关系权重和属性会被保留
</details>
## 多模态文档处理(RAG-Anything 集成)
LightRAG 现已与 [RAG-Anything](https://github.com/HKUDS/RAG-Anything) 无缝集成,这是一个专门为 LightRAG 构建的**全能多模态文档处理 RAG 系统**。RAG-Anything 能够实现先进的解析和检索增强生成(RAG)能力,允许您无缝处理多模态文档,并从各种文档格式中提取结构化内容——包括文本、图像、表格和公式——以集成到您的 RAG 流程中。
**核心特性:**
- **端到端多模态流程**:从文档摄取解析到智能多模态问答的完整工作流程
- **通用文档支持**:无缝处理 PDF、Office 文档(DOC/DOCX/PPT/PPTX/XLS/XLSX)、图像及多种文件格式
- **专业内容分析**:针对图像、表格、数学公式及异构内容类型的专用处理器
- **多模态知识图谱**:自动实体提取和跨模态关系发现,增强理解力
- **混合智能检索**:跨越文本和多模态内容的高级搜索能力,具备上下文理解
**快速开始:**
1. 安装 RAG-Anything:
```bash
pip install raganything
```
2. 处理多模态文档:
<details>
<summary> <b> RAGAnything 使用示例 </b></summary>
```python
import asyncio
from raganything import RAGAnything
from lightrag import LightRAG
from lightrag.llm.openai import openai_complete_if_cache, openai_embed
from lightrag.utils import EmbeddingFunc
import os
async def load_existing_lightrag():
# 首先,创建或加载一个现有的 LightRAG 实例
lightrag_working_dir = "./existing_lightrag_storage"
# 检查先前的 LightRAG 实例是否存在
if os.path.exists(lightrag_working_dir) and os.listdir(lightrag_working_dir):
print("✅ Found existing LightRAG instance, loading...")
else:
print("❌ No existing LightRAG instance found, will create new one")
from functools import partial
# 使用您的配置创建/加载 LightRAG 实例
lightrag_instance = LightRAG(
working_dir=lightrag_working_dir,
llm_model_func=lambda prompt, system_prompt=None, history_messages=[], **kwargs: openai_complete_if_cache(
"gpt-4o-mini",
prompt,
system_prompt=system_prompt,
history_messages=history_messages,
api_key="your-api-key",
**kwargs,
),
embedding_func=EmbeddingFunc(
embedding_dim=3072,
max_token_size=8192,
model="text-embedding-3-large",
func=partial(
openai_embed.func, # 使用 .func 访问未封装的原始函数
model="text-embedding-3-large",
api_key=api_key,
base_url=base_url,
),
)
)
# 初始化存储(这将加载现有数据,如果有的话)
await lightrag_instance.initialize_storages()
# 现在使用现有的 LightRAG 实例初始化 RAGAnything
rag = RAGAnything(
lightrag=lightrag_instance, # 传入现有的 LightRAG 实例
# 仅在多模态处理时需要视觉模型
vision_model_func=lambda prompt, system_prompt=None, history_messages=[], image_data=None, **kwargs: openai_complete_if_cache(
"gpt-4o",
"",
system_prompt=None,
history_messages=[],
messages=[
{"role": "system", "content": system_prompt} if system_prompt else None,
{"role": "user", "content": [
{"type": "text", "text": prompt},
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image_data}"}}
]} if image_data else {"role": "user", "content": prompt}
],
api_key="your-api-key",
**kwargs,
) if image_data else openai_complete_if_cache(
"gpt-4o-mini",
prompt,
system_prompt=system_prompt,
history_messages=history_messages,
api_key="your-api-key",
**kwargs,
)
# 注意:working_dir, llm_model_func, embedding_func 等都继承自 lightrag_instance
)
# 查询现有的知识库
result = await rag.query_with_multimodal(
"What data has been processed in this LightRAG instance?",
mode="hybrid"
)
print("Query result:", result)
# 向现有的 LightRAG 实例添加新的多模态文档
await rag.process_document_complete(
file_path="path/to/new/multimodal_document.pdf",
output_dir="./output"
)
if __name__ == "__main__":
asyncio.run(load_existing_lightrag())
```
</details>
有关详细文档和高级用法,请参考 [RAG-Anything 仓库](https://github.com/HKUDS/RAG-Anything)。
## Token 使用量跟踪
<details>
<summary> <b>概览与用法</b> </summary>
LightRAG 提供了一个 TokenTracker 工具,用于监控和管理大语言模型的 token 消耗情况。此功能对于控制 API 成本和优化性能非常有用。
### 用法
```python
from lightrag.utils import TokenTracker
# 创建 TokenTracker 实例
token_tracker = TokenTracker()
# 方法 1:使用上下文管理器(推荐)
# 适用于需要自动跟踪 token 使用量的场景
with token_tracker:
result1 = await llm_model_func("your question 1")
result2 = await llm_model_func("your question 2")
# 方法 2:手动添加 token 使用记录
# 适用于需要更精细控制 token 统计的场景
token_tracker.reset()
rag.insert()
rag.query("your question 1", param=QueryParam(mode="naive"))
rag.query("your question 2", param=QueryParam(mode="mix"))
# 显示总 token 使用量(包括插入和查询操作)
print("Token usage:", token_tracker.get_usage())
```
### 使用技巧
- 在长会话或批量操作中使用上下文管理器,自动跟踪所有 token 消耗
- 对于需要分段统计的场景,使用手动模式并在适当时候调用 reset()
- 定期检查 token 使用量有助于及早发现异常消耗
- 在开发和测试过程中积极使用此功能,以优化生产成本
### 实践案例
您可以参考以下示例来实施 token 跟踪:
- `examples/lightrag_gemini_track_token_demo.py`:使用 Google Gemini 模型的 token 跟踪示例
- `examples/lightrag_siliconcloud_track_token_demo.py`:使用 SiliconCloud 模型的 token 跟踪示例
这些示例展示了如何在不同模型和场景下有效地使用 TokenTracker 功能。
</details>
## 数据导出功能
### 概览
LightRAG 允许您以各种格式导出知识图谱数据,用于分析、共享和备份。系统支持导出实体、关系及关系数据。
### 导出函数
<details>
<summary> <b> 基础用法 </b></summary>
```python
# 基础 CSV 导出(默认格式)
rag.export_data("knowledge_graph.csv")
# 指定任意格式
rag.export_data("output.xlsx", file_format="excel")
```
</details>
<details>
<summary> <b> 支持的不同文件格式 </b></summary>
```python
# 以 CSV 格式导出数据
rag.export_data("graph_data.csv", file_format="csv")
# 导出到 Excel 工作表
rag.export_data("graph_data.xlsx", file_format="excel")
# 以 markdown 格式导出数据
rag.export_data("graph_data.md", file_format="md")
# 导出为纯文本
rag.export_data("graph_data.txt", file_format="txt")
```
</details>
<details>
<summary> <b> 附加选项 </b></summary>
在导出中包含向量嵌入(可选):
```python
rag.export_data("complete_data.csv", include_vector_data=True)
```
</details>
### 导出中包含的数据
所有导出均包含:
* 实体信息(名称、ID、元数据)
* 关系数据(实体间的连接)
* 来自向量数据库的关系信息
## 缓存
<details>
<summary> <b>清除缓存</b> </summary>
您可以使用 `aclear_cache()` 清空当前配置的 LLM 响应缓存存储。该 API 会清除 `llm_response_cache` 中的全部缓存项,不支持按模式或缓存类型进行选择性清理。
```python
# 清除所有缓存
await rag.aclear_cache()
# 同步版本
rag.clear_cache()
```
如果需要按类型管理查询相关缓存,可以使用 `lightrag.tools.clean_llm_query_cache` 工具,并参考说明文档 [lightrag/tools/README_CLEAN_LLM_QUERY_CACHE.md](./lightrag/tools/README_CLEAN_LLM_QUERY_CACHE.md)。该工具可管理 `mix`、`hybrid`、`local` 和 `global` 模式下的查询缓存与关键词缓存;它不会清理 `default:extract:*` 和 `default:summary:*` 这类提取缓存。
</details>
## 故障排除
### 常见初始化错误
如果您在使用 LightRAG 时遇到以下错误:
1. **`AttributeError: __aenter__`**
- **原因**:存储后端未初始化
- **解决方案**:在创建 LightRAG 实例后调用 `await rag.initialize_storages()`
2. **`KeyError: 'history_messages'`**
- **原因**:流水线状态未初始化
- **解决方案**:在创建 LightRAG 实例后调用 `await rag.initialize_storages()`
3. **两个错误相继出现**
- **原因**:两个初始化方法都未被调用
- **解决方案**:始终遵循以下模式:
```python
rag = LightRAG(...)
await rag.initialize_storages()
```
### 模型切换问题
在不同的嵌入模型(embedding models)之间切换时,您必须清空数据目录以避免错误。如果您希望保留 LLM 缓存,唯一可以保留的文件是 `kv_store_llm_response_cache.json`。
## LightRAG API
LightRAG 服务器旨在提供 Web UI 和 API 支持。**有关 LightRAG 服务器的更多信息,请参考 [LightRAG Server](./lightrag/api/README.md)。**
## 图谱可视化
LightRAG 服务器提供了全面的知识图谱可视化功能。它支持各种重力布局、节点查询、子图过滤等。**有关 LightRAG 服务器的更多信息,请参考 [LightRAG Server](./lightrag/api/README.md)。**

## Langfuse 可观测性集成
Langfuse 提供了一个可以直接替换 OpenAI 客户端的方案,自动跟踪所有 LLM 交互,使开发者能够在不更改代码的情况下监控、调试和优化其 RAG 系统。
### 安装可观测性选项
```bash
pip install lightrag-hku
pip install lightrag-hku[observability]
# 或从源代码安装并启用调试模式
pip install -e .
pip install -e ".[observability]"
```
### 配置 Langfuse 环境变量
修改 .env 文件:
```bash
## Langfuse Observability (Optional)
# LLM observability and tracing platform
# Install with: pip install lightrag-hku[observability]
# Sign up at: https://cloud.langfuse.com or self-host
LANGFUSE_SECRET_KEY=""
LANGFUSE_PUBLIC_KEY=""
LANGFUSE_HOST="https://cloud.langfuse.com" # 或您的自托管实例
LANGFUSE_ENABLE_TRACE=true
```
### Langfuse 用法
安装并配置完成后,Langfuse 会自动追踪所有 OpenAI LLM 调用。Langfuse 仪表板功能包括:
- **追踪(Tracing)**:查看完整的 LLM 调用链
- **分析(Analytics)**:Token 使用情况、延迟、成本指标
- **调试(Debugging)**:检查提示词和响应
- **评估(Evaluation)**:比较模型输出
- **监控(Monitoring)**:实时告警
### 重要通知
**注意**:LightRAG 目前仅将 OpenAI 兼容的 API 调用与 Langfuse 集成。Ollama、Azure 和 AWS Bedrock 等 API 尚不支持 Langfuse 可观测性。
## 基于 RAGAS 的评估
**RAGAS** (Retrieval Augmented Generation Assessment) 是一个使用 LLM 对 RAG 系统进行无参考评估的框架。项目中包含一个基于 RAGAS 的评估脚本。有关详细信息,请参考 [基于 RAGAS 的评估框架](lightrag/evaluation/README_EVALUASTION_RAGAS.md)。
## 评估
### 数据集
LightRAG 中使用的数据集可以从 [TommyChien/UltraDomain](https://huggingface.co/datasets/TommyChien/UltraDomain) 下载。
### 生成查询
LightRAG 使用以下提示(prompt)生成高层级查询,相应代码位于 `examples/generate_query.py`。
<details>
<summary> 提示词 </summary>
```python
Given the following description of a dataset:
{description}
Please identify 5 potential users who would engage with this dataset. For each user, list 5 tasks they would perform with this dataset. Then, for each (user, task) combination, generate 5 questions that require a high-level understanding of the entire dataset.
Output the results in the following structure:
- User 1: [user description]
- Task 1: [task description]
- Question 1:
- Question 2:
- Question 3:
- Question 4:
- Question 5:
- Task 2: [task description]
...
- Task 5: [task description]
- User 2: [user description]
...
- User 5: [user description]
...
```
</details>
### 批量评估
为了在处理高层级查询时评估两个 RAG 系统的性能,LightRAG 使用以下提示词,具体代码见 `reproduce/batch_eval.py`。
<details>
<summary> 提示词 </summary>
```python
---Role---
You are an expert tasked with evaluating two answers to the same question based on three criteria: **Comprehensiveness**, **Diversity**, and **Empowerment**.
---Goal---
You will evaluate two answers to the same question based on three criteria: **Comprehensiveness**, **Diversity**, and **Empowerment**.
- **Comprehensiveness**: How much detail does the answer provide to cover all aspects and details of the question?
- **Diversity**: How varied and rich is the answer in providing different perspectives and insights on the question?
- **Empowerment**: How well does the answer help the reader understand and make informed judgments about the topic?
For each criterion, choose the better answer (either Answer 1 or Answer 2) and explain why. Then, select an overall winner based on these three categories.
Here is the question:
{query}
Here are the two answers:
**Answer 1:**
{answer1}
**Answer 2:**
{answer2}
Evaluate both answers using the three criteria listed above and provide detailed explanations for each criterion.
Output your evaluation in the following JSON format:
{{
"Comprehensiveness": {{
"Winner": "[Answer 1 or Answer 2]",
"Explanation": "[Provide explanation here]"
}},
"Empowerment": {{
"Winner": "[Answer 1 or Answer 2]",
"Explanation": "[Provide explanation here]"
}},
"Overall Winner": {{
"Winner": "[Answer 1 or Answer 2]",
"Explanation": "[Summarize why this answer is the overall winner based on the three criteria]"
}}
}}
```
</details>
### 总体性能表
||**农业**||**计算机科学**||**法律**||**混合**||
|----------------------|---------------|------------|------|------------|---------|------------|-------|------------|
||NaiveRAG|**LightRAG**|NaiveRAG|**LightRAG**|NaiveRAG|**LightRAG**|NaiveRAG|**LightRAG**|
|**全面性**|32.4%|**67.6%**|38.4%|**61.6%**|16.4%|**83.6%**|38.8%|**61.2%**|
|**多样性**|23.6%|**76.4%**|38.0%|**62.0%**|13.6%|**86.4%**|32.4%|**67.6%**|
|**赋能性**|32.4%|**67.6%**|38.8%|**61.2%**|16.4%|**83.6%**|42.8%|**57.2%**|
|**总体**|32.4%|**67.6%**|38.8%|**61.2%**|15.2%|**84.8%**|40.0%|**60.0%**|
||RQ-RAG|**LightRAG**|RQ-RAG|**LightRAG**|RQ-RAG|**LightRAG**|RQ-RAG|**LightRAG**|
|**全面性**|31.6%|**68.4%**|38.8%|**61.2%**|15.2%|**84.8%**|39.2%|**60.8%**|
|**多样性**|29.2%|**70.8%**|39.2%|**60.8%**|11.6%|**88.4%**|30.8%|**69.2%**|
|**赋能性**|31.6%|**68.4%**|36.4%|**63.6%**|15.2%|**84.8%**|42.4%|**57.6%**|
|**总体**|32.4%|**67.6%**|38.0%|**62.0%**|14.4%|**85.6%**|40.0%|**60.0%**|
||HyDE|**LightRAG**|HyDE|**LightRAG**|HyDE|**LightRAG**|HyDE|**LightRAG**|
|**全面性**|26.0%|**74.0%**|41.6%|**58.4%**|26.8%|**73.2%**|40.4%|**59.6%**|
|**多样性**|24.0%|**76.0%**|38.8%|**61.2%**|20.0%|**80.0%**|32.4%|**67.6%**|
|**赋能性**|25.2%|**74.8%**|40.8%|**59.2%**|26.0%|**74.0%**|46.0%|**54.0%**|
|**总体**|24.8%|**75.2%**|41.6%|**58.4%**|26.4%|**73.6%**|42.4%|**57.6%**|
||GraphRAG|**LightRAG**|GraphRAG|**LightRAG**|GraphRAG|**LightRAG**|GraphRAG|**LightRAG**|
|**全面性**|45.6%|**54.4%**|48.4%|**51.6%**|48.4%|**51.6%**|**50.4%**|49.6%|
|**多样性**|22.8%|**77.2%**|40.8%|**59.2%**|26.4%|**73.6%**|36.0%|**64.0%**|
|**赋能性**|41.2%|**58.8%**|45.2%|**54.8%**|43.6%|**56.4%**|**50.8%**|49.2%|
|**总体**|45.2%|**54.8%**|48.0%|**52.0%**|47.2%|**52.8%**|**50.4%**|49.6%|
## 复现
所有代码均可在 `./reproduce` 目录中找到。
### Step-0 提取唯一上下文
首先,我们需要提取数据集中的唯一上下文(unique contexts)。
<details>
<summary> 代码 </summary>
```python
def extract_unique_contexts(input_directory, output_directory):
os.makedirs(output_directory, exist_ok=True)
jsonl_files = glob.glob(os.path.join(input_directory, '*.jsonl'))
print(f"Found {len(jsonl_files)} JSONL files.")
for file_path in jsonl_files:
filename = os.path.basename(file_path)
name, ext = os.path.splitext(filename)
output_filename = f"{name}_unique_contexts.json"
output_path = os.path.join(output_directory, output_filename)
unique_contexts_dict = {}
print(f"Processing file: {filename}")
try:
with open(file_path, 'r', encoding='utf-8') as infile:
for line_number, line in enumerate(infile, start=1):
line = line.strip()
if not line:
continue
try:
json_obj = json.loads(line)
context = json_obj.get('context')
if context and context not in unique_contexts_dict:
unique_contexts_dict[context] = None
except json.JSONDecodeError as e:
print(f"JSON decoding error in file {filename} at line {line_number}: {e}")
except FileNotFoundError:
print(f"File not found: {filename}")
continue
except Exception as e:
print(f"An error occurred while processing file {filename}: {e}")
continue
unique_contexts_list = list(unique_contexts_dict.keys())
print(f"There are {len(unique_contexts_list)} unique `context` entries in the file {filename}.")
try:
with open(output_path, 'w', encoding='utf-8') as outfile:
json.dump(unique_contexts_list, outfile, ensure_ascii=False, indent=4)
print(f"Unique `context` entries have been saved to: {output_filename}")
except Exception as e:
print(f"An error occurred while saving to the file {output_filename}: {e}")
print("All files have been processed.")
```
</details>
### Step-1 插入上下文
我们将提取出的上下文插入到 LightRAG 系统中。
<details>
<summary> 代码 </summary>
```python
def insert_text(rag, file_path):
with open(file_path, mode='r') as f:
unique_contexts = json.load(f)
retries = 0
max_retries = 3
while retries < max_retries:
try:
rag.insert(unique_contexts)
break
except Exception as e:
retries += 1
print(f"Insertion failed, retrying ({retries}/{max_retries}), error: {e}")
time.sleep(10)
if retries == max_retries:
print("Insertion failed after exceeding the maximum number of retries")
```
</details>
### Step-2 生成查询
我们从数据集每个上下文的前半部分和后半部分提取 token,然后将它们组合作为数据集描述来生成查询。
<details>
<summary> 代码 </summary>
```python
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
def get_summary(context, tot_tokens=2000):
tokens = tokenizer.tokenize(context)
half_tokens = tot_tokens // 2
start_tokens = tokens[1000:1000 + half_tokens]
end_tokens = tokens[-(1000 + half_tokens):1000]
summary_tokens = start_tokens + end_tokens
summary = tokenizer.convert_tokens_to_string(summary_tokens)
return summary
```
</details>
### Step-3 查询
对于 Step-2 中生成的查询,我们将提取它们并对 LightRAG 进行查询。
<details>
<summary> 代码 </summary>
```python
def extract_queries(file_path):
with open(file_path, 'r') as f:
data = f.read()
data = data.replace('**', '')
queries = re.findall(r'- Question \d+: (.+)', data)
return queries
```
</details>
## 🔗 相关项目
*生态与扩展*
<div align="center">
<table>
<tr>
<td align="center">
<a href="https://github.com/HKUDS/RAG-Anything">
<div style="width: 100px; height: 100px; background: linear-gradient(135deg, rgba(0, 217, 255, 0.1) 0%, rgba(0, 217, 255, 0.05) 100%); border-radius: 15px; border: 1px solid rgba(0, 217, 255, 0.2); display: flex; align-items: center; justify-content: center; margin-bottom: 10px;">
<span style="font-size: 32px;">📸</span>
</div>
<b>RAG-Anything</b><br>
<sub>多模态 RAG</sub>
</a>
</td>
<td align="center">
<a href="https://github.com/HKUDS/VideoRAG">
<div style="width: 100px; height: 100px; background: linear-gradient(135deg, rgba(0, 217, 255, 0.1) 0%, rgba(0, 217, 255, 0.05) 100%); border-radius: 15px; border: 1px solid rgba(0, 217, 255, 0.2); display: flex; align-items: center; justify-content: center; margin-bottom: 10px;">
<span style="font-size: 32px;">🎥</span>
</div>
<b>VideoRAG</b><br>
<sub>极端长上下文视频 RAG</sub>
</a>
</td>
<td align="center">
<a href="https://github.com/HKUDS/MiniRAG">
<div style="width: 100px; height: 100px; background: linear-gradient(135deg, rgba(0, 217, 255, 0.1) 0%, rgba(0, 217, 255, 0.05) 100%); border-radius: 15px; border: 1px solid rgba(0, 217, 255, 0.2); display: flex; align-items: center; justify-content: center; margin-bottom: 10px;">
<span style="font-size: 32px;">✨</span>
</div>
<b>MiniRAG</b><br>
<sub>极简 RAG</sub>
</a>
</td>
</tr>
</table>
</div>
---
## ⭐ Star 历史
<a href="https://star-history.com/#HKUDS/LightRAG&Date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=HKUDS/LightRAG&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=HKUDS/LightRAG&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=HKUDS/LightRAG&type=Date" />
</picture>
</a>
## 🤝 贡献
<div align="center">
我们感谢所有贡献者做出的宝贵贡献。
</div>
<div align="center">
<a href="https://github.com/HKUDS/LightRAG/graphs/contributors">
<img src="https://contrib.rocks/image?repo=HKUDS/LightRAG" style="border-radius: 15px; box-shadow: 0 0 20px rgba(0, 217, 255, 0.3);" />
</a>
</div>
---
## 📖 引用
```python
@article{guo2024lightrag,
title={LightRAG: Simple and Fast Retrieval-Augmented Generation},
author={Zirui Guo and Lianghao Xia and Yanhua Yu and Tu Ao and Chao Huang},
year={2024},
eprint={2410.05779},
archivePrefix={arXiv},
primaryClass={cs.IR}
}
```
---
<div align="center" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; padding: 30px; margin: 30px 0;">
<div>
<img src="https://user-images.githubusercontent.com/74038190/212284100-561aa473-3905-4a80-b561-0d28506553ee.gif" width="500">
</div>
<div style="margin-top: 20px;">
<a href="https://github.com/HKUDS/LightRAG" style="text-decoration: none;">
<img src="https://img.shields.io/badge/⭐%20在%20GitHub%20上点亮星星-1a1a2e?style=for-the-badge&logo=github&logoColor=white">
</a>
<a href="https://github.com/HKUDS/LightRAG/issues" style="text-decoration: none;">
<img src="https://img.shields.io/badge/🐛%20报告问题-ff6b6b?style=for-the-badge&logo=github&logoColor=white">
</a>
<a href="https://github.com/HKUDS/LightRAG/discussions" style="text-decoration: none;">
<img src="https://img.shields.io/badge/💬%20讨论-4ecdc4?style=for-the-badge&logo=github&logoColor=white">
</a>
</div>
</div>
<div align="center">
<div style="width: 100%; max-width: 600px; margin: 20px auto; padding: 20px; background: linear-gradient(135deg, rgba(0, 217, 255, 0.1) 0%, rgba(0, 217, 255, 0.05) 100%); border-radius: 15px; border: 1px solid rgba(0, 217, 255, 0.2);">
<div style="display: flex; justify-content: center; align-items: center; gap: 15px;">
<span style="font-size: 24px;">⭐</span>
<span style="color: #00d9ff; font-size: 18px;">感谢您访问 LightRAG!</span>
<span style="font-size: 24px;">⭐</span>
</div>
</div>
</div>
================================================
FILE: README.md
================================================
<div align="center">
<div style="margin: 20px 0;">
<img src="./assets/logo.png" width="120" height="120" alt="LightRAG Logo" style="border-radius: 20px; box-shadow: 0 8px 32px rgba(0, 217, 255, 0.3);">
</div>
# 🚀 LightRAG: Simple and Fast Retrieval-Augmented Generation
<div align="center">
<a href="https://trendshift.io/repositories/13043" target="_blank"><img src="https://trendshift.io/api/badge/repositories/13043" alt="HKUDS%2FLightRAG | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
</div>
<div align="center">
<div style="width: 100%; height: 2px; margin: 20px 0; background: linear-gradient(90deg, transparent, #00d9ff, transparent);"></div>
</div>
<div align="center">
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; padding: 25px; text-align: center;">
<p>
<a href='https://github.com/HKUDS/LightRAG'><img src='https://img.shields.io/badge/🔥Project-Page-00d9ff?style=for-the-badge&logo=github&logoColor=white&labelColor=1a1a2e'></a>
<a href='https://arxiv.org/abs/2410.05779'><img src='https://img.shields.io/badge/📄arXiv-2410.05779-ff6b6b?style=for-the-badge&logo=arxiv&logoColor=white&labelColor=1a1a2e'></a>
<a href="https://github.com/HKUDS/LightRAG/stargazers"><img src='https://img.shields.io/github/stars/HKUDS/LightRAG?color=00d9ff&style=for-the-badge&logo=star&logoColor=white&labelColor=1a1a2e' /></a>
</p>
<p>
<img src="https://img.shields.io/badge/🐍Python-3.10-4ecdc4?style=for-the-badge&logo=python&logoColor=white&labelColor=1a1a2e">
<a href="https://pypi.org/project/lightrag-hku/"><img src="https://img.shields.io/pypi/v/lightrag-hku.svg?style=for-the-badge&logo=pypi&logoColor=white&labelColor=1a1a2e&color=ff6b6b"></a>
</p>
<p>
<a href="https://discord.gg/yF2MmDJyGJ"><img src="https://img.shields.io/badge/💬Discord-Community-7289da?style=for-the-badge&logo=discord&logoColor=white&labelColor=1a1a2e"></a>
<a href="https://github.com/HKUDS/LightRAG/issues/285"><img src="https://img.shields.io/badge/💬WeChat-Group-07c160?style=for-the-badge&logo=wechat&logoColor=white&labelColor=1a1a2e"></a>
</p>
<p>
<a href="README-zh.md"><img src="https://img.shields.io/badge/🇨🇳中文版-1a1a2e?style=for-the-badge"></a>
<a href="README.md"><img src="https://img.shields.io/badge/🇺🇸English-1a1a2e?style=for-the-badge"></a>
</p>
<p>
<a href="https://pepy.tech/projects/lightrag-hku"><img src="https://static.pepy.tech/personalized-badge/lightrag-hku?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads"></a>
</p>
</div>
</div>
</div>
<div align="center" style="margin: 30px 0;">
<img src="https://user-images.githubusercontent.com/74038190/212284100-561aa473-3905-4a80-b561-0d28506553ee.gif" width="800">
</div>
<div align="center" style="margin: 30px 0;">
<img src="./README.assets/b2aaf634151b4706892693ffb43d9093.png" width="800" alt="LightRAG Diagram">
</div>
---
<div align="center">
<table>
<tr>
<td style="vertical-align: middle;">
<img src="./assets/LiteWrite.png"
width="56"
height="56"
alt="LiteWrite"
style="border-radius: 12px;" />
</td>
<td style="vertical-align: middle; padding-left: 12px;">
<a href="https://litewrite.ai">
<img src="https://img.shields.io/badge/🚀%20LiteWrite-AI%20Native%20LaTeX%20Editor-ff6b6b?style=for-the-badge&logoColor=white&labelColor=1a1a2e">
</a>
</td>
</tr>
</table>
</div>
---
## 🎉 News
- [2025.11]🎯[New Feature]: Integrated **RAGAS for Evaluation** and **Langfuse for Tracing**. Updated the API to return retrieved contexts alongside query results to support context precision metrics.
- [2025.10]🎯[Scalability Enhancement]: Eliminated processing bottlenecks to support **Large-Scale Datasets Efficiently**.
- [2025.09]🎯[New Feature] Enhances knowledge graph extraction accuracy for **Open-Sourced LLMs** such as Qwen3-30B-A3B.
- [2025.08]🎯[New Feature] **Reranker** is now supported, significantly boosting performance for mixed queries (set as default query mode).
- [2025.08]🎯[New Feature] Added **Document Deletion** with automatic KG regeneration to ensure optimal query performance.
- [2025.06]🎯[New Release] Our team has released [RAG-Anything](https://github.com/HKUDS/RAG-Anything) — an **All-in-One Multimodal RAG** system for seamless processing of text, images, tables, and equations.
- [2025.06]🎯[New Feature] LightRAG now supports comprehensive multimodal data handling through [RAG-Anything](https://github.com/HKUDS/RAG-Anything) integration, enabling seamless document parsing and RAG capabilities across diverse formats including PDFs, images, Office documents, tables, and formulas. Please refer to the new [multimodal section](https://github.com/HKUDS/LightRAG/?tab=readme-ov-file#multimodal-document-processing-rag-anything-integration) for details.
- [2025.03]🎯[New Feature] LightRAG now supports citation functionality, enabling proper source attribution and enhanced document traceability.
- [2025.02]🎯[New Feature] You can now use MongoDB as an all-in-one storage solution for unified data management.
- [2025.02]🎯[New Release] Our team has released [VideoRAG](https://github.com/HKUDS/VideoRAG)-a RAG system for understanding extremely long-context videos
- [2025.01]🎯[New Release] Our team has released [MiniRAG](https://github.com/HKUDS/MiniRAG) making RAG simpler with small models.
- [2025.01]🎯You can now use PostgreSQL as an all-in-one storage solution for data management.
- [2024.11]🎯[New Resource] A comprehensive guide to LightRAG is now available on [LearnOpenCV](https://learnopencv.com/lightrag). — explore in-depth tutorials and best practices. Many thanks to the blog author for this excellent contribution!
- [2024.11]🎯[New Feature] Introducing the LightRAG WebUI — an interface that allows you to insert, query, and visualize LightRAG knowledge through an intuitive web-based dashboard.
- [2024.11]🎯[New Feature] You can now [use Neo4J for Storage](https://github.com/HKUDS/LightRAG?tab=readme-ov-file#using-neo4j-for-storage)-enabling graph database support.
- [2024.10]🎯[New Feature] We've added a link to a [LightRAG Introduction Video](https://youtu.be/oageL-1I0GE). — a walkthrough of LightRAG's capabilities. Thanks to the author for this excellent contribution!
- [2024.10]🎯[New Channel] We have created a [Discord channel](https://discord.gg/yF2MmDJyGJ)!💬 Welcome to join our community for sharing, discussions, and collaboration! 🎉🎉
- [2024.10]🎯[New Feature] LightRAG now supports [Ollama models](https://github.com/HKUDS/LightRAG?tab=readme-ov-file#quick-start)!
<details>
<summary style="font-size: 1.4em; font-weight: bold; cursor: pointer; display: list-item;">
Algorithm Flowchart
</summary>

*Figure 1: LightRAG Indexing Flowchart - Img Caption : [Source](https://learnopencv.com/lightrag/)*

*Figure 2: LightRAG Retrieval and Querying Flowchart - Img Caption : [Source](https://learnopencv.com/lightrag/)*
</details>
## Installation
> **💡 Using uv for Package Management**: This project uses [uv](https://docs.astral.sh/uv/) for fast and reliable Python package management.
> Install uv first: `curl -LsSf https://astral.sh/uv/install.sh | sh` (Unix/macOS) or `powershell -c "irm https://astral.sh/uv/install.ps1 | iex"` (Windows)
>
> **Note**: You can also use pip if you prefer, but uv is recommended for better performance and more reliable dependency management.
>
> **📦 Offline Deployment**: For offline or air-gapped environments, see the [Offline Deployment Guide](./docs/OfflineDeployment.md) for instructions on pre-installing all dependencies and cache files.
### Install LightRAG Server
The LightRAG Server is designed to provide Web UI and API support. The Web UI facilitates document indexing, knowledge graph exploration, and a simple RAG query interface. LightRAG Server also provide an Ollama compatible interfaces, aiming to emulate LightRAG as an Ollama chat model. This allows AI chat bot, such as Open WebUI, to access LightRAG easily.
* Install from PyPI
```bash
### Install LightRAG Server as tool using uv (recommended)
uv tool install "lightrag-hku[api]"
### Or using pip
# python -m venv .venv
# source .venv/bin/activate # Windows: .venv\Scripts\activate
# pip install "lightrag-hku[api]"
### Build front-end artifacts
cd lightrag_webui
bun install --frozen-lockfile
bun run build
cd ..
# Setup env file
# Obtain the env.example file by downloading it from the GitHub repository root
# or by copying it from a local source checkout.
cp env.example .env # Update the .env with your LLM and embedding configurations
# Launch the server
lightrag-server
```
* Installation from Source
```bash
git clone https://github.com/HKUDS/LightRAG.git
cd LightRAG
# Using uv (recommended)
# Note: uv sync automatically creates a virtual environment in .venv/
uv sync --extra api
source .venv/bin/activate # Activate the virtual environment (Linux/macOS)
# Or on Windows: .venv\Scripts\activate
### Or using pip with virtual environment
# python -m venv .venv
# source .venv/bin/activate # Windows: .venv\Scripts\activate
# pip install -e ".[api]"
# Build front-end artifacts
cd lightrag_webui
bun install --frozen-lockfile
bun run build
cd ..
# setup env file
cp env.example .env # Update the .env with your LLM and embedding configurations
# Launch API-WebUI server
lightrag-server
```
* Launching the LightRAG Server with Docker Compose
```bash
git clone https://github.com/HKUDS/LightRAG.git
cd LightRAG
cp env.example .env # Update the .env with your LLM and embedding configurations
# modify LLM and Embedding settings in .env
docker compose up
```
> Historical versions of LightRAG docker images can be found here: [LightRAG Docker Images]( https://github.com/HKUDS/LightRAG/pkgs/container/lightrag)
### Create .env File With Setup Tool
Instead of editing `env.example` by hand, use the interactive setup wizard to generate a configured `.env` and, when needed, `docker-compose.final.yml`:
```bash
make env-base # Required first step: LLM, embedding, reranker
make env-storage # Optional: storage backends and database services
make env-server # Optional: server port, auth, and SSL
make env-base-rewrite # Optional: force-regenerate wizard-managed compose services
make env-storage-rewrite # Optional: force-regenerate wizard-managed compose services
make env-security-check # Optional: audit the current .env for security risks
```
For full description of every target see [docs/InteractiveSetup.md](./docs/InteractiveSetup.md).
The setup wizards update configuration only; run `make env-security-check` separately to audit the
current `.env` for security risks before deployment.
By default, rerunning the setup preserves unchanged wizard-managed compose service blocks; use a
`*-rewrite` target only when you need to rebuild those managed blocks from the bundled templates.
### Install LightRAG Core
* Install from source (Recommended)
```bash
cd LightRAG
# Note: uv sync automatically creates a virtual environment in .venv/
uv sync
source .venv/bin/activate # Activate the virtual environment (Linux/macOS)
# Or on Windows: .venv\Scripts\activate
# Or: pip install -e .
```
* Install from PyPI
```bash
uv pip install lightrag-hku
# Or: pip install lightrag-hku
```
## Quick Start
### LLM and Technology Stack Requirements for LightRAG
LightRAG's demands on the capabilities of Large Language Models (LLMs) are significantly higher than those of traditional RAG, as it requires the LLM to perform entity-relationship extraction tasks from documents. Configuring appropriate Embedding and Reranker models is also crucial for improving query performance.
- **LLM Selection**:
- It is recommended to use an LLM with at least 32 billion parameters.
- The context length should be at least 32KB, with 64KB being recommended.
- It is not recommended to choose reasoning models during the document indexing stage.
- During the query stage, it is recommended to choose models with stronger capabilities than those used in the indexing stage to achieve better query results.
- **Embedding Model**:
- A high-performance Embedding model is essential for RAG.
- We recommend using mainstream multilingual Embedding models, such as: `BAAI/bge-m3` and `text-embedding-3-large`.
- **Important Note**: The Embedding model must be determined before document indexing, and the same model must be used during the document query phase. For certain storage solutions (e.g., PostgreSQL), the vector dimension must be defined upon initial table creation. Therefore, when changing embedding models, it is necessary to delete the existing vector-related tables and allow LightRAG to recreate them with the new dimensions.
- **Reranker Model Configuration**:
- Configuring a Reranker model can significantly enhance LightRAG's retrieval performance.
- When a Reranker model is enabled, it is recommended to set the "mix mode" as the default query mode.
- We recommend using mainstream Reranker models, such as: `BAAI/bge-reranker-v2-m3` or models provided by services like Jina.
### Quick Start for LightRAG Server
* For more information about LightRAG Server, please refer to [LightRAG Server](./lightrag/api/README.md).
### Quick Start for LightRAG core
To get started with LightRAG core, refer to the sample codes available in the `examples` folder. Additionally, a [video demo](https://www.youtube.com/watch?v=g21royNJ4fw) demonstration is provided to guide you through the local setup process. If you already possess an OpenAI API key, you can run the demo right away:
```bash
### you should run the demo code with project folder
cd LightRAG
### provide your API-KEY for OpenAI
export OPENAI_API_KEY="sk-...your_opeai_key..."
### download the demo document of "A Christmas Carol" by Charles Dickens
curl https://raw.githubusercontent.com/gusye1234/nano-graphrag/main/tests/mock_data.txt > ./book.txt
### run the demo code
python examples/lightrag_openai_demo.py
```
For a streaming response implementation example, please see `examples/lightrag_openai_compatible_demo.py`. Prior to execution, ensure you modify the sample code's LLM and embedding configurations accordingly.
**Note 1**: When running the demo program, please be aware that different test scripts may use different embedding models. If you switch to a different embedding model, you must clear the data directory (`./dickens`); otherwise, the program may encounter errors. If you wish to retain the LLM cache, you can preserve the `kv_store_llm_response_cache.json` file while clearing the data directory.
**Note 2**: Only `lightrag_openai_demo.py` and `lightrag_openai_compatible_demo.py` are officially supported sample codes. Other sample files are community contributions that haven't undergone full testing and optimization.
## Programming with LightRAG Core
> ⚠️ **If you would like to integrate LightRAG into your project, we recommend utilizing the REST API provided by the LightRAG Server**. LightRAG Core is typically intended for embedded applications or for researchers who wish to conduct studies and evaluations.
### ⚠️ Important: Initialization Requirements
**LightRAG requires explicit initialization before use.** You must call `await rag.initialize_storages()` after creating a LightRAG instance, otherwise you will encounter errors.
### A Simple Program
Use the below Python snippet to initialize LightRAG, insert text to it, and perform queries:
```python
import os
import asyncio
from lightrag import LightRAG, QueryParam
from lightrag.llm.openai import gpt_4o_mini_complete, gpt_4o_complete, openai_embed
from lightrag.utils import setup_logger
setup_logger("lightrag", level="INFO")
WORKING_DIR = "./rag_storage"
if not os.path.exists(WORKING_DIR):
os.mkdir(WORKING_DIR)
async def initialize_rag():
rag = LightRAG(
working_dir=WORKING_DIR,
embedding_func=openai_embed,
llm_model_func=gpt_4o_mini_complete,
)
# IMPORTANT: Both initialization calls are required!
await rag.initialize_storages() # Initialize storage backends
return rag
async def main():
try:
# Initialize RAG instance
rag = await initialize_rag()
await rag.ainsert("Your text")
# Perform hybrid search
mode = "hybrid"
print(
await rag.aquery(
"What are the top themes in this story?",
param=QueryParam(mode=mode)
)
)
except Exception as e:
print(f"An error occurred: {e}")
finally:
if rag:
await rag.finalize_storages()
if __name__ == "__main__":
asyncio.run(main())
```
Important notes for the above snippet:
- Export your OPENAI_API_KEY environment variable before running the script.
- This program uses the default storage settings for LightRAG, so all data will be persisted to WORKING_DIR/rag_storage.
- This program demonstrates only the simplest way to initialize a LightRAG object: Injecting the embedding and LLM functions, and initializing storage and pipeline status after creating the LightRAG object.
### LightRAG init parameters
A full list of LightRAG init parameters:
<details>
<summary> Parameters </summary>
| **Parameter** | **Type** | **Explanation** | **Default** |
| -------------- | ---------- | ----------------- | ------------- |
| **working_dir** | `str` | Directory where the cache will be stored | `lightrag_cache+timestamp` |
| **workspace** | str | Workspace name for data isolation between different LightRAG Instances | |
| **kv_storage** | `str` | Storage type for documents and text chunks. Supported types: `JsonKVStorage`,`PGKVStorage`,`RedisKVStorage`,`MongoKVStorage`,`OpenSearchKVStorage` | `JsonKVStorage` |
| **vector_storage** | `str` | Storage type for embedding vectors. Supported types: `NanoVectorDBStorage`,`PGVectorStorage`,`MilvusVectorDBStorage`,`ChromaVectorDBStorage`,`FaissVectorDBStorage`,`MongoVectorDBStorage`,`QdrantVectorDBStorage`,`OpenSearchVectorDBStorage` | `NanoVectorDBStorage` |
| **graph_storage** | `str` | Storage type for graph edges and nodes. Supported types: `NetworkXStorage`,`Neo4JStorage`,`PGGraphStorage`,`AGEStorage`,`OpenSearchGraphStorage` | `NetworkXStorage` |
| **doc_status_storage** | `str` | Storage type for documents process status. Supported types: `JsonDocStatusStorage`,`PGDocStatusStorage`,`MongoDocStatusStorage`,`OpenSearchDocStatusStorage` | `JsonDocStatusStorage` |
| **chunk_token_size** | `int` | Maximum token size per chunk when splitting documents | `1200` |
| **chunk_overlap_token_size** | `int` | Overlap token size between two chunks when splitting documents | `100` |
| **tokenizer** | `Tokenizer` | The function used to convert text into tokens (numbers) and back using .encode() and .decode() functions following `TokenizerInterface` protocol. If you don't specify one, it will use the default Tiktoken tokenizer. | `TiktokenTokenizer` |
| **tiktoken_model_name** | `str` | If you're using the default Tiktoken tokenizer, this is the name of the specific Tiktoken model to use. This setting is ignored if you provide your own tokenizer. | `gpt-4o-mini` |
| **entity_extract_max_gleaning** | `int` | Number of loops in the entity extraction process, appending history messages | `1` |
| **node_embedding_algorithm** | `str` | Algorithm for node embedding (currently not used) | `node2vec` |
| **node2vec_params** | `dict` | Parameters for node embedding | `{"dimensions": 1536,"num_walks": 10,"walk_length": 40,"window_size": 2,"iterations": 3,"random_seed": 3,}` |
| **embedding_func** | `EmbeddingFunc` | Function to generate embedding vectors from text | `openai_embed` |
| **embedding_batch_num** | `int` | Maximum batch size for embedding processes (multiple texts sent per batch) | `32` |
| **embedding_func_max_async** | `int` | Maximum number of concurrent asynchronous embedding processes | `16` |
| **llm_model_func** | `callable` | Function for LLM generation | `gpt_4o_mini_complete` |
| **llm_model_name** | `str` | LLM model name for generation | `meta-llama/Llama-3.2-1B-Instruct` |
| **summary_context_size** | `int` | Maximum tokens send to LLM to generate summaries for entity relation merging | `10000`(configured by env var SUMMARY_CONTEXT_SIZE) |
| **summary_max_tokens** | `int` | Maximum token size for entity/relation description | `500`(configured by env var SUMMARY_MAX_TOKENS) |
| **llm_model_max_async** | `int` | Maximum number of concurrent asynchronous LLM processes | `4`(default value changed by env var MAX_ASYNC) |
| **llm_model_kwargs** | `dict` | Additional parameters for LLM generation | |
| **vector_db_storage_cls_kwargs** | `dict` | Additional parameters for vector database, like setting the threshold for nodes and relations retrieval | cosine_better_than_threshold: 0.2(default value changed by env var COSINE_THRESHOLD) |
| **enable_llm_cache** | `bool` | If `TRUE`, stores LLM results in cache; repeated prompts return cached responses | `TRUE` |
| **enable_llm_cache_for_entity_extract** | `bool` | If `TRUE`, stores LLM results in cache for entity extraction; Good for beginners to debug your application | `TRUE` |
| **addon_params** | `dict` | Additional parameters, e.g., `{"language": "Simplified Chinese", "entity_types": ["organization", "person", "location", "event"]}`: sets example limit, entity/relation extraction output language | language: English` |
| **embedding_cache_config** | `dict` | Configuration for question-answer caching. Contains three parameters: `enabled`: Boolean value to enable/disable cache lookup functionality. When enabled, the system will check cached responses before generating new answers. `similarity_threshold`: Float value (0-1), similarity threshold. When a new question's similarity with a cached question exceeds this threshold, the cached answer will be returned directly without calling the LLM. `use_llm_check`: Boolean value to enable/disable LLM similarity verification. When enabled, LLM will be used as a secondary check to verify the similarity between questions before returning cached answers. | Default: `{"enabled": False, "similarity_threshold": 0.95, "use_llm_check": False}` |
</details>
### Query Param
Use QueryParam to control the behavior your query:
```python
class QueryParam:
"""Configuration parameters for query execution in LightRAG."""
mode: Literal["local", "global", "hybrid", "naive", "mix", "bypass"] = "global"
"""Specifies the retrieval mode:
- "local": Focuses on context-dependent information.
- "global": Utilizes global knowledge.
- "hybrid": Combines local and global retrieval methods.
- "naive": Performs a basic search without advanced techniques.
- "mix": Integrates knowledge graph and vector retrieval.
"""
only_need_context: bool = False
"""If True, only returns the retrieved context without generating a response."""
only_need_prompt: bool = False
"""If True, only returns the generated prompt without producing a response."""
response_type: str = "Multiple Paragraphs"
"""Defines the response format. Examples: 'Multiple Paragraphs', 'Single Paragraph', 'Bullet Points'."""
stream: bool = False
"""If True, enables streaming output for real-time responses."""
top_k: int = int(os.getenv("TOP_K", "60"))
"""Number of top items to retrieve. Represents entities in 'local' mode and relationships in 'global' mode."""
chunk_top_k: int = int(os.getenv("CHUNK_TOP_K", "20"))
"""Number of text chunks to retrieve initially from vector search and keep after reranking.
If None, defaults to top_k value.
"""
max_entity_tokens: int = int(os.getenv("MAX_ENTITY_TOKENS", "6000"))
"""Maximum number of tokens allocated for entity context in unified token control system."""
max_relation_tokens: int = int(os.getenv("MAX_RELATION_TOKENS", "8000"))
"""Maximum number of tokens allocated for relationship context in unified token control system."""
max_total_tokens: int = int(os.getenv("MAX_TOTAL_TOKENS", "30000"))
"""Maximum total tokens budget for the entire query context (entities + relations + chunks + system prompt)."""
# History messages are only sent to LLM for context, not used for retrieval
conversation_history: list[dict[str, str]] = field(default_factory=list)
"""Stores past conversation history to maintain context.
Format: [{"role": "user/assistant", "content": "message"}].
"""
# Deprecated (ids filter lead to potential hallucination effects)
ids: list[str] | None = None
"""List of ids to filter the results."""
model_func: Callable[..., object] | None = None
"""Optional override for the LLM model function to use for this specific query.
If provided, this will be used instead of the global model function.
This allows using different models for different query modes.
"""
user_prompt: str | None = None
"""User-provided prompt for the query.
Addition instructions for LLM. If provided, this will be inject into the prompt template.
It's purpose is the let user customize the way LLM generate the response.
"""
enable_rerank: bool = True
"""Enable reranking for retrieved text chunks. If True but no rerank model is configured, a warning will be issued.
Default is True to enable reranking when rerank model is available.
"""
```
> default value of Top_k can be change by environment variables TOP_K.
### LLM and Embedding Injection
LightRAG requires the utilization of LLM and Embedding models to accomplish document indexing and querying tasks. During the initialization phase, it is necessary to inject the invocation methods of the relevant models into LightRAG:
<details>
<summary> <b>Using Open AI-like APIs</b> </summary>
* LightRAG also supports Open AI-like chat/embeddings APIs:
```python
import os
import numpy as np
from lightrag.utils import wrap_embedding_func_with_attrs
from lightrag.llm.openai import openai_complete_if_cache, openai_embed
async def llm_model_func(
prompt, system_prompt=None, history_messages=[], keyword_extraction=False, **kwargs
) -> str:
return await openai_complete_if_cache(
"solar-mini",
prompt,
system_prompt=system_prompt,
history_messages=history_messages,
api_key=os.getenv("UPSTAGE_API_KEY"),
base_url="https://api.upstage.ai/v1/solar",
**kwargs
)
@wrap_embedding_func_with_attrs(embedding_dim=4096, max_token_size=8192, model_name="solar-embedding-1-large-query")
async def embedding_func(texts: list[str]) -> np.ndarray:
return await openai_embed.func(
texts,
model="solar-embedding-1-large-query",
api_key=os.getenv("UPSTAGE_API_KEY"),
base_url="https://api.upstage.ai/v1/solar"
)
async def initialize_rag():
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=llm_model_func,
embedding_func=embedding_func # Pass the decorated function directly
)
await rag.initialize_storages()
return rag
```
> **Important Note on Embedding Function Wrapping:**
>
> `EmbeddingFunc` cannot be nested. Functions that have been decorated with `@wrap_embedding_func_with_attrs` (such as `openai_embed`, `ollama_embed`, etc.) cannot be wrapped again using `EmbeddingFunc()`. This is why we call `xxx_embed.func` (the underlying unwrapped function) instead of `xxx_embed` directly when creating custom embedding functions.
</details>
<details>
<summary> <b>Using Hugging Face Models</b> </summary>
* If you want to use Hugging Face models, you only need to set LightRAG as follows:
See `lightrag_hf_demo.py`
```python
from functools import partial
from transformers import AutoTokenizer, AutoModel
# Pre-load tokenizer and model
tokenizer = AutoTokenizer.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")
embed_model = AutoModel.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")
# Initialize LightRAG with Hugging Face model
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=hf_model_complete, # Use Hugging Face model for text generation
llm_model_name='meta-llama/Llama-3.1-8B-Instruct', # Model name from Hugging Face
# Use Hugging Face embedding function
embedding_func=EmbeddingFunc(
embedding_dim=384,
max_token_size=2048,
model_name="sentence-transformers/all-MiniLM-L6-v2",
func=partial(
hf_embed.func, # Use .func to access the unwrapped function
tokenizer=tokenizer,
embed_model=embed_model
)
),
)
```
</details>
<details>
<summary> <b>Using Ollama Models</b> </summary>
**Overview**
If you want to use Ollama models, you need to pull model you plan to use and embedding model, for example `nomic-embed-text`.
Then you only need to set LightRAG as follows:
```python
import numpy as np
from lightrag.utils import wrap_embedding_func_with_attrs
from lightrag.llm.ollama import ollama_model_complete, ollama_embed
@wrap_embedding_func_with_attrs(embedding_dim=768, max_token_size=8192, model_name="nomic-embed-text")
async def embedding_func(texts: list[str]) -> np.ndarray:
return await ollama_embed.func(texts, embed_model="nomic-embed-text")
# Initialize LightRAG with Ollama model
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=ollama_model_complete, # Use Ollama model for text generation
llm_model_name='your_model_name', # Your model name
embedding_func=embedding_func, # Pass the decorated function directly
)
```
* **Increasing context size**
In order for LightRAG to work context should be at least 32k tokens. By default Ollama models have context size of 8k. You can achieve this using one of two ways:
* **Increasing the `num_ctx` parameter in Modelfile**
1. Pull the model:
```bash
ollama pull qwen2
```
2. Display the model file:
```bash
ollama show --modelfile qwen2 > Modelfile
```
3. Edit the Modelfile by adding the following line:
```bash
PARAMETER num_ctx 32768
```
4. Create the modified model:
```bash
ollama create -f Modelfile qwen2m
```
* **Setup `num_ctx` via Ollama API**
Tiy can use `llm_model_kwargs` param to configure ollama:
```python
import numpy as np
from lightrag.utils import wrap_embedding_func_with_attrs
from lightrag.llm.ollama import ollama_model_complete, ollama_embed
@wrap_embedding_func_with_attrs(embedding_dim=768, max_token_size=8192, model_name="nomic-embed-text")
async def embedding_func(texts: list[str]) -> np.ndarray:
return await ollama_embed.func(texts, embed_model="nomic-embed-text")
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=ollama_model_complete, # Use Ollama model for text generation
llm_model_name='your_model_name', # Your model name
llm_model_kwargs={"options": {"num_ctx": 32768}},
embedding_func=embedding_func, # Pass the decorated function directly
)
```
> **Important Note on Embedding Function Wrapping:**
>
> `EmbeddingFunc` cannot be nested. Functions that have been decorated with `@wrap_embedding_func_with_attrs` (such as `openai_embed`, `ollama_embed`, etc.) cannot be wrapped again using `EmbeddingFunc()`. This is why we call `xxx_embed.func` (the underlying unwrapped function) instead of `xxx_embed` directly when creating custom embedding functions.
* **Low RAM GPUs**
In order to run this experiment on low RAM GPU you should select small model and tune context window (increasing context increase memory consumption). For example, running this ollama example on repurposed mining GPU with 6Gb of RAM required to set context size to 26k while using `gemma2:2b`. It was able to find 197 entities and 19 relations on `book.txt`.
</details>
<details>
<summary> <b>LlamaIndex</b> </summary>
LightRAG supports integration with LlamaIndex (`llm/llama_index_impl.py`):
- Integrates with OpenAI and other providers through LlamaIndex
- See [LlamaIndex Documentation](https://developers.llamaindex.ai/python/framework/) for detailed setup or the [examples](examples/unofficial-sample/)
**Example Usage**
```python
# Using LlamaIndex with direct OpenAI access
import asyncio
from lightrag import LightRAG
from lightrag.llm.llama_index_impl import llama_index_complete_if_cache, llama_index_embed
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI
from lightrag.utils import setup_logger
# Setup log handler for LightRAG
setup_logger("lightrag", level="INFO")
async def initialize_rag():
rag = LightRAG(
working_dir="your/path",
llm_model_func=llama_index_complete_if_cache, # LlamaIndex-compatible completion function
embedding_func=EmbeddingFunc( # LlamaIndex-compatible embedding function
embedding_dim=1536,
max_token_size=2048,
model_name=embed_model,
func=partial(llama_index_embed.func, embed_model=embed_model) # Use .func to access the unwrapped function
),
)
await rag.initialize_storages()
return rag
def main():
# Initialize RAG instance
rag = asyncio.run(initialize_rag())
with open("./book.txt", "r", encoding="utf-8") as f:
rag.insert(f.read())
# Perform naive search
print(
rag.query("What are the top themes in this story?", param=QueryParam(mode="naive"))
)
# Perform local search
print(
rag.query("What are the top themes in this story?", param=QueryParam(mode="local"))
)
# Perform global search
print(
rag.query("What are the top themes in this story?", param=QueryParam(mode="global"))
)
# Perform hybrid search
print(
rag.query("What are the top themes in this story?", param=QueryParam(mode="hybrid"))
)
if __name__ == "__main__":
main()
```
**For detailed documentation and examples, see:**
- [LlamaIndex Documentation](https://developers.llamaindex.ai/python/framework/)
- [Direct OpenAI Example](examples/unofficial-sample/lightrag_llamaindex_direct_demo.py)
- [LiteLLM Proxy Example](examples/unofficial-sample/lightrag_llamaindex_litellm_demo.py)
- [LiteLLM Proxy with Opik Example](examples/unofficial-sample/lightrag_llamaindex_litellm_opik_demo.py)
</details>
<details>
<summary> <b>Using Azure OpenAI Models</b> </summary>
If you want to use Azure OpenAI models, you only need to set up LightRAG as follows:
```python
import os
import numpy as np
from lightrag.utils import wrap_embedding_func_with_attrs
from lightrag.llm.azure_openai import azure_openai_complete_if_cache, azure_openai_embed
# Configure the generation model
async def llm_model_func(
prompt, system_prompt=None, history_messages=[], keyword_extraction=False, **kwargs
) -> str:
return await azure_openai_complete_if_cache(
prompt,
system_prompt=system_prompt,
history_messages=history_messages,
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
api_version=os.getenv("AZURE_OPENAI_API_VERSION"),
deployment_name=os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME"),
**kwargs
)
# Configure the embedding model
@wrap_embedding_func_with_attrs(
embedding_dim=1536,
max_token_size=8192,
model_name=os.getenv("AZURE_OPENAI_EMBEDDING_MODEL")
)
async def embedding_func(texts: list[str]) -> np.ndarray:
return await azure_openai_embed.func(
texts,
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
api_version=os.getenv("AZURE_OPENAI_API_VERSION"),
deployment_name=os.getenv("AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME")
)
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=llm_model_func,
embedding_func=embedding_func
)
```
</details>
<details>
<summary> <b>Using Google Gemini Models</b> </summary>
If you want to use Google Gemini models, you only need to set up LightRAG as follows:
```python
import os
import numpy as np
from lightrag.utils import wrap_embedding_func_with_attrs
from lightrag.llm.gemini import gemini_model_complete, gemini_embed
# Configure the generation model
async def llm_model_func(
prompt, system_prompt=None, history_messages=[], keyword_extraction=False, **kwargs
) -> str:
return await gemini_model_complete(
prompt,
system_prompt=system_prompt,
history_messages=history_messages,
api_key=os.getenv("GEMINI_API_KEY"),
model_name="gemini-2.0-flash",
**kwargs
)
# Configure the embedding model
@wrap_embedding_func_with_attrs(
embedding_dim=768,
max_token_size=2048,
model_name="models/text-embedding-004"
)
async def embedding_func(texts: list[str]) -> np.ndarray:
return await gemini_embed.func(
texts,
api_key=os.getenv("GEMINI_API_KEY"),
model="models/text-embedding-004"
)
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=llm_model_func,
llm_model_name="gemini-2.0-flash",
embedding_func=embedding_func
)
```
</details>
### Rerank Function Injection
To enhance retrieval quality, documents can be re-ranked based on a more effective relevance scoring model. The `rerank.py` file provides three Reranker provider driver functions:
* **Cohere / vLLM**: `cohere_rerank`
* **Jina AI**: `jina_rerank`
* **Aliyun**: `ali_rerank`
You can inject one of these functions into the `rerank_model_func` attribute of the LightRAG object. This will enable LightRAG's query function to re-order retrieved text blocks using the injected function. For detailed usage, please refer to the `examples/rerank_example.py` file.
### User Prompt vs. Query
When using LightRAG for content queries, avoid combining the search process with unrelated output processing, as this significantly impacts query effectiveness. The `user_prompt` parameter in Query Param is specifically designed to address this issue — it does not participate in the RAG retrieval phase, but rather guides the LLM on how to process the retrieved results after the query is completed. Here's how to use it:
```python
# Create query parameters
query_param = QueryParam(
mode = "hybrid", # Other modes:local, global, hybrid, mix, naive
user_prompt = "For diagrams, use mermaid format with English/Pinyin node names and Chinese display labels",
)
# Query and process
response_default = rag.query(
"Please draw a character relationship diagram for Scrooge",
param=query_param
)
print(response_default)
```
### Insert
<details>
<summary> <b> Basic Insert </b></summary>
```python
# Basic Insert
rag.insert("Text")
```
</details>
<details>
<summary> <b> Batch Insert </b></summary>
```python
# Basic Batch Insert: Insert multiple texts at once
rag.insert(["TEXT1", "TEXT2",...])
# Batch Insert with custom batch size configuration
rag = LightRAG(
...
working_dir=WORKING_DIR,
max_parallel_insert = 4
)
rag.insert(["TEXT1", "TEXT2", "TEXT3", ...]) # Documents will be processed in batches of 4
```
The `max_parallel_insert` parameter determines the number of documents processed concurrently in the document indexing pipeline. If unspecified, the default value is **2**. We recommend keeping this setting **below 10**, as the performance bottleneck typically lies with the LLM (Large Language Model) processing.
</details>
<details>
<summary> <b> Insert with ID </b></summary>
If you want to provide your own IDs for your documents, number of documents and number of IDs must be the same.
```python
# Insert single text, and provide ID for it
rag.insert("TEXT1", ids=["ID_FOR_TEXT1"])
# Insert multiple texts, and provide IDs for them
rag.insert(["TEXT1", "TEXT2",...], ids=["ID_FOR_TEXT1", "ID_FOR_TEXT2"])
```
</details>
<details>
<summary><b>Insert using Pipeline</b></summary>
The `apipeline_enqueue_documents` and `apipeline_process_enqueue_documents` functions allow you to perform incremental insertion of documents into the graph.This is useful for scenarios where you want to process documents in the background while still allowing the main thread to continue executing.
```python
rag = LightRAG(..)
await rag.apipeline_enqueue_documents(input)
# Your routine in loop
await rag.apipeline_process_enqueue_documents(input)
```
</details>
<details>
<summary><b>Insert Multi-file Type Support</b></summary>
The `textract` supports reading file types such as TXT, DOCX, PPTX, CSV, and PDF.
```python
import textract
file_path = 'TEXT.pdf'
text_content = textract.process(file_path)
rag.insert(text_content.decode('utf-8'))
```
</details>
<details>
<summary><b>Citation Functionality</b></summary>
By providing file paths, the system ensures that sources can be traced back to their original documents.
```python
# Define documents and their file paths
documents = ["Document content 1", "Document content 2"]
file_paths = ["path/to/doc1.txt", "path/to/doc2.txt"]
# Insert documents with file paths
rag.insert(documents, file_paths=file_paths)
```
</details>
### Storage
LightRAG uses 4 types of storage for different purposes:
* KV_STORAGE: llm response cache, text chunks, document information
* VECTOR_STORAGE: entities vectors, relation vectors, chunks vectors
* GRAPH_STORAGE: entity relation graph
* DOC_STATUS_STORAGE: document indexing status
Each storage type has several implementations:
* KV_STORAGE supported implementations:
```
JsonKVStorage JsonFile (default)
PGKVStorage Postgres
RedisKVStorage Redis
MongoKVStorage MongoDB
OpenSearchKVStorage OpenSearch
```
* GRAPH_STORAGE supported implementations:
```
NetworkXStorage NetworkX (default)
Neo4JStorage Neo4J
PGGraphStorage PostgreSQL with AGE plugin
MemgraphStorage Memgraph
OpenSearchGraphStorage OpenSearch
```
> Testing has shown that Neo4J delivers superior performance in production environments compared to PostgreSQL with AGE plugin.
* VECTOR_STORAGE supported implementations:
```
NanoVectorDBStorage NanoVector (default)
PGVectorStorage Postgres
MilvusVectorDBStorage Milvus
FaissVectorDBStorage Faiss
QdrantVectorDBStorage Qdrant
MongoVectorDBStorage MongoDB
OpenSearchVectorDBStorage OpenSearch
```
* DOC_STATUS_STORAGE: supported implementations:
```
JsonDocStatusStorage JsonFile (default)
PGDocStatusStorage Postgres
MongoDocStatusStorage MongoDB
OpenSearchDocStatusStorage OpenSearch
```
Example connection configurations for each storage type can be found in the repository's `env.example` file. The database instance in the connection string needs to be created by you on the database server beforehand. LightRAG is only responsible for creating tables within the database instance, not for creating the database instance itself. If using Redis as storage, remember to configure automatic data persistence rules for Redis, otherwise data will be lost after the Redis service restarts. If using PostgreSQL, it is recommended to use version 16.6 or above.
<details>
<summary> <b>Using Neo4J Storage</b> </summary>
* For production level scenarios you will most likely want to leverage an enterprise solution
* for KG storage. Running Neo4J in Docker is recommended for seamless local testing.
* See: https://hub.docker.com/_/neo4j
```python
export NEO4J_URI="neo4j://localhost:7687"
export NEO4J_USERNAME="neo4j"
export NEO4J_PASSWORD="password"
export NEO4J_DATABASE="neo4j" #<----------- If you are using community edition neo4j docker image.
# Setup logger for LightRAG
setup_logger("lightrag", level="INFO")
# When you launch the project be sure to override the default KG by specifying graph_storage="Neo4JStorage".
# Initialize LightRAG with Neo4J implementation.
async def initialize_rag():
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=gpt_4o_mini_complete, # Use gpt_4o_mini_complete LLM model
graph_storage="Neo4JStorage", #<-----------override KG default
)
# Initialize database connections
await rag.initialize_storages()
# Initialize pipeline status for document processing
return rag
```
see test_neo4j.py for a working example.
</details>
<details>
<summary> <b>Using PostgreSQL Storage</b> </summary>
For production level scenarios you will most likely want to leverage an enterprise solution. PostgreSQL can provide a one-stop solution for you as KV store, VectorDB (pgvector) and GraphDB (apache AGE). PostgreSQL version 16.6 or higher is supported.
* PostgreSQL is lightweight,the whole binary distribution including all necessary plugins can be zipped to 40MB: Ref to [Windows Release](https://github.com/ShanGor/apache-age-windows/releases/tag/PG17%2Fv1.5.0-rc0) as it is easy to install for Linux/Mac.
* If you prefer docker, please start with this image if you are a beginner to avoid hiccups (Default user password:rag/rag): https://hub.docker.com/r/gzdaniel/postgres-for-rag
* How to start? Ref to: [examples/lightrag_gemini_postgres_demo.py](https://github.com/HKUDS/LightRAG/blob/main/examples/lightrag_gemini_postgres_demo.py)
* For high-performance graph database requirements, Neo4j is recommended as Apache AGE's performance is not as competitive.
</details>
<details>
<summary> <b>Using Faiss Storage</b> </summary>
Before using Faiss vector database, you must manually install `faiss-cpu` or `faiss-gpu`.
- Install the required dependencies:
```
pip install faiss-cpu
```
You can also install `faiss-gpu` if you have GPU support.
- Here we are using `sentence-transformers` but you can also use `OpenAIEmbedding` model with `3072` dimensions.
```python
async def embedding_func(texts: list[str]) -> np.ndarray:
model = SentenceTransformer('all-MiniLM-L6-v2')
embeddings = model.encode(texts, convert_to_numpy=True)
return embeddings
# Initialize LightRAG with the LLM model function and embedding function
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=llm_model_func,
embedding_func=EmbeddingFunc(
embedding_dim=384,
max_token_size=2048,
model_name="all-MiniLM-L6-v2",
func=embedding_func,
),
vector_storage="FaissVectorDBStorage",
vector_db_storage_cls_kwargs={
"cosine_better_than_threshold": 0.3 # Your desired threshold
}
)
```
</details>
<details>
<summary> <b>Using Memgraph for Storage</b> </summary>
* Memgraph is a high-performance, in-memory graph database compatible with the Neo4j Bolt protocol.
* You can run Memgraph locally using Docker for easy testing:
* See: https://memgraph.com/download
```python
export MEMGRAPH_URI="bolt://localhost:7687"
# Setup logger for LightRAG
setup_logger("lightrag", level="INFO")
# When you launch the project, override the default KG: NetworkX
# by specifying kg="MemgraphStorage".
# Note: Default settings use NetworkX
# Initialize LightRAG with Memgraph implementation.
async def initialize_rag():
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=gpt_4o_mini_complete, # Use gpt_4o_mini_complete LLM model
graph_storage="MemgraphStorage", #<-----------override KG default
)
# Initialize database connections
await rag.initialize_storages()
# Initialize pipeline status for document processing
return rag
```
</details>
<details>
<summary> <b>Using Milvus for Vector Storage</b> </summary>
Milvus is a high-performance, scalable vector database for production-level vector storage. LightRAG provides three ways to configure Milvus, plus support for configurable index types to optimize performance and memory usage.
### Supported Index Types
- `AUTOINDEX` (default): Milvus automatically selects the best index
- `HNSW`: Hierarchical Navigable Small World graph for high recall
- `HNSW_SQ`: HNSW with scalar quantization for memory savings (requires Milvus 2.6.8+)
- `HNSW_PQ`, `HNSW_PRQ`: HNSW with product / product-residual quantization
- `IVF_FLAT`, `IVF_SQ8`, `IVF_PQ`: Inverted-file family indexes
- `DISKANN`: Disk-based approximate nearest neighbor
- `SCANN`: Scalable nearest neighbor
### Supported Metric Types
`COSINE` (default), `L2`, `IP`
---
### Config Approach 1 — Environment Variables (`.env` file)
Best for: **LightRAG Server deployments and Docker/k8s setups**.
```bash
# Connection
MILVUS_URI=http://localhost:19530
MILVUS_DB_NAME=lightrag
# MILVUS_USER=root
# MILVUS_PASSWORD=your_password
# MILVUS_TOKEN=your_token
# Storage selection
LIGHTRAG_VECTOR_STORAGE=MilvusVectorDBStorage
# Index configuration (all optional — sensible defaults apply)
MILVUS_INDEX_TYPE=HNSW # Default: AUTOINDEX
MILVUS_METRIC_TYPE=COSINE # Default: COSINE
MILVUS_HNSW_M=16 # Default: 16, range [2-2048]
MILVUS_HNSW_EF_CONSTRUCTION=360 # Default: 360
MILVUS_HNSW_EF=200 # Default: 200
# HNSW_SQ options (requires Milvus 2.6.8+)
# MILVUS_INDEX_TYPE=HNSW_SQ
# MILVUS_HNSW_SQ_TYPE=SQ8 # SQ4U, SQ6, SQ8, BF16, FP16
# MILVUS_HNSW_SQ_REFINE=false # Enable refinement
# MILVUS_HNSW_SQ_REFINE_TYPE=FP32 # Refinement precision
# MILVUS_HNSW_SQ_REFINE_K=10 # Refinement expansion factor
# IVF options
# MILVUS_IVF_NLIST=1024
# MILVUS_IVF_NPROBE=16
```
Then in Python code:
```python
from lightrag import LightRAG
async def initialize_rag():
rag = LightRAG(
working_dir="./rag_storage",
llm_model_func=...,
embedding_func=...,
vector_storage="MilvusVectorDBStorage",
)
await rag.initialize_storages()
return rag
```
### Config Approach 2 — `vector_db_storage_cls_kwargs` (Python SDK)
Best for: **Python SDK / framework integration** where you want all config in code.
```python
from lightrag import LightRAG
async def initialize_rag():
rag = LightRAG(
working_dir="./rag_storage",
llm_model_func=...,
embedding_func=...,
vector_storage="MilvusVectorDBStorage",
vector_db_storage_cls_kwargs={
"milvus_uri": "http://localhost:19530",
"milvus_db_name": "lightrag",
"index_type": "HNSW",
"metric_type": "COSINE",
"hnsw_m": 16,
"hnsw_ef_construction": 360,
"hnsw_ef": 200,
"cosine_better_than_threshold": 0.2,
},
)
await rag.initialize_storages()
return rag
```
### Config Approach 3 — `config.ini` (legacy)
Connection parameters only; index settings use env vars or kwargs.
```ini
[milvus]
uri = http://localhost:19530
db_name = lightrag
# user = root
# password = your_password
# token = your_token
```
### Configuration Priority
| Setting | 1st (highest) | 2nd | 3rd (lowest) |
|---|---|---|---|
| Connection (`uri`, …) | `vector_db_storage_cls_kwargs` | Environment variables | `config.ini` |
| Index (`index_type`, …) | `vector_db_storage_cls_kwargs` | Environment variables | defaults |
### HNSW_SQ Compression Trade-offs
| SQ Type | Compression | Precision | Notes |
|---|---|---|---|
| `SQ4U` | ~8× | Lower | Best memory savings |
| `SQ6` | ~5.3× | Balanced | Good trade-off |
| `SQ8` | ~4× | Good | **Recommended** |
| `BF16` / `FP16` | ~2× | High | Near-lossless |
**Version Requirements:**
- HNSW_SQ index type requires **Milvus 2.6.8 or higher**
- LightRAG will automatically validate the server version and raise an error if requirements are not met
- Other index types work with Milvus 2.0+
**Backward Compatibility:**
- If no index configuration is provided, LightRAG uses AUTOINDEX (Milvus default behavior)
- Existing collections are not affected; index configuration only applies to newly created collections
For complete configuration options, see `env.example` and `docs/MilvusConfigurationGuide.md`.
</details>
<details>
<summary> <b>Using MongoDB Storage</b> </summary>
MongoDB provides a one-stop storage solution for LightRAG. MongoDB offers native KV storage and vector storage. LightRAG uses MongoDB collections to implement a simple graph storage. `MongoVectorDBStorage` requires a MongoDB deployment with Atlas Search / Vector Search support, such as MongoDB Atlas or Atlas local. The setup wizard's bundled local Docker MongoDB service is MongoDB Community Edition, so it can be used for KV/graph/doc-status storage but not for `MongoVectorDBStorage`.
</details>
<details>
<summary> <b>Using Redis Storage</b> </summary>
LightRAG supports using Redis as KV storage. When using Redis storage, attention should be paid to persistence configuration and memory usage configuration. The following is the recommended Redis configuration:
```
save 900 1
save 300 10
save 60 1000
stop-writes-on-bgsave-error yes
maxmemory 4gb
maxmemory-policy noeviction
maxclients 500
```
When the interactive setup manages a local Redis container, it stages a user-editable config at `./data/config/redis.conf` and mounts it into the container. Setup preserves that file on reruns so local Redis tuning can be adjusted without losing manual edits.
</details>
<details>
<summary> <b>Using OpenSearch Storage</b> </summary>
OpenSearch provides a unified storage solution for all four LightRAG storage types (KV, Vector, Graph, DocStatus). It offers native k-NN vector search, full-text search, and horizontal scalability — all without cloud-only restrictions.
* **Requirements**: OpenSearch 3.x or higher with k-NN plugin enabled.
Install with Docker (without plugins):
```bash
docker run -d -p 9200:9200 -e "discovery.type=single-node" \
-e "OPENSEARCH_INITIAL_ADMIN_PASSWORD=<custom-admin-password>" \
opensearchproject/opensearch:latest
```
Install with Docker Compose (Recommended, with plugins):
```bash
curl -O https://raw.githubusercontent.com/opensearch-project/opensearch-build/main/docker/release/dockercomposefiles/docker-compose-3.x.yml
# Launch OpenSearch cluster
OPENSEARCH_INITIAL_ADMIN_PASSWORD=<custom-admin-password> docker-compose -f docker-compose-3.x.yml up -d
```
* **Configuration**: Set environment variables (see `env.example` for full list):
```bash
export OPENSEARCH_HOSTS=localhost:9200
export OPENSEARCH_USER=admin
export OPENSEARCH_PASSWORD=<custom-admin-password>
export OPENSEARCH_USE_SSL=true
export OPENSEARCH_VERIFY_CERTS=false
```
* **Usage**:
```python
rag = LightRAG(
working_dir=WORKING_DIR,
llm_model_func=your_llm_func,
embedding_func=your_embed_func,
kv_storage="OpenSearchKVStorage",
doc_status_storage="OpenSearchDocStatusStorage",
graph_storage="OpenSearchGraphStorage",
vector_storage="OpenSearchVectorDBStorage",
)
```
* **Graph Traversal**: When the OpenSearch SQL plugin with PPL support is available, graph queries use server-side BFS via the `graphlookup` command for optimal performance. Otherwise, it falls back to client-side batched BFS. This is auto-detected at startup, or can be forced via `OPENSEARCH_USE_PPL_GRAPHLOOKUP=true|false`.
* **Integration Testing**: To run integration tests against a live OpenSearch cluster:
1. Start OpenSearch using Docker Compose (download [`docker-compose-3.x.yml`](https://raw.githubusercontent.com/opensearch-project/opensearch-build/main/docker/release/dockercomposefiles/docker-compose-3.x.yml)):
```bash
OPENSEARCH_INITIAL_ADMIN_PASSWORD=<custom-admin-password> docker-compose -f docker-compose-3.x.yml up -d
```
2. Verify the cluster is running:
```bash
curl -sk -u admin:<custom-admin-password> https://localhost:9200
curl -sk -u admin:<custom-admin-password> https://localhost:9200/_cat/plugins?v
```
3. Run the unit tests (no OpenSearch required — uses mocks):
```bash
python -m pytest tests/test_opensearch_storage.py -v
```
4. Run the OpenSearch storage demo against the live cluster:
```bash
export OPENSEARCH_HOSTS=localhost:9200
export OPENSEARCH_USER=admin
export OPENSEARCH_PASSWORD=<custom-admin-password>
export OPENSEARCH_USE_SSL=true
export OPENSEARCH_VERIFY_CERTS=false
python examples/opensearch_storage_demo.py
```
5. Run the full OpenAI + OpenSearch demo (requires `OPENAI_API_KEY`):
```bash
export OPENAI_API_KEY=your-api-key
python examples/lightrag_openai_opensearch_graph_demo.py
```
6. Visualize the knowledge graph via LightRAG WebUI or standalone HTML:
Requires [building front-end artifacts](https://github.com/HKUDS/LightRAG/blob/main/lightrag/api/README.md) before starting LightRAG Server.
```bash
# Starting lightrag-server with OpenSearch Storage
LIGHTRAG_KV_STORAGE=OpenSearchKVStorage \
LIGHTRAG_DOC_STATUS_STORAGE=OpenSearchDocStatusStorage \
LIGHTRAG_GRAPH_STORAGE=OpenSearchGraphStorage \
LIGHTRAG_VECTOR_STORAGE=OpenSearchVectorDBStorage \
LLM_BINDING=openai \
EMBEDDING_BINDING=openai \
EMBEDDING_MODEL=text-embedding-3-large \
EMBEDDING_DIM=3072 \
OPENAI_API_KEY=your-api-key \
lightrag-server
# Display the knowledge graph via LightRAG WebUI
python examples/graph_visual_with_opensearch.py
# Open http://localhost:9621/webui/ -> Knowledge Graph
# Or generate standalone HTML file
python examples/graph_visual_with_opensearch.py --html
```
</details>
### Data Isolation Between LightRAG Instances
The `workspace` parameter ensures data isolation between different LightRAG instances. Once initialized, the `workspace` is immutable and cannot be changed. Here is how workspaces are implemented for different types of storage:
- **For local file-based databases, data isolation is achieved through workspace subdirectories:** `JsonKVStorage`, `JsonDocStatusStorage`, `NetworkXStorage`, `NanoVectorDBStorage`, `FaissVectorDBStorage`.
- **For databases that store data in collections, it's done by adding a workspace prefix to the collection name:** `RedisKVStorage`, `RedisDocStatusStorage`, `MilvusVectorDBStorage`, `MongoKVStorage`, `MongoDocStatusStorage`, `MongoVectorDBStorage`, `MongoGraphStorage`, `PGGraphStorage`.
- **For Qdrant vector database, data isolation is achieved through payload-based partitioning (Qdrant's recommended multitenancy approach):** `QdrantVectorDBStorage` uses shared collections with payload filtering for unlimited workspace scalability.
- **For relational databases, data isolation is achieved by adding a `workspace` field to the tables for logical data separation:** `PGKVStorage`, `PGVectorStorage`, `PGDocStatusStorage`.
- **For the Neo4j graph database, logical data isolation is achieved through labels:** `Neo4JStorage`
- **For OpenSearch, data isolation is achieved through index name prefixes:** `OpenSearchKVStorage`, `OpenSearchDocStatusStorage`, `OpenSearchGraphStorage`, `OpenSearchVectorDBStorage`
To maintain compatibility with legacy data, the default workspace for PostgreSQL non-graph storage is `default` and, for PostgreSQL AGE graph storage is null, for Neo4j graph storage is `base` when no workspace is configured. For all external storages, the system provides dedicated workspace environment variables to override the common `WORKSPACE` environment variable configuration. These storage-specific workspace environment variables are: `REDIS_WORKSPACE`, `MILVUS_WORKSPACE`, `QDRANT_WORKSPACE`, `MONGODB_WORKSPACE`, `POSTGRES_WORKSPACE`, `NEO4J_WORKSPACE`, `OPENSEARCH_WORKSPACE`.
**Usage Example:**
For a practical demonstration of managing multiple isolated knowledge bases (e.g., separating "Book" content from "HR Policies") within a single application, refer to the [Workspace Demo](examples/lightrag_gemini_workspace_demo.py).
### AGENTS.md -- Guiding Coding Agents
AGENTS.md is a simple, open format for guiding coding agents (https://agents.md/). It is a dedicated, predictable place to provide the context and instructions to help AI coding agents work on LightRAG project. Different AI coders should not maintain separate guidance files individually. If any AI coder cannot automatically recognize AGENTS.md, symbolic links can be used as a solution. After establishing symbolic links, you can prevent them from being committed to the Git repository by configuring your local `.gitignore_global`.
## Edit Entities and Relations
LightRAG now supports comprehensive knowledge graph management capabilities, allowing you to create, edit, and delete entities and relationships within your knowledge graph.
<details>
<summary> <b> Create Entities and Relations </b></summary>
```python
# Create new entity
entity = rag.create_entity("Google", {
"description": "Google is a multinational technology company specializing in internet-related services and products.",
"entity_type": "company"
})
# Create another entity
product = rag.create_entity("Gmail", {
"description": "Gmail is an email service developed by Google.",
"entity_type": "product"
})
# Create relation between entities
relation = rag.create_relation("Google", "Gmail", {
"description": "Google develops and operates Gmail.",
"keywords": "develops operates service",
"weight": 2.0
})
```
</details>
<details>
<summary> <b> Edit Entities and Relations </b></summary>
```python
# Edit an existing entity
updated_entity = rag.edit_entity("Google", {
"description": "Google is a subsidiary of Alphabet Inc., founded in 1998.",
"entity_type": "tech_company"
})
# Rename an entity (with all its relationships properly migrated)
renamed_entity = rag.edit_entity("Gmail", {
"entity_name": "Google Mail",
"description": "Google Mail (formerly Gmail) is an email service."
})
# Edit a relation between entities
updated_relation = rag.edit_relation("Google", "Google Mail", {
"description": "Google created and maintains Google Mail service.",
"keywords": "creates maintains email service",
"weight": 3.0
})
```
All operations are available in both synchronous and asynchronous versions. The asynchronous versions have the prefix "a" (e.g., `acreate_entity
gitextract_rq0j1lje/
├── .clinerules/
│ └── 01-basic.md
├── .dockerignore
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.yml
│ │ ├── config.yml
│ │ ├── feature_request.yml
│ │ └── question.yml
│ ├── dependabot.yml
│ ├── pull_request_template.md
│ └── workflows/
│ ├── claude.yml
│ ├── copilot-setup-steps.yml
│ ├── docker-build-lite.yml
│ ├── docker-build-manual.yml
│ ├── docker-publish.yml
│ ├── linting.yaml
│ ├── pypi-publish.yml
│ ├── stale.yaml
│ └── tests.yml
├── .gitignore
├── .pre-commit-config.yaml
├── AGENTS.md
├── Dockerfile
├── Dockerfile.lite
├── LICENSE
├── MANIFEST.in
├── Makefile
├── README-zh.md
├── README.md
├── SECURITY.md
├── config.ini.example
├── docker-build-push.sh
├── docker-compose-full.yml
├── docker-compose.yml
├── docs/
│ ├── Algorithm.md
│ ├── DockerDeployment.md
│ ├── FrontendBuildGuide.md
│ ├── InteractiveSetup.md
│ ├── LightRAG_concurrent_explain.md
│ ├── MilvusConfigurationGuide.md
│ ├── OfflineDeployment.md
│ └── UV_LOCK_GUIDE.md
├── env.example
├── examples/
│ ├── generate_query.py
│ ├── graph_visual_with_html.py
│ ├── graph_visual_with_neo4j.py
│ ├── graph_visual_with_opensearch.py
│ ├── insert_custom_kg.py
│ ├── lightrag_azure_openai_demo.py
│ ├── lightrag_gemini_demo.py
│ ├── lightrag_gemini_postgres_demo.py
│ ├── lightrag_gemini_workspace_demo.py
│ ├── lightrag_ollama_demo.py
│ ├── lightrag_openai_compatible_demo.py
│ ├── lightrag_openai_demo.py
│ ├── lightrag_openai_mongodb_graph_demo.py
│ ├── lightrag_openai_opensearch_graph_demo.py
│ ├── lightrag_vllm_demo.py
│ ├── milvus_kwargs_configuration_demo.py
│ ├── modalprocessors_example.py
│ ├── opensearch_storage_demo.py
│ ├── raganything_example.py
│ ├── rerank_example.py
│ └── unofficial-sample/
│ ├── copy_llm_cache_to_another_storage.py
│ ├── lightrag_bedrock_demo.py
│ ├── lightrag_cloudflare_demo.py
│ ├── lightrag_hf_demo.py
│ ├── lightrag_llamaindex_direct_demo.py
│ ├── lightrag_llamaindex_litellm_demo.py
│ ├── lightrag_llamaindex_litellm_opik_demo.py
│ ├── lightrag_lmdeploy_demo.py
│ ├── lightrag_nvidia_demo.py
│ └── lightrag_openai_neo4j_milvus_redis_demo.py
├── k8s-deploy/
│ ├── README-zh.md
│ ├── README.md
│ ├── databases/
│ │ ├── 00-config.sh
│ │ ├── 01-prepare.sh
│ │ ├── 02-install-database.sh
│ │ ├── 03-uninstall-database.sh
│ │ ├── 04-cleanup.sh
│ │ ├── README.md
│ │ ├── elasticsearch/
│ │ │ └── values.yaml
│ │ ├── install-kubeblocks.sh
│ │ ├── mongodb/
│ │ │ └── values.yaml
│ │ ├── neo4j/
│ │ │ └── values.yaml
│ │ ├── postgresql/
│ │ │ └── values.yaml
│ │ ├── qdrant/
│ │ │ └── values.yaml
│ │ ├── redis/
│ │ │ └── values.yaml
│ │ ├── scripts/
│ │ │ └── common.sh
│ │ └── uninstall-kubeblocks.sh
│ ├── install_lightrag.sh
│ ├── install_lightrag_dev.sh
│ ├── lightrag/
│ │ ├── .helmignore
│ │ ├── Chart.yaml
│ │ ├── templates/
│ │ │ ├── NOTES.txt
│ │ │ ├── _helpers.tpl
│ │ │ ├── deployment.yaml
│ │ │ ├── pvc.yaml
│ │ │ ├── secret.yaml
│ │ │ └── service.yaml
│ │ └── values.yaml
│ ├── uninstall_lightrag.sh
│ └── uninstall_lightrag_dev.sh
├── lightrag/
│ ├── __init__.py
│ ├── api/
│ │ ├── .gitignore
│ │ ├── README-zh.md
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── auth.py
│ │ ├── config.py
│ │ ├── gunicorn_config.py
│ │ ├── lightrag_server.py
│ │ ├── routers/
│ │ │ ├── __init__.py
│ │ │ ├── document_routes.py
│ │ │ ├── graph_routes.py
│ │ │ ├── ollama_api.py
│ │ │ └── query_routes.py
│ │ ├── run_with_gunicorn.py
│ │ ├── runtime_validation.py
│ │ ├── static/
│ │ │ └── swagger-ui/
│ │ │ ├── swagger-ui-bundle.js
│ │ │ └── swagger-ui.css
│ │ └── utils_api.py
│ ├── base.py
│ ├── constants.py
│ ├── evaluation/
│ │ ├── README_EVALUASTION_RAGAS.md
│ │ ├── __init__.py
│ │ ├── eval_rag_quality.py
│ │ ├── sample_dataset.json
│ │ └── sample_documents/
│ │ ├── 01_lightrag_overview.md
│ │ ├── 02_rag_architecture.md
│ │ ├── 03_lightrag_improvements.md
│ │ ├── 04_supported_databases.md
│ │ ├── 05_evaluation_and_deployment.md
│ │ └── README.md
│ ├── exceptions.py
│ ├── kg/
│ │ ├── __init__.py
│ │ ├── deprecated/
│ │ │ └── chroma_impl.py
│ │ ├── faiss_impl.py
│ │ ├── json_doc_status_impl.py
│ │ ├── json_kv_impl.py
│ │ ├── memgraph_impl.py
│ │ ├── milvus_impl.py
│ │ ├── mongo_impl.py
│ │ ├── nano_vector_db_impl.py
│ │ ├── neo4j_impl.py
│ │ ├── networkx_impl.py
│ │ ├── opensearch_impl.py
│ │ ├── postgres_impl.py
│ │ ├── qdrant_impl.py
│ │ ├── redis_impl.py
│ │ └── shared_storage.py
│ ├── lightrag.py
│ ├── llm/
│ │ ├── __init__.py
│ │ ├── anthropic.py
│ │ ├── azure_openai.py
│ │ ├── bedrock.py
│ │ ├── binding_options.py
│ │ ├── deprecated/
│ │ │ └── siliconcloud.py
│ │ ├── gemini.py
│ │ ├── hf.py
│ │ ├── jina.py
│ │ ├── llama_index_impl.py
│ │ ├── lmdeploy.py
│ │ ├── lollms.py
│ │ ├── nvidia_openai.py
│ │ ├── ollama.py
│ │ ├── openai.py
│ │ └── zhipu.py
│ ├── namespace.py
│ ├── operate.py
│ ├── prompt.py
│ ├── rerank.py
│ ├── tools/
│ │ ├── README_CLEAN_LLM_QUERY_CACHE.md
│ │ ├── README_MIGRATE_LLM_CACHE.md
│ │ ├── __init__.py
│ │ ├── check_initialization.py
│ │ ├── clean_llm_query_cache.py
│ │ ├── download_cache.py
│ │ ├── lightrag_visualizer/
│ │ │ ├── README-zh.md
│ │ │ ├── README.md
│ │ │ ├── __init__.py
│ │ │ ├── assets/
│ │ │ │ ├── LICENSE - Geist.txt
│ │ │ │ ├── LICENSE - SmileySans.txt
│ │ │ │ └── place_font_here
│ │ │ ├── graph_visualizer.py
│ │ │ └── requirements.txt
│ │ ├── migrate_llm_cache.py
│ │ └── prepare_qdrant_legacy_data.py
│ ├── types.py
│ ├── utils.py
│ └── utils_graph.py
├── lightrag.service.example
├── lightrag_webui/
│ ├── .gitignore
│ ├── .prettierrc.json
│ ├── README.md
│ ├── components.json
│ ├── env.development.smaple
│ ├── env.local.sample
│ ├── eslint.config.js
│ ├── index.html
│ ├── package.json
│ ├── src/
│ │ ├── App.tsx
│ │ ├── AppRouter.tsx
│ │ ├── api/
│ │ │ └── lightrag.ts
│ │ ├── components/
│ │ │ ├── ApiKeyAlert.tsx
│ │ │ ├── AppSettings.tsx
│ │ │ ├── LanguageToggle.tsx
│ │ │ ├── Root.tsx
│ │ │ ├── ThemeProvider.tsx
│ │ │ ├── ThemeToggle.tsx
│ │ │ ├── documents/
│ │ │ │ ├── ClearDocumentsDialog.tsx
│ │ │ │ ├── DeleteDocumentsDialog.tsx
│ │ │ │ ├── PipelineStatusDialog.tsx
│ │ │ │ └── UploadDocumentsDialog.tsx
│ │ │ ├── graph/
│ │ │ │ ├── EditablePropertyRow.tsx
│ │ │ │ ├── FocusOnNode.tsx
│ │ │ │ ├── FullScreenControl.tsx
│ │ │ │ ├── GraphControl.tsx
│ │ │ │ ├── GraphLabels.tsx
│ │ │ │ ├── GraphSearch.tsx
│ │ │ │ ├── LayoutsControl.tsx
│ │ │ │ ├── Legend.tsx
│ │ │ │ ├── LegendButton.tsx
│ │ │ │ ├── MergeDialog.tsx
│ │ │ │ ├── PropertiesView.tsx
│ │ │ │ ├── PropertyEditDialog.tsx
│ │ │ │ ├── PropertyRowComponents.tsx
│ │ │ │ ├── Settings.tsx
│ │ │ │ ├── SettingsDisplay.tsx
│ │ │ │ └── ZoomControl.tsx
│ │ │ ├── retrieval/
│ │ │ │ ├── ChatMessage.tsx
│ │ │ │ └── QuerySettings.tsx
│ │ │ ├── status/
│ │ │ │ ├── StatusCard.tsx
│ │ │ │ ├── StatusDialog.tsx
│ │ │ │ └── StatusIndicator.tsx
│ │ │ └── ui/
│ │ │ ├── Alert.tsx
│ │ │ ├── AlertDialog.tsx
│ │ │ ├── AsyncSearch.tsx
│ │ │ ├── AsyncSelect.tsx
│ │ │ ├── Badge.tsx
│ │ │ ├── Button.tsx
│ │ │ ├── Card.tsx
│ │ │ ├── Checkbox.tsx
│ │ │ ├── Command.tsx
│ │ │ ├── DataTable.tsx
│ │ │ ├── Dialog.tsx
│ │ │ ├── EmptyCard.tsx
│ │ │ ├── FileUploader.tsx
│ │ │ ├── Input.tsx
│ │ │ ├── NumberInput.tsx
│ │ │ ├── PaginationControls.tsx
│ │ │ ├── Popover.tsx
│ │ │ ├── Progress.tsx
│ │ │ ├── ScrollArea.tsx
│ │ │ ├── Select.tsx
│ │ │ ├── Separator.tsx
│ │ │ ├── TabContent.tsx
│ │ │ ├── Table.tsx
│ │ │ ├── Tabs.tsx
│ │ │ ├── Text.tsx
│ │ │ ├── Textarea.tsx
│ │ │ ├── Tooltip.tsx
│ │ │ └── UserPromptInputWithHistory.tsx
│ │ ├── contexts/
│ │ │ ├── TabVisibilityProvider.tsx
│ │ │ ├── context.ts
│ │ │ ├── types.ts
│ │ │ └── useTabVisibility.ts
│ │ ├── features/
│ │ │ ├── ApiSite.tsx
│ │ │ ├── DocumentManager.tsx
│ │ │ ├── GraphViewer.tsx
│ │ │ ├── LoginPage.tsx
│ │ │ ├── RetrievalTesting.tsx
│ │ │ └── SiteHeader.tsx
│ │ ├── hooks/
│ │ │ ├── useDebounce.tsx
│ │ │ ├── useLightragGraph.tsx
│ │ │ ├── useRandomGraph.tsx
│ │ │ └── useTheme.tsx
│ │ ├── i18n.ts
│ │ ├── index.css
│ │ ├── lib/
│ │ │ ├── constants.ts
│ │ │ ├── extensions.ts
│ │ │ └── utils.ts
│ │ ├── locales/
│ │ │ ├── ar.json
│ │ │ ├── de.json
│ │ │ ├── en.json
│ │ │ ├── fr.json
│ │ │ ├── ja.json
│ │ │ ├── ko.json
│ │ │ ├── ru.json
│ │ │ ├── uk.json
│ │ │ ├── vi.json
│ │ │ ├── zh.json
│ │ │ └── zh_TW.json
│ │ ├── main.tsx
│ │ ├── services/
│ │ │ └── navigation.ts
│ │ ├── stores/
│ │ │ ├── graph.ts
│ │ │ ├── settings.ts
│ │ │ └── state.ts
│ │ ├── types/
│ │ │ └── katex.d.ts
│ │ ├── utils/
│ │ │ ├── SearchHistoryManager.ts
│ │ │ ├── clipboard.ts
│ │ │ ├── graphColor.ts
│ │ │ └── remarkFootnotes.ts
│ │ └── vite-env.d.ts
│ ├── tailwind.config.js
│ ├── tsconfig.json
│ └── vite.config.ts
├── pyproject.toml
├── reproduce/
│ ├── Step_0.py
│ ├── Step_1.py
│ ├── Step_1_openai_compatible.py
│ ├── Step_2.py
│ ├── Step_3.py
│ ├── Step_3_openai_compatible.py
│ └── batch_eval.py
├── requirements-offline-llm.txt
├── requirements-offline-storage.txt
├── requirements-offline.txt
├── scripts/
│ ├── setup/
│ │ ├── lib/
│ │ │ ├── file_ops.sh
│ │ │ ├── presets.sh
│ │ │ ├── prompts.sh
│ │ │ ├── storage_requirements.sh
│ │ │ └── validation.sh
│ │ ├── setup.sh
│ │ └── templates/
│ │ ├── memgraph.yml
│ │ ├── milvus-gpu.yml
│ │ ├── milvus.yml
│ │ ├── mongodb.yml
│ │ ├── neo4j.yml
│ │ ├── opensearch.yml
│ │ ├── postgres.yml
│ │ ├── qdrant-gpu.yml
│ │ ├── qdrant.yml
│ │ ├── redis.conf.template
│ │ ├── redis.yml
│ │ ├── vllm-embed-gpu.yml
│ │ ├── vllm-embed.yml
│ │ ├── vllm-rerank-gpu.yml
│ │ └── vllm-rerank.yml
│ └── test.sh
├── setup.py
└── tests/
├── README_WORKSPACE_ISOLATION_TESTS.md
├── conftest.py
├── test_aquery_data_endpoint.py
├── test_batch_embeddings.py
├── test_chunking.py
├── test_curl_aquery_data.sh
├── test_description_api_validation.py
├── test_dimension_mismatch.py
├── test_doc_status_chunk_preservation.py
├── test_document_file_path_normalization.py
├── test_extract_entities.py
├── test_faiss_meta_inconsistency.py
├── test_graph_storage.py
├── test_interactive_setup_outputs.py
├── test_lightrag_ollama_chat.py
├── test_llm_cache_tools_opensearch.py
├── test_milvus_index_config.py
├── test_milvus_index_creation.py
├── test_milvus_kwargs_bridge.py
├── test_neo4j_fulltext_index.py
├── test_no_model_suffix_safety.py
├── test_opensearch_storage.py
├── test_overlap_validation.py
├── test_postgres_index_name.py
├── test_postgres_migration.py
├── test_postgres_retry_integration.py
├── test_postgres_upsert.py
├── test_qdrant_migration.py
├── test_qdrant_upsert_batching.py
├── test_rerank_chunking.py
├── test_runtime_target_validation.py
├── test_token_auto_renewal.py
├── test_unified_lock_safety.py
├── test_workspace_isolation.py
├── test_workspace_migration_isolation.py
├── test_workspace_sanitization.py
├── test_write_json_optimization.py
└── test_zhipu_llm.py
Showing preview only (569K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (5562 symbols across 185 files)
FILE: examples/generate_query.py
function openai_complete_if_cache (line 6) | def openai_complete_if_cache(
FILE: examples/graph_visual_with_neo4j.py
function xml_to_json (line 17) | def xml_to_json(xml_file):
function convert_xml_to_json (line 77) | def convert_xml_to_json(xml_path, output_path):
function process_in_batches (line 94) | def process_in_batches(tx, query, data, batch_size):
function main (line 101) | def main():
FILE: examples/graph_visual_with_opensearch.py
function fetch_graph (line 49) | def fetch_graph(server_url: str, label: str = "*", max_nodes: int = 300)...
function generate_html (line 58) | def generate_html(graph_data: dict, output_file: str) -> str:
function main (line 113) | def main():
FILE: examples/lightrag_azure_openai_demo.py
function llm_model_func (line 32) | async def llm_model_func(
function embedding_func (line 58) | async def embedding_func(texts: list[str]) -> np.ndarray:
function test_funcs (line 70) | async def test_funcs():
function initialize_rag (line 84) | async def initialize_rag():
function main (line 99) | def main():
FILE: examples/lightrag_gemini_demo.py
function llm_model_func (line 47) | async def llm_model_func(prompt, system_prompt=None, history_messages=[]...
function embedding_func (line 67) | async def embedding_func(texts: list[str]) -> np.ndarray:
function initialize_rag (line 76) | async def initialize_rag():
function main (line 92) | def main():
FILE: examples/lightrag_gemini_postgres_demo.py
function llm_model_func (line 68) | async def llm_model_func(
function embedding_func (line 93) | async def embedding_func(texts: list[str]) -> np.ndarray:
function initialize_rag (line 104) | async def initialize_rag() -> LightRAG:
function main (line 132) | async def main():
FILE: examples/lightrag_gemini_workspace_demo.py
function llm_model_func (line 36) | async def llm_model_func(
function embedding_func (line 53) | async def embedding_func(texts: list[str]) -> np.ndarray:
function initialize_rag (line 60) | async def initialize_rag(
function main (line 96) | async def main():
FILE: examples/lightrag_ollama_demo.py
function configure_logging (line 18) | def configure_logging():
function initialize_rag (line 85) | async def initialize_rag():
function print_stream (line 115) | async def print_stream(stream):
function main (line 120) | async def main():
FILE: examples/lightrag_openai_compatible_demo.py
function configure_logging (line 19) | def configure_logging():
function llm_model_func (line 88) | async def llm_model_func(
function print_stream (line 102) | async def print_stream(stream):
function initialize_rag (line 108) | async def initialize_rag():
function main (line 131) | async def main():
FILE: examples/lightrag_openai_demo.py
function configure_logging (line 12) | def configure_logging():
function initialize_rag (line 79) | async def initialize_rag():
function main (line 91) | async def main():
FILE: examples/lightrag_openai_mongodb_graph_demo.py
function embedding_func (line 28) | async def embedding_func(texts: list[str]) -> np.ndarray:
function get_embedding_dimension (line 39) | async def get_embedding_dimension():
function create_embedding_function_instance (line 45) | async def create_embedding_function_instance():
function initialize_rag (line 56) | async def initialize_rag():
function main (line 71) | def main():
FILE: examples/lightrag_openai_opensearch_graph_demo.py
function embedding_func (line 66) | async def embedding_func(texts: list[str]) -> np.ndarray:
function get_embedding_dimension (line 73) | async def get_embedding_dimension():
function create_embedding_function_instance (line 79) | async def create_embedding_function_instance():
function initialize_rag (line 91) | async def initialize_rag() -> LightRAG:
function main (line 132) | async def main():
FILE: examples/lightrag_vllm_demo.py
function llm_model_func (line 56) | async def llm_model_func(
function initialize_rag (line 110) | async def initialize_rag():
function main (line 132) | async def main():
FILE: examples/milvus_kwargs_configuration_demo.py
function main (line 18) | async def main():
FILE: examples/modalprocessors_example.py
function get_llm_model_func (line 21) | def get_llm_model_func(api_key: str, base_url: str = None):
function get_vision_model_func (line 35) | def get_vision_model_func(api_key: str, base_url: str = None):
function process_image_example (line 84) | async def process_image_example(lightrag: LightRAG, vision_model_func):
function process_table_example (line 111) | async def process_table_example(lightrag: LightRAG, llm_model_func):
function process_equation_example (line 143) | async def process_equation_example(lightrag: LightRAG, llm_model_func):
function initialize_rag (line 166) | async def initialize_rag(api_key: str, base_url: str = None):
function main (line 199) | def main():
function main_async (line 214) | async def main_async(api_key: str, base_url: str = None):
FILE: examples/opensearch_storage_demo.py
class MockEmbeddingFunc (line 34) | class MockEmbeddingFunc:
method __init__ (line 37) | def __init__(self, dim=128):
method __call__ (line 42) | async def __call__(self, texts, **kwargs):
function check (line 56) | def check(condition, msg):
function test_connection_manager (line 66) | async def test_connection_manager():
function test_kv_storage (line 76) | async def test_kv_storage():
function test_doc_status_storage (line 108) | async def test_doc_status_storage():
function test_graph_storage (line 190) | async def test_graph_storage():
function test_vector_storage (line 287) | async def test_vector_storage():
function main (line 328) | async def main():
FILE: examples/raganything_example.py
function configure_logging (line 28) | def configure_logging():
function process_with_rag (line 84) | async def process_with_rag(
function main (line 240) | def main():
FILE: examples/rerank_example.py
function llm_model_func (line 47) | async def llm_model_func(
function embedding_func (line 61) | async def embedding_func(texts: list[str]) -> np.ndarray:
function create_rag_with_rerank (line 80) | async def create_rag_with_rerank():
function test_rerank_with_different_settings (line 105) | async def test_rerank_with_different_settings():
function test_direct_rerank (line 166) | async def test_direct_rerank():
function main (line 203) | async def main():
FILE: examples/unofficial-sample/copy_llm_cache_to_another_storage.py
function copy_from_postgres_to_json (line 39) | async def copy_from_postgres_to_json():
function copy_from_json_to_postgres (line 77) | async def copy_from_json_to_postgres():
FILE: examples/unofficial-sample/lightrag_bedrock_demo.py
function initialize_rag (line 24) | async def initialize_rag():
function main (line 38) | def main():
FILE: examples/unofficial-sample/lightrag_cloudflare_demo.py
class CloudflareWorker (line 36) | class CloudflareWorker:
method __init__ (line 37) | def __init__(
method _send_request (line 53) | async def _send_request(self, model_name: str, input_: dict, debug_log...
method query (line 90) | async def query(self, prompt, system_prompt: str = "", **kwargs) -> str:
method embedding_chunk (line 111) | async def embedding_chunk(self, texts: list[str]) -> np.ndarray:
function configure_logging (line 131) | def configure_logging():
function initialize_rag (line 200) | async def initialize_rag():
function print_stream (line 227) | async def print_stream(stream):
function main (line 232) | async def main():
FILE: examples/unofficial-sample/lightrag_hf_demo.py
function initialize_rag (line 19) | async def initialize_rag():
function main (line 43) | def main():
FILE: examples/unofficial-sample/lightrag_llamaindex_direct_demo.py
function llm_model_func (line 37) | async def llm_model_func(prompt, system_prompt=None, history_messages=[]...
function embedding_func (line 62) | async def embedding_func(texts):
function get_embedding_dim (line 75) | async def get_embedding_dim():
function initialize_rag (line 83) | async def initialize_rag():
function main (line 100) | def main():
FILE: examples/unofficial-sample/lightrag_llamaindex_litellm_demo.py
function llm_model_func (line 38) | async def llm_model_func(prompt, system_prompt=None, history_messages=[]...
function embedding_func (line 63) | async def embedding_func(texts):
function get_embedding_dim (line 77) | async def get_embedding_dim():
function initialize_rag (line 85) | async def initialize_rag():
function main (line 102) | def main():
FILE: examples/unofficial-sample/lightrag_llamaindex_litellm_opik_demo.py
function llm_model_func (line 38) | async def llm_model_func(prompt, system_prompt=None, history_messages=[]...
function embedding_func (line 74) | async def embedding_func(texts):
function get_embedding_dim (line 88) | async def get_embedding_dim():
function initialize_rag (line 96) | async def initialize_rag():
function main (line 113) | def main():
FILE: examples/unofficial-sample/lightrag_lmdeploy_demo.py
function lmdeploy_model_complete (line 20) | async def lmdeploy_model_complete(
function initialize_rag (line 44) | async def initialize_rag():
function main (line 68) | def main():
FILE: examples/unofficial-sample/lightrag_nvidia_demo.py
function llm_model_func (line 32) | async def llm_model_func(
function indexing_embedding_func (line 53) | async def indexing_embedding_func(texts: list[str]) -> np.ndarray:
function query_embedding_func (line 66) | async def query_embedding_func(texts: list[str]) -> np.ndarray:
function get_embedding_dim (line 80) | async def get_embedding_dim():
function test_funcs (line 88) | async def test_funcs():
function initialize_rag (line 99) | async def initialize_rag():
function main (line 121) | async def main():
FILE: examples/unofficial-sample/lightrag_openai_neo4j_milvus_redis_demo.py
function llm_model_func (line 31) | async def llm_model_func(
function initialize_rag (line 54) | async def initialize_rag():
function main (line 72) | def main():
FILE: lightrag/api/auth.py
class TokenPayload (line 16) | class TokenPayload(BaseModel):
class AuthHandler (line 23) | class AuthHandler:
method __init__ (line 24) | def __init__(self):
method create_token (line 36) | def create_token(
method validate_token (line 73) | def validate_token(self, token: str) -> dict:
FILE: lightrag/api/config.py
class DefaultRAGStorageConfig (line 56) | class DefaultRAGStorageConfig:
function get_default_host (line 63) | def get_default_host(binding_type: str) -> str:
function parse_args (line 78) | def parse_args() -> argparse.Namespace:
function update_uvicorn_mode_config (line 479) | def update_uvicorn_mode_config():
function initialize_config (line 495) | def initialize_config(args=None, force=False):
function get_config (line 532) | def get_config():
class _GlobalArgsProxy (line 543) | class _GlobalArgsProxy:
method __getattribute__ (line 554) | def __getattribute__(self, name):
method __setattr__ (line 578) | def __setattr__(self, name, value):
method __repr__ (line 584) | def __repr__(self):
FILE: lightrag/api/gunicorn_config.py
function on_starting (line 95) | def on_starting(server):
function on_exit (line 124) | def on_exit(server):
function post_fork (line 140) | def post_fork(server, worker):
FILE: lightrag/api/lightrag_server.py
class LLMConfigCache (line 85) | class LLMConfigCache:
method __init__ (line 88) | def __init__(self, args):
function check_frontend_build (line 159) | def check_frontend_build():
function create_app (line 288) | def create_app(args):
function get_application (line 1379) | def get_application(args=None):
function configure_logging (line 1386) | def configure_logging():
function check_and_install_dependencies (line 1467) | def check_and_install_dependencies():
function main (line 1483) | def main():
FILE: lightrag/api/routers/document_routes.py
function _is_docling_available (line 36) | def _is_docling_available() -> bool:
function format_datetime (line 54) | def format_datetime(dt: Any) -> Optional[str]:
function normalize_file_path (line 89) | def normalize_file_path(file_path: str | None) -> str:
function sanitize_filename (line 101) | def sanitize_filename(filename: str, input_dir: Path) -> str:
class ScanResponse (line 146) | class ScanResponse(BaseModel):
class ReprocessResponse (line 174) | class ReprocessResponse(BaseModel):
class CancelPipelineResponse (line 203) | class CancelPipelineResponse(BaseModel):
class InsertTextRequest (line 226) | class InsertTextRequest(BaseModel):
method strip_text_after (line 244) | def strip_text_after(cls, text: str) -> str:
method normalize_source_before (line 249) | def normalize_source_before(cls, file_source: Optional[str]) -> str:
class InsertTextsRequest (line 262) | class InsertTextsRequest(BaseModel):
method strip_texts_after (line 280) | def strip_texts_after(cls, texts: list[str]) -> list[str]:
method normalize_sources_before (line 285) | def normalize_sources_before(
class InsertResponse (line 308) | class InsertResponse(BaseModel):
class ClearDocumentsResponse (line 334) | class ClearDocumentsResponse(BaseModel):
class ClearCacheRequest (line 357) | class ClearCacheRequest(BaseModel):
class ClearCacheResponse (line 367) | class ClearCacheResponse(BaseModel):
class DeleteDocRequest (line 406) | class DeleteDocRequest(BaseModel):
method validate_doc_ids (line 419) | def validate_doc_ids(cls, doc_ids: List[str]) -> List[str]:
class DeleteEntityRequest (line 436) | class DeleteEntityRequest(BaseModel):
method validate_entity_name (line 441) | def validate_entity_name(cls, entity_name: str) -> str:
class DeleteRelationRequest (line 447) | class DeleteRelationRequest(BaseModel):
method validate_entity_names (line 453) | def validate_entity_names(cls, entity_name: str) -> str:
class DocStatusResponse (line 459) | class DocStatusResponse(BaseModel):
class DocsStatusesResponse (line 499) | class DocsStatusesResponse(BaseModel):
class TrackStatusResponse (line 566) | class TrackStatusResponse(BaseModel):
class DocumentsRequest (line 609) | class DocumentsRequest(BaseModel):
class PaginationInfo (line 647) | class PaginationInfo(BaseModel):
class PaginatedDocsResponse (line 680) | class PaginatedDocsResponse(BaseModel):
class StatusCountsResponse (line 735) | class StatusCountsResponse(BaseModel):
class PipelineStatusResponse (line 759) | class PipelineStatusResponse(BaseModel):
method parse_job_start (line 790) | def parse_job_start(cls, value):
class DocumentManager (line 797) | class DocumentManager:
method __init__ (line 798) | def __init__(
method scan_directory_for_new_files (line 861) | def scan_directory_for_new_files(self) -> List[Path]:
method mark_as_indexed (line 871) | def mark_as_indexed(self, file_path: Path):
method is_supported_file (line 874) | def is_supported_file(self, filename: str) -> bool:
function validate_file_path_security (line 878) | def validate_file_path_security(file_path_str: str, base_dir: Path) -> O...
function get_unique_filename_in_enqueued (line 932) | def get_unique_filename_in_enqueued(target_dir: Path, original_name: str...
function _convert_with_docling (line 968) | def _convert_with_docling(file_path: Path) -> str:
function _extract_pdf_pypdf (line 984) | def _extract_pdf_pypdf(file_bytes: bytes, password: str = None) -> str:
function _extract_docx (line 1019) | def _extract_docx(file_bytes: bytes) -> str:
function _extract_pptx (line 1098) | def _extract_pptx(file_bytes: bytes) -> str:
function _extract_xlsx (line 1119) | def _extract_xlsx(file_bytes: bytes) -> str:
function pipeline_enqueue_file (line 1228) | async def pipeline_enqueue_file(
function pipeline_index_file (line 1685) | async def pipeline_index_file(rag: LightRAG, file_path: Path, track_id: ...
function pipeline_index_files (line 1705) | async def pipeline_index_files(
function pipeline_index_texts (line 1739) | async def pipeline_index_texts(
function run_scanning_process (line 1774) | async def run_scanning_process(
function background_delete_documents (line 1833) | async def background_delete_documents(
function create_document_routes (line 2083) | def create_document_routes(
FILE: lightrag/api/routers/graph_routes.py
class EntityUpdateRequest (line 16) | class EntityUpdateRequest(BaseModel):
class RelationUpdateRequest (line 23) | class RelationUpdateRequest(BaseModel):
class EntityMergeRequest (line 29) | class EntityMergeRequest(BaseModel):
class EntityCreateRequest (line 44) | class EntityCreateRequest(BaseModel):
class RelationCreateRequest (line 63) | class RelationCreateRequest(BaseModel):
function create_graph_routes (line 89) | def create_graph_routes(rag, api_key: Optional[str] = None):
FILE: lightrag/api/routers/ollama_api.py
class SearchMode (line 18) | class SearchMode(str, Enum):
class OllamaMessage (line 28) | class OllamaMessage(BaseModel):
class OllamaChatRequest (line 34) | class OllamaChatRequest(BaseModel):
class OllamaChatResponse (line 42) | class OllamaChatResponse(BaseModel):
class OllamaGenerateRequest (line 49) | class OllamaGenerateRequest(BaseModel):
class OllamaGenerateResponse (line 57) | class OllamaGenerateResponse(BaseModel):
class OllamaVersionResponse (line 71) | class OllamaVersionResponse(BaseModel):
class OllamaModelDetails (line 75) | class OllamaModelDetails(BaseModel):
class OllamaModel (line 84) | class OllamaModel(BaseModel):
class OllamaTagResponse (line 93) | class OllamaTagResponse(BaseModel):
class OllamaRunningModelDetails (line 97) | class OllamaRunningModelDetails(BaseModel):
class OllamaRunningModel (line 106) | class OllamaRunningModel(BaseModel):
class OllamaPsResponse (line 116) | class OllamaPsResponse(BaseModel):
function parse_request_body (line 120) | async def parse_request_body(
function estimate_tokens (line 159) | def estimate_tokens(text: str) -> int:
function parse_query_mode (line 165) | def parse_query_mode(query: str) -> tuple[str, SearchMode, bool, Optiona...
class OllamaAPI (line 220) | class OllamaAPI:
method __init__ (line 221) | def __init__(self, rag: LightRAG, top_k: int = 60, api_key: Optional[s...
method setup_routes (line 229) | def setup_routes(self):
FILE: lightrag/api/routers/query_routes.py
class QueryRequest (line 16) | class QueryRequest(BaseModel):
method query_strip_after (line 115) | def query_strip_after(cls, query: str) -> str:
method conversation_history_role_check (line 120) | def conversation_history_role_check(
method to_query_params (line 132) | def to_query_params(self, is_stream: bool) -> "QueryParam":
class ReferenceItem (line 146) | class ReferenceItem(BaseModel):
class QueryResponse (line 157) | class QueryResponse(BaseModel):
class QueryDataResponse (line 167) | class QueryDataResponse(BaseModel):
class StreamChunkResponse (line 178) | class StreamChunkResponse(BaseModel):
function create_query_routes (line 193) | def create_query_routes(rag, api_key: Optional[str] = None, top_k: int =...
FILE: lightrag/api/run_with_gunicorn.py
function check_and_install_dependencies (line 21) | def check_and_install_dependencies():
function main (line 37) | def main():
FILE: lightrag/api/runtime_validation.py
class RuntimeEnvironment (line 15) | class RuntimeEnvironment:
method label (line 23) | def label(self) -> str:
function _read_cgroup_content (line 31) | def _read_cgroup_content() -> str:
function detect_runtime_environment (line 42) | def detect_runtime_environment(
function load_runtime_target_from_env_file (line 72) | def load_runtime_target_from_env_file(env_path: str | Path = ".env") -> ...
function validate_runtime_target (line 82) | def validate_runtime_target(
function validate_runtime_target_from_env_file (line 121) | def validate_runtime_target_from_env_file(
FILE: lightrag/api/static/swagger-ui/swagger-ui-bundle.js
function getPropType (line 2) | function getPropType(s){var o=typeof s;return Array.isArray(s)?"array":s...
function createChainableTypeChecker (line 2) | function createChainableTypeChecker(s){function checkType(o,i,a,u,_,w){f...
function createIterableSubclassTypeChecker (line 2) | function createIterableSubclassTypeChecker(s,o){return function createIm...
function emptyFunction (line 2) | function emptyFunction(){}
function emptyFunctionWithReset (line 2) | function emptyFunctionWithReset(){}
function shim (line 2) | function shim(s,o,i,u,_,w){if(w!==a){var x=new Error("Calling PropTypes ...
function getShim (line 2) | function getShim(){return shim}
function _defineProperty (line 2) | function _defineProperty(s,o,i){return(o=function _toPropertyKey(s){var ...
function createIterResult (line 2) | function createIterResult(s,o){return{value:s,done:o}}
function readAndResolve (line 2) | function readAndResolve(s){var o=s[w];if(null!==o){var i=s[$].read();nul...
function onReadable (line 2) | function onReadable(s){u.nextTick(readAndResolve,s)}
method stream (line 2) | get stream(){return this[$]}
class Namespace (line 2) | class Namespace{constructor(s){this.elementMap={},this.elementDetection=...
method constructor (line 2) | constructor(s){this.elementMap={},this.elementDetection=[],this.Elemen...
method use (line 2) | use(s){return s.namespace&&s.namespace({base:this}),s.load&&s.load({ba...
method useDefault (line 2) | useDefault(){return this.register("null",j.NullElement).register("stri...
method register (line 2) | register(s,o){return this._elements=void 0,this.elementMap[s]=o,this}
method unregister (line 2) | unregister(s){return this._elements=void 0,delete this.elementMap[s],t...
method detect (line 2) | detect(s,o,i){return void 0===i||i?this.elementDetection.unshift([s,o]...
method toElement (line 2) | toElement(s){if(s instanceof this.Element)return s;let o;for(let i=0;i...
method getElementClass (line 2) | getElementClass(s){const o=this.elementMap[s];return void 0===o?this.E...
method fromRefract (line 2) | fromRefract(s){return this.serialiser.deserialise(s)}
method toRefract (line 2) | toRefract(s){return this.serialiser.serialise(s)}
method elements (line 2) | get elements(){return void 0===this._elements&&(this._elements={Elemen...
method serialiser (line 2) | get serialiser(){return new C(this)}
method constructor (line 2) | constructor(){super(),this.register("annotation",ku),this.register("co...
class ArrayElement (line 2) | class ArrayElement extends u{constructor(s,o,i){super(s||[],o,i),this.el...
method constructor (line 2) | constructor(s,o,i){super(s||[],o,i),this.element="array"}
method primitive (line 2) | primitive(){return"array"}
method get (line 2) | get(s){return this.content[s]}
method getValue (line 2) | getValue(s){const o=this.get(s);if(o)return o.toValue()}
method getIndex (line 2) | getIndex(s){return this.content[s]}
method set (line 2) | set(s,o){return this.content[s]=this.refract(o),this}
method remove (line 2) | remove(s){const o=this.content.splice(s,1);return o.length?o[0]:null}
method map (line 2) | map(s,o){return this.content.map(s,o)}
method flatMap (line 2) | flatMap(s,o){return this.map(s,o).reduce(((s,o)=>s.concat(o)),[])}
method compactMap (line 2) | compactMap(s,o){const i=[];return this.forEach((a=>{const u=s.bind(o)(...
method filter (line 2) | filter(s,o){return new _(this.content.filter(s,o))}
method reject (line 2) | reject(s,o){return this.filter(a(s),o)}
method reduce (line 2) | reduce(s,o){let i,a;void 0!==o?(i=0,a=this.refract(o)):(i=1,a="object"...
method forEach (line 2) | forEach(s,o){this.content.forEach(((i,a)=>{s.bind(o)(i,this.refract(a)...
method shift (line 2) | shift(){return this.content.shift()}
method unshift (line 2) | unshift(s){this.content.unshift(this.refract(s))}
method push (line 2) | push(s){return this.content.push(this.refract(s)),this}
method add (line 2) | add(s){this.push(s)}
method findElements (line 2) | findElements(s,o){const i=o||{},a=!!i.recursive,u=void 0===i.results?[...
method find (line 2) | find(s){return new _(this.findElements(s,{recursive:!0}))}
method findByElement (line 2) | findByElement(s){return this.find((o=>o.element===s))}
method findByClass (line 2) | findByClass(s){return this.find((o=>o.classes.includes(s)))}
method getById (line 2) | getById(s){return this.find((o=>o.id.toValue()===s)).first}
method includes (line 2) | includes(s){return this.content.some((o=>o.equals(s)))}
method contains (line 2) | contains(s){return this.includes(s)}
method empty (line 2) | empty(){return new this.constructor([])}
method "fantasy-land/empty" (line 2) | "fantasy-land/empty"(){return this.empty()}
method concat (line 2) | concat(s){return new this.constructor(this.content.concat(s.content))}
method "fantasy-land/concat" (line 2) | "fantasy-land/concat"(s){return this.concat(s)}
method "fantasy-land/map" (line 2) | "fantasy-land/map"(s){return new this.constructor(this.map(s))}
method "fantasy-land/chain" (line 2) | "fantasy-land/chain"(s){return this.map((o=>s(o)),this).reduce(((s,o)=...
method "fantasy-land/filter" (line 2) | "fantasy-land/filter"(s){return new this.constructor(this.content.filt...
method "fantasy-land/reduce" (line 2) | "fantasy-land/reduce"(s,o){return this.content.reduce(s,o)}
method length (line 2) | get length(){return this.content.length}
method isEmpty (line 2) | get isEmpty(){return 0===this.content.length}
method first (line 2) | get first(){return this.getIndex(0)}
method second (line 2) | get second(){return this.getIndex(1)}
method last (line 2) | get last(){return this.getIndex(this.length-1)}
function _extends (line 2) | function _extends(){var o;return s.exports=_extends=a?u(o=a).call(o):fun...
method constructor (line 2) | constructor(s={}){__publicField(this,"counter"),__publicField(this,"debu...
function createClass (line 2) | function createClass(s,o){o&&(s.prototype=Object.create(o.prototype)),s....
function Iterable (line 2) | function Iterable(s){return isIterable(s)?s:Seq(s)}
function KeyedIterable (line 2) | function KeyedIterable(s){return isKeyed(s)?s:KeyedSeq(s)}
function IndexedIterable (line 2) | function IndexedIterable(s){return isIndexed(s)?s:IndexedSeq(s)}
function SetIterable (line 2) | function SetIterable(s){return isIterable(s)&&!isAssociative(s)?s:SetSeq...
function isIterable (line 2) | function isIterable(s){return!(!s||!s[o])}
function isKeyed (line 2) | function isKeyed(s){return!(!s||!s[i])}
function isIndexed (line 2) | function isIndexed(s){return!(!s||!s[a])}
function isAssociative (line 2) | function isAssociative(s){return isKeyed(s)||isIndexed(s)}
function isOrdered (line 2) | function isOrdered(s){return!(!s||!s[u])}
function MakeRef (line 2) | function MakeRef(s){return s.value=!1,s}
function SetRef (line 2) | function SetRef(s){s&&(s.value=!0)}
function OwnerID (line 2) | function OwnerID(){}
function arrCopy (line 2) | function arrCopy(s,o){o=o||0;for(var i=Math.max(0,s.length-o),a=new Arra...
function ensureSize (line 2) | function ensureSize(s){return void 0===s.size&&(s.size=s.__iterate(retur...
function wrapIndex (line 2) | function wrapIndex(s,o){if("number"!=typeof o){var i=o>>>0;if(""+i!==o||...
function returnTrue (line 2) | function returnTrue(){return!0}
function wholeSlice (line 2) | function wholeSlice(s,o,i){return(0===s||void 0!==i&&s<=-i)&&(void 0===o...
function resolveBegin (line 2) | function resolveBegin(s,o){return resolveIndex(s,o,0)}
function resolveEnd (line 2) | function resolveEnd(s,o){return resolveIndex(s,o,o)}
function resolveIndex (line 2) | function resolveIndex(s,o,i){return void 0===s?i:s<0?Math.max(0,o+s):voi...
function Iterator (line 2) | function Iterator(s){this.next=s}
function iteratorValue (line 2) | function iteratorValue(s,o,i,a){var u=0===s?o:1===s?i:[o,i];return a?a.v...
function iteratorDone (line 2) | function iteratorDone(){return{value:void 0,done:!0}}
function hasIterator (line 2) | function hasIterator(s){return!!getIteratorFn(s)}
function isIterator (line 2) | function isIterator(s){return s&&"function"==typeof s.next}
function getIterator (line 2) | function getIterator(s){var o=getIteratorFn(s);return o&&o.call(s)}
function getIteratorFn (line 2) | function getIteratorFn(s){var o=s&&(z&&s[z]||s[Y]);if("function"==typeof...
function isArrayLike (line 2) | function isArrayLike(s){return s&&"number"==typeof s.length}
function Seq (line 2) | function Seq(s){return null==s?emptySequence():isIterable(s)?s.toSeq():s...
function KeyedSeq (line 2) | function KeyedSeq(s){return null==s?emptySequence().toKeyedSeq():isItera...
function IndexedSeq (line 2) | function IndexedSeq(s){return null==s?emptySequence():isIterable(s)?isKe...
function SetSeq (line 2) | function SetSeq(s){return(null==s?emptySequence():isIterable(s)?isKeyed(...
function ArraySeq (line 2) | function ArraySeq(s){this._array=s,this.size=s.length}
function ObjectSeq (line 2) | function ObjectSeq(s){var o=Object.keys(s);this._object=s,this._keys=o,t...
function IterableSeq (line 2) | function IterableSeq(s){this._iterable=s,this.size=s.length||s.size}
function IteratorSeq (line 2) | function IteratorSeq(s){this._iterator=s,this._iteratorCache=[]}
function isSeq (line 2) | function isSeq(s){return!(!s||!s[ce])}
function emptySequence (line 2) | function emptySequence(){return ee||(ee=new ArraySeq([]))}
function keyedSeqFromValue (line 2) | function keyedSeqFromValue(s){var o=Array.isArray(s)?new ArraySeq(s).fro...
function indexedSeqFromValue (line 2) | function indexedSeqFromValue(s){var o=maybeIndexedSeqFromValue(s);if(!o)...
function seqFromValue (line 2) | function seqFromValue(s){var o=maybeIndexedSeqFromValue(s)||"object"==ty...
function maybeIndexedSeqFromValue (line 2) | function maybeIndexedSeqFromValue(s){return isArrayLike(s)?new ArraySeq(...
function seqIterate (line 2) | function seqIterate(s,o,i,a){var u=s._cache;if(u){for(var _=u.length-1,w...
function seqIterator (line 2) | function seqIterator(s,o,i,a){var u=s._cache;if(u){var _=u.length-1,w=0;...
function fromJS (line 2) | function fromJS(s,o){return o?fromJSWith(o,s,"",{"":s}):fromJSDefault(s)}
function fromJSWith (line 2) | function fromJSWith(s,o,i,a){return Array.isArray(o)?s.call(a,i,IndexedS...
function fromJSDefault (line 2) | function fromJSDefault(s){return Array.isArray(s)?IndexedSeq(s).map(from...
function isPlainObj (line 2) | function isPlainObj(s){return s&&(s.constructor===Object||void 0===s.con...
function is (line 2) | function is(s,o){if(s===o||s!=s&&o!=o)return!0;if(!s||!o)return!1;if("fu...
function deepEqual (line 2) | function deepEqual(s,o){if(s===o)return!0;if(!isIterable(o)||void 0!==s....
function Repeat (line 2) | function Repeat(s,o){if(!(this instanceof Repeat))return new Repeat(s,o)...
function invariant (line 2) | function invariant(s,o){if(!s)throw new Error(o)}
function Range (line 2) | function Range(s,o,i){if(!(this instanceof Range))return new Range(s,o,i...
function Collection (line 2) | function Collection(){throw TypeError("Abstract")}
function KeyedCollection (line 2) | function KeyedCollection(){}
function IndexedCollection (line 2) | function IndexedCollection(){}
function SetCollection (line 2) | function SetCollection(){}
function smi (line 2) | function smi(s){return s>>>1&1073741824|3221225471&s}
function hash (line 2) | function hash(s){if(!1===s||null==s)return 0;if("function"==typeof s.val...
function cachedHashString (line 2) | function cachedHashString(s){var o=Pe[s];return void 0===o&&(o=hashStrin...
function hashString (line 2) | function hashString(s){for(var o=0,i=0;i<s.length;i++)o=31*o+s.charCodeA...
function hashJSObj (line 2) | function hashJSObj(s){var o;if(ye&&void 0!==(o=fe.get(s)))return o;if(vo...
function getIENodeHash (line 2) | function getIENodeHash(s){if(s&&s.nodeType>0)switch(s.nodeType){case 1:r...
function assertNotInfinite (line 2) | function assertNotInfinite(s){invariant(s!==1/0,"Cannot perform this act...
function Map (line 2) | function Map(s){return null==s?emptyMap():isMap(s)&&!isOrdered(s)?s:empt...
function isMap (line 2) | function isMap(s){return!(!s||!s[Re])}
function ArrayMapNode (line 2) | function ArrayMapNode(s,o){this.ownerID=s,this.entries=o}
function BitmapIndexedNode (line 2) | function BitmapIndexedNode(s,o,i){this.ownerID=s,this.bitmap=o,this.node...
function HashArrayMapNode (line 2) | function HashArrayMapNode(s,o,i){this.ownerID=s,this.count=o,this.nodes=i}
function HashCollisionNode (line 2) | function HashCollisionNode(s,o,i){this.ownerID=s,this.keyHash=o,this.ent...
function ValueNode (line 2) | function ValueNode(s,o,i){this.ownerID=s,this.keyHash=o,this.entry=i}
function MapIterator (line 2) | function MapIterator(s,o,i){this._type=o,this._reverse=i,this._stack=s._...
function mapIteratorValue (line 2) | function mapIteratorValue(s,o){return iteratorValue(s,o[0],o[1])}
function mapIteratorFrame (line 2) | function mapIteratorFrame(s,o){return{node:s,index:0,__prev:o}}
function makeMap (line 2) | function makeMap(s,o,i,a){var u=Object.create($e);return u.size=s,u._roo...
function emptyMap (line 2) | function emptyMap(){return Te||(Te=makeMap(0))}
function updateMap (line 2) | function updateMap(s,o,i){var a,u;if(s._root){var _=MakeRef(L),w=MakeRef...
function updateNode (line 2) | function updateNode(s,o,i,a,u,_,w,x){return s?s.update(o,i,a,u,_,w,x):_=...
function isLeafNode (line 2) | function isLeafNode(s){return s.constructor===ValueNode||s.constructor==...
function mergeIntoNode (line 2) | function mergeIntoNode(s,o,i,a,u){if(s.keyHash===a)return new HashCollis...
function createNodes (line 2) | function createNodes(s,o,i,a){s||(s=new OwnerID);for(var u=new ValueNode...
function packNodes (line 2) | function packNodes(s,o,i,a){for(var u=0,_=0,w=new Array(i),x=0,C=1,j=o.l...
function expandNodes (line 2) | function expandNodes(s,o,i,a,u){for(var _=0,w=new Array(x),C=0;0!==i;C++...
function mergeIntoMapWith (line 2) | function mergeIntoMapWith(s,o,i){for(var a=[],u=0;u<i.length;u++){var _=...
function deepMerger (line 2) | function deepMerger(s,o,i){return s&&s.mergeDeep&&isIterable(o)?s.mergeD...
function deepMergerWith (line 2) | function deepMergerWith(s){return function(o,i,a){if(o&&o.mergeDeepWith&...
function mergeIntoCollectionWith (line 2) | function mergeIntoCollectionWith(s,o,i){return 0===(i=i.filter((function...
function updateInDeepMap (line 2) | function updateInDeepMap(s,o,i,a){var u=s===j,_=o.next();if(_.done){var ...
function popCount (line 2) | function popCount(s){return s=(s=(858993459&(s-=s>>1&1431655765))+(s>>2&...
function setIn (line 2) | function setIn(s,o,i,a){var u=a?s:arrCopy(s);return u[o]=i,u}
function spliceIn (line 2) | function spliceIn(s,o,i,a){var u=s.length+1;if(a&&o+1===u)return s[o]=i,...
function spliceOut (line 2) | function spliceOut(s,o,i){var a=s.length-1;if(i&&o===a)return s.pop(),s;...
function List (line 2) | function List(s){var o=emptyList();if(null==s)return o;if(isList(s))retu...
function isList (line 2) | function isList(s){return!(!s||!s[He])}
function VNode (line 2) | function VNode(s,o){this.array=s,this.ownerID=o}
function iterateList (line 2) | function iterateList(s,o){var i=s._origin,a=s._capacity,u=getTailOffset(...
function makeList (line 2) | function makeList(s,o,i,a,u,_,w){var x=Object.create(Ye);return x.size=o...
function emptyList (line 2) | function emptyList(){return Xe||(Xe=makeList(0,0,w))}
function updateList (line 2) | function updateList(s,o,i){if((o=wrapIndex(s,o))!=o)return s;if(o>=s.siz...
function updateVNode (line 2) | function updateVNode(s,o,i,a,u,_){var x,j=a>>>i&C,L=s&&j<s.array.length;...
function editableVNode (line 2) | function editableVNode(s,o){return o&&s&&o===s.ownerID?s:new VNode(s?s.a...
function listNodeFor (line 2) | function listNodeFor(s,o){if(o>=getTailOffset(s._capacity))return s._tai...
function setListBounds (line 2) | function setListBounds(s,o,i){void 0!==o&&(o|=0),void 0!==i&&(i|=0);var ...
function mergeIntoListWith (line 2) | function mergeIntoListWith(s,o,i){for(var a=[],u=0,_=0;_<i.length;_++){v...
function getTailOffset (line 2) | function getTailOffset(s){return s<x?0:s-1>>>w<<w}
function OrderedMap (line 2) | function OrderedMap(s){return null==s?emptyOrderedMap():isOrderedMap(s)?...
function isOrderedMap (line 2) | function isOrderedMap(s){return isMap(s)&&isOrdered(s)}
function makeOrderedMap (line 2) | function makeOrderedMap(s,o,i,a){var u=Object.create(OrderedMap.prototyp...
function emptyOrderedMap (line 2) | function emptyOrderedMap(){return Qe||(Qe=makeOrderedMap(emptyMap(),empt...
function updateOrderedMap (line 2) | function updateOrderedMap(s,o,i){var a,u,_=s._map,w=s._list,C=_.get(o),L...
function ToKeyedSequence (line 2) | function ToKeyedSequence(s,o){this._iter=s,this._useKeys=o,this.size=s.s...
function ToIndexedSequence (line 2) | function ToIndexedSequence(s){this._iter=s,this.size=s.size}
function ToSetSequence (line 2) | function ToSetSequence(s){this._iter=s,this.size=s.size}
function FromEntriesSequence (line 2) | function FromEntriesSequence(s){this._iter=s,this.size=s.size}
function flipFactory (line 2) | function flipFactory(s){var o=makeSequence(s);return o._iter=s,o.size=s....
function mapFactory (line 2) | function mapFactory(s,o,i){var a=makeSequence(s);return a.size=s.size,a....
function reverseFactory (line 2) | function reverseFactory(s,o){var i=makeSequence(s);return i._iter=s,i.si...
function filterFactory (line 2) | function filterFactory(s,o,i,a){var u=makeSequence(s);return a&&(u.has=f...
function countByFactory (line 2) | function countByFactory(s,o,i){var a=Map().asMutable();return s.__iterat...
function groupByFactory (line 2) | function groupByFactory(s,o,i){var a=isKeyed(s),u=(isOrdered(s)?OrderedM...
function sliceFactory (line 2) | function sliceFactory(s,o,i,a){var u=s.size;if(void 0!==o&&(o|=0),void 0...
function takeWhileFactory (line 2) | function takeWhileFactory(s,o,i){var a=makeSequence(s);return a.__iterat...
function skipWhileFactory (line 2) | function skipWhileFactory(s,o,i,a){var u=makeSequence(s);return u.__iter...
function concatFactory (line 2) | function concatFactory(s,o){var i=isKeyed(s),a=[s].concat(o).map((functi...
function flattenFactory (line 2) | function flattenFactory(s,o,i){var a=makeSequence(s);return a.__iterateU...
function flatMapFactory (line 2) | function flatMapFactory(s,o,i){var a=iterableClass(s);return s.toSeq().m...
function interposeFactory (line 2) | function interposeFactory(s,o){var i=makeSequence(s);return i.size=s.siz...
function sortFactory (line 2) | function sortFactory(s,o,i){o||(o=defaultComparator);var a=isKeyed(s),u=...
function maxFactory (line 2) | function maxFactory(s,o,i){if(o||(o=defaultComparator),i){var a=s.toSeq(...
function maxCompare (line 2) | function maxCompare(s,o,i){var a=s(i,o);return 0===a&&i!==o&&(null==i||i...
function zipWithFactory (line 2) | function zipWithFactory(s,o,i){var a=makeSequence(s);return a.size=new A...
function reify (line 2) | function reify(s,o){return isSeq(s)?o:s.constructor(o)}
function validateEntry (line 2) | function validateEntry(s){if(s!==Object(s))throw new TypeError("Expected...
function resolveSize (line 2) | function resolveSize(s){return assertNotInfinite(s.size),ensureSize(s)}
function iterableClass (line 2) | function iterableClass(s){return isKeyed(s)?KeyedIterable:isIndexed(s)?I...
function makeSequence (line 2) | function makeSequence(s){return Object.create((isKeyed(s)?KeyedSeq:isInd...
function cacheResultThrough (line 2) | function cacheResultThrough(){return this._iter.cacheResult?(this._iter....
function defaultComparator (line 2) | function defaultComparator(s,o){return s>o?1:s<o?-1:0}
function forceIterator (line 2) | function forceIterator(s){var o=getIterator(s);if(!o){if(!isArrayLike(s)...
function Record (line 2) | function Record(s,o){var i,a=function Record(_){if(_ instanceof a)return...
function makeRecord (line 2) | function makeRecord(s,o,i){var a=Object.create(Object.getPrototypeOf(s))...
function recordName (line 2) | function recordName(s){return s._name||s.constructor.name||"Record"}
function setProps (line 2) | function setProps(s,o){try{o.forEach(setProp.bind(void 0,s))}catch(s){}}
function setProp (line 2) | function setProp(s,o){Object.defineProperty(s,o,{get:function(){return t...
function Set (line 2) | function Set(s){return null==s?emptySet():isSet(s)&&!isOrdered(s)?s:empt...
function isSet (line 2) | function isSet(s){return!(!s||!s[nt])}
function updateSet (line 2) | function updateSet(s,o){return s.__ownerID?(s.size=o.size,s._map=o,s):o=...
function makeSet (line 2) | function makeSet(s,o){var i=Object.create(st);return i.size=s?s.size:0,i...
function emptySet (line 2) | function emptySet(){return rt||(rt=makeSet(emptyMap()))}
function OrderedSet (line 2) | function OrderedSet(s){return null==s?emptyOrderedSet():isOrderedSet(s)?...
function isOrderedSet (line 2) | function isOrderedSet(s){return isSet(s)&&isOrdered(s)}
function makeOrderedSet (line 2) | function makeOrderedSet(s,o){var i=Object.create(it);return i.size=s?s.s...
function emptyOrderedSet (line 2) | function emptyOrderedSet(){return ot||(ot=makeOrderedSet(emptyOrderedMap...
function Stack (line 2) | function Stack(s){return null==s?emptyStack():isStack(s)?s:emptyStack()....
function isStack (line 2) | function isStack(s){return!(!s||!s[ct])}
function makeStack (line 2) | function makeStack(s,o,i,a){var u=Object.create(lt);return u.size=s,u._h...
function emptyStack (line 2) | function emptyStack(){return at||(at=makeStack(0))}
function mixin (line 2) | function mixin(s,o){var keyCopier=function(i){s.prototype[i]=o[i]};retur...
function keyMapper (line 2) | function keyMapper(s,o){return o}
function entryMapper (line 2) | function entryMapper(s,o){return[o,s]}
function not (line 2) | function not(s){return function(){return!s.apply(this,arguments)}}
function neg (line 2) | function neg(s){return function(){return-s.apply(this,arguments)}}
function quoteString (line 2) | function quoteString(s){return"string"==typeof s?JSON.stringify(s):Strin...
function defaultZipper (line 2) | function defaultZipper(){return arrCopy(arguments)}
function defaultNegComparator (line 2) | function defaultNegComparator(s,o){return s<o?1:s>o?-1:0}
function hashIterable (line 2) | function hashIterable(s){if(s.size===1/0)return 0;var o=isOrdered(s),i=i...
function murmurHashOfSize (line 2) | function murmurHashOfSize(s,o){return o=le(o,3432918353),o=le(o<<15|o>>>...
function hashMerge (line 2) | function hashMerge(s,o){return s^o+2654435769+(s<<6)+(s>>2)}
class Element (line 2) | class Element{constructor(s,o,i){o&&(this.meta=o),i&&(this.attributes=i)...
method constructor (line 2) | constructor(s,o,i){o&&(this.meta=o),i&&(this.attributes=i),this.conten...
method freeze (line 2) | freeze(){Object.isFrozen(this)||(this._meta&&(this.meta.parent=this,th...
method primitive (line 2) | primitive(){}
method clone (line 2) | clone(){const s=new this.constructor;return s.element=this.element,thi...
method toValue (line 2) | toValue(){return this.content instanceof Element?this.content.toValue(...
method toRef (line 2) | toRef(s){if(""===this.id.toValue())throw Error("Cannot create referenc...
method findRecursive (line 2) | findRecursive(...s){if(arguments.length>1&&!this.isFrozen)throw new Er...
method set (line 2) | set(s){return this.content=s,this}
method equals (line 2) | equals(s){return a(this.toValue(),s)}
method getMetaProperty (line 2) | getMetaProperty(s,o){if(!this.meta.hasKey(s)){if(this.isFrozen){const ...
method setMetaProperty (line 2) | setMetaProperty(s,o){this.meta.set(s,o)}
method element (line 2) | get element(){return this._storedElement||"element"}
method element (line 2) | set element(s){this._storedElement=s}
method content (line 2) | get content(){return this._content}
method content (line 2) | set content(s){if(s instanceof Element)this._content=s;else if(s insta...
method meta (line 2) | get meta(){if(!this._meta){if(this.isFrozen){const s=new this.ObjectEl...
method meta (line 2) | set meta(s){s instanceof this.ObjectElement?this._meta=s:this.meta.set...
method attributes (line 2) | get attributes(){if(!this._attributes){if(this.isFrozen){const s=new t...
method attributes (line 2) | set attributes(s){s instanceof this.ObjectElement?this._attributes=s:t...
method id (line 2) | get id(){return this.getMetaProperty("id","")}
method id (line 2) | set id(s){this.setMetaProperty("id",s)}
method classes (line 2) | get classes(){return this.getMetaProperty("classes",[])}
method classes (line 2) | set classes(s){this.setMetaProperty("classes",s)}
method title (line 2) | get title(){return this.getMetaProperty("title","")}
method title (line 2) | set title(s){this.setMetaProperty("title",s)}
method description (line 2) | get description(){return this.getMetaProperty("description","")}
method description (line 2) | set description(s){this.setMetaProperty("description",s)}
method links (line 2) | get links(){return this.getMetaProperty("links",[])}
method links (line 2) | set links(s){this.setMetaProperty("links",s)}
method isFrozen (line 2) | get isFrozen(){return Object.isFrozen(this)}
method parents (line 2) | get parents(){let{parent:s}=this;const o=new _;for(;s;)o.push(s),s=s.p...
method children (line 2) | get children(){if(Array.isArray(this.content))return new _(this.conten...
method recursiveChildren (line 2) | get recursiveChildren(){const s=new _;return this.children.forEach((o=...
class ObjectSlice (line 2) | class ObjectSlice extends u{map(s,o){return this.elements.map((i=>s.bind...
method map (line 2) | map(s,o){return this.elements.map((i=>s.bind(o)(i.value,i.key,i)))}
method filter (line 2) | filter(s,o){return new ObjectSlice(this.elements.filter((i=>s.bind(o)(...
method reject (line 2) | reject(s,o){return this.filter(a(s.bind(o)))}
method forEach (line 2) | forEach(s,o){return this.elements.forEach(((i,a)=>{s.bind(o)(i.value,i...
method keys (line 2) | keys(){return this.map(((s,o)=>o.toValue()))}
method values (line 2) | values(){return this.map((s=>s.toValue()))}
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="boolean"}
method primitive (line 2) | primitive(){return"boolean"}
method constructor (line 2) | constructor(s,o,i){super(s||[],o,i),this.element="ref",this.path||(this....
method path (line 2) | get path(){return this.attributes.get("path")}
method path (line 2) | set path(s){this.attributes.set("path",s)}
function cloneUnlessOtherwiseSpecified (line 2) | function cloneUnlessOtherwiseSpecified(s,o){return!1!==o.clone&&o.isMerg...
function defaultArrayMerge (line 2) | function defaultArrayMerge(s,o,i){return s.concat(o).map((function(s){re...
function getKeys (line 2) | function getKeys(s){return Object.keys(s).concat(function getEnumerableO...
function propertyIsOnObject (line 2) | function propertyIsOnObject(s,o){try{return o in s}catch(s){return!1}}
function mergeObject (line 2) | function mergeObject(s,o,i){var a={};return i.isMergeableObject(s)&&getK...
function deepmerge (line 2) | function deepmerge(s,i,a){(a=a||{}).arrayMerge=a.arrayMerge||defaultArra...
function E (line 2) | function E(s,o,i){this.props=s,this.context=o,this.refs=Y,this.updater=i...
function F (line 2) | function F(){}
function G (line 2) | function G(s,o,i){this.props=s,this.context=o,this.refs=Y,this.updater=i...
function M (line 2) | function M(s,o,a){var u,_={},w=null,x=null;if(null!=o)for(u in void 0!==...
function O (line 2) | function O(s){return"object"==typeof s&&null!==s&&s.$$typeof===i}
function Q (line 2) | function Q(s,o){return"object"==typeof s&&null!==s&&null!=s.key?function...
function R (line 2) | function R(s,o,u,_,w){var x=typeof s;"undefined"!==x&&"boolean"!==x||(s=...
function S (line 2) | function S(s,o,i){if(null==s)return s;var a=[],u=0;return R(s,a,"","",(f...
function T (line 2) | function T(s){if(-1===s._status){var o=s._result;(o=o()).then((function(...
function X (line 2) | function X(){throw Error("act(...) is not supported in production builds...
function CorkedRequest (line 2) | function CorkedRequest(s){var o=this;this.next=null,this.entry=null,this...
function nop (line 2) | function nop(){}
function WritableState (line 2) | function WritableState(s,o,_){a=a||i(25382),s=s||{},"boolean"!=typeof _&...
function Writable (line 2) | function Writable(s){var o=this instanceof(a=a||i(25382));if(!o&&!j.call...
function doWrite (line 2) | function doWrite(s,o,i,a,u,_,w){o.writelen=a,o.writecb=w,o.writing=!0,o....
function afterWrite (line 2) | function afterWrite(s,o,i,a){i||function onwriteDrain(s,o){0===o.length&...
function clearBuffer (line 2) | function clearBuffer(s,o){o.bufferProcessing=!0;var i=o.bufferedRequest;...
function needFinish (line 2) | function needFinish(s){return s.ending&&0===s.length&&null===s.bufferedR...
function callFinal (line 2) | function callFinal(s,o){s._final((function(i){o.pendingcb--,i&&ce(s,i),o...
function finishMaybe (line 2) | function finishMaybe(s,o){var i=needFinish(o);if(i&&(function prefinish(...
function source (line 2) | function source(s){return s?"string"==typeof s?s:s.source:null}
function lookahead (line 2) | function lookahead(s){return concat("(?=",s,")")}
function concat (line 2) | function concat(...s){return s.map((s=>source(s))).join("")}
function either (line 2) | function either(...s){return"("+s.map((s=>source(s))).join("|")+")"}
function resolve (line 2) | function resolve(s,o,i){var a,_=function create_indent(s,o){return new A...
function format (line 2) | function format(s,o,i){if("object"!=typeof o)return s(!1,o);var a=o.inte...
function delay (line 2) | function delay(s){C?a.nextTick(s):s()}
function append (line 2) | function append(s,o){if(void 0!==o&&(u+=o),s&&!w&&(i=i||new _,w=!0),s&&w...
function add (line 2) | function add(s,o){format(append,resolve(s,x,x?1:0),o)}
function end (line 2) | function end(){if(i){var s=u;delay((function(){i.emit("data",s),i.emit("...
function isObject (line 2) | function isObject(s){var o=typeof s;return!!s&&("object"==o||"function"=...
function toNumber (line 2) | function toNumber(s){if("number"==typeof s)return s;if(function isSymbol...
function invokeFunc (line 2) | function invokeFunc(o){var i=a,_=u;return a=u=void 0,j=o,w=s.apply(_,i)}
function shouldInvoke (line 2) | function shouldInvoke(s){var i=s-C;return void 0===C||i>=o||i<0||B&&s-j>=_}
function timerExpired (line 2) | function timerExpired(){var s=now();if(shouldInvoke(s))return trailingEd...
function trailingEdge (line 2) | function trailingEdge(s){return x=void 0,V&&a?invokeFunc(s):(a=u=void 0,w)}
function debounced (line 2) | function debounced(){var s=now(),i=shouldInvoke(s);if(a=arguments,u=this...
class NonError (line 2) | class NonError extends Error{constructor(s){super(NonError._prepareSuper...
method constructor (line 2) | constructor(s){super(NonError._prepareSuperMessage(s)),Object.definePr...
method _prepareSuperMessage (line 2) | static _prepareSuperMessage(s){try{return JSON.stringify(s)}catch{retu...
function Hash (line 2) | function Hash(s){var o=-1,i=null==s?0:s.length;for(this.clear();++o<i;){...
function p (line 2) | function p(s){for(var o="https://reactjs.org/docs/error-decoder.html?inv...
function fa (line 2) | function fa(s,o){ha(s,o),ha(s+"Capture",o)}
function ha (line 2) | function ha(s,o){for(w[s]=o,s=0;s<o.length;s++)_.add(o[s])}
function v (line 2) | function v(s,o,i,a,u,_,w){this.acceptsBooleans=2===o||3===o||4===o,this....
function sa (line 2) | function sa(s){return s[1].toUpperCase()}
function ta (line 2) | function ta(s,o,i,a){var u=$.hasOwnProperty(o)?$[o]:null;(null!==u?0!==u...
function Ka (line 2) | function Ka(s){return null===s||"object"!=typeof s?null:"function"==type...
function Ma (line 2) | function Ma(s){if(void 0===Se)try{throw Error()}catch(s){var o=s.stack.t...
function Oa (line 2) | function Oa(s,o){if(!s||xe)return"";xe=!0;var i=Error.prepareStackTrace;...
function Pa (line 2) | function Pa(s){switch(s.tag){case 5:return Ma(s.type);case 16:return Ma(...
function Qa (line 2) | function Qa(s){if(null==s)return null;if("function"==typeof s)return s.d...
function Ra (line 2) | function Ra(s){var o=s.type;switch(s.tag){case 24:return"Cache";case 9:r...
function Sa (line 2) | function Sa(s){switch(typeof s){case"boolean":case"number":case"string":...
function Ta (line 2) | function Ta(s){var o=s.type;return(s=s.nodeName)&&"input"===s.toLowerCas...
function Va (line 2) | function Va(s){s._valueTracker||(s._valueTracker=function Ua(s){var o=Ta...
function Wa (line 2) | function Wa(s){if(!s)return!1;var o=s._valueTracker;if(!o)return!0;var i...
function Xa (line 2) | function Xa(s){if(void 0===(s=s||("undefined"!=typeof document?document:...
function Ya (line 2) | function Ya(s,o){var i=o.checked;return we({},o,{defaultChecked:void 0,d...
function Za (line 2) | function Za(s,o){var i=null==o.defaultValue?"":o.defaultValue,a=null!=o....
function ab (line 2) | function ab(s,o){null!=(o=o.checked)&&ta(s,"checked",o,!1)}
function bb (line 2) | function bb(s,o){ab(s,o);var i=Sa(o.value),a=o.type;if(null!=i)"number"=...
function db (line 2) | function db(s,o,i){if(o.hasOwnProperty("value")||o.hasOwnProperty("defau...
function cb (line 2) | function cb(s,o,i){"number"===o&&Xa(s.ownerDocument)===s||(null==i?s.def...
function fb (line 2) | function fb(s,o,i,a){if(s=s.options,o){o={};for(var u=0;u<i.length;u++)o...
function gb (line 2) | function gb(s,o){if(null!=o.dangerouslySetInnerHTML)throw Error(p(91));r...
function hb (line 2) | function hb(s,o){var i=o.value;if(null==i){if(i=o.children,o=o.defaultVa...
function ib (line 2) | function ib(s,o){var i=Sa(o.value),a=Sa(o.defaultValue);null!=i&&((i=""+...
function jb (line 2) | function jb(s){var o=s.textContent;o===s._wrapperState.initialValue&&""!...
function kb (line 2) | function kb(s){switch(s){case"svg":return"http://www.w3.org/2000/svg";ca...
function lb (line 2) | function lb(s,o){return null==s||"http://www.w3.org/1999/xhtml"===s?kb(o...
function ob (line 2) | function ob(s,o){if(o){var i=s.firstChild;if(i&&i===s.lastChild&&3===i.n...
function rb (line 2) | function rb(s,o,i){return null==o||"boolean"==typeof o||""===o?"":i||"nu...
function sb (line 2) | function sb(s,o){for(var i in s=s.style,o)if(o.hasOwnProperty(i)){var a=...
function ub (line 2) | function ub(s,o){if(o){if(We[s]&&(null!=o.children||null!=o.dangerouslyS...
function vb (line 2) | function vb(s,o){if(-1===s.indexOf("-"))return"string"==typeof o.is;swit...
function xb (line 2) | function xb(s){return(s=s.target||s.srcElement||window).correspondingUse...
function Bb (line 2) | function Bb(s){if(s=Cb(s)){if("function"!=typeof Ye)throw Error(p(280));...
function Eb (line 2) | function Eb(s){Xe?Qe?Qe.push(s):Qe=[s]:Xe=s}
function Fb (line 2) | function Fb(){if(Xe){var s=Xe,o=Qe;if(Qe=Xe=null,Bb(s),o)for(s=0;s<o.len...
function Gb (line 2) | function Gb(s,o){return s(o)}
function Hb (line 2) | function Hb(){}
function Jb (line 2) | function Jb(s,o,i){if(et)return s(o,i);et=!0;try{return Gb(s,o,i)}finall...
function Kb (line 2) | function Kb(s,o){var i=s.stateNode;if(null===i)return null;var a=Db(i);i...
function Nb (line 2) | function Nb(s,o,i,a,u,_,w,x,C){var j=Array.prototype.slice.call(argument...
function Tb (line 2) | function Tb(s,o,i,a,u,_,w,x,C){nt=!1,st=null,Nb.apply(at,arguments)}
function Vb (line 2) | function Vb(s){var o=s,i=s;if(s.alternate)for(;o.return;)o=o.return;else...
function Wb (line 2) | function Wb(s){if(13===s.tag){var o=s.memoizedState;if(null===o&&(null!=...
function Xb (line 2) | function Xb(s){if(Vb(s)!==s)throw Error(p(188))}
function Zb (line 2) | function Zb(s){return null!==(s=function Yb(s){var o=s.alternate;if(!o){...
function $b (line 2) | function $b(s){if(5===s.tag||6===s.tag)return s;for(s=s.child;null!==s;)...
function tc (line 2) | function tc(s){switch(s&-s){case 1:return 1;case 2:return 2;case 4:retur...
function uc (line 2) | function uc(s,o){var i=s.pendingLanes;if(0===i)return 0;var a=0,u=s.susp...
function vc (line 2) | function vc(s,o){switch(s){case 1:case 2:case 4:return o+250;case 8:case...
function xc (line 2) | function xc(s){return 0!==(s=-1073741825&s.pendingLanes)?s:1073741824&s?...
function yc (line 2) | function yc(){var s=kt;return!(4194240&(kt<<=1))&&(kt=64),s}
function zc (line 2) | function zc(s){for(var o=[],i=0;31>i;i++)o.push(s);return o}
function Ac (line 2) | function Ac(s,o,i){s.pendingLanes|=o,536870912!==o&&(s.suspendedLanes=0,...
function Cc (line 2) | function Cc(s,o){var i=s.entangledLanes|=o;for(s=s.entanglements;i;){var...
function Dc (line 2) | function Dc(s){return 1<(s&=-s)?4<s?268435455&s?16:536870912:4:1}
function Sc (line 2) | function Sc(s,o){switch(s){case"focusin":case"focusout":Rt=null;break;ca...
function Tc (line 2) | function Tc(s,o,i,a,u,_){return null===s||s.nativeEvent!==_?(s={blockedO...
function Vc (line 2) | function Vc(s){var o=Wc(s.target);if(null!==o){var i=Vb(o);if(null!==i)i...
function Xc (line 2) | function Xc(s){if(null!==s.blockedOn)return!1;for(var o=s.targetContaine...
function Zc (line 2) | function Zc(s,o,i){Xc(s)&&i.delete(o)}
function $c (line 2) | function $c(){Nt=!1,null!==Rt&&Xc(Rt)&&(Rt=null),null!==Dt&&Xc(Dt)&&(Dt=...
function ad (line 2) | function ad(s,o){s.blockedOn===o&&(s.blockedOn=null,Nt||(Nt=!0,u.unstabl...
function bd (line 2) | function bd(s){function b(o){return ad(o,s)}if(0<Mt.length){ad(Mt[0],s);...
function ed (line 2) | function ed(s,o,i,a){var u=At,_=Ut.transition;Ut.transition=null;try{At=...
function gd (line 2) | function gd(s,o,i,a){var u=At,_=Ut.transition;Ut.transition=null;try{At=...
function fd (line 2) | function fd(s,o,i,a){if(Vt){var u=Yc(s,o,i,a);if(null===u)hd(s,o,a,zt,i)...
function Yc (line 2) | function Yc(s,o,i,a){if(zt=null,null!==(s=Wc(s=xb(a))))if(null===(o=Vb(s...
function jd (line 2) | function jd(s){switch(s){case"cancel":case"click":case"close":case"conte...
function nd (line 2) | function nd(){if(Ht)return Ht;var s,o,i=Jt,a=i.length,u="value"in Wt?Wt....
function od (line 2) | function od(s){var o=s.keyCode;return"charCode"in s?0===(s=s.charCode)&&...
function pd (line 2) | function pd(){return!0}
function qd (line 2) | function qd(){return!1}
function rd (line 2) | function rd(s){function b(o,i,a,u,_){for(var w in this._reactName=o,this...
function Pd (line 2) | function Pd(s){var o=this.nativeEvent;return o.getModifierState?o.getMod...
function zd (line 2) | function zd(){return Pd}
function ge (line 2) | function ge(s,o){switch(s){case"keyup":return-1!==Sr.indexOf(o.keyCode);...
function he (line 2) | function he(s){return"object"==typeof(s=s.detail)&&"data"in s?s.data:null}
function me (line 2) | function me(s){var o=s&&s.nodeName&&s.nodeName.toLowerCase();return"inpu...
function ne (line 2) | function ne(s,o,i,a){Eb(a),0<(o=oe(o,"onChange")).length&&(i=new Qt("onC...
function re (line 2) | function re(s){se(s,0)}
function te (line 2) | function te(s){if(Wa(ue(s)))return s}
function ve (line 2) | function ve(s,o){if("change"===s)return o}
function Ae (line 2) | function Ae(){Pr&&(Pr.detachEvent("onpropertychange",Be),Ir=Pr=null)}
function Be (line 2) | function Be(s){if("value"===s.propertyName&&te(Ir)){var o=[];ne(o,Ir,s,x...
function Ce (line 2) | function Ce(s,o,i){"focusin"===s?(Ae(),Ir=i,(Pr=o).attachEvent("onproper...
function De (line 2) | function De(s){if("selectionchange"===s||"keyup"===s||"keydown"===s)retu...
function Ee (line 2) | function Ee(s,o){if("click"===s)return te(o)}
function Fe (line 2) | function Fe(s,o){if("input"===s||"change"===s)return te(o)}
function Ie (line 2) | function Ie(s,o){if(Dr(s,o))return!0;if("object"!=typeof s||null===s||"o...
function Je (line 2) | function Je(s){for(;s&&s.firstChild;)s=s.firstChild;return s}
function Ke (line 2) | function Ke(s,o){var i,a=Je(s);for(s=0;a;){if(3===a.nodeType){if(i=s+a.t...
function Le (line 2) | function Le(s,o){return!(!s||!o)&&(s===o||(!s||3!==s.nodeType)&&(o&&3===...
function Me (line 2) | function Me(){for(var s=window,o=Xa();o instanceof s.HTMLIFrameElement;)...
function Ne (line 2) | function Ne(s){var o=s&&s.nodeName&&s.nodeName.toLowerCase();return o&&(...
function Oe (line 2) | function Oe(s){var o=Me(),i=s.focusedElem,a=s.selectionRange;if(o!==i&&i...
function Ue (line 2) | function Ue(s,o,i){var a=i.window===i?i.document:9===i.nodeType?i:i.owne...
function Ve (line 2) | function Ve(s,o){var i={};return i[s.toLowerCase()]=o.toLowerCase(),i["W...
function Ze (line 2) | function Ze(s){if(Vr[s])return Vr[s];if(!Ur[s])return s;var o,i=Ur[s];fo...
function ff (line 2) | function ff(s,o){Gr.set(s,o),fa(o,[s])}
function nf (line 2) | function nf(s,o,i){var a=s.type||"unknown-event";s.currentTarget=i,funct...
function se (line 2) | function se(s,o){o=!!(4&o);for(var i=0;i<s.length;i++){var a=s[i],u=a.ev...
function D (line 2) | function D(s,o){var i=o[mn];void 0===i&&(i=o[mn]=new Set);var a=s+"__bub...
function qf (line 2) | function qf(s,o,i){var a=0;o&&(a|=4),pf(i,s,a,o)}
function sf (line 2) | function sf(s){if(!s[tn]){s[tn]=!0,_.forEach((function(o){"selectionchan...
function pf (line 2) | function pf(s,o,i,a){switch(jd(o)){case 1:var u=ed;break;case 4:u=gd;bre...
function hd (line 2) | function hd(s,o,i,a,u){var _=a;if(!(1&o||2&o||null===a))e:for(;;){if(nul...
function tf (line 2) | function tf(s,o,i){return{instance:s,listener:o,currentTarget:i}}
function oe (line 2) | function oe(s,o){for(var i=o+"Capture",a=[];null!==s;){var u=s,_=u.state...
function vf (line 2) | function vf(s){if(null===s)return null;do{s=s.return}while(s&&5!==s.tag)...
function wf (line 2) | function wf(s,o,i,a,u){for(var _=o._reactName,w=[];null!==i&&i!==a;){var...
function zf (line 2) | function zf(s){return("string"==typeof s?s:""+s).replace(rn,"\n").replac...
function Af (line 2) | function Af(s,o,i){if(o=zf(o),zf(s)!==o&&i)throw Error(p(425))}
function Bf (line 2) | function Bf(){}
function Ef (line 2) | function Ef(s,o){return"textarea"===s||"noscript"===s||"string"==typeof ...
function If (line 2) | function If(s){setTimeout((function(){throw s}))}
function Kf (line 2) | function Kf(s,o){var i=o,a=0;do{var u=i.nextSibling;if(s.removeChild(i),...
function Lf (line 2) | function Lf(s){for(;null!=s;s=s.nextSibling){var o=s.nodeType;if(1===o||...
function Mf (line 2) | function Mf(s){s=s.previousSibling;for(var o=0;s;){if(8===s.nodeType){va...
function Wc (line 2) | function Wc(s){var o=s[hn];if(o)return o;for(var i=s.parentNode;i;){if(o...
function Cb (line 2) | function Cb(s){return!(s=s[hn]||s[fn])||5!==s.tag&&6!==s.tag&&13!==s.tag...
function ue (line 2) | function ue(s){if(5===s.tag||6===s.tag)return s.stateNode;throw Error(p(...
function Db (line 2) | function Db(s){return s[dn]||null}
function Uf (line 2) | function Uf(s){return{current:s}}
function E (line 2) | function E(s){0>bn||(s.current=vn[bn],vn[bn]=null,bn--)}
function G (line 2) | function G(s,o){bn++,vn[bn]=s.current,s.current=o}
function Yf (line 2) | function Yf(s,o){var i=s.type.contextTypes;if(!i)return _n;var a=s.state...
function Zf (line 2) | function Zf(s){return null!=(s=s.childContextTypes)}
function $f (line 2) | function $f(){E(En),E(Sn)}
function ag (line 2) | function ag(s,o,i){if(Sn.current!==_n)throw Error(p(168));G(Sn,o),G(En,i)}
function bg (line 2) | function bg(s,o,i){var a=s.stateNode;if(o=o.childContextTypes,"function"...
function cg (line 2) | function cg(s){return s=(s=s.stateNode)&&s.__reactInternalMemoizedMerged...
function dg (line 2) | function dg(s,o,i){var a=s.stateNode;if(!a)throw Error(p(169));i?(s=bg(s...
function hg (line 2) | function hg(s){null===xn?xn=[s]:xn.push(s)}
function jg (line 2) | function jg(){if(!On&&null!==xn){On=!0;var s=0,o=At;try{var i=xn;for(At=...
function tg (line 2) | function tg(s,o){An[Cn++]=Pn,An[Cn++]=jn,jn=s,Pn=o}
function ug (line 2) | function ug(s,o,i){In[Tn++]=Mn,In[Tn++]=Rn,In[Tn++]=Nn,Nn=s;var a=Mn;s=R...
function vg (line 2) | function vg(s){null!==s.return&&(tg(s,1),ug(s,1,0))}
function wg (line 2) | function wg(s){for(;s===jn;)jn=An[--Cn],An[Cn]=null,Pn=An[--Cn],An[Cn]=n...
function Ag (line 2) | function Ag(s,o){var i=Bg(5,null,null,0);i.elementType="DELETED",i.state...
function Cg (line 2) | function Cg(s,o){switch(s.tag){case 5:var i=s.type;return null!==(o=1!==...
function Dg (line 2) | function Dg(s){return!(!(1&s.mode)||128&s.flags)}
function Eg (line 2) | function Eg(s){if(Fn){var o=Ln;if(o){var i=o;if(!Cg(s,o)){if(Dg(s))throw...
function Fg (line 2) | function Fg(s){for(s=s.return;null!==s&&5!==s.tag&&3!==s.tag&&13!==s.tag...
function Gg (line 2) | function Gg(s){if(s!==Dn)return!1;if(!Fn)return Fg(s),Fn=!0,!1;var o;if(...
function Hg (line 2) | function Hg(){for(var s=Ln;s;)s=Lf(s.nextSibling)}
function Ig (line 2) | function Ig(){Ln=Dn=null,Fn=!1}
function Jg (line 2) | function Jg(s){null===Bn?Bn=[s]:Bn.push(s)}
function Lg (line 2) | function Lg(s,o,i){if(null!==(s=i.ref)&&"function"!=typeof s&&"object"!=...
function Mg (line 2) | function Mg(s,o){throw s=Object.prototype.toString.call(o),Error(p(31,"[...
function Ng (line 2) | function Ng(s){return(0,s._init)(s._payload)}
function Og (line 2) | function Og(s){function b(o,i){if(s){var a=o.deletions;null===a?(o.delet...
function $g (line 2) | function $g(){Jn=Wn=zn=null}
function ah (line 2) | function ah(s){var o=Vn.current;E(Vn),s._currentValue=o}
function bh (line 2) | function bh(s,o,i){for(;null!==s;){var a=s.alternate;if((s.childLanes&o)...
function ch (line 2) | function ch(s,o){zn=s,Jn=Wn=null,null!==(s=s.dependencies)&&null!==s.fir...
function eh (line 2) | function eh(s){var o=s._currentValue;if(Jn!==s)if(s={context:s,memoizedV...
function gh (line 2) | function gh(s){null===Hn?Hn=[s]:Hn.push(s)}
function hh (line 2) | function hh(s,o,i,a){var u=o.interleaved;return null===u?(i.next=i,gh(o)...
function ih (line 2) | function ih(s,o){s.lanes|=o;var i=s.alternate;for(null!==i&&(i.lanes|=o)...
function kh (line 2) | function kh(s){s.updateQueue={baseState:s.memoizedState,firstBaseUpdate:...
function lh (line 2) | function lh(s,o){s=s.updateQueue,o.updateQueue===s&&(o.updateQueue={base...
function mh (line 2) | function mh(s,o){return{eventTime:s,lane:o,tag:0,payload:null,callback:n...
function nh (line 2) | function nh(s,o,i){var a=s.updateQueue;if(null===a)return null;if(a=a.sh...
function oh (line 2) | function oh(s,o,i){if(null!==(o=o.updateQueue)&&(o=o.shared,4194240&i)){...
function ph (line 2) | function ph(s,o){var i=s.updateQueue,a=s.alternate;if(null!==a&&i===(a=a...
function qh (line 2) | function qh(s,o,i,a){var u=s.updateQueue;Kn=!1;var _=u.firstBaseUpdate,w...
function sh (line 2) | function sh(s,o,i){if(s=o.effects,o.effects=null,null!==s)for(o=0;o<s.le...
function xh (line 2) | function xh(s){if(s===Gn)throw Error(p(174));return s}
function yh (line 2) | function yh(s,o){switch(G(Qn,o),G(Xn,s),G(Yn,Gn),s=o.nodeType){case 9:ca...
function zh (line 2) | function zh(){E(Yn),E(Xn),E(Qn)}
function Ah (line 2) | function Ah(s){xh(Qn.current);var o=xh(Yn.current),i=lb(o,s.type);o!==i&...
function Bh (line 2) | function Bh(s){Xn.current===s&&(E(Yn),E(Xn))}
function Ch (line 2) | function Ch(s){for(var o=s;null!==o;){if(13===o.tag){var i=o.memoizedSta...
function Eh (line 2) | function Eh(){for(var s=0;s<es.length;s++)es[s]._workInProgressVersionPr...
function P (line 2) | function P(){throw Error(p(321))}
function Mh (line 2) | function Mh(s,o){if(null===o)return!1;for(var i=0;i<o.length&&i<s.length...
function Nh (line 2) | function Nh(s,o,i,a,u,_){if(ns=_,ss=o,o.memoizedState=null,o.updateQueue...
function Sh (line 2) | function Sh(){var s=0!==us;return us=0,s}
function Th (line 2) | function Th(){var s={memoizedState:null,baseState:null,baseQueue:null,qu...
function Uh (line 2) | function Uh(){if(null===os){var s=ss.alternate;s=null!==s?s.memoizedStat...
function Vh (line 2) | function Vh(s,o){return"function"==typeof o?o(s):o}
function Wh (line 2) | function Wh(s){var o=Uh(),i=o.queue;if(null===i)throw Error(p(311));i.la...
function Xh (line 2) | function Xh(s){var o=Uh(),i=o.queue;if(null===i)throw Error(p(311));i.la...
function Yh (line 2) | function Yh(){}
function Zh (line 2) | function Zh(s,o){var i=ss,a=Uh(),u=o(),_=!Dr(a.memoizedState,u);if(_&&(a...
function di (line 2) | function di(s,o,i){s.flags|=16384,s={getSnapshot:o,value:i},null===(o=ss...
function ci (line 2) | function ci(s,o,i,a){o.value=i,o.getSnapshot=a,ei(o)&&fi(s)}
function ai (line 2) | function ai(s,o,i){return i((function(){ei(o)&&fi(s)}))}
function ei (line 2) | function ei(s){var o=s.getSnapshot;s=s.value;try{var i=o();return!Dr(s,i...
function fi (line 2) | function fi(s){var o=ih(s,1);null!==o&&gi(o,s,1,-1)}
function hi (line 2) | function hi(s){var o=Th();return"function"==typeof s&&(s=s()),o.memoized...
function bi (line 2) | function bi(s,o,i,a){return s={tag:s,create:o,destroy:i,deps:a,next:null...
function ji (line 2) | function ji(){return Uh().memoizedState}
function ki (line 2) | function ki(s,o,i,a){var u=Th();ss.flags|=s,u.memoizedState=bi(1|o,i,voi...
function li (line 2) | function li(s,o,i,a){var u=Uh();a=void 0===a?null:a;var _=void 0;if(null...
function mi (line 2) | function mi(s,o){return ki(8390656,8,s,o)}
function $h (line 2) | function $h(s,o){return li(2048,8,s,o)}
function ni (line 2) | function ni(s,o){return li(4,2,s,o)}
function oi (line 2) | function oi(s,o){return li(4,4,s,o)}
function pi (line 2) | function pi(s,o){return"function"==typeof o?(s=s(),o(s),function(){o(nul...
function qi (line 2) | function qi(s,o,i){return i=null!=i?i.concat([s]):null,li(4,4,pi.bind(nu...
function ri (line 2) | function ri(){}
function si (line 2) | function si(s,o){var i=Uh();o=void 0===o?null:o;var a=i.memoizedState;re...
function ti (line 2) | function ti(s,o){var i=Uh();o=void 0===o?null:o;var a=i.memoizedState;re...
function ui (line 2) | function ui(s,o,i){return 21&ns?(Dr(i,o)||(i=yc(),ss.lanes|=i,Ws|=i,s.ba...
function vi (line 2) | function vi(s,o){var i=At;At=0!==i&&4>i?i:4,s(!0);var a=rs.transition;rs...
function wi (line 2) | function wi(){return Uh().memoizedState}
function xi (line 2) | function xi(s,o,i){var a=yi(s);if(i={lane:a,action:i,hasEagerState:!1,ea...
function ii (line 2) | function ii(s,o,i){var a=yi(s),u={lane:a,action:i,hasEagerState:!1,eager...
function zi (line 2) | function zi(s){var o=s.alternate;return s===ss||null!==o&&o===ss}
function Ai (line 2) | function Ai(s,o){ls=cs=!0;var i=s.pending;null===i?o.next=o:(o.next=i.ne...
function Bi (line 2) | function Bi(s,o,i){if(4194240&i){var a=o.lanes;i|=a&=s.pendingLanes,o.la...
function Ci (line 2) | function Ci(s,o){if(s&&s.defaultProps){for(var i in o=we({},o),s=s.defau...
function Di (line 2) | function Di(s,o,i,a){i=null==(i=i(a,o=s.memoizedState))?o:we({},o,i),s.m...
function Fi (line 2) | function Fi(s,o,i,a,u,_,w){return"function"==typeof(s=s.stateNode).shoul...
function Gi (line 2) | function Gi(s,o,i){var a=!1,u=_n,_=o.contextType;return"object"==typeof ...
function Hi (line 2) | function Hi(s,o,i,a){s=o.state,"function"==typeof o.componentWillReceive...
function Ii (line 2) | function Ii(s,o,i,a){var u=s.stateNode;u.props=i,u.state=s.memoizedState...
function Ji (line 2) | function Ji(s,o){try{var i="",a=o;do{i+=Pa(a),a=a.return}while(a);var u=...
function Ki (line 2) | function Ki(s,o,i){return{value:s,source:null,stack:null!=i?i:null,diges...
function Li (line 2) | function Li(s,o){try{console.error(o.value)}catch(s){setTimeout((functio...
function Ni (line 2) | function Ni(s,o,i){(i=mh(-1,i)).tag=3,i.payload={element:null};var a=o.v...
function Qi (line 2) | function Qi(s,o,i){(i=mh(-1,i)).tag=3;var a=s.type.getDerivedStateFromEr...
function Si (line 2) | function Si(s,o,i){var a=s.pingCache;if(null===a){a=s.pingCache=new ys;v...
function Ui (line 2) | function Ui(s){do{var o;if((o=13===s.tag)&&(o=null===(o=s.memoizedState)...
function Vi (line 2) | function Vi(s,o,i,a,u){return 1&s.mode?(s.flags|=65536,s.lanes=u,s):(s==...
function Xi (line 2) | function Xi(s,o,i,a){o.child=null===s?Un(o,null,i,a):qn(o,s.child,i,a)}
function Yi (line 2) | function Yi(s,o,i,a,u){i=i.render;var _=o.ref;return ch(o,u),a=Nh(s,o,i,...
function $i (line 2) | function $i(s,o,i,a,u){if(null===s){var _=i.type;return"function"!=typeo...
function bj (line 2) | function bj(s,o,i,a,u){if(null!==s){var _=s.memoizedProps;if(Ie(_,a)&&s....
function dj (line 2) | function dj(s,o,i){var a=o.pendingProps,u=a.children,_=null!==s?s.memoiz...
function gj (line 2) | function gj(s,o){var i=o.ref;(null===s&&null!==i||null!==s&&s.ref!==i)&&...
function cj (line 2) | function cj(s,o,i,a,u){var _=Zf(i)?wn:Sn.current;return _=Yf(o,_),ch(o,u...
function hj (line 2) | function hj(s,o,i,a,u){if(Zf(i)){var _=!0;cg(o)}else _=!1;if(ch(o,u),nul...
function jj (line 2) | function jj(s,o,i,a,u,_){gj(s,o);var w=!!(128&o.flags);if(!a&&!w)return ...
function kj (line 2) | function kj(s){var o=s.stateNode;o.pendingContext?ag(0,o.pendingContext,...
function lj (line 2) | function lj(s,o,i,a,u){return Ig(),Jg(u),o.flags|=256,Xi(s,o,i,a),o.child}
function nj (line 2) | function nj(s){return{baseLanes:s,cachePool:null,transitions:null}}
function oj (line 2) | function oj(s,o,i){var a,u=o.pendingProps,_=Zn.current,w=!1,x=!!(128&o.f...
function qj (line 2) | function qj(s,o){return(o=pj({mode:"visible",children:o},s.mode,0,null))...
function sj (line 2) | function sj(s,o,i,a){return null!==a&&Jg(a),qn(o,s.child,null,i),(s=qj(o...
function vj (line 2) | function vj(s,o,i){s.lanes|=o;var a=s.alternate;null!==a&&(a.lanes|=o),b...
function wj (line 2) | function wj(s,o,i,a,u){var _=s.memoizedState;null===_?s.memoizedState={i...
function xj (line 2) | function xj(s,o,i){var a=o.pendingProps,u=a.revealOrder,_=a.tail;if(Xi(s...
function ij (line 2) | function ij(s,o){!(1&o.mode)&&null!==s&&(s.alternate=null,o.alternate=nu...
function Zi (line 2) | function Zi(s,o,i){if(null!==s&&(o.dependencies=s.dependencies),Ws|=o.la...
function Dj (line 2) | function Dj(s,o){if(!Fn)switch(s.tailMode){case"hidden":o=s.tail;for(var...
function S (line 2) | function S(s){var o=null!==s.alternate&&s.alternate.child===s.child,i=0,...
function Ej (line 2) | function Ej(s,o,i){var a=o.pendingProps;switch(wg(o),o.tag){case 2:case ...
function Ij (line 2) | function Ij(s,o){switch(wg(o),o.tag){case 1:return Zf(o.type)&&$f(),6553...
function Lj (line 2) | function Lj(s,o){var i=s.ref;if(null!==i)if("function"==typeof i)try{i(n...
function Mj (line 2) | function Mj(s,o,i){try{i()}catch(i){W(s,o,i)}}
function Pj (line 2) | function Pj(s,o,i){var a=o.updateQueue;if(null!==(a=null!==a?a.lastEffec...
function Qj (line 2) | function Qj(s,o){if(null!==(o=null!==(o=o.updateQueue)?o.lastEffect:null...
function Rj (line 2) | function Rj(s){var o=s.ref;if(null!==o){var i=s.stateNode;s.tag,s=i,"fun...
function Sj (line 2) | function Sj(s){var o=s.alternate;null!==o&&(s.alternate=null,Sj(o)),s.ch...
function Tj (line 2) | function Tj(s){return 5===s.tag||3===s.tag||4===s.tag}
function Uj (line 2) | function Uj(s){e:for(;;){for(;null===s.sibling;){if(null===s.return||Tj(...
function Vj (line 2) | function Vj(s,o,i){var a=s.tag;if(5===a||6===a)s=s.stateNode,o?8===i.nod...
function Wj (line 2) | function Wj(s,o,i){var a=s.tag;if(5===a||6===a)s=s.stateNode,o?i.insertB...
function Yj (line 2) | function Yj(s,o,i){for(i=i.child;null!==i;)Zj(s,o,i),i=i.sibling}
function Zj (line 2) | function Zj(s,o,i){if(St&&"function"==typeof St.onCommitFiberUnmount)try...
function ak (line 2) | function ak(s){var o=s.updateQueue;if(null!==o){s.updateQueue=null;var i...
function ck (line 2) | function ck(s,o){var i=o.deletions;if(null!==i)for(var a=0;a<i.length;a+...
function dk (line 2) | function dk(s,o){var i=s.alternate,a=s.flags;switch(s.tag){case 0:case 1...
function ek (line 2) | function ek(s){var o=s.flags;if(2&o){try{e:{for(var i=s.return;null!==i;...
function hk (line 2) | function hk(s,o,i){Cs=s,ik(s,o,i)}
function ik (line 2) | function ik(s,o,i){for(var a=!!(1&s.mode);null!==Cs;){var u=Cs,_=u.child...
function kk (line 2) | function kk(s){for(;null!==Cs;){var o=Cs;if(8772&o.flags){var i=o.altern...
function gk (line 2) | function gk(s){for(;null!==Cs;){var o=Cs;if(o===s){Cs=null;break}var i=o...
function jk (line 2) | function jk(s){for(;null!==Cs;){var o=Cs;try{switch(o.tag){case 0:case 1...
function R (line 2) | function R(){return 6&Ls?ht():-1!==ao?ao:ao=ht()}
function yi (line 2) | function yi(s){return 1&s.mode?2&Ls&&0!==$s?$s&-$s:null!==$n.transition?...
function gi (line 2) | function gi(s,o,i,a){if(50<oo)throw oo=0,io=null,Error(p(185));Ac(s,i,a)...
function Dk (line 2) | function Dk(s,o){var i=s.callbackNode;!function wc(s,o){for(var i=s.susp...
function Gk (line 2) | function Gk(s,o){if(ao=-1,co=0,6&Ls)throw Error(p(327));var i=s.callback...
function Nk (line 2) | function Nk(s,o){var i=Ks;return s.current.memoizedState.isDehydrated&&(...
function Fj (line 2) | function Fj(s){null===Gs?Gs=s:Gs.push.apply(Gs,s)}
function Ck (line 2) | function Ck(s,o){for(o&=~Hs,o&=~Js,s.suspendedLanes|=o,s.pingedLanes&=~o...
function Ek (line 2) | function Ek(s){if(6&Ls)throw Error(p(327));Hk();var o=uc(s,0);if(!(1&o))...
function Qk (line 2) | function Qk(s,o){var i=Ls;Ls|=1;try{return s(o)}finally{0===(Ls=i)&&(Xs=...
function Rk (line 2) | function Rk(s){null!==no&&0===no.tag&&!(6&Ls)&&Hk();var o=Ls;Ls|=1;var i...
function Hj (line 2) | function Hj(){qs=Us.current,E(Us)}
function Kk (line 2) | function Kk(s,o){s.finishedWork=null,s.finishedLanes=0;var i=s.timeoutHa...
function Mk (line 2) | function Mk(s,o){for(;;){var i=Bs;try{if($g(),ts.current=hs,cs){for(var ...
function Jk (line 2) | function Jk(){var s=Ms.current;return Ms.current=hs,null===s?hs:s}
function tj (line 2) | function tj(){0!==Vs&&3!==Vs&&2!==Vs||(Vs=4),null===Fs||!(268435455&Ws)&...
function Ik (line 2) | function Ik(s,o){var i=Ls;Ls|=2;var a=Jk();for(Fs===s&&$s===o||(Qs=null,...
function Tk (line 2) | function Tk(){for(;null!==Bs;)Uk(Bs)}
function Lk (line 2) | function Lk(){for(;null!==Bs&&!ut();)Uk(Bs)}
function Uk (line 2) | function Uk(s){var o=Ts(s.alternate,s,qs);s.memoizedProps=s.pendingProps...
function Sk (line 2) | function Sk(s){var o=s;do{var i=o.alternate;if(s=o.return,32768&o.flags)...
function Pk (line 2) | function Pk(s,o,i){var a=At,u=Ds.transition;try{Ds.transition=null,At=1,...
function Hk (line 2) | function Hk(){if(null!==no){var s=Dc(so),o=Ds.transition,i=At;try{if(Ds....
function Xk (line 2) | function Xk(s,o,i){s=nh(s,o=Ni(0,o=Ji(i,o),1),1),o=R(),null!==s&&(Ac(s,1...
function W (line 2) | function W(s,o,i){if(3===s.tag)Xk(s,s,i);else for(;null!==o;){if(3===o.t...
function Ti (line 2) | function Ti(s,o,i){var a=s.pingCache;null!==a&&a.delete(o),o=R(),s.pinge...
function Yk (line 2) | function Yk(s,o){0===o&&(1&s.mode?(o=Ot,!(130023424&(Ot<<=1))&&(Ot=41943...
function uj (line 2) | function uj(s){var o=s.memoizedState,i=0;null!==o&&(i=o.retryLane),Yk(s,i)}
function bk (line 2) | function bk(s,o){var i=0;switch(s.tag){case 13:var a=s.stateNode,u=s.mem...
function Fk (line 2) | function Fk(s,o){return ct(s,o)}
function $k (line 2) | function $k(s,o,i,a){this.tag=s,this.key=i,this.sibling=this.child=this....
function Bg (line 2) | function Bg(s,o,i,a){return new $k(s,o,i,a)}
function aj (line 2) | function aj(s){return!(!(s=s.prototype)||!s.isReactComponent)}
function Pg (line 2) | function Pg(s,o){var i=s.alternate;return null===i?((i=Bg(s.tag,o,s.key,...
function Rg (line 2) | function Rg(s,o,i,a,u,_){var w=2;if(a=s,"function"==typeof s)aj(s)&&(w=1...
function Tg (line 2) | function Tg(s,o,i,a){return(s=Bg(7,s,a,o)).lanes=i,s}
function pj (line 2) | function pj(s,o,i,a){return(s=Bg(22,s,a,o)).elementType=be,s.lanes=i,s.s...
function Qg (line 2) | function Qg(s,o,i){return(s=Bg(6,s,null,o)).lanes=i,s}
function Sg (line 2) | function Sg(s,o,i){return(o=Bg(4,null!==s.children?s.children:[],s.key,o...
function al (line 2) | function al(s,o,i,a,u){this.tag=o,this.containerInfo=s,this.finishedWork...
function bl (line 2) | function bl(s,o,i,a,u,_,w,x,C){return s=new al(s,o,i,x,C),1===o?(o=1,!0=...
function dl (line 2) | function dl(s){if(!s)return _n;e:{if(Vb(s=s._reactInternals)!==s||1!==s....
function el (line 2) | function el(s,o,i,a,u,_,w,x,C){return(s=bl(i,a,!0,s,0,_,0,x,C)).context=...
function fl (line 2) | function fl(s,o,i,a){var u=o.current,_=R(),w=yi(u);return i=dl(i),null==...
function gl (line 2) | function gl(s){return(s=s.current).child?(s.child.tag,s.child.stateNode)...
function hl (line 2) | function hl(s,o){if(null!==(s=s.memoizedState)&&null!==s.dehydrated){var...
function il (line 2) | function il(s,o){hl(s,o),(s=s.alternate)&&hl(s,o)}
function ll (line 2) | function ll(s){this._internalRoot=s}
function ml (line 2) | function ml(s){this._internalRoot=s}
function nl (line 2) | function nl(s){return!(!s||1!==s.nodeType&&9!==s.nodeType&&11!==s.nodeTy...
function ol (line 2) | function ol(s){return!(!s||1!==s.nodeType&&9!==s.nodeType&&11!==s.nodeTy...
function pl (line 2) | function pl(){}
function rl (line 2) | function rl(s,o,i,a,u){var _=i._reactRootContainer;if(_){var w=_;if("fun...
function Sha256 (line 2) | function Sha256(){this.init(),this._w=x,u.call(this,64,56)}
function ch (line 2) | function ch(s,o,i){return i^s&(o^i)}
function maj (line 2) | function maj(s,o,i){return s&o|i&(s|o)}
function sigma0 (line 2) | function sigma0(s){return(s>>>2|s<<30)^(s>>>13|s<<19)^(s>>>22|s<<10)}
function sigma1 (line 2) | function sigma1(s){return(s>>>6|s<<26)^(s>>>11|s<<21)^(s>>>25|s<<7)}
function gamma0 (line 2) | function gamma0(s){return(s>>>7|s<<25)^(s>>>18|s<<14)^s>>>3}
function _typeof (line 2) | function _typeof(s){return _typeof="function"==typeof Symbol&&"symbol"==...
function _interopRequireDefault (line 2) | function _interopRequireDefault(s){return s&&s.__esModule?s:{default:s}}
function ownKeys (line 2) | function ownKeys(s,o){var i=Object.keys(s);if(Object.getOwnPropertySymbo...
function _objectSpread (line 2) | function _objectSpread(s){for(var o=1;o<arguments.length;o++){var i=null...
function _objectWithoutProperties (line 2) | function _objectWithoutProperties(s,o){if(null==s)return{};var i,a,u=fun...
function _defineProperties (line 2) | function _defineProperties(s,o){for(var i=0;i<o.length;i++){var a=o[i];a...
function _setPrototypeOf (line 2) | function _setPrototypeOf(s,o){return _setPrototypeOf=Object.setPrototype...
function _createSuper (line 2) | function _createSuper(s){var o=function _isNativeReflectConstruct(){if("...
function _assertThisInitialized (line 2) | function _assertThisInitialized(s){if(void 0===s)throw new ReferenceErro...
function _getPrototypeOf (line 2) | function _getPrototypeOf(s){return _getPrototypeOf=Object.setPrototypeOf...
function _defineProperty (line 2) | function _defineProperty(s,o,i){return o in s?Object.defineProperty(s,o,...
function CopyToClipboard (line 2) | function CopyToClipboard(){var s;!function _classCallCheck(s,o){if(!(s i...
function Duplex (line 2) | function Duplex(s){if(!(this instanceof Duplex))return new Duplex(s);_.c...
function onend (line 2) | function onend(){this._writableState.ended||a.nextTick(onEndNT,this)}
function onEndNT (line 2) | function onEndNT(s){s.end()}
function format (line 2) | function format(s){for(var o,i,a,u,_=1,w=[].slice.call(arguments),x=0,C=...
function getType (line 2) | function getType(s){return u(s)?"ClosingTag":function isOpeningTag(s){re...
function Sha224 (line 2) | function Sha224(){this.init(),this._w=x,_.call(this,64,56)}
function Sha (line 2) | function Sha(){this.init(),this._w=x,u.call(this,64,56)}
function rotl30 (line 2) | function rotl30(s){return s<<30|s>>>2}
function ft (line 2) | function ft(s,o,i,a){return 0===s?o&i|~o&a:2===s?o&i|o&a|i&a:o^i^a}
function f (line 2) | function f(s,o){var i=s.length;s.push(o);e:for(;0<i;){var a=i-1>>>1,u=s[...
function h (line 2) | function h(s){return 0===s.length?null:s[0]}
function k (line 2) | function k(s){if(0===s.length)return null;var o=s[0],i=s.pop();if(i!==o)...
function g (line 2) | function g(s,o){var i=s.sortIndex-o.sortIndex;return 0!==i?i:s.id-o.id}
function G (line 2) | function G(s){for(var o=h(w);null!==o;){if(null===o.callback)k(w);else{i...
function H (line 2) | function H(s){if($=!1,G(s),!B)if(null!==h(_))B=!0,I(J);else{var o=h(w);n...
function J (line 2) | function J(s,i){B=!1,$&&($=!1,V(ie),ie=-1),L=!0;var a=j;try{for(G(i),C=h...
function M (line 2) | function M(){return!(o.unstable_now()-ce<ae)}
function R (line 2) | function R(){if(null!==ee){var s=o.unstable_now();ce=s;var i=!0;try{i=ee...
function I (line 2) | function I(s){ee=s,Z||(Z=!0,Y())}
function K (line 2) | function K(s,i){ie=U((function(){s(o.unstable_now())}),i)}
function LazyWrapper (line 2) | function LazyWrapper(s){this.__wrapped__=s,this.__actions__=[],this.__di...
function Sha384 (line 2) | function Sha384(){this.init(),this._w=x,_.call(this,128,112)}
function writeInt64BE (line 2) | function writeInt64BE(o,i,a){s.writeInt32BE(o,a),s.writeInt32BE(i,a+4)}
function concat (line 2) | function concat(...s){return s.map((s=>function source(s){return s?"stri...
function EventEmitter (line 2) | function EventEmitter(){EventEmitter.init.call(this)}
function errorListener (line 2) | function errorListener(i){s.removeListener(o,resolver),a(i)}
function resolver (line 2) | function resolver(){"function"==typeof s.removeListener&&s.removeListene...
function checkListener (line 2) | function checkListener(s){if("function"!=typeof s)throw new TypeError('T...
function _getMaxListeners (line 2) | function _getMaxListeners(s){return void 0===s._maxListeners?EventEmitte...
function _addListener (line 2) | function _addListener(s,o,i,a){var u,_,w;if(checkListener(i),void 0===(_...
function onceWrapper (line 2) | function onceWrapper(){if(!this.fired)return this.target.removeListener(...
function _onceWrap (line 2) | function _onceWrap(s,o,i){var a={fired:!1,wrapFn:void 0,target:s,type:o,...
function _listeners (line 2) | function _listeners(s,o,i){var a=s._events;if(void 0===a)return[];var u=...
function listenerCount (line 2) | function listenerCount(s){var o=this._events;if(void 0!==o){var i=o[s];i...
function arrayClone (line 2) | function arrayClone(s,o){for(var i=new Array(o),a=0;a<o;++a)i[a]=s[a];re...
function eventTargetAgnosticAddListener (line 2) | function eventTargetAgnosticAddListener(s,o,i,a){if("function"==typeof s...
function Stack (line 2) | function Stack(s){var o=this.__data__=new a(s);this.size=o.size}
function invokeFunc (line 2) | function invokeFunc(o){var i=C,a=j;return C=j=void 0,V=o,B=s.apply(a,i)}
function shouldInvoke (line 2) | function shouldInvoke(s){var i=s-U;return void 0===U||i>=o||i<0||Y&&s-V>=L}
function timerExpired (line 2) | function timerExpired(){var s=u();if(shouldInvoke(s))return trailingEdge...
function trailingEdge (line 2) | function trailingEdge(s){return $=void 0,Z&&C?invokeFunc(s):(C=j=void 0,B)}
function debounced (line 2) | function debounced(){var s=u(),i=shouldInvoke(s);if(C=arguments,j=this,U...
function SetCache (line 2) | function SetCache(s){var o=-1,i=null==s?0:s.length;for(this.__data__=new...
function object (line 2) | function object(){}
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="number"}
method primitive (line 2) | primitive(){return"number"}
method constructor (line 2) | constructor(s,o,i){super(s||null,o,i),this.element="null"}
method primitive (line 2) | primitive(){return"null"}
method set (line 2) | set(){return new Error("Cannot set the value of null")}
method constructor (line 2) | constructor(s,o){if(this._setDefaults(s),s instanceof RegExp)this.ignore...
method _setDefaults (line 2) | _setDefaults(s){this.max=null!=s.max?s.max:null!=RandExp.prototype.max?R...
method gen (line 2) | gen(){return this._gen(this.tokens,[])}
method _gen (line 2) | _gen(s,o){var i,a,u,w,x;switch(s.type){case _.ROOT:case _.GROUP:if(s.fol...
method _toOtherCase (line 2) | _toOtherCase(s){return s+(97<=s&&s<=122?-32:65<=s&&s<=90?32:0)}
method _randBool (line 2) | _randBool(){return!this.randInt(0,1)}
method _randSelect (line 2) | _randSelect(s){return s instanceof u?s.index(this.randInt(0,s.length-1))...
method _expand (line 2) | _expand(s){if(s.type===a.types.CHAR)return new u(s.value);if(s.type===a....
method randInt (line 2) | randInt(s,o){return s+Math.floor(Math.random()*(1+o-s))}
method defaultRange (line 2) | get defaultRange(){return this._range=this._range||new u(32,126)}
method defaultRange (line 2) | set defaultRange(s){this._range=s}
method randexp (line 2) | static randexp(s,o){var i;return"string"==typeof s&&(s=new RegExp(s,o)),...
method sugar (line 2) | static sugar(){RegExp.prototype.gen=function(){return RandExp.randexp(th...
function highlight (line 2) | function highlight(s,o,i){var w,x=a.configure({}),C=(i||{}).prefix;if("s...
function Emitter (line 2) | function Emitter(s){this.options=s,this.rootNode={children:[]},this.stac...
function noop (line 2) | function noop(){}
function ReadableState (line 2) | function ReadableState(s,o,u){a=a||i(25382),s=s||{},"boolean"!=typeof u&...
function Readable (line 2) | function Readable(s){if(a=a||i(25382),!(this instanceof Readable))return...
function readableAddChunk (line 2) | function readableAddChunk(s,o,i,a,u){j("readableAddChunk",o);var _,w=s._...
function addChunk (line 2) | function addChunk(s,o,i,a){o.flowing&&0===o.length&&!o.sync?(o.awaitDrai...
function howMuchToRead (line 2) | function howMuchToRead(s,o){return s<=0||0===o.length&&o.ended?0:o.objec...
function emitReadable (line 2) | function emitReadable(s){var o=s._readableState;j("emitReadable",o.needR...
function emitReadable_ (line 2) | function emitReadable_(s){var o=s._readableState;j("emitReadable_",o.des...
function maybeReadMore (line 2) | function maybeReadMore(s,o){o.readingMore||(o.readingMore=!0,u.nextTick(...
function maybeReadMore_ (line 2) | function maybeReadMore_(s,o){for(;!o.reading&&!o.ended&&(o.length<o.high...
function updateReadableListening (line 2) | function updateReadableListening(s){var o=s._readableState;o.readableLis...
function nReadingNextTick (line 2) | function nReadingNextTick(s){j("readable nexttick read 0"),s.read(0)}
function resume_ (line 2) | function resume_(s,o){j("resume",o.reading),o.reading||s.read(0),o.resum...
function flow (line 2) | function flow(s){var o=s._readableState;for(j("flow",o.flowing);o.flowin...
function fromList (line 2) | function fromList(s,o){return 0===o.length?null:(o.objectMode?i=o.buffer...
function endReadable (line 2) | function endReadable(s){var o=s._readableState;j("endReadable",o.endEmit...
function endReadableNT (line 2) | function endReadableNT(s,o){if(j("endReadableNT",s.endEmitted,s.length),...
function indexOf (line 2) | function indexOf(s,o){for(var i=0,a=s.length;i<a;i++)if(s[i]===o)return ...
function onunpipe (line 2) | function onunpipe(o,u){j("onunpipe"),o===i&&u&&!1===u.hasUnpiped&&(u.has...
function onend (line 2) | function onend(){j("onend"),s.end()}
function ondata (line 2) | function ondata(o){j("ondata");var u=s.write(o);j("dest.write",u),!1===u...
function onerror (line 2) | function onerror(o){j("onerror",o),unpipe(),s.removeListener("error",one...
function onclose (line 2) | function onclose(){s.removeListener("finish",onfinish),unpipe()}
function onfinish (line 2) | function onfinish(){j("onfinish"),s.removeListener("close",onclose),unpi...
function unpipe (line 2) | function unpipe(){j("unpipe"),i.unpipe(s)}
function deepFreeze (line 2) | function deepFreeze(s){return s instanceof Map?s.clear=s.delete=s.set=fu...
class Response (line 2) | class Response{constructor(s){void 0===s.data&&(s.data={}),this.data=s.d...
method constructor (line 2) | constructor(s){void 0===s.data&&(s.data={}),this.data=s.data,this.isMa...
method ignoreMatch (line 2) | ignoreMatch(){this.isMatchIgnored=!0}
function escapeHTML (line 2) | function escapeHTML(s){return s.replace(/&/g,"&").replace(/</g,"<...
function inherit (line 2) | function inherit(s,...o){const i=Object.create(null);for(const o in s)i[...
class HTMLRenderer (line 2) | class HTMLRenderer{constructor(s,o){this.buffer="",this.classPrefix=o.cl...
method constructor (line 2) | constructor(s,o){this.buffer="",this.classPrefix=o.classPrefix,s.walk(...
method addText (line 2) | addText(s){this.buffer+=escapeHTML(s)}
method openNode (line 2) | openNode(s){if(!emitsWrappingTags(s))return;let o=s.kind;s.sublanguage...
method closeNode (line 2) | closeNode(s){emitsWrappingTags(s)&&(this.buffer+="</span>")}
method value (line 2) | value(){return this.buffer}
method span (line 2) | span(s){this.buffer+=`<span class="${s}">`}
class TokenTree (line 2) | class TokenTree{constructor(){this.rootNode={children:[]},this.stack=[th...
method constructor (line 2) | constructor(){this.rootNode={children:[]},this.stack=[this.rootNode]}
method top (line 2) | get top(){return this.stack[this.stack.length-1]}
method root (line 2) | get root(){return this.rootNode}
method add (line 2) | add(s){this.top.children.push(s)}
method openNode (line 2) | openNode(s){const o={kind:s,children:[]};this.add(o),this.stack.push(o)}
method closeNode (line 2) | closeNode(){if(this.stack.length>1)return this.stack.pop()}
method closeAllNodes (line 2) | closeAllNodes(){for(;this.closeNode(););}
method toJSON (line 2) | toJSON(){return JSON.stringify(this.rootNode,null,4)}
method walk (line 2) | walk(s){return this.constructor._walk(s,this.rootNode)}
method _walk (line 2) | static _walk(s,o){return"string"==typeof o?s.addText(o):o.children&&(s...
method _collapse (line 2) | static _collapse(s){"string"!=typeof s&&s.children&&(s.children.every(...
class TokenTreeEmitter (line 2) | class TokenTreeEmitter extends TokenTree{constructor(s){super(),this.opt...
method constructor (line 2) | constructor(s){super(),this.options=s}
method addKeyword (line 2) | addKeyword(s,o){""!==s&&(this.openNode(o),this.addText(s),this.closeNo...
method addText (line 2) | addText(s){""!==s&&this.add(s)}
method addSublanguage (line 2) | addSublanguage(s,o){const i=s.root;i.kind=o,i.sublanguage=!0,this.add(i)}
method toHTML (line 2) | toHTML(){return new HTMLRenderer(this,this.options).value()}
method finalize (line 2) | finalize(){return!0}
function source (line 2) | function source(s){return s?"string"==typeof s?s:s.source:null}
function skipIfhasPrecedingDot (line 2) | function skipIfhasPrecedingDot(s,o){"."===s.input[s.index-1]&&o.ignoreMa...
function beginKeywords (line 2) | function beginKeywords(s,o){o&&s.beginKeywords&&(s.begin="\\b("+s.beginK...
function compileIllegal (line 2) | function compileIllegal(s,o){Array.isArray(s.illegal)&&(s.illegal=functi...
function compileMatch (line 2) | function compileMatch(s,o){if(s.match){if(s.begin||s.end)throw new Error...
function compileRelevance (line 2) | function compileRelevance(s,o){void 0===s.relevance&&(s.relevance=1)}
function compileKeywords (line 2) | function compileKeywords(s,o,i="keyword"){const a={};return"string"==typ...
function scoreForKeyword (line 2) | function scoreForKeyword(s,o){return o?Number(o):function commonKeyword(...
function compileLanguage (line 2) | function compileLanguage(s,{plugins:o}){function langRe(o,i){return new ...
function dependencyOnParent (line 2) | function dependencyOnParent(s){return!!s&&(s.endsWithParent||dependencyO...
function BuildVuePlugin (line 2) | function BuildVuePlugin(s){const o={props:["language","code","autodetect...
function selectStream (line 2) | function selectStream(){return s.length&&o.length?s[0].offset!==o[0].off...
function open (line 2) | function open(s){function attributeString(s){return" "+s.nodeName+'="'+e...
function close (line 2) | function close(s){u+="</"+tag(s)+">"}
function render (line 2) | function render(s){("start"===s.event?open:close)(s.node)}
function tag (line 2) | function tag(s){return s.nodeName.toLowerCase()}
function nodeStream (line 2) | function nodeStream(s){const o=[];return function _nodeStream(s,i){for(l...
function shouldNotHighlight (line 2) | function shouldNotHighlight(s){return j.noHighlightRe.test(s)}
function highlight (line 2) | function highlight(s,o,i,a){let u="",_="";"object"==typeof o?(u=s,i=o.ig...
function _highlight (line 2) | function _highlight(s,o,a,w){function keywordData(s,o){const i=L.case_in...
function highlightAuto (line 2) | function highlightAuto(s,o){o=o||j.languages||Object.keys(i);const a=fun...
function highlightElement (line 2) | function highlightElement(s){let o=null;const i=function blockLanguage(s...
function highlightAll (line 2) | function highlightAll(){if("loading"===document.readyState)return void(U...
function getLanguage (line 2) | function getLanguage(s){return s=(s||"").toLowerCase(),i[s]||i[a[s]]}
function registerAliases (line 2) | function registerAliases(s,{languageName:o}){"string"==typeof s&&(s=[s])...
function autoDetection (line 2) | function autoDetection(s){const o=getLanguage(s);return o&&!o.disableAut...
function fire (line 2) | function fire(s,o){const i=s;u.forEach((function(s){s[i]&&s[i](o)}))}
function classNames (line 2) | function classNames(){for(var s="",o=0;o<arguments.length;o++){var i=arg...
function parseValue (line 2) | function parseValue(s){if("string"==typeof s||"number"==typeof s)return ...
function appendClass (line 2) | function appendClass(s,o){return o?s?s+" "+o:s+o:s}
function createBuffer (line 2) | function createBuffer(s){if(s>w)throw new RangeError('The value "'+s+'" ...
function Buffer (line 2) | function Buffer(s,o,i){if("number"==typeof s){if("string"==typeof o)thro...
function from (line 2) | function from(s,o,i){if("string"==typeof s)return function fromString(s,...
function assertSize (line 2) | function assertSize(s){if("number"!=typeof s)throw new TypeError('"size"...
function allocUnsafe (line 2) | function allocUnsafe(s){return assertSize(s),createBuffer(s<0?0:0|checke...
function fromArrayLike (line 2) | function fromArrayLike(s){const o=s.length<0?0:0|checked(s.length),i=cre...
function fromArrayBuffer (line 2) | function fromArrayBuffer(s,o,i){if(o<0||s.byteLength<o)throw new RangeEr...
function checked (line 2) | function checked(s){if(s>=w)throw new RangeError("Attempt to allocate Bu...
function byteLength (line 2) | function byteLength(s,o){if(Buffer.isBuffer(s))return s.length;if(ArrayB...
function slowToString (line 2) | function slowToString(s,o,i){let a=!1;if((void 0===o||o<0)&&(o=0),o>this...
function swap (line 2) | function swap(s,o,i){const a=s[o];s[o]=s[i],s[i]=a}
function bidirectionalIndexOf (line 2) | function bidirectionalIndexOf(s,o,i,a,u){if(0===s.length)return-1;if("st...
function arrayIndexOf (line 2) | function arrayIndexOf(s,o,i,a,u){let _,w=1,x=s.length,C=o.length;if(void...
function hexWrite (line 2) | function hexWrite(s,o,i,a){i=Number(i)||0;const u=s.length-i;a?(a=Number...
function utf8Write (line 2) | function utf8Write(s,o,i,a){return blitBuffer(utf8ToBytes(o,s.length-i),...
function asciiWrite (line 2) | function asciiWrite(s,o,i,a){return blitBuffer(function asciiToBytes(s){...
function base64Write (line 2) | function base64Write(s,o,i,a){return blitBuffer(base64ToBytes(o),s,i,a)}
function ucs2Write (line 2) | function ucs2Write(s,o,i,a){return blitBuffer(function utf16leToBytes(s,...
function base64Slice (line 2) | function base64Slice(s,o,i){return 0===o&&i===s.length?a.fromByteArray(s...
function utf8Slice (line 2) | function utf8Slice(s,o,i){i=Math.min(s.length,i);const a=[];let u=o;for(...
function asciiSlice (line 2) | function asciiSlice(s,o,i){let a="";i=Math.min(s.length,i);for(let u=o;u...
function latin1Slice (line 2) | function latin1Slice(s,o,i){let a="";i=Math.min(s.length,i);for(let u=o;...
function hexSlice (line 2) | function hexSlice(s,o,i){const a=s.length;(!o||o<0)&&(o=0),(!i||i<0||i>a...
function utf16leSlice (line 2) | function utf16leSlice(s,o,i){const a=s.slice(o,i);let u="";for(let s=0;s...
function checkOffset (line 2) | function checkOffset(s,o,i){if(s%1!=0||s<0)throw new RangeError("offset ...
function checkInt (line 2) | function checkInt(s,o,i,a,u,_){if(!Buffer.isBuffer(s))throw new TypeErro...
function wrtBigUInt64LE (line 2) | function wrtBigUInt64LE(s,o,i,a,u){checkIntBI(o,a,u,s,i,7);let _=Number(...
function wrtBigUInt64BE (line 2) | function wrtBigUInt64BE(s,o,i,a,u){checkIntBI(o,a,u,s,i,7);let _=Number(...
function checkIEEE754 (line 2) | function checkIEEE754(s,o,i,a,u,_){if(i+a>s.length)throw new RangeError(...
function writeFloat (line 2) | function writeFloat(s,o,i,a,_){return o=+o,i>>>=0,_||checkIEEE754(s,0,i,...
function writeDouble (line 2) | function writeDouble(s,o,i,a,_){return o=+o,i>>>=0,_||checkIEEE754(s,0,i...
function E (line 2) | function E(s,o,i){C[s]=class NodeError extends i{constructor(){super(),O...
function addNumericalSeparator (line 2) | function addNumericalSeparator(s){let o="",i=s.length;const a="-"===s[0]...
function checkIntBI (line 2) | function checkIntBI(s,o,i,a,u,_){if(s>i||s<o){const a="bigint"==typeof o...
function validateNumber (line 2) | function validateNumber(s,o){if("number"!=typeof s)throw new C.ERR_INVAL...
function boundsError (line 2) | function boundsError(s,o,i){if(Math.floor(s)!==s)throw validateNumber(s,...
function utf8ToBytes (line 2) | function utf8ToBytes(s,o){let i;o=o||1/0;const a=s.length;let u=null;con...
function base64ToBytes (line 2) | function base64ToBytes(s){return a.toByteArray(function base64clean(s){i...
function blitBuffer (line 2) | function blitBuffer(s,o,i,a){let u;for(u=0;u<a&&!(u+i>=o.length||u>=s.le...
function isInstance (line 2) | function isInstance(s,o){return s instanceof o||null!=s&&null!=s.constru...
function numberIsNaN (line 2) | function numberIsNaN(s){return s!=s}
function defineBigIntMethod (line 2) | function defineBigIntMethod(s){return"undefined"==typeof BigInt?BufferBi...
function BufferBigIntNotDefined (line 2) | function BufferBigIntNotDefined(){throw new Error("BigInt not supported")}
function curry (line 2) | function curry(s,o,i){var u=a(s,8,void 0,void 0,void 0,void 0,void 0,o=i...
function memoize (line 2) | function memoize(s,o){if("function"!=typeof s||null!=o&&"function"!=type...
function MapCache (line 2) | function MapCache(s){var o=-1,i=null==s?0:s.length;for(this.clear();++o<...
function lodash (line 2) | function lodash(s){if(x(s)&&!w(s)&&!(s instanceof a)){if(s instanceof u)...
function _interopRequireDefault (line 2) | function _interopRequireDefault(s){return s&&s.__esModule?s:{default:s}}
class KeyValuePair (line 2) | class KeyValuePair{constructor(s,o){this.key=s,this.value=o}clone(){cons...
method constructor (line 2) | constructor(s,o){this.key=s,this.value=o}
method clone (line 2) | clone(){const s=new KeyValuePair;return this.key&&(s.key=this.key.clon...
function LodashWrapper (line 2) | function LodashWrapper(s,o){this.__wrapped__=s,this.__actions__=[],this....
function F (line 2) | function F(){}
function noop (line 2) | function noop(s){if(s)throw s}
function call (line 2) | function call(s){s()}
function pipe (line 2) | function pipe(s,o){return s.pipe(o)}
method constructor (line 2) | constructor(s,o,i){super(s||[],o,i),this.element="object"}
method primitive (line 2) | primitive(){return"object"}
method toValue (line 2) | toValue(){return this.content.reduce(((s,o)=>(s[o.key.toValue()]=o.value...
method get (line 2) | get(s){const o=this.getMember(s);if(o)return o.value}
method getMember (line 2) | getMember(s){if(void 0!==s)return this.content.find((o=>o.key.toValue()=...
method remove (line 2) | remove(s){let o=null;return this.content=this.content.filter((i=>i.key.t...
method getKey (line 2) | getKey(s){const o=this.getMember(s);if(o)return o.key}
method set (line 2) | set(s,o){if(u(s))return Object.keys(s).forEach((o=>{this.set(o,s[o])})),...
method keys (line 2) | keys(){return this.content.map((s=>s.key.toValue()))}
method values (line 2) | values(){return this.content.map((s=>s.value.toValue()))}
method hasKey (line 2) | hasKey(s){return this.content.some((o=>o.key.equals(s)))}
method items (line 2) | items(){return this.content.map((s=>[s.key.toValue(),s.value.toValue()]))}
method map (line 2) | map(s,o){return this.content.map((i=>s.bind(o)(i.value,i.key,i)))}
method compactMap (line 2) | compactMap(s,o){const i=[];return this.forEach(((a,u,_)=>{const w=s.bind...
method filter (line 2) | filter(s,o){return new x(this.content).filter(s,o)}
method reject (line 2) | reject(s,o){return this.filter(a(s),o)}
method forEach (line 2) | forEach(s,o){return this.content.forEach((i=>s.bind(o)(i.value,i.key,i)))}
function trimLeft (line 2) | function trimLeft(s){return(s||"").toString().replace(_,"")}
function lolcation (line 2) | function lolcation(s){var o,a=("undefined"!=typeof window?window:void 0!...
function isSpecial (line 2) | function isSpecial(s){return"file:"===s||"ftp:"===s||"http:"===s||"https...
function extractProtocol (line 2) | function extractProtocol(s,o){s=(s=trimLeft(s)).replace(w,""),o=o||{};va...
function Url (line 2) | function Url(s,o,i){if(s=(s=trimLeft(s)).replace(w,""),!(this instanceof...
function PassThrough (line 2) | function PassThrough(s){if(!(this instanceof PassThrough))return new Pas...
function Sha1 (line 2) | function Sha1(){this.init(),this._w=x,u.call(this,64,56)}
function rotl5 (line 2) | function rotl5(s){return s<<5|s>>>27}
function rotl30 (line 2) | function rotl30(s){return s<<30|s>>>2}
function ft (line 2) | function ft(s,o,i,a){return 0===s?o&i|~o&a:2===s?o&i|o&a|i&a:o^i^a}
function defaultSetTimout (line 2) | function defaultSetTimout(){throw new Error("setTimeout has not been def...
function defaultClearTimeout (line 2) | function defaultClearTimeout(){throw new Error("clearTimeout has not bee...
function runTimeout (line 2) | function runTimeout(s){if(o===setTimeout)return setTimeout(s,0);if((o===...
function cleanUpNextTick (line 2) | function cleanUpNextTick(){w&&u&&(w=!1,u.length?_=u.concat(_):x=-1,_.len...
function drainQueue (line 2) | function drainQueue(){if(!w){var s=runTimeout(cleanUpNextTick);w=!0;for(...
function Item (line 2) | function Item(s,o){this.fun=s,this.array=o}
function noop (line 2) | function noop(){}
function getLens (line 2) | function getLens(s){var o=s.length;if(o%4>0)throw new Error("Invalid str...
function encodeChunk (line 2) | function encodeChunk(s,o,a){for(var u,_,w=[],x=o;x<a;x+=3)u=(s[x]<<16&16...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="string"}
method primitive (line 2) | primitive(){return"string"}
method length (line 2) | get length(){return this.content.length}
function concat (line 2) | function concat(...s){return s.map((s=>function source(s){return s?"stri...
function baseAry (line 2) | function baseAry(s,o){return 2==o?function(o,i){return s(o,i)}:function(...
function cloneArray (line 2) | function cloneArray(s){for(var o=s?s.length:0,i=Array(o);o--;)i[o]=s[o];...
function wrapImmutable (line 2) | function wrapImmutable(s,o){return function(){var i=arguments.length;if(...
function castCap (line 2) | function castCap(s,o){if(j){var i=a.iterateeRearg[s];if(i)return functio...
function castFixed (line 2) | function castFixed(s,o,i){if(B&&(Y||!a.skipFixed[s])){var u=a.methodSpre...
function castRearg (line 2) | function castRearg(s,o,i){return U&&i>1&&(Z||!a.skipRearg[s])?we(o,a.met...
function cloneByPath (line 2) | function cloneByPath(s,o){for(var i=-1,a=(o=Pe(o)).length,u=a-1,_=le(Obj...
function createConverter (line 2) | function createConverter(s,o){var i=a.aliasToReal[s]||s,u=a.remap[i]||i,...
function overArg (line 2) | function overArg(s,o){return function(){var i=arguments.length;if(!i)ret...
function wrap (line 2) | function wrap(s,o,i){var u,_=a.aliasToReal[s]||s,w=o,x=Re[_];return x?w=...
function decode (line 2) | function decode(s){try{return decodeURIComponent(s.replace(/\+/g," "))}c...
function encode (line 2) | function encode(s){try{return encodeURIComponent(s)}catch(s){return null}}
function afterTransform (line 2) | function afterTransform(s,o){var i=this._transformState;i.transforming=!...
function Transform (line 2) | function Transform(s){if(!(this instanceof Transform))return new Transfo...
function prefinish (line 2) | function prefinish(){var s=this;"function"!=typeof this._flush||this._re...
function done (line 2) | function done(s,o,i){if(o)return s.emit("error",o);if(null!=i&&s.push(i)...
method serialise (line 2) | serialise(s){if(!(s instanceof this.namespace.elements.Element))throw ne...
method shouldSerialiseContent (line 2) | shouldSerialiseContent(s,o){return"parseResult"===s.element||"httpReques...
method refSerialiseContent (line 2) | refSerialiseContent(s,o){return delete o.attributes,{href:s.toValue(),pa...
method sourceMapSerialiseContent (line 2) | sourceMapSerialiseContent(s){return s.toValue()}
method dataStructureSerialiseContent (line 2) | dataStructureSerialiseContent(s){return[this.serialiseContent(s.content)]}
method enumSerialiseAttributes (line 2) | enumSerialiseAttributes(s){const o=s.attributes.clone(),i=o.remove("enum...
method enumSerialiseContent (line 2) | enumSerialiseContent(s){if(s._attributes){const o=s.attributes.get("enum...
method deserialise (line 2) | deserialise(s){if("string"==typeof s)return new this.namespace.elements....
method serialiseContent (line 2) | serialiseContent(s){if(s instanceof this.namespace.elements.Element)retu...
method deserialiseContent (line 2) | deserialiseContent(s){if(s){if(s.element)return this.deserialise(s);if(s...
method shouldRefract (line 2) | shouldRefract(s){return!!(s._attributes&&s.attributes.keys().length||s._...
method convertKeyToRefract (line 2) | convertKeyToRefract(s,o){return this.shouldRefract(o)?this.serialise(o):...
method serialiseEnum (line 2) | serialiseEnum(s){return s.children.map((s=>this.serialise(s)))}
method serialiseObject (line 2) | serialiseObject(s){const o={};return s.forEach(((s,i)=>{if(s){const a=i....
method deserialiseObject (line 2) | deserialiseObject(s,o){Object.keys(s).forEach((i=>{o.set(i,this.deserial...
function emitErrorAndCloseNT (line 2) | function emitErrorAndCloseNT(s,o){emitErrorNT(s,o),emitCloseNT(s)}
function emitCloseNT (line 2) | function emitCloseNT(s){s._writableState&&!s._writableState.emitClose||s...
function emitErrorNT (line 2) | function emitErrorNT(s,o){s.emit("error",o)}
class SubRange (line 2) | class SubRange{constructor(s,o){this.low=s,this.high=o,this.length=1+o-s...
method constructor (line 2) | constructor(s,o){this.low=s,this.high=o,this.length=1+o-s}
method overlaps (line 2) | overlaps(s){return!(this.high<s.low||this.low>s.high)}
method touches (line 2) | touches(s){return!(this.high+1<s.low||this.low-1>s.high)}
method add (line 2) | add(s){return new SubRange(Math.min(this.low,s.low),Math.max(this.high...
method subtract (line 2) | subtract(s){return s.low<=this.low&&s.high>=this.high?[]:s.low>this.lo...
method toString (line 2) | toString(){return this.low==this.high?this.low.toString():this.low+"-"...
class DRange (line 2) | class DRange{constructor(s,o){this.ranges=[],this.length=0,null!=s&&this...
method constructor (line 2) | constructor(s,o){this.ranges=[],this.length=0,null!=s&&this.add(s,o)}
method _update_length (line 2) | _update_length(){this.length=this.ranges.reduce(((s,o)=>s+o.length),0)}
method add (line 2) | add(s,o){var _add=s=>{for(var o=0;o<this.ranges.length&&!s.touches(thi...
method subtract (line 2) | subtract(s,o){var _subtract=s=>{for(var o=0;o<this.ranges.length&&!s.o...
method intersect (line 2) | intersect(s,o){var i=[],_intersect=s=>{for(var o=0;o<this.ranges.lengt...
method index (line 2) | index(s){for(var o=0;o<this.ranges.length&&this.ranges[o].length<=s;)s...
method toString (line 2) | toString(){return"[ "+this.ranges.join(", ")+" ]"}
method clone (line 2) | clone(){return new DRange(this)}
method numbers (line 2) | numbers(){return this.ranges.reduce(((s,o)=>{for(var i=o.low;i<=o.high...
method subranges (line 2) | subranges(){return this.ranges.map((s=>({low:s.low,high:s.high,length:...
function ListCache (line 2) | function ListCache(s){var o=-1,i=null==s?0:s.length;for(this.clear();++o...
function ownKeys (line 2) | function ownKeys(s,o){var i=Object.keys(s);if(Object.getOwnPropertySymbo...
function _objectSpread (line 2) | function _objectSpread(s){for(var o=1;o<arguments.length;o++){var i=null...
function _defineProperty (line 2) | function _defineProperty(s,o,i){return(o=_toPropertyKey(o))in s?Object.d...
function _defineProperties (line 2) | function _defineProperties(s,o){for(var i=0;i<o.length;i++){var a=o[i];a...
function _toPropertyKey (line 2) | function _toPropertyKey(s){var o=function _toPrimitive(s,o){if("object"!...
function BufferList (line 2) | function BufferList(){!function _classCallCheck(s,o){if(!(s instanceof o...
function _typeof (line 2) | function _typeof(s){return _typeof="function"==typeof Symbol&&"symbol"==...
function _interopRequireDefault (line 2) | function _interopRequireDefault(s){return s&&s.__esModule?s:{default:s}}
function _objectWithoutProperties (line 2) | function _objectWithoutProperties(s,o){if(null==s)return{};var i,a,u=fun...
function ownKeys (line 2) | function ownKeys(s,o){var i=Object.keys(s);if(Object.getOwnPropertySymbo...
function _objectSpread (line 2) | function _objectSpread(s){for(var o=1;o<arguments.length;o++){var i=null...
function _defineProperties (line 2) | function _defineProperties(s,o){for(var i=0;i<o.length;i++){var a=o[i];a...
function _setPrototypeOf (line 2) | function _setPrototypeOf(s,o){return _setPrototypeOf=Object.setPrototype...
function _createSuper (line 2) | function _createSuper(s){var o=function _isNativeReflectConstruct(){if("...
function _assertThisInitialized (line 2) | function _assertThisInitialized(s){if(void 0===s)throw new ReferenceErro...
function _getPrototypeOf (line 2) | function _getPrototypeOf(s){return _getPrototypeOf=Object.setPrototypeOf...
function _defineProperty (line 2) | function _defineProperty(s,o,i){return o in s?Object.defineProperty(s,o,...
function DebounceInput (line 2) | function DebounceInput(s){var i;!function _classCallCheck(s,o){if(!(s in...
function isSpecificValue (line 2) | function isSpecificValue(s){return s instanceof a||s instanceof Date||s ...
function cloneSpecificValue (line 2) | function cloneSpecificValue(s){if(s instanceof a){var o=a.alloc?a.alloc(...
function deepCloneArray (line 2) | function deepCloneArray(s){var o=[];return s.forEach((function(s,i){"obj...
function safeGetProperty (line 2) | function safeGetProperty(s,o){return"__proto__"===o?void 0:s[o]}
function _interopRequireDefault (line 2) | function _interopRequireDefault(s){return s&&s.__esModule?s:{default:s}}
function Sha512 (line 2) | function Sha512(){this.init(),this._w=x,u.call(this,128,112)}
function Ch (line 2) | function Ch(s,o,i){return i^s&(o^i)}
function maj (line 2) | function maj(s,o,i){return s&o|i&(s|o)}
function sigma0 (line 2) | function sigma0(s,o){return(s>>>28|o<<4)^(o>>>2|s<<30)^(o>>>7|s<<25)}
function sigma1 (line 2) | function sigma1(s,o){return(s>>>14|o<<18)^(s>>>18|o<<14)^(o>>>9|s<<23)}
function Gamma0 (line 2) | function Gamma0(s,o){return(s>>>1|o<<31)^(s>>>8|o<<24)^s>>>7}
function Gamma0l (line 2) | function Gamma0l(s,o){return(s>>>1|o<<31)^(s>>>8|o<<24)^(s>>>7|o<<25)}
function Gamma1 (line 2) | function Gamma1(s,o){return(s>>>19|o<<13)^(o>>>29|s<<3)^s>>>6}
function Gamma1l (line 2) | function Gamma1l(s,o){return(s>>>19|o<<13)^(o>>>29|s<<3)^(s>>>6|o<<26)}
function getCarry (line 2) | function getCarry(s,o){return s>>>0<o>>>0?1:0}
function writeInt64BE (line 2) | function writeInt64BE(o,i,a){s.writeInt32BE(o,a),s.writeInt32BE(i,a+4)}
function StringDecoder (line 2) | function StringDecoder(s){var o;switch(this.encoding=function normalizeE...
function utf8CheckByte (line 2) | function utf8CheckByte(s){return s<=127?0:s>>5==6?2:s>>4==14?3:s>>3==30?...
function utf8FillLast (line 2) | function utf8FillLast(s){var o=this.lastTotal-this.lastNeed,i=function u...
function utf16Text (line 2) | function utf16Text(s,o){if((s.length-o)%2==0){var i=s.toString("utf16le"...
function utf16End (line 2) | function utf16End(s){var o=s&&s.length?this.write(s):"";if(this.lastNeed...
function base64Text (line 2) | function base64Text(s,o){var i=(s.length-o)%3;return 0===i?s.toString("b...
function base64End (line 2) | function base64End(s){var o=s&&s.length?this.write(s):"";return this.las...
function simpleWrite (line 2) | function simpleWrite(s){return s.toString(this.encoding)}
function simpleEnd (line 2) | function simpleEnd(s){return s&&s.length?this.write(s):""}
method constructor (line 2) | constructor(s){this.namespace=s||new this.Namespace}
method serialise (line 2) | serialise(s){if(!(s instanceof this.namespace.elements.Element))throw ne...
method deserialise (line 2) | deserialise(s){if(!s.element)throw new Error("Given value is not an obje...
method serialiseContent (line 2) | serialiseContent(s){if(s instanceof this.namespace.elements.Element)retu...
method deserialiseContent (line 2) | deserialiseContent(s){if(s){if(s.element)return this.deserialise(s);if(s...
method serialiseObject (line 2) | serialiseObject(s){const o={};if(s.forEach(((s,i)=>{s&&(o[i.toValue()]=t...
method deserialiseObject (line 2) | deserialiseObject(s,o){Object.keys(s).forEach((i=>{o.set(i,this.deserial...
function create (line 2) | function create(s){return FormattedError.displayName=s.displayName||s.na...
function createErrorType (line 2) | function createErrorType(s,i,a){a||(a=Error);var u=function(s){function ...
function oneOf (line 2) | function oneOf(s,o){if(Array.isArray(s)){var i=s.length;return s=s.map((...
function noop (line 2) | function noop(){}
method constructor (line 2) | constructor(s,o,i){super(s||[],o,i),this.element="link"}
method relation (line 2) | get relation(){return this.attributes.get("relation")}
method relation (line 2) | set relation(s){this.attributes.set("relation",s)}
method href (line 2) | get href(){return this.attributes.get("href")}
method href (line 2) | set href(s){this.attributes.set("href",s)}
function refract (line 2) | function refract(s){if(s instanceof a)return s;if("string"==typeof s)ret...
method constructor (line 2) | constructor(s,o,i,u){super(new a,i,u),this.element="member",this.key=s,t...
method key (line 2) | get key(){return this.content.key}
method key (line 2) | set key(s){this.content.key=this.refract(s)}
method value (line 2) | get value(){return this.content.value}
method value (line 2) | set value(s){this.content.value=this.refract(s)}
function Stream (line 2) | function Stream(){a.call(this)}
function ondata (line 2) | function ondata(o){s.writable&&!1===s.write(o)&&i.pause&&i.pause()}
function ondrain (line 2) | function ondrain(){i.readable&&i.resume&&i.resume()}
function onend (line 2) | function onend(){u||(u=!0,s.end())}
function onclose (line 2) | function onclose(){u||(u=!0,"function"==typeof s.destroy&&s.destroy())}
function onerror (line 2) | function onerror(s){if(cleanup(),0===a.listenerCount(this,"error"))throw s}
function cleanup (line 2) | function cleanup(){i.removeListener("data",ondata),s.removeListener("dra...
function Hash (line 2) | function Hash(s,o){this._block=a.alloc(s),this._finalSize=o,this._blockS...
function coerceElementMatchingCallback (line 2) | function coerceElementMatchingCallback(s){return"string"==typeof s?o=>o....
class ArraySlice (line 2) | class ArraySlice{constructor(s){this.elements=s||[]}toValue(){return thi...
method constructor (line 2) | constructor(s){this.elements=s||[]}
method toValue (line 2) | toValue(){return this.elements.map((s=>s.toValue()))}
method map (line 2) | map(s,o){return this.elements.map(s,o)}
method flatMap (line 2) | flatMap(s,o){return this.map(s,o).reduce(((s,o)=>s.concat(o)),[])}
method compactMap (line 2) | compactMap(s,o){const i=[];return this.forEach((a=>{const u=s.bind(o)(...
method filter (line 2) | filter(s,o){return s=coerceElementMatchingCallback(s),new ArraySlice(t...
method reject (line 2) | reject(s,o){return s=coerceElementMatchingCallback(s),new ArraySlice(t...
method find (line 2) | find(s,o){return s=coerceElementMatchingCallback(s),this.elements.find...
method forEach (line 2) | forEach(s,o){this.elements.forEach(s,o)}
method reduce (line 2) | reduce(s,o){return this.elements.reduce(s,o)}
method includes (line 2) | includes(s){return this.elements.some((o=>o.equals(s)))}
method shift (line 2) | shift(){return this.elements.shift()}
method unshift (line 2) | unshift(s){this.elements.unshift(this.refract(s))}
method push (line 2) | push(s){return this.elements.push(this.refract(s)),this}
method add (line 2) | add(s){this.push(s)}
method get (line 2) | get(s){return this.elements[s]}
method getValue (line 2) | getValue(s){const o=this.elements[s];if(o)return o.toValue()}
method length (line 2) | get length(){return this.elements.length}
method isEmpty (line 2) | get isEmpty(){return 0===this.elements.length}
method first (line 2) | get first(){return this.elements[0]}
function copyProps (line 2) | function copyProps(s,o){for(var i in s)o[i]=s[i]}
function SafeBuffer (line 2) | function SafeBuffer(s,o,i){return u(s,o,i)}
function config (line 2) | function config(s){try{if(!i.g.localStorage)return!1}catch(s){return!1}v...
function lookahead (line 2) | function lookahead(s){return concat("(?=",s,")")}
function concat (line 2) | function concat(...s){return s.map((s=>function source(s){return s?"stri...
function __webpack_require__ (line 2) | function __webpack_require__(i){var a=o[i];if(void 0!==a)return a.export...
function formatProdErrorMessage (line 2) | function formatProdErrorMessage(s){return`Minified Redux error #${s}; vi...
function isPlainObject (line 2) | function isPlainObject(s){if("object"!=typeof s||null===s)return!1;let o...
function createStore (line 2) | function createStore(s,o,i){if("function"!=typeof s)throw new Error(form...
function bindActionCreator (line 2) | function bindActionCreator(s,o){return function(...i){return o(s.apply(t...
function compose (line 2) | function compose(...s){return 0===s.length?s=>s:1===s.length?s[0]:s.redu...
function newThrownErr (line 2) | function newThrownErr(s){return{type:rt,payload:(0,Qe.serializeError)(s)}}
function newThrownErrBatch (line 2) | function newThrownErrBatch(s){return{type:nt,payload:s}}
function newSpecErr (line 2) | function newSpecErr(s){return{type:st,payload:s}}
function newSpecErrBatch (line 2) | function newSpecErrBatch(s){return{type:ot,payload:s}}
function newAuthErr (line 2) | function newAuthErr(s){return{type:it,payload:s}}
function clear (line 2) | function clear(s={}){return{type:at,payload:s}}
function clearBy (line 2) | function clearBy(s=()=>!0){return{type:ct,payload:s}}
function getParameterSchema (line 2) | function getParameterSchema(s,{isOAS3:o}={}){if(!We().Map.isMap(s))retur...
function objectify (line 2) | function objectify(s){return isObject(s)?immutableToJS(s):{}}
function fromJSOrdered (line 2) | function fromJSOrdered(s){if(isImmutable(s))return s;if(s instanceof lt....
function normalizeArray (line 2) | function normalizeArray(s){return Array.isArray(s)?s:[s]}
function isFn (line 2) | function isFn(s){return"function"==typeof s}
function isObject (line 2) | function isObject(s){return!!s&&"object"==typeof s}
function isFunc (line 2) | function isFunc(s){return"function"==typeof s}
function isArray (line 2) | function isArray(s){return Array.isArray(s)}
function objMap (line 2) | function objMap(s,o){return Object.keys(s).reduce(((i,a)=>(i[a]=o(s[a],a...
function objReduce (line 2) | function objReduce(s,o){return Object.keys(s).reduce(((i,a)=>{let u=o(s[...
function systemThunkMiddleware (line 2) | function systemThunkMiddleware(s){return({dispatch:o,getState:i})=>o=>i=...
function validateValueBySchema (line 2) | function validateValueBySchema(s,o,i,a,u){if(!o)return[];let _=[],w=o.ge...
function requiresValidationURL (line 2) | function requiresValidationURL(s){return!(!s||s.indexOf("localhost")>=0|...
function deeplyStripKey (line 2) | function deeplyStripKey(s,o,i=()=>!0){if("object"!=typeof s||Array.isArr...
function stringify (line 2) | function stringify(s){if("string"==typeof s)return s;if(s&&s.toJS&&(s=s....
function paramToIdentifier (line 2) | function paramToIdentifier(s,{returnAll:o=!1,allowHashes:i=!0}={}){if(!W...
function paramToValue (line 2) | function paramToValue(s,o){return paramToIdentifier(s,{returnAll:!0}).ma...
function b64toB64UrlEncoded (line 2) | function b64toB64UrlEncoded(s){return s.replace(/\+/g,"-").replace(/\//g...
function createStoreWithMiddleware (line 2) | function createStoreWithMiddleware(s,o,i){let a=[systemThunkMiddleware(i...
class Store (line 2) | class Store{constructor(s={}){Ye()(this,{state:{},plugins:[],system:{con...
method constructor (line 2) | constructor(s={}){Ye()(this,{state:{},plugins:[],system:{configs:{},fn...
method getStore (line 2) | getStore(){return this.store}
method register (line 2) | register(s,o=!0){var i=combinePlugins(s,this.getSystem());systemExtend...
method buildSystem (line 2) | buildSystem(s=!0){let o=this.getStore().dispatch,i=this.getStore().get...
method _getSystem (line 2) | _getSystem(){return this.boundSystem}
method getRootInjects (line 2) | getRootInjects(){return Object.assign({getSystem:this.getSystem,getSto...
method _getConfigs (line 2) | _getConfigs(){return this.system.configs}
method getConfigs (line 2) | getConfigs(){return{configs:this.system.configs}}
method setConfigs (line 2) | setConfigs(s){this.system.configs=s}
method rebuildReducer (line 2) | rebuildReducer(){this.store.replaceReducer(function buildReducer(s,o){...
method getType (line 2) | getType(s){let o=s[0].toUpperCase()+s.slice(1);return objReduce(this.s...
method getSelectors (line 2) | getSelectors(){return this.getType("selectors")}
method getActions (line 2) | getActions(){return objMap(this.getType("actions"),(s=>objReduce(s,((s...
method getWrappedAndBoundActions (line 2) | getWrappedAndBoundActions(s){return objMap(this.getBoundActions(s),((s...
method getWrappedAndBoundSelectors (line 2) | getWrappedAndBoundSelectors(s,o){return objMap(this.getBoundSelectors(...
method getStates (line 2) | getStates(s){return Object.keys(this.system.statePlugins).reduce(((o,i...
method getStateThunks (line 2) | getStateThunks(s){return Object.keys(this.system.statePlugins).reduce(...
method getFn (line 2) | getFn(){return{fn:this.system.fn}}
method getComponents (line 2) | getComponents(s){const o=this.system.components[s];return Array.isArra...
method getBoundSelectors (line 2) | getBoundSelectors(s,o){return objMap(this.getSelectors(),((i,a)=>{let ...
method getBoundActions (line 2) | getBoundActions(s){s=s||this.getStore().dispatch;const o=this.getActio...
method getMapStateToProps (line 2) | getMapStateToProps(){return()=>Object.assign({},this.getSystem())}
method getMapDispatchToProps (line 2) | getMapDispatchToProps(s){return o=>Ye()({},this.getWrappedAndBoundActi...
function combinePlugins (line 2) | function combinePlugins(s,o){return isObject(s)&&!isArray(s)?tt()({},s):...
function callAfterLoad (line 2) | function callAfterLoad(s,o,{hasLoaded:i}={}){let a=i;return isObject(s)&...
function systemExtend (line 2) | function systemExtend(s={},o={}){if(!isObject(s))return{};if(!isObject(o...
function wrapWithTryCatch (line 2) | function wrapWithTryCatch(s,o,{logErrors:i=!0}={}){return"function"!=typ...
function showDefinitions (line 2) | function showDefinitions(s){return{type:Mt,payload:s}}
function authorize (line 2) | function authorize(s){return{type:Rt,payload:s}}
function logout (line 2) | function logout(s){return{type:Dt,payload:s}}
function authorizeOauth2 (line 2) | function authorizeOauth2(s){return{type:Lt,payload:s}}
function configureAuth (line 2) | function configureAuth(s){return{type:Ft,payload:s}}
function restoreAuthorization (line 2) | function restoreAuthorization(s){return{type:Bt,payload:s}}
function assertIsFunction (line 2) | function assertIsFunction(s,o="expected a function, instead received "+t...
function getDependencies (line 2) | function getDependencies(s){const o=Array.isArray(s[0])?s[0]:s;return fu...
method constructor (line 2) | constructor(s){this.value=s}
method deref (line 2) | deref(){return this.value}
function weakMapMemoize (line 2) | function weakMapMemoize(s,o={}){let i={s:0,v:void 0,o:null,p:null};const...
function createSelectorCreator (line 2) | function createSelectorCreator(s,...o){const i="function"==typeof s?{mem...
class LockAuthIcon (line 2) | class LockAuthIcon extends Re.Component{mapStateToProps(s,o){return{stat...
method mapStateToProps (line 2) | mapStateToProps(s,o){return{state:s,ownProps:Gt()(o,Object.keys(o.getS...
method render (line 2) | render(){const{getComponent:s,ownProps:o}=this.props,i=s("LockIcon");r...
class UnlockAuthIcon (line 2) | class UnlockAuthIcon extends Re.Component{mapStateToProps(s,o){return{st...
method mapStateToProps (line 2) | mapStateToProps(s,o){return{state:s,ownProps:Gt()(o,Object.keys(o.getS...
method render (line 2) | render(){const{getComponent:s,ownProps:o}=this.props,i=s("UnlockIcon")...
function auth (line 2) | function auth(){return{afterLoad(s){this.rootInjects=this.rootInjects||{...
function preauthorizeBasic (line 2) | function preauthorizeBasic(s,o,i,a){const{authActions:{authorize:u},spec...
function preauthorizeApiKey (line 2) | function preauthorizeApiKey(s,o,i){const{authActions:{authorize:a},specS...
function isNothing (line 2) | function isNothing(s){return null==s}
function formatError (line 2) | function formatError(s,o){var i="",a=s.reason||"(unknown reason)";return...
function YAMLException$1 (line 2) | function YAMLException$1(s,o){Error.call(this),this.name="YAMLException"...
function getLine (line 2) | function getLine(s,o,i,a,u){var _="",w="",x=Math.floor(u/2)-1;return a-o...
function padStart (line 2) | function padStart(s,o){return er.repeat(" ",o-s.length)+s}
function compileList (line 2) | function compileList(s,o){var i=[];return s[o].forEach((function(s){var ...
function Schema$1 (line 2) | function Schema$1(s){return this.extend(s)}
function collectType (line 2) | function collectType(s){s.multi?(i.multi[s.kind].push(s),i.multi.fallbac...
function isOctCode (line 2) | function isOctCode(s){return 48<=s&&s<=55}
function isDecCode (line 2) | function isDecCode(s){return 48<=s&&s<=57}
function _class (line 2) | function _class(s){return Object.prototype.toString.call(s)}
function is_EOL (line 2) | function is_EOL(s){return 10===s||13===s}
function is_WHITE_SPACE (line 2) | function is_WHITE_SPACE(s){return 9===s||32===s}
function is_WS_OR_EOL (line 2) | function is_WS_OR_EOL(s){return 9===s||32===s||10===s||13===s}
function is_FLOW_INDICATOR (line 2) | function is_FLOW_INDICATOR(s){return 44===s||91===s||93===s||123===s||12...
function fromHexCode (line 2) | function fromHexCode(s){var o;return 48<=s&&s<=57?s-48:97<=(o=32|s)&&o<=...
function simpleEscapeSequence (line 2) | function simpleEscapeSequence(s){return 48===s?"\0":97===s?"":98===s?"\...
function charFromCodepoint (line 2) | function charFromCodepoint(s){return s<=65535?String.fromCharCode(s):Str...
function State$1 (line 2) | function State$1(s,o){this.input=s,this.filename=o.filename||null,this.s...
function generateError (line 2) | function generateError(s,o){var i={name:s.filename,buffer:s.input.slice(...
function throwError (line 2) | function throwError(s,o){throw generateError(s,o)}
function throwWarning (line 2) | function throwWarning(s,o){s.onWarning&&s.onWarning.call(null,generateEr...
function captureSegment (line 2) | function captureSegment(s,o,i,a){var u,_,w,x;if(o<i){if(x=s.input.slice(...
function mergeMappings (line 2) | function mergeMappings(s,o,i,a){var u,_,w,x;for(er.isObject(i)||throwErr...
function storeMappingPair (line 2) | function storeMappingPair(s,o,i,a,u,_,w,x,C){var j,L;if(Array.isArray(u)...
function readLineBreak (line 2) | function readLineBreak(s){var o;10===(o=s.input.charCodeAt(s.position))?...
function skipSeparationSpace (line 2) | function skipSeparationSpace(s,o,i){for(var a=0,u=s.input.charCodeAt(s.p...
function testDocumentSeparator (line 2) | function testDocumentSeparator(s){var o,i=s.position;return!(45!==(o=s.i...
function writeFoldedLines (line 2) | function writeFoldedLines(s,o){1===o?s.result+=" ":o>1&&(s.result+=er.re...
function readBlockSequence (line 2) | function readBlockSequence(s,o){var i,a,u=s.tag,_=s.anchor,w=[],x=!1;if(...
function readTagProperty (line 2) | function readTagProperty(s){var o,i,a,u,_=!1,w=!1;if(33!==(u=s.input.cha...
function readAnchorProperty (line 2) | function readAnchorProperty(s){var o,i;if(38!==(i=s.input.charCodeAt(s.p...
function composeNode (line 2) | function composeNode(s,o,i,a,u){var _,w,x,C,j,L,B,$,U,V=1,z=!1,Y=!1;if(n...
function readDocument (line 2) | function readDocument(s){var o,i,a,u,_=s.position,w=!1;for(s.version=nul...
function loadDocuments (line 2) | function loadDocuments(s,o){o=o||{},0!==(s=String(s)).length&&(10!==s.ch...
function encodeHex (line 2) | function encodeHex(s){var o,i,a;if(o=s.toString(16).toUpperCase(),s<=255...
function State (line 2) | function State(s){this.schema=s.schema||Mr,this.indent=Math.max(1,s.inde...
function indentString (line 2) | function indentString(s,o){for(var i,a=er.repeat(" ",o),u=0,_=-1,w="",x=...
function generateNextLine (line 2) | function generateNextLine(s,o){return"\n"+er.repeat(" ",s.indent*o)}
function isWhitespace (line 2) | function isWhitespace(s){return 32===s||9===s}
function isPrintable (line 2) | function isPrintable(s){return 32<=s&&s<=126||161<=s&&s<=55295&&8232!==s...
function isNsCharOrWhitespace (line 2) | function isNsCharOrWhitespace(s){return isPrintable(s)&&s!==Kr&&13!==s&&...
function isPlainSafe (line 2) | function isPlainSafe(s,o,i){var a=isNsCharOrWhitespace(s),u=a&&!isWhites...
function codePointAt (line 2) | function codePointAt(s,o){var i,a=s.charCodeAt(o);return a>=55296&&a<=56...
function needIndentIndicator (line 2) | function needIndentIndicator(s){return/^\n* /.test(s)}
function chooseScalarStyle (line 2) | function chooseScalarStyle(s,o,i,a,u,_,w,x){var C,j=0,L=null,B=!1,$=!1,U...
function writeScalar (line 2) | function writeScalar(s,o,i,a,u){s.dump=function(){if(0===o.length)return...
function blockHeader (line 2) | function blockHeader(s,o){var i=needIndentIndicator(s)?String(o):"",a="\...
function dropEndingNewline (line 2) | function dropEndingNewline(s){return"\n"===s[s.length-1]?s.slice(0,-1):s}
function foldLine (line 2) | function foldLine(s,o){if(""===s||" "===s[0])return s;for(var i,a,u=/ [^...
function writeBlockSequence (line 2) | function writeBlockSequence(s,o,i,a){var u,_,w,x="",C=s.tag;for(u=0,_=i....
function detectType (line 2) | function detectType(s,o,i){var a,u,_,w,x,C;for(_=0,w=(u=i?s.explicitType...
function writeNode (line 2) | function writeNode(s,o,i,a,u,_,w){s.tag=null,s.dump=i,detectType(s,i,!1)...
function getDuplicateReferences (line 2) | function getDuplicateReferences(s,o){var i,a,u=[],_=[];for(inspectNode(s...
function inspectNode (line 2) | function inspectNode(s,o,i){var a,u,_;if(null!==s&&"object"==typeof s)if...
function renamed (line 2) | function renamed(s,o){return function(){throw new Error("Function yaml."...
function update (line 2) | function update(s,o){return{type:mn,payload:{[s]:o}}}
function toggle (line 2) | function toggle(s){return{type:gn,payload:s}}
function next (line 2) | function next(u){u instanceof Error||u.status>=400?(a.updateLoadingStatu...
function configsPlugin (line 2) | function configsPlugin(){return{statePlugins:{configs:{reducers:yn,actio...
method isShownKeyFromUrlHashArray (line 2) | isShownKeyFromUrlHashArray(s,o){const[i,a]=o;return a?["operations",i,a]...
method urlHashArrayFromIsShownKey (line 2) | urlHashArrayFromIsShownKey(s,o){let[i,a,u]=o;return"operations"==i?[a,u]...
method render (line 2) | render(){return Re.createElement("span",{ref:this.onLoad},Re.createEleme...
method render (line 2) | render(){return Re.createElement("span",{ref:this.onLoad},Re.createEleme...
function deep_linking (line 2) | function deep_linking(){return[En,{statePlugins:{configs:{wrapActions:{l...
function transform (line 2) | function transform(s){return s.map((s=>{let o="is not of a type(s)",i=s....
function parameter_oneof_transform (line 2) | function parameter_oneof_transform(s,{jsSpec:o}){return s}
function transformErrors (line 2) | function transformErrors(s){let o={jsSpec:{}},i=On()(jn,((s,i)=>{try{ret...
function err (line 2) | function err(o){return{statePlugins:{err:{reducers:{[rt]:(s,{payload:o})...
function opsFilter (line 2) | function opsFilter(s,o){return s.filter(((s,i)=>-1!==i.indexOf(o)))}
function filter (line 2) | function filter(){return{fn:{opsFilter}}}
function updateLayout (line 2) | function updateLayout(s){return{type:Rn,payload:s}}
function updateFilter (line 2) | function updateFilter(s){return{type:Dn,payload:s}}
function actions_show (line 2) | function actions_show(s,o=!0){return s=normalizeArray(s),{type:Fn,payloa...
function changeMode (line 2) | function changeMode(s,o=""){return s=normalizeArray(s),{type:Ln,payload:...
function plugins_layout (line 2) | function plugins_layout(){return{statePlugins:{layout:{reducers:Bn,actio...
function logs (line 2) | function logs({configs:s}){const o={debug:0,info:1,log:2,warn:3,error:4}...
function on_complete (line 2) | function on_complete(){return{statePlugins:{spec:{wrapActions:{updateSpe...
class ModelCollapse (line 2) | class ModelCollapse extends Re.Component{static defaultProps={collapsedC...
method constructor (line 2) | constructor(s,o){super(s,o);let{expanded:i,collapsedContent:a}=this.pr...
method componentDidMount (line 2) | componentDidMount(){const{hideSelfOnExpand:s,expanded:o,modelName:i}=t...
method UNSAFE_componentWillReceiveProps (line 2) | UNSAFE_componentWillReceiveProps(s){this.props.expanded!==s.expanded&&...
method render (line 2) | render(){const{title:s,classes:o}=this.props;return this.state.expande...
class ModelWrapper (line 2) | class ModelWrapper extends Re.Component{onToggle=(s,o)=>{this.props.layo...
method render (line 2) | render(){let{getComponent:s,getConfigs:o}=this.props;const i=s("Model"...
function _typeof (line 2) | function _typeof(s){return _typeof="function"==typeof Symbol&&"symbol"==...
function _defineProperties (line 2) | function _defineProperties(s,o){for(var i=0;i<o.length;i++){var a=o[i];a...
function _defineProperty (line 2) | function _defineProperty(s,o,i){return o in s?Object.defineProperty(s,o,...
function ownKeys (line 2) | function ownKeys(s,o){var i=Object.keys(s);if(Object.getOwnPropertySymbo...
function _getPrototypeOf (line 2) | function _getPrototypeOf(s){return _getPrototypeOf=Object.setPrototypeOf...
function _setPrototypeOf (line 2) | function _setPrototypeOf(s,o){return _setPrototypeOf=Object.setPrototype...
function _possibleConstructorReturn (line 2) | function _possibleConstructorReturn(s,o){return!o||"object"!=typeof o&&"...
function react_immutable_pure_component_es_get (line 2) | function react_immutable_pure_component_es_get(s,o,i){return function is...
function getIn (line 2) | function getIn(s,o,i){for(var a=0;a!==o.length;)if((s=react_immutable_pu...
function check (line 2) | function check(s){var o=arguments.length>1&&void 0!==arguments[1]?argume...
function ImmutablePureComponent (line 2) | function ImmutablePureComponent(){return function _classCallCheck(s,o){i...
function _extends (line 2) | function _extends(){return _extends=Object.assign?Object.assign.bind():f...
class Model (line 2) | class Model extends Xn{static propTypes={schema:xn().map.isRequired,getC...
method render (line 2) | render(){let{getComponent:s,getConfigs:o,specSelectors:i,schema:a,requ...
class Models (line 2) | class Models extends Re.Component{getSchemaBasePath=()=>this.props.specS...
method render (line 2) | render(){let{specSelectors:s,getComponent:o,layoutSelectors:i,layoutAc...
function isAbsoluteUrl (line 2) | function isAbsoluteUrl(s){return s.match(/^(?:[a-z]+:)?\/\//i)}
function buildBaseUrl (line 2) | function buildBaseUrl(s,o){return s?isAbsoluteUrl(s)?function addProtoco...
function safeBuildUrl (line 2) | function safeBuildUrl(s,o,{selectedServer:i=""}={}){try{return function ...
function sanitizeUrl (line 2) | function sanitizeUrl(s){if("string"!=typeof s||""===s.trim())return"";co...
class ObjectModel (line 2) | class ObjectModel extends Re.Component{render(){let{schema:s,name:o,disp...
method render (line 2) | render(){let{schema:s,name:o,displayName:i,isRef:a,getComponent:u,getC...
class ArrayModel (line 2) | class ArrayModel extends Re.Component{render(){let{getComponent:s,getCon...
method render (line 2) | render(){let{getComponent:s,getConfigs:o,schema:i,depth:a,expandDepth:...
class Primitive (line 2) | class Primitive extends Re.Component{render(){let{schema:s,getComponent:...
method render (line 2) | render(){let{schema:s,getComponent:o,getConfigs:i,name:a,displayName:u...
class Schemes (line 2) | class Schemes extends Re.Component{UNSAFE_componentWillMount(){let{schem...
method UNSAFE_componentWillMount (line 2) | UNSAFE_componentWillMount(){let{schemes:s}=this.props;this.setScheme(s...
method UNSAFE_componentWillReceiveProps (line 2) | UNSAFE_componentWillReceiveProps(s){this.props.currentScheme&&s.scheme...
method render (line 2) | render(){let{schemes:s,currentScheme:o}=this.props;return Re.createEle...
class SchemesContainer (line 2) | class SchemesContainer extends Re.Component{render(){const{specActions:s...
method render (line 2) | render(){const{specActions:s,specSelectors:o,getComponent:i}=this.prop...
class JsonSchemaForm (line 2) | class JsonSchemaForm extends Re.Component{static defaultProps=ss;compone...
method componentDidMount (line 2) | componentDidMount(){const{dispatchInitialValue:s,value:o,onChange:i}=t...
method render (line 2) | render(){let{schema:s,errors:o,value:i,onChange:a,getComponent:u,fn:_,...
class JsonSchema_string (line 2) | class JsonSchema_string extends Re.Component{static defaultProps=ss;onCh...
method render (line 2) | render(){let{getComponent:s,value:o,schema:i,errors:a,required:u,descr...
class JsonSchema_array (line 2) | class JsonSchema_array extends Re.PureComponent{static defaultProps=ss;c...
method constructor (line 2) | constructor(s,o){super(s,o),this.state={value:valueOrEmptyList(s.value...
method UNSAFE_componentWillReceiveProps (line 2) | UNSAFE_componentWillReceiveProps(s){const o=valueOrEmptyList(s.value);...
method render (line 2) | render(){let{getComponent:s,required:o,schema:i,errors:a,fn:u,disabled...
class JsonSchemaArrayItemText (line 2) | class JsonSchemaArrayItemText extends Re.Component{static defaultProps=s...
method render (line 2) | render(){let{value:s,errors:o,description:i,disabled:a}=this.props;ret...
class JsonSchemaArrayItemFile (line 2) | class JsonSchemaArrayItemFile extends Re.Component{static defaultProps=s...
method render (line 2) | render(){let{getComponent:s,errors:o,disabled:i}=this.props;const a=s(...
class JsonSchema_boolean (line 2) | class JsonSchema_boolean extends Re.Component{static defaultProps=ss;onE...
method render (line 2) | render(){let{getComponent:s,value:o,errors:i,schema:a,required:u,disab...
class JsonSchema_object (line 2) | class JsonSchema_object extends Re.PureComponent{constructor(){super()}s...
method constructor (line 2) | constructor(){super()}
method render (line 2) | render(){let{getComponent:s,value:o,errors:i,disabled:a}=this.props;co...
function valueOrEmptyList (line 2) | function valueOrEmptyList(s){return ze.List.isList(s)?s:Array.isArray(s)...
class Cache (line 2) | class Cache extends Map{delete(s){const o=Array.from(this.keys()).find(s...
method delete (line 2) | delete(s){const o=Array.from(this.keys()).find(shallowArrayEquals(s));...
method get (line 2) | get(s){const o=Array.from(this.keys()).find(shallowArrayEquals(s));ret...
method has (line 2) | has(s){return-1!==Array.from(this.keys()).findIndex(shallowArrayEquals...
function getParameter (line 2) | function getParameter(s,o,i,a){return o=o||[],s.getIn(["meta","paths",.....
function parameterValues (line 2) | function parameterValues(s,o,i){return o=o||[],operationWithMeta(s,...o)...
function parametersIncludeIn (line 2) | function parametersIncludeIn(s,o=""){if(ze.List.isList(s))return s.some(...
function parametersIncludeType (line 2) | function parametersIncludeType(s,o=""){if(ze.List.isList(s))return s.som...
function contentTypeValues (line 2) | function contentTypeValues(s,o){o=o||[];let i=Ns(s).getIn(["paths",...o]...
function currentProducesFor (line 2) | function currentProducesFor(s,o){o=o||[];const i=Ns(s).getIn(["paths",.....
function producesOptionsFor (line 2) | function producesOptionsFor(s,o){o=o||[];const i=Ns(s),a=i.getIn(["paths...
function consumesOptionsFor (line 2) | function consumesOptionsFor(s,o){o=o||[];const i=Ns(s),a=i.getIn(["paths...
function returnSelfOrNewMap (line 2) | function returnSelfOrNewMap(s){return ze.Map.isMap(s)?s:new ze.Map}
function updateSpec (line 2) | function updateSpec(s){const o=toStr(s).replace(/\t/g," ");if("string"=...
function updateResolved (line 2) | function updateResolved(s){return{type:Oo,payload:s}}
function updateUrl (line 2) | function updateUrl(s){return{type:ho,payload:s}}
function updateJsonSpec (line 2) | function updateJsonSpec(s){return{type:fo,payload:s}}
function changeParam (line 2) | function changeParam(s,o,i,a,u){return{type:mo,payload:{path:s,value:a,p...
function changeParamByIdentity (line 2) | function changeParamByIdentity(s,o,i,a){return{type:mo,payload:{path:s,p...
function clearValidateParams (line 2) | function clearValidateParams(s){return{type:xo,payload:{pathMethod:s}}}
function changeConsumesValue (line 2) | function changeConsumesValue(s,o){return{type:ko,payload:{path:s,value:o...
function changeProducesValue (line 2) | function changeProducesValue(s,o){return{type:ko,payload:{path:s,value:o...
function clearResponse (line 2) | function clearResponse(s,o){return{type:Eo,payload:{path:s,method:o}}}
function clearRequest (line 2) | function clearRequest(s,o){return{type:wo,payload:{path:s,method:o}}}
function setScheme (line 2) | function setScheme(s,o,i){return{type:Co,payload:{scheme:s,path:o,method...
function __ (line 2) | function __(){this.constructor=s}
function module_helpers_hasOwnProperty (line 2) | function module_helpers_hasOwnProperty(s,o){return Mo.call(s,o)}
function _objectKeys (line 2) | function _objectKeys(s){if(Array.isArray(s)){for(var o=new Array(s.lengt...
function _deepClone (line 2) | function _deepClone(s){switch(typeof s){case"object":return JSON.parse(J...
function helpers_isInteger (line 2) | function helpers_isInteger(s){for(var o,i=0,a=s.length;i<a;){if(!((o=s.c...
function escapePathComponent (line 2) | function escapePathComponent(s){return-1===s.indexOf("/")&&-1===s.indexO...
function unescapePathComponent (line 2) | function unescapePathComponent(s){return s.replace(/~1/g,"/").replace(/~...
function hasUndefined (line 2) | function hasUndefined(s){if(void 0===s)return!0;if(s)if(Array.isArray(s)...
function patchErrorMessageFormatter (line 2) | function patchErrorMessageFormatter(s,o){var i=[s];for(var a in o){var u...
function PatchError (line 2) | function PatchError(o,i,a,u,_){var w=this.constructor,x=s.call(this,patc...
function getValueByPointer (line 2) | function getValueByPointer(s,o){if(""==o)return s;var i={op:"_get",path:...
function applyOperation (line 2) | function applyOperation(s,o,i,a,u,_){if(void 0===i&&(i=!1),void 0===a&&(...
function applyPatch (line 2) | function applyPatch(s,o,i,a,u){if(void 0===a&&(a=!0),void 0===u&&(u=!0),...
function applyReducer (line 2) | function applyReducer(s,o,i){var a=applyOperation(s,o);if(!1===a.test)th...
function validator (line 2) | function validator(s,o,i,a){if("object"!=typeof s||null===s||Array.isArr...
function validate (line 2) | function validate(s,o,i){try{if(!Array.isArray(s))throw new Do("Patch se...
function _areEquals (line 2) | function _areEquals(s,o){if(s===o)return!0;if(s&&o&&"object"==typeof s&&...
function unobserve (line 2) | function unobserve(s,o){o.unobserve()}
function observe (line 2) | function observe(s,o){var i,a=function getMirror(s){return $o.get(s)}(s)...
function generate (line 2) | function generate(s,o){void 0===o&&(o=!1);var i=$o.get(s.object);_genera...
function _generate (line 2) | function _generate(s,o,i,a,u){if(o!==s){"function"==typeof o.toJSON&&(o=...
function compare (line 2) | function compare(s,o,i){void 0===i&&(i=!1);var a=[];return _generate(s,o...
function normalizeJSONPath (line 2) | function normalizeJSONPath(s){return Array.isArray(s)?s.length<1?"":`/${...
function replace (line 2) | function replace(s,o,i){return{op:"replace",path:s,value:o,meta:i}}
function forEachNewPatch (line 2) | function forEachNewPatch(s,o,i){return cleanArray(flatten(s.filter(isAdd...
function forEachPrimitive (line 2) | function forEachPrimitive(s,o,i){return i=i||[],Array.isArray(s)?s.map((...
function forEach (line 2) | function forEach(s,o,i){let a=[];if((i=i||[]).length>0){const u=o(s,i[i....
function lib_normalizeArray (line 2) | function lib_normalizeArray(s){return Array.isArray(s)?s:[s]}
function flatten (line 2) | function flatten(s){return[].concat(...s.map((s=>Array.isArray(s)?flatte...
function cleanArray (line 2) | function cleanArray(s){return s.filter((s=>void 0!==s))}
function lib_isObject (line 2) | function lib_isObject(s){return s&&"object"==typeof s}
function lib_isFunction (line 2) | function lib_isFunction(s){return s&&"function"==typeof s}
function isJsonPatch (line 2) | function isJsonPatch(s){if(isPatch(s)){const{op:o}=s;return"add"===o||"r...
function isMutation (line 2) | function isMutation(s){return isJsonPatch(s)||isPatch(s)&&"mutation"===s...
function isAdditiveMutation (line 2) | function isAdditiveMutation(s){return isMutation(s)&&("add"===s.op||"rep...
function isPatch (line 2) | function isPatch(s){return s&&"object"==typeof s}
function getInByJsonPath (line 2) | function getInByJsonPath(s,o){try{return getValueByPointer(s,o)}catch(s)...
method constructor (line 2) | constructor(s,o,i){if(super(s,o,i),this.name=this.constructor.name,"stri...
class ApiDOMError (line 2) | class ApiDOMError extends Error{static[Symbol.hasInstance](s){return sup...
method constructor (line 2) | constructor(s,o){if(super(s,o),this.name=this.constructor.name,"string...
method [Symbol.hasInstance] (line 2) | static[Symbol.hasInstance](s){return super[Symbol.hasInstance](s)||Funct...
method constructor (line 2) | constructor(s,o){if(super(s,o),null!=o&&"object"==typeof o){const{cause:...
function _isPlaceholder (line 2) | function _isPlaceholder(s){return null!=s&&"object"==typeof s&&!0===s["@...
function _curry1 (line 2) | function _curry1(s){return function f1(o){return 0===arguments.length||_...
function _curry2 (line 2) | function _curry2(s){return function f2(o,i){switch(arguments.length){cas...
function _curry3 (line 2) | function _curry3(s){return function f3(o,i,a){switch(arguments.length){c...
function _isString (line 2) | function _isString(s){return"[object String]"===Object.prototype.toStrin...
function _nth (line 2) | function _nth(s,o){var i=s<0?o.length+s:s;return _isString(o)?o.charAt(i...
function _path (line 2) | function _path(s,o){for(var i=o,a=0;a<s.length;a+=1){if(null==i)return;v...
function _cloneRegExp (line 2) | function _cloneRegExp(s){return new RegExp(s.source,s.flags?s.flags:(s.g...
function _arrayFromIterator (line 2) | function _arrayFromIterator(s){for(var o,i=[];!(o=s.next()).done;)i.push...
function _includesWith (line 2) | function _includesWith(s,o,i){for(var a=0,u=i.length;a<u;){if(s(o,i[a]))...
function _has (line 2) | function _has(s,o){return Object.prototype.hasOwnProperty.call(o,s)}
function _uniqContentEquals (line 2) | function _uniqContentEquals(s,o,i,a){var u=_arrayFromIterator(s);functio...
function _equals (line 2) | function _equals(s,o,i,a){if(Zo(s,o))return!0;var u=ra(s);if(u!==ra(o))r...
function _includes (line 2) | function _includes(s,o){return function _indexOf(s,o,i){var a,u;if("func...
function _map (line 2) | function _map(s,o){for(var i=0,a=o.length,u=Array(a);i<a;)u[i]=s(o[i]),i...
function _quote (line 2) | function _quote(s){return'"'+s.replace(/\\/g,"\\\\").replace(/[\b]/g,"\\...
function _complement (line 2) | function _complement(s){return function(){return!s.apply(this,arguments)}}
function _arrayReduce (line 2) | function _arrayReduce(s,o,i){for(var a=0,u=i.length;a<u;)o=s(o,i[a]),a+=...
function _dispatchable (line 2) | function _dispatchable(s,o,i){return function(){if(0===arguments.length)...
function _isObject (line 2) | function _isObject(s){return"[object Object]"===Object.prototype.toStrin...
function XFilter (line 2) | function XFilter(s,o){this.xf=o,this.f=s}
function _xfilter (line 2) | function _xfilter(s){return function(o){return new la(s,o)}}
function _toString_toString (line 2) | function _toString_toString(s,o){var i=function recur(i){var a=o.concat(...
function _arity (line 2) | function _arity(s,o){switch(s){case 0:return function(){return o.apply(t...
function _pipe (line 2) | function _pipe(s,o){return function(){return o.call(this,s.apply(this,ar...
function _createReduce (line 2) | function _createReduce(s,o,i){return function _reduce(a,u,_){if(ba(_))re...
function _xArrayReduce (line 2) | function _xArrayReduce(s,o,i){for(var a=0,u=i.length;a<u;){if((o=s["@@tr...
function _xIterableReduce (line 2) | function _xIterableReduce(s,o,i){for(var a=i.next();!a.done;){if((o=s["@...
function _xMethodReduce (line 2) | function _xMethodReduce(s,o,i,a){return s["@@transducer/result"](i[a](Ea...
function XWrap (line 2) | function XWrap(s){this.f=s}
function _xwrap (line 2) | function _xwrap(s){return new xa(s)}
function _checkForMethod (line 2) | function _checkForMethod(s,o){return function(){var i=arguments.length;i...
function pipe (line 2) | function pipe(){if(0===arguments.length)throw new Error("pipe requires a...
function _curryN (line 2) | function _curryN(s,o,i){return function(){for(var a=[],u=0,_=s,w=0,x=!1;...
function _isFunction (line 2) | function _isFunction(s){var o=Object.prototype.toString.call(s);return"[...
function dropLastWhile (line 2) | function dropLastWhile(s,o){for(var i=o.length-1;i>=0&&s(o[i]);)i-=1;ret...
function XDropLastWhile (line 2) | function XDropLastWhile(s,o){this.f=s,this.retained=[],this.xf=o}
function _xdropLastWhile (line 2) | function _xdropLastWhile(s){return function(o){return new Ga(s,o)}}
function _iterableReduce (line 2) | function _iterableReduce(s,o,i){for(var a=i.next();!a.done;)o=s(o,a.valu...
function _methodReduce (line 2) | function _methodReduce(s,o,i,a){return i[a](s,o)}
function XMap (line 2) | function XMap(s,o){this.xf=o,this.f=s}
function safeMax (line 2) | function safeMax(s,o){if(s>o!=o>s)return o>s?o:s}
function _array_like_to_array (line 2) | function _array_like_to_array(s,o){(null==o||o>s.length)&&(o=s.length);f...
function legacy_defineProperties (line 2) | function legacy_defineProperties(s,o){for(var i=0;i<o.length;i++){var a=...
function _instanceof (line 2) | function _instanceof(s,o){return null!=o&&"undefined"!=typeof Symbol&&o[...
function _sliced_to_array (line 2) | function _sliced_to_array(s,o){return function _array_with_holes(s){if(A...
function _type_of (line 2) | function _type_of(s){return s&&"undefined"!=typeof Symbol&&s.constructor...
function own_enumerable_keys (line 2) | function own_enumerable_keys(s){for(var o=Object.keys(s),i=Cl(s),a=0;a<i...
function is_writable (line 2) | function is_writable(s,o){var i;return!(null===(i=Ol(s,o))||void 0===i?v...
function legacy_copy (line 2) | function legacy_copy(s,o){if("object"===(void 0===s?"undefined":_type_of...
function walk (line 2) | function walk(s,o){var i=arguments.length>2&&void 0!==arguments[2]?argum...
function Traverse (line 2) | function Traverse(s){var o=arguments.length>1&&void 0!==arguments[1]?arg...
function isFreelyNamed (line 2) | function isFreelyNamed(s){const o=s[s.length-1],i=s[s.length-2],a=s.join...
function absolutifyPointer (line 2) | function absolutifyPointer(s,o){const[i,a]=s.split("#"),u=null!=o?o:"",_...
class JSONRefError (line 2) | class JSONRefError extends Go{}
function pointToAncestor (line 2) | function pointToAncestor(s){return Wo.isObject(s)&&(i.indexOf(s)>=0||Obj...
function absoluteify (line 2) | function absoluteify(s,o){if(!Wl.test(s)){if(!o)throw new JSONRefError(`...
function wrapError (line 2) | function wrapError(s,o){let i;return i=s&&s.response&&s.response.body?`$...
function refs_split (line 2) | function refs_split(s){return(s+"").split("#")}
function extractFromDoc (line 2) | function extractFromDoc(s,o){const i=Jl[s];if(i&&!Wo.isPromise(i))try{co...
function getDoc (line 2) | function getDoc(s){const o=Jl[s];return o?Wo.isPromise(o)?o:Promise.reso...
function extract (line 2) | function extract(s,o){const i=jsonPointerToArray(s);if(i.length<1)return...
function jsonPointerToArray (line 2) | function jsonPointerToArray(s){if("string"!=typeof s)throw new TypeError...
function unescapeJsonPointerToken (line 2) | function unescapeJsonPointerToken(s){if("string"!=typeof s)return s;retu...
function escapeJsonPointerToken (line 2) | function escapeJsonPointerToken(s){return new URLSearchParams([["",s.rep...
function pointerIsAParent (line 2) | function pointerIsAParent(s,o){if(pointerBoundaryChar(o))return!0;const ...
class ContextTree (line 2) | class ContextTree{constructor(s){this.root=context_tree_createNode(s||{}...
method constructor (line 2) | constructor(s){this.root=context_tree_createNode(s||{})}
method set (line 2) | set(s,o){const i=this.getParent(s,!0);if(!i)return void context_tree_u...
method get (line 2) | get(s){if((s=s||[]).length<1)return this.root.value;let o,i,a=this.roo...
method getParent (line 2) | getParent(s,o){return!s||s.length<1?null:s.length<2?this.root:s.slice(...
function context_tree_createNode (line 2) | function context_tree_createNode(s,o){return context_tree_updateNode({ch...
function context_tree_updateNode (line 2) | function context_tree_updateNode(s,o,i){return s.value=o||{},s.protoValu...
class SpecMap (line 2) | class SpecMap{static getPluginName(s){return s.pluginName}static getPatc...
method getPluginName (line 2) | static getPluginName(s){return s.pluginName}
method getPatchesOfType (line 2) | static getPatchesOfType(s,o){return s.filter(o)}
method constructor (line 2) | constructor(s){Object.assign(this,{spec:"",debugLevel:"info",plugins:[...
method debug (line 2) | debug(s,...o){this.debugLevel===s&&console.log(...o)}
method verbose (line 2) | verbose(s,...o){"verbose"===this.debugLevel&&console.log(`[${s}] `,....
method wrapPlugin (line 2) | wrapPlugin(s,o){const{pathDiscriminator:i}=this;let a,u=null;return s[...
method nextPlugin (line 2) | nextPlugin(){return this.wrappedPlugins.find((s=>this.getMutationsForP...
method nextPromisedPatch (line 2) | nextPromisedPatch(){if(this.promisedPatches.length>0)return Promise.ra...
method getPluginHistory (line 2) | getPluginHistory(s){const o=this.constructor.getPluginName(s);return t...
method getPluginRunCount (line 2) | getPluginRunCount(s){return this.getPluginHistory(s).length}
method getPluginHistoryTip (line 2) | getPluginHistoryTip(s){const o=this.getPluginHistory(s);return o&&o[o....
method getPluginMutationIndex (line 2) | getPluginMutationIndex(s){const o=this.getPluginHistoryTip(s).mutation...
method updatePluginHistory (line 2) | updatePluginHistory(s,o){const i=this.constructor.getPluginName(s);thi...
method updatePatches (line 2) | updatePatches(s){Wo.normalizeArray(s).forEach((s=>{if(s instanceof Err...
method updateMutations (line 2) | updateMutations(s){"object"==typeof s.value&&!Array.isArray(s.value)&&...
method removePromisedPatch (line 2) | removePromisedPatch(s){const o=this.promisedPatches.indexOf(s);o<0?thi...
method promisedPatchThen (line 2) | promisedPatchThen(s){return s.value=s.value.then((o=>{const i={...s,va...
method getMutations (line 2) | getMutations(s,o){return s=s||0,"number"!=typeof o&&(o=this.mutations....
method getCurrentMutations (line 2) | getCurrentMutations(){return this.getMutationsForPlugin(this.getCurren...
method getMutationsForPlugin (line 2) | getMutationsForPlugin(s){const o=this.getPluginMutationIndex(s);return...
method getCurrentPlugin (line 2) | getCurrentPlugin(){return this.currentPlugin}
method getLib (line 2) | getLib(){return this.libMethods}
method _get (line 2) | _get(s){return Wo.getIn(this.state,s)}
method _getContext (line 2) | _getContext(s){return this.contextTree.get(s)}
method setContext (line 2) | setContext(s,o){return this.contextTree.set(s,o)}
method _hasRun (line 2) | _hasRun(s){return this.getPluginRunCount(this.getCurrentPlugin())>(s||0)}
method dispatch (line 2) | dispatch(){const s=this,o=this.nextPlugin();if(!o){const s=this.nextPr...
function makeFetchJSON (line 2) | function makeFetchJSON(s,o={}){const{requestInterceptor:i,responseInterc...
function isFile (line 2) | function isFile(s,o){return o||"undefined"==typeof navigator||(o=navigat...
function isArrayOfFile (line 2) | function isArrayOfFile(s,o){return Array.isArray(s)&&s.some((s=>isFile(s...
class FileWithData (line 2) | class FileWithData extends File{constructor(s,o="",i={}){super([s],o,i),...
method constructor (line 2) | constructor(s,o="",i={}){super([s],o,i),this.data=s}
method valueOf (line 2) | valueOf(){return this.data}
method toString (line 2) | toString(){return this.valueOf()}
function encodeCharacters (line 2) | function encodeCharacters(s,o="reserved"){return[...s].map((s=>{if(isRfc...
function stylize (line 2) | function stylize(s){const{value:o}=s;return Array.isArray(o)?function en...
function valueEncoder (line 2) | function valueEncoder(s,o=!1){return Array.isArray(s)||null!==s&&"object...
function formatKeyValue (line 2) | function formatKeyValue(s,o,i=!1){const{collectionFormat:a,allowEmptyVal...
function formatKeyValueBySerializationOption (line 2) | function formatKeyValueBySerializationOption(s,o,i,a){const u=a.style||"...
function encodeFormOrQuery (line 2) | function encodeFormOrQuery(s){return((s,{encode:o=!0}={})=>{const buildN...
function serializeRequest (line 2) | function serializeRequest(s={}){const{url:o="",query:i,form:a}=s;if(a){c...
function serializeHeaders (line 2) | function serializeHeaders(s={}){return"function"!=typeof s.entries?{}:Ar...
function serializeResponse (line 2) | function serializeResponse(s,o,{loadSpec:i=!1}={}){const a={ok:s.ok,url:...
function http_http (line 2) | async function http_http(s,o={}){"object"==typeof s&&(s=(o=s).url),o.hea...
function resolveGenericStrategy (line 2) | async function resolveGenericStrategy(s){const{spec:o,mode:i,allowMetaPa...
function isOfTypeObject_typeof (line 2) | function isOfTypeObject_typeof(s){return isOfTypeObject_typeof="function...
function opId (line 2) | function opId(s,o,i="",{v2OperationIdCompatibilityMode:a}={}){if(!s||"ob...
function normalize_normalize (line 2) | function normalize_normalize(s){const{spec:o}=s,{paths:i}=o,a={};if(!i||...
method normalize (line 2) | normalize(s){const{spec:o}=normalize_normalize({spec:s});return o}
method normalize (line 2) | normalize(s){const{spec:o}=normalize_normalize({spec:s});return o}
method normalize (line 2) | normalize(s){const{spec:o}=normalize_normalize({spec:s});return o}
function _reduced (line 2) | function _reduced(s){return s&&s["@@transducer/reduced"]?s:{"@@transduce...
function XAll (line 2) | function XAll(s,o){this.xf=o,this.f=s,this.all=!0}
function _xall (line 2) | function _xall(s){return function(o){return new Eu(s,o)}}
class Annotation (line 2) | class Annotation extends Su.Om{constructor(s,o,i){super(s,o,i),this.elem...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="annotation"}
method code (line 2) | get code(){return this.attributes.get("code")}
method code (line 2) | set code(s){this.attributes.set("code",s)}
class Comment (line 2) | class Comment extends Su.Om{constructor(s,o,i){super(s,o,i),this.element...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="comment"}
class ParseResult (line 2) | class ParseResult extends Su.wE{constructor(s,o,i){super(s,o,i),this.ele...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="parseResult"}
method api (line 2) | get api(){return this.children.filter((s=>s.classes.contains("api")))....
method results (line 2) | get results(){return this.children.filter((s=>s.classes.contains("resu...
method result (line 2) | get result(){return this.results.first}
method annotations (line 2) | get annotations(){return this.children.filter((s=>"annotation"===s.ele...
method warnings (line 2) | get warnings(){return this.children.filter((s=>"annotation"===s.elemen...
method errors (line 2) | get errors(){return this.children.filter((s=>"annotation"===s.element&...
method isEmpty (line 2) | get isEmpty(){return this.children.reject((s=>"annotation"===s.element...
method replaceResult (line 2) | replaceResult(s){const{result:o}=this;if(bc(o))return!1;const i=this.c...
class SourceMap (line 2) | class SourceMap extends Su.wE{constructor(s,o,i){super(s,o,i),this.eleme...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="sourceMap"}
method positionStart (line 2) | get positionStart(){return this.children.filter((s=>s.classes.contains...
method positionEnd (line 2) | get positionEnd(){return this.children.filter((s=>s.classes.contains("...
method position (line 2) | set position(s){if(void 0===s)return;const o=new Su.wE([s.start.row,s....
method enter (line 2) | enter(j,L,B,$,U,V){let z=j,Y=!1;const Z={...V,replaceWith(s,o){V.replace...
method leave (line 2) | leave(u,w,j,L,B,$){let U=u;const V={...$,replaceWith(s,o){$.replaceWith(...
method enter (line 2) | async enter(j,L,B,$,U,V){let z=j,Y=!1;const Z={...V,replaceWith(s,o){V.r...
method leave (line 2) | async leave(u,w,j,L,B,$){let U=u;const V={...$,replaceWith(s,o){$.replac...
method replaceWith (line 2) | replaceWith(o,a){"function"==typeof a?a(o,ae,i,z,ce,le):z&&(z[i]=o),s||(...
method replaceWith (line 2) | replaceWith(o,a){"function"==typeof a?a(o,ae,i,z,ce,le):z&&(z[i]=o),s||(...
method constructor (line 2) | constructor(s,o){super(s,o),void 0!==o&&(this.value=o.value)}
class PredicateVisitor (line 2) | class PredicateVisitor{result;predicate;returnOnTrue;returnOnFalse;const...
method constructor (line 2) | constructor({predicate:s=es_F,returnOnTrue:o,returnOnFalse:i}={}){this...
method enter (line 2) | enter(s){return this.predicate(s)?(this.result.push(s),this.returnOnTr...
method constructor (line 2) | constructor(s){this.content=s,this.reference=[]}
method toReference (line 2) | toReference(){return this.reference}
method toArray (line 2) | toArray(){return this.reference.push(...this.content),this.reference}
method constructor (line 2) | constructor(s){this.content=s,this.reference={}}
method toReference (line 2) | toReference(){return this.reference}
method toObject (line 2) | toObject(){return Object.assign(this.reference,Object.fromEntries(this.c...
class Visitor (line 2) | class Visitor{ObjectElement={enter:s=>{if(this.references.has(s))return ...
method BooleanElement (line 2) | BooleanElement(s){return s.toValue()}
method NumberElement (line 2) | NumberElement(s){return s.toValue()}
method StringElement (line 2) | StringElement(s){return s.toValue()}
method NullElement (line 2) | NullElement(){return null}
method RefElement (line 2) | RefElement(s,...o){var i;const a=o[3];return"EphemeralObject"===(null=...
method LinkElement (line 2) | LinkElement(s){return Pu(s.href)?s.href.toValue():""}
class Namespace (line 2) | class Namespace extends Su.g${constructor(){super(),this.register("annot...
method constructor (line 2) | constructor(s){this.elementMap={},this.elementDetection=[],this.Elemen...
method use (line 2) | use(s){return s.namespace&&s.namespace({base:this}),s.load&&s.load({ba...
method useDefault (line 2) | useDefault(){return this.register("null",j.NullElement).register("stri...
method register (line 2) | register(s,o){return this._elements=void 0,this.elementMap[s]=o,this}
method unregister (line 2) | unregister(s){return this._elements=void 0,delete this.elementMap[s],t...
method detect (line 2) | detect(s,o,i){return void 0===i||i?this.elementDetection.unshift([s,o]...
method toElement (line 2) | toElement(s){if(s instanceof this.Element)return s;let o;for(let i=0;i...
method getElementClass (line 2) | getElementClass(s){const o=this.elementMap[s];return void 0===o?this.E...
method fromRefract (line 2) | fromRefract(s){return this.serialiser.deserialise(s)}
method toRefract (line 2) | toRefract(s){return this.serialiser.serialise(s)}
method elements (line 2) | get elements(){return void 0===this._elements&&(this._elements={Elemen...
method serialiser (line 2) | get serialiser(){return new C(this)}
method constructor (line 2) | constructor(){super(),this.register("annotation",ku),this.register("co...
method constructor (line 2) | constructor({element:s}){this.element=s}
method transclude (line 2) | transclude(s,o){var i;if(s===this.element)return o;if(s===o)return this....
function indent (line 2) | function indent(s){let o="";for(;s-- >0;)o+=" ";return o}
function grammar (line 2) | function grammar(){this.grammarObject="grammarObject",this.rules=[],this...
class JSONPointerError (line 2) | class JSONPointerError extends Error{constructor(s,o=void 0){if(super(s,...
method constructor (line 2) | constructor(s,o=void 0){if(super(s,o),this.name=this.constructor.name,...
method constructor (line 2) | constructor(){super(),this.callbacks["json-pointer"]=callbacks_cst("json...
method getTree (line 2) | getTree(){const s={stack:[],root:null};return this.translate(s),delete s...
method getTree (line 2) | getTree(){const{root:s}=super.getTree();return s.children.filter((({type...
method toString (line 2) | toString(){return this.map((s=>`"${String(s)}"`)).join(", ")}
method inferExpectations (line 2) | inferExpectations(){const s=this.displayTrace().split("\n"),o=new Set;le...
method constructor (line 2) | constructor(s,o={}){this.#e=s,this.#e.steps=[],this.#e.failed=!1,this.#e...
method step (line 2) | step({referenceToken:s,input:o,output:i,success:a=!0,reason:u}){const _=...
method isArray (line 2) | isArray(s){throw new wp("Realm.isArray(node) must be implemented in a su...
method isObject (line 2) | isObject(s){throw new wp("Realm.isObject(node) must be implemented in a ...
method sizeOf (line 2) | sizeOf(s){throw new wp("Realm.sizeOf(node) must be implemented in a subc...
method has (line 2) | has(s,o){throw new wp("Realm.has(node) must be implemented in a subclass")}
method evaluate (line 2) | evaluate(s,o){throw new wp("Realm.evaluate(node) must be implemented in ...
method isArray (line 2) | isArray(s){return Array.isArray(s)}
method isObject (line 2) | isObject(s){return"object"==typeof s&&null!==s&&!this.isArray(s)}
method sizeOf (line 2) | sizeOf(s){return this.isArray(s)?s.length:this.isObject(s)?Object.keys(s...
method has (line 2) | has(s,o){if(this.isArray(s)){const i=Number(o),a=i>>>0;if(i!==a)throw ne...
method evaluate (line 2) | evaluate(s,o){return this.isArray(s)?s[Number(o)]:s[o]}
method isArray (line 2) | isArray(s){return Ru(s)}
method isObject (line 2) | isObject(s){return Mu(s)}
method sizeOf (line 2) | sizeOf(s){return this.isArray(s)||this.isObject(s)?s.length:0}
method has (line 2) | has(s,o){if(this.isArray(s)){const i=Number(o),a=i>>>0;if(i!==a)throw ne...
method evaluate (line 2) | evaluate(s,o){return this.isArray(s)?s.get(Number(o)):s.get(o)}
class Callback (line 2) | class Callback extends Su.Sh{constructor(s,o,i){super(s,o,i),this.elemen...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="callback"}
class Components (line 2) | class Components extends Su.Sh{constructor(s,o,i){super(s,o,i),this.elem...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="components"}
method schemas (line 2) | get schemas(){return this.get("schemas")}
method schemas (line 2) | set schemas(s){this.set("schemas",s)}
method responses (line 2) | get responses(){return this.get("responses")}
method responses (line 2) | set responses(s){this.set("responses",s)}
method parameters (line 2) | get parameters(){return this.get("parameters")}
method parameters (line 2) | set parameters(s){this.set("parameters",s)}
method examples (line 2) | get examples(){return this.get("examples")}
method examples (line 2) | set examples(s){this.set("examples",s)}
method requestBodies (line 2) | get requestBodies(){return this.get("requestBodies")}
method requestBodies (line 2) | set requestBodies(s){this.set("requestBodies",s)}
method headers (line 2) | get headers(){return this.get("headers")}
method headers (line 2) | set headers(s){this.set("headers",s)}
method securitySchemes (line 2) | get securitySchemes(){return this.get("securitySchemes")}
method securitySchemes (line 2) | set securitySchemes(s){this.set("securitySchemes",s)}
method links (line 2) | get links(){return this.get("links")}
method links (line 2) | set links(s){this.set("links",s)}
method callbacks (line 2) | get callbacks(){return this.get("callbacks")}
method callbacks (line 2) | set callbacks(s){this.set("callbacks",s)}
class Contact (line 2) | class Contact extends Su.Sh{constructor(s,o,i){super(s,o,i),this.element...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="contact"}
method name (line 2) | get name(){return this.get("name")}
method name (line 2) | set name(s){this.set("name",s)}
method url (line 2) | get url(){return this.get("url")}
method url (line 2) | set url(s){this.set("url",s)}
method email (line 2) | get email(){return this.get("email")}
method email (line 2) | set email(s){this.set("email",s)}
class Discriminator (line 2) | class Discriminator extends Su.Sh{constructor(s,o,i){super(s,o,i),this.e...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="discriminator"}
method propertyName (line 2) | get propertyName(){return this.get("propertyName")}
method propertyName (line 2) | set propertyName(s){this.set("propertyName",s)}
method mapping (line 2) | get mapping(){return this.get("mapping")}
method mapping (line 2) | set mapping(s){this.set("mapping",s)}
class Encoding (line 2) | class Encoding extends Su.Sh{constructor(s,o,i){super(s,o,i),this.elemen...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="encoding"}
method contentType (line 2) | get contentType(){return this.get("contentType")}
method contentType (line 2) | set contentType(s){this.set("contentType",s)}
method headers (line 2) | get headers(){return this.get("headers")}
method headers (line 2) | set headers(s){this.set("headers",s)}
method style (line 2) | get style(){return this.get("style")}
method style (line 2) | set style(s){this.set("style",s)}
method explode (line 2) | get explode(){return this.get("explode")}
method explode (line 2) | set explode(s){this.set("explode",s)}
method allowedReserved (line 2) | get allowedReserved(){return this.get("allowedReserved")}
method allowedReserved (line 2) | set allowedReserved(s){this.set("allowedReserved",s)}
class Example (line 2) | class Example extends Su.Sh{constructor(s,o,i){super(s,o,i),this.element...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="example"}
method summary (line 2) | get summary(){return this.get("summary")}
method summary (line 2) | set summary(s){this.set("summary",s)}
method description (line 2) | get description(){return this.get("description")}
method description (line 2) | set description(s){this.set("description",s)}
method value (line 2) | get value(){return this.get("value")}
method value (line 2) | set value(s){this.set("value",s)}
method externalValue (line 2) | get externalValue(){return this.get("externalValue")}
method externalValue (line 2) | set externalValue(s){this.set("externalValue",s)}
class ExternalDocumentation (line 2) | class ExternalDocumentation extends Su.Sh{constructor(s,o,i){super(s,o,i...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="externalDocumentation"}
method description (line 2) | get description(){return this.get("description")}
method description (line 2) | set description(s){this.set("description",s)}
method url (line 2) | get url(){return this.get("url")}
method url (line 2) | set url(s){this.set("url",s)}
class Header (line 2) | class Header extends Su.Sh{constructor(s,o,i){super(s,o,i),this.element=...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="header"}
method required (line 2) | get required(){return this.hasKey("required")?this.get("required"):new...
method required (line 2) | set required(s){this.set("required",s)}
method deprecated (line 2) | get deprecated(){return this.hasKey("deprecated")?this.get("deprecated...
method deprecated (line 2) | set deprecated(s){this.set("deprecated",s)}
method allowEmptyValue (line 2) | get allowEmptyValue(){return this.get("allowEmptyValue")}
method allowEmptyValue (line 2) | set allowEmptyValue(s){this.set("allowEmptyValue",s)}
method style (line 2) | get style(){return this.get("style")}
method style (line 2) | set style(s){this.set("style",s)}
method explode (line 2) | get explode(){return this.get("explode")}
method explode (line 2) | set explode(s){this.set("explode",s)}
method allowReserved (line 2) | get allowReserved(){return this.get("allowReserved")}
method allowReserved (line 2) | set allowReserved(s){this.set("allowReserved",s)}
method schema (line 2) | get schema(){return this.get("schema")}
method schema (line 2) | set schema(s){this.set("schema",s)}
method example (line 2) | get example(){return this.get("example")}
method example (line 2) | set example(s){this.set("example",s)}
method examples (line 2) | get examples(){return this.get("examples")}
method examples (line 2) | set examples(s){this.set("examples",s)}
method contentProp (line 2) | get contentProp(){return this.get("content")}
method contentProp (line 2) | set contentProp(s){this.set("content",s)}
method get (line 2) | get(){return this.get("description")}
method set (line 2) | set(s){this.set("description",s)}
class Info (line 2) | class Info extends Su.Sh{constructor(s,o,i){super(s,o,i),this.element="i...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="info",this.classes.push(...
method title (line 2) | get title(){return this.get("title")}
method title (line 2) | set title(s){this.set("title",s)}
method description (line 2) | get description(){return this.get("description")}
method description (line 2) | set description(s){this.set("description",s)}
method termsOfService (line 2) | get termsOfService(){return this.get("termsOfService")}
method termsOfService (line 2) | set termsOfService(s){this.set("termsOfService",s)}
method contact (line 2) | get contact(){return this.get("contact")}
method contact (line 2) | set contact(s){this.set("contact",s)}
method license (line 2) | get license(){return this.get("license")}
method license (line 2) | set license(s){this.set("license",s)}
method version (line 2) | get version(){return this.get("version")}
method version (line 2) | set version(s){this.set("version",s)}
class License (line 2) | class License extends Su.Sh{constructor(s,o,i){super(s,o,i),this.element...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="license"}
method name (line 2) | get name(){return this.get("name")}
method name (line 2) | set name(s){this.set("name",s)}
method url (line 2) | get url(){return this.get("url")}
method url (line 2) | set url(s){this.set("url",s)}
class Link (line 2) | class Link extends Su.Sh{constructor(s,o,i){super(s,o,i),this.element="l...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="link"}
method operationRef (line 2) | get operationRef(){return this.get("operationRef")}
method operationRef (line 2) | set operationRef(s){this.set("operationRef",s)}
method operationId (line 2) | get operationId(){return this.get("operationId")}
method operationId (line 2) | set operationId(s){this.set("operationId",s)}
method operation (line 2) | get operation(){var s,o;return Pu(this.operationRef)?null===(s=this.op...
method operation (line 2) | set operation(s){this.set("operation",s)}
method parameters (line 2) | get parameters(){return this.get("parameters")}
method parameters (line 2) | set parameters(s){this.set("parameters",s)}
method requestBody (line 2) | get requestBody(){return this.get("requestBody")}
method requestBody (line 2) | set requestBody(s){this.set("requestBody",s)}
method description (line 2) | get description(){return this.get("description")}
method description (line 2) | set description(s){this.set("description",s)}
method server (line 2) | get server(){return this.get("server")}
method server (line 2) | set server(s){this.set("server",s)}
class MediaType (line 2) | class MediaType extends Su.Sh{constructor(s,o,i){super(s,o,i),this.eleme...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="mediaType"}
method schema (line 2) | get schema(){return this.get("schema")}
method schema (line 2) | set schema(s){this.set("schema",s)}
method example (line 2) | get example(){return this.get("example")}
method example (line 2) | set example(s){this.set("example",s)}
method examples (line 2) | get examples(){return this.get("examples")}
method examples (line 2) | set examples(s){this.set("examples",s)}
method encoding (line 2) | get encoding(){return this.get("encoding")}
method encoding (line 2) | set encoding(s){this.set("encoding",s)}
class OAuthFlow (line 2) | class OAuthFlow extends Su.Sh{constructor(s,o,i){super(s,o,i),this.eleme...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="oAuthFlow"}
method authorizationUrl (line 2) | get authorizationUrl(){return this.get("authorizationUrl")}
method authorizationUrl (line 2) | set authorizationUrl(s){this.set("authorizationUrl",s)}
method tokenUrl (line 2) | get tokenUrl(){return this.get("tokenUrl")}
method tokenUrl (line 2) | set tokenUrl(s){this.set("tokenUrl",s)}
method refreshUrl (line 2) | get refreshUrl(){return this.get("refreshUrl")}
method refreshUrl (line 2) | set refreshUrl(s){this.set("refreshUrl",s)}
method scopes (line 2) | get scopes(){return this.get("scopes")}
method scopes (line 2) | set scopes(s){this.set("scopes",s)}
class OAuthFlows (line 2) | class OAuthFlows extends Su.Sh{constructor(s,o,i){super(s,o,i),this.elem...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="oAuthFlows"}
method implicit (line 2) | get implicit(){return this.get("implicit")}
method implicit (line 2) | set implicit(s){this.set("implicit",s)}
method password (line 2) | get password(){return this.get("password")}
method password (line 2) | set password(s){this.set("password",s)}
method clientCredentials (line 2) | get clientCredentials(){return this.get("clientCredentials")}
method clientCredentials (line 2) | set clientCredentials(s){this.set("clientCredentials",s)}
method authorizationCode (line 2) | get authorizationCode(){return this.get("authorizationCode")}
method authorizationCode (line 2) | set authorizationCode(s){this.set("authorizationCode",s)}
class Openapi (line 2) | class Openapi extends Su.Om{constructor(s,o,i){super(s,o,i),this.element...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="openapi",this.classes.pu...
class OpenApi3_0 (line 2) | class OpenApi3_0 extends Su.Sh{constructor(s,o,i){super(s,o,i),this.elem...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="openApi3_0",this.classes...
method openapi (line 2) | get openapi(){return this.get("openapi")}
method openapi (line 2) | set openapi(s){this.set("openapi",s)}
method info (line 2) | get info(){return this.get("info")}
method info (line 2) | set info(s){this.set("info",s)}
method servers (line 2) | get servers(){return this.get("servers")}
method servers (line 2) | set servers(s){this.set("servers",s)}
method paths (line 2) | get paths(){return this.get("paths")}
method paths (line 2) | set paths(s){this.set("paths",s)}
method components (line 2) | get components(){return this.get("components")}
method components (line 2) | set components(s){this.set("components",s)}
method security (line 2) | get security(){return this.get("security")}
method security (line 2) | set security(s){this.set("security",s)}
method tags (line 2) | get tags(){return this.get("tags")}
method tags (line 2) | set tags(s){this.set("tags",s)}
method externalDocs (line 2) | get externalDocs(){return this.get("externalDocs")}
method externalDocs (line 2) | set externalDocs(s){this.set("externalDocs",s)}
class Operation (line 2) | class Operation extends Su.Sh{constructor(s,o,i){super(s,o,i),this.eleme...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="operation"}
method tags (line 2) | get tags(){return this.get("tags")}
method tags (line 2) | set tags(s){this.set("tags",s)}
method summary (line 2) | get summary(){return this.get("summary")}
method summary (line 2) | set summary(s){this.set("summary",s)}
method description (line 2) | get description(){return this.get("description")}
method description (line 2) | set description(s){this.set("description",s)}
method externalDocs (line 2) | set externalDocs(s){this.set("externalDocs",s)}
method externalDocs (line 2) | get externalDocs(){return this.get("externalDocs")}
method operationId (line 2) | get operationId(){return this.get("operationId")}
method operationId (line 2) | set operationId(s){this.set("operationId",s)}
method parameters (line 2) | get parameters(){return this.get("parameters")}
method parameters (line 2) | set parameters(s){this.set("parameters",s)}
method requestBody (line 2) | get requestBody(){return this.get("requestBody")}
method requestBody (line 2) | set requestBody(s){this.set("requestBody",s)}
method responses (line 2) | get responses(){return this.get("responses")}
method responses (line 2) | set responses(s){this.set("responses",s)}
method callbacks (line 2) | get callbacks(){return this.get("callbacks")}
method callbacks (line 2) | set callbacks(s){this.set("callbacks",s)}
method deprecated (line 2) | get deprecated(){return this.hasKey("deprecated")?this.get("deprecated...
method deprecated (line 2) | set deprecated(s){this.set("deprecated",s)}
method security (line 2) | get security(){return this.get("security")}
method security (line 2) | set security(s){this.set("security",s)}
method servers (line 2) | get servers(){return this.get("severs")}
method servers (line 2) | set servers(s){this.set("servers",s)}
class Parameter (line 2) | class Parameter extends Su.Sh{constructor(s,o,i){super(s,o,i),this.eleme...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="parameter"}
method name (line 2) | get name(){return this.get("name")}
method name (line 2) | set name(s){this.set("name",s)}
method in (line 2) | get in(){return this.get("in")}
method in (line 2) | set in(s){this.set("in",s)}
method required (line 2) | get required(){return this.hasKey("required")?this.get("required"):new...
method required (line 2) | set required(s){this.set("required",s)}
method deprecated (line 2) | get deprecated(){return this.hasKey("deprecated")?this.get("deprecated...
method deprecated (line 2) | set deprecated(s){this.set("deprecated",s)}
method allowEmptyValue (line 2) | get allowEmptyValue(){return this.get("allowEmptyValue")}
method allowEmptyValue (line 2) | set allowEmptyValue(s){this.set("allowEmptyValue",s)}
method style (line 2) | get style(){return this.get("style")}
method style (line 2) | set style(s){this.set("style",s)}
method explode (line 2) | get explode(){return this.get("explode")}
method explode (line 2) | set explode(s){this.set("explode",s)}
method allowReserved (line 2) | get allowReserved(){return this.get("allowReserved")}
method allowReserved (line 2) | set allowReserved(s){this.set("allowReserved",s)}
method schema (line 2) | get schema(){return this.get("schema")}
method schema (line 2) | set schema(s){this.set("schema",s)}
method example (line 2) | get example(){return this.get("example")}
method example (line 2) | set example(s){this.set("example",s)}
method examples (line 2) | get examples(){return this.get("examples")}
method examples (line 2) | set examples(s){this.set("examples",s)}
method contentProp (line 2) | get contentProp(){return this.get("content")}
method contentProp (line 2) | set contentProp(s){this.set("content",s)}
method get (line 2) | get(){return this.get("description")}
method set (line 2) | set(s){this.set("description",s)}
class PathItem (line 2) | class PathItem extends Su.Sh{constructor(s,o,i){super(s,o,i),this.elemen...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="pathItem"}
method $ref (line 2) | get $ref(){return this.get("$ref")}
method $ref (line 2) | set $ref(s){this.set("$ref",s)}
method summary (line 2) | get summary(){return this.get("summary")}
method summary (line 2) | set summary(s){this.set("summary",s)}
method description (line 2) | get description(){return this.get("description")}
method description (line 2) | set description(s){this.set("description",s)}
method GET (line 2) | get GET(){return this.get("get")}
method GET (line 2) | set GET(s){this.set("GET",s)}
method PUT (line 2) | get PUT(){return this.get("put")}
method PUT (line 2) | set PUT(s){this.set("PUT",s)}
method POST (line 2) | get POST(){return this.get("post")}
method POST (line 2) | set POST(s){this.set("POST",s)}
method DELETE (line 2) | get DELETE(){return this.get("delete")}
method DELETE (line 2) | set DELETE(s){this.set("DELETE",s)}
method OPTIONS (line 2) | get OPTIONS(){return this.get("options")}
method OPTIONS (line 2) | set OPTIONS(s){this.set("OPTIONS",s)}
method HEAD (line 2) | get HEAD(){return this.get("head")}
method HEAD (line 2) | set HEAD(s){this.set("HEAD",s)}
method PATCH (line 2) | get PATCH(){return this.get("patch")}
method PATCH (line 2) | set PATCH(s){this.set("PATCH",s)}
method TRACE (line 2) | get TRACE(){return this.get("trace")}
method TRACE (line 2) | set TRACE(s){this.set("TRACE",s)}
method servers (line 2) | get servers(){return this.get("servers")}
method servers (line 2) | set servers(s){this.set("servers",s)}
method parameters (line 2) | get parameters(){return this.get("parameters")}
method parameters (line 2) | set parameters(s){this.set("parameters",s)}
class Paths (line 2) | class Paths extends Su.Sh{constructor(s,o,i){super(s,o,i),this.element="...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="paths"}
class Reference (line 2) | class Reference extends Su.Sh{constructor(s,o,i){super(s,o,i),this.eleme...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="reference",this.classes....
method $ref (line 2) | get $ref(){return this.get("$ref")}
method $ref (line 2) | set $ref(s){this.set("$ref",s)}
class RequestBody (line 2) | class RequestBody extends Su.Sh{constructor(s,o,i){super(s,o,i),this.ele...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="requestBody"}
method description (line 2) | get description(){return this.get("description")}
method description (line 2) | set description(s){this.set("description",s)}
method contentProp (line 2) | get contentProp(){return this.get("content")}
method contentProp (line 2) | set contentProp(s){this.set("content",s)}
method required (line 2) | get required(){return this.hasKey("required")?this.get("required"):new...
method required (line 2) | set required(s){this.set("required",s)}
class Response_Response (line 2) | class Response_Response extends Su.Sh{constructor(s,o,i){super(s,o,i),th...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="response"}
method description (line 2) | get description(){return this.get("description")}
method description (line 2) | set description(s){this.set("description",s)}
method headers (line 2) | get headers(){return this.get("headers")}
method headers (line 2) | set headers(s){this.set("headers",s)}
method contentProp (line 2) | get contentProp(){return this.get("content")}
method contentProp (line 2) | set contentProp(s){this.set("content",s)}
method links (line 2) | get links(){return this.get("links")}
method links (line 2) | set links(s){this.set("links",s)}
class Responses (line 2) | class Responses extends Su.Sh{constructor(s,o,i){super(s,o,i),this.eleme...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="responses"}
method default (line 2) | get default(){return this.get("default")}
method default (line 2) | set default(s){this.set("default",s)}
class JSONSchema (line 2) | class JSONSchema extends Su.Sh{constructor(s,o,i){super(s,o,i),this.elem...
method constructor (line 2) | constructor(s,o,i){super(s,o,i),this.element="JSONSchemaDraft4"}
method idProp (line 2) | get idProp(){return this.get("id")}
method idProp (line 2) | set idProp(s){this.set("id",s)}
method $schema (line 2) | get $schema(){return this.get("$schema")}
method $schema (line 2) | set $schema(s){this.set("$schema",s)}
method multipleOf (line 2) | get multipleOf(){return this.get("multipleOf")}
method multipleOf (line 2) | set multipleOf(s){this.set("multipleOf",s)}
method maximum (line 2) | get maximum(){return this.get("maximum")}
method maximum (line 2) | set maximum(s){this.set("maximum",s)}
method exclusiveMaximum (line 2) | get exclusiveMaximum(){return this.get("exclusiveMaximum")}
method exclusiveMaximum (line 2) | set exclusiveMaximum(s){this.set("exclusiveMaximum",s)}
method minimum (line 2) | get minimum(){return this.get("minimum")}
method minimum (line 2) | set minimum(s){this.set("minimum",s)}
method exclusiveMinimum (line 2) | get exclusiveMinimum(){return this.get("exclusiveMinimum")}
method exclusiveMinimum (line 2) | set exclusiveMinimum(s){this.set("exclusiveMinimum",s)}
method maxLength (line 2) | get maxLength(){return this.get("maxLength")}
method maxLength (line 2) | set maxLength(s){this.set("maxLength",s)}
method minLength (line 2) | get minLength(){return this.get("minLength")}
method minLength (line 2) | set minLength(s){this.set("minLength",s)}
method pattern (line 2) | get pattern(){return this.get("pattern")}
method pattern (line 2) | set pattern(s){this.set("pattern",s)}
method additionalItems (line 2) | get additionalItems(){return this.get("additionalItems")}
method additionalItems (line 2) | set additionalItems(s){this.set("additionalItems",s)}
method items (line 2) | get items(){return this.get("items")}
method items (line 2) | set items(s){this.set("items",s)}
method maxItems (line 2) | get maxItems(){return this.ge
Condensed preview — 378 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (6,829K chars).
[
{
"path": ".clinerules/01-basic.md",
"chars": 11494,
"preview": "# LightRAG Project Intelligence (.clinerules)\n\n## Project Overview\nLightRAG is a mature, production-ready Retrieval-Augm"
},
{
"path": ".dockerignore",
"chars": 740,
"preview": "# Python-related files and directories\n__pycache__\n.cache\n\n# Virtual environment directories\n*.venv\n\n# Env\nenv/\n*.env*\n."
},
{
"path": ".gitattributes",
"chars": 70,
"preview": "lightrag/api/webui/** binary\nlightrag/api/webui/** linguist-generated\n"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.yml",
"chars": 2063,
"preview": "name: Bug Report\ndescription: File a bug report\ntitle: \"[Bug]:\"\nlabels: [\"bug\", \"triage\"]\n\nbody:\n - type: checkboxes\n "
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 28,
"preview": "blank_issues_enabled: false\n"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.yml",
"chars": 1063,
"preview": "name: Feature Request\ndescription: File a feature request\nlabels: [\"enhancement\"]\ntitle: \"[Feature Request]:\"\n\nbody:\n -"
},
{
"path": ".github/ISSUE_TEMPLATE/question.yml",
"chars": 980,
"preview": "name: Question\ndescription: Ask a general question\nlabels: [\"question\"]\ntitle: \"[Question]:\"\n\nbody:\n - type: checkboxes"
},
{
"path": ".github/dependabot.yml",
"chars": 5495,
"preview": "# Keep GitHub Actions up to date with GitHub's Dependabot...\n# https://docs.github.com/en/code-security/dependabot/worki"
},
{
"path": ".github/pull_request_template.md",
"chars": 732,
"preview": "<!--\nThanks for contributing to LightRAG!\n\nPlease ensure your pull request is ready for review before submitting.\n\nAbout"
},
{
"path": ".github/workflows/claude.yml",
"chars": 4142,
"preview": "name: Claude Code\n\non:\n issue_comment:\n types: [created]\n pull_request_review_comment:\n types: [created]\n issue"
},
{
"path": ".github/workflows/copilot-setup-steps.yml",
"chars": 1965,
"preview": "name: \"Copilot Setup Steps\"\n\n# Automatically run the setup steps when they are changed to allow for easy validation, and"
},
{
"path": ".github/workflows/docker-build-lite.yml",
"chars": 2606,
"preview": "name: Build Lite Docker Image\n\non:\n workflow_dispatch:\n inputs:\n _notes_:\n description: '⚠️ Create lite "
},
{
"path": ".github/workflows/docker-build-manual.yml",
"chars": 2588,
"preview": "name: Build Test Docker Image manually\n\non:\n workflow_dispatch:\n inputs:\n _notes_:\n description: '⚠️ Ple"
},
{
"path": ".github/workflows/docker-publish.yml",
"chars": 2318,
"preview": "name: Build Latest Docker Image on Release\n\non:\n release:\n types: [published]\n workflow_dispatch:\n\npermissions:\n c"
},
{
"path": ".github/workflows/linting.yaml",
"chars": 718,
"preview": "name: Linting and Formatting\n\non:\n push:\n branches:\n - main\n pull_request:\n branches:\n "
},
{
"path": ".github/workflows/pypi-publish.yml",
"chars": 2314,
"preview": "name: Upload LightRAG-hku Package\n\non:\n release:\n types: [published]\n workflow_dispatch:\n\npermissions:\n contents: "
},
{
"path": ".github/workflows/stale.yaml",
"chars": 1355,
"preview": "# .github/workflows/stale.yml\nname: Mark stale issues and pull requests\n\non:\n schedule:\n - cron: '30 22 * * *' # run"
},
{
"path": ".github/workflows/tests.yml",
"chars": 1367,
"preview": "name: Offline Unit Tests\n\non:\n push:\n branches: [ main, dev ]\n pull_request:\n branches: [ main, dev ]\n\njobs:\n o"
},
{
"path": ".gitignore",
"chars": 994,
"preview": "# Python-related files\n__pycache__/\n*.py[cod]\n*.egg-info/\n.eggs/\n*.tgz\n*.tar.gz\n*.ini\n\n# Virtual Environment\n.venv/\nvenv"
},
{
"path": ".pre-commit-config.yaml",
"chars": 711,
"preview": "repos:\n - repo: https://github.com/pre-commit/pre-commit-hooks\n rev: v5.0.0\n hooks:\n - id: trailing-whitespa"
},
{
"path": "AGENTS.md",
"chars": 6399,
"preview": "# Repository Guidelines\n\nLightRAG is an advanced Retrieval-Augmented Generation (RAG) framework designed to enhance info"
},
{
"path": "Dockerfile",
"chars": 3626,
"preview": "# syntax=docker/dockerfile:1\n\n# Frontend build stage\n# Build frontend assets on the native build platform to avoid\n# cro"
},
{
"path": "Dockerfile.lite",
"chars": 3552,
"preview": "# syntax=docker/dockerfile:1\n\n# Frontend build stage\n# Build frontend assets on the native build platform to avoid\n# cro"
},
{
"path": "LICENSE",
"chars": 1070,
"preview": "MIT License\n\nCopyright (c) 2025 LightRAG Team\n\nPermission is hereby granted, free of charge, to any person obtaining a c"
},
{
"path": "MANIFEST.in",
"chars": 142,
"preview": "include requirements.txt\ninclude lightrag/api/requirements.txt\nrecursive-include lightrag/api/webui *\nrecursive-include "
},
{
"path": "Makefile",
"chars": 3235,
"preview": "SHELL := /bin/bash\nSETUP_SCRIPT := scripts/setup/setup.sh\nSETUP_BASH ?= $(or $(firstword $(wildcard /opt/homebrew/bin/ba"
},
{
"path": "README-zh.md",
"chars": 72372,
"preview": "<div align=\"center\">\n\n<div style=\"margin: 20px 0;\">\n <img src=\"./assets/logo.png\" width=\"120\" height=\"120\" alt=\"LightRA"
},
{
"path": "README.md",
"chars": 96179,
"preview": "<div align=\"center\">\n\n<div style=\"margin: 20px 0;\">\n <img src=\"./assets/logo.png\" width=\"120\" height=\"120\" alt=\"LightRA"
},
{
"path": "SECURITY.md",
"chars": 972,
"preview": "# Reporting Security Issues\n\nThe LightRAG team and community take security bugs seriously. We appreciate your efforts to"
},
{
"path": "config.ini.example",
"chars": 948,
"preview": "[neo4j]\nuri = neo4j+s://xxxxxxxx.databases.neo4j.io\nusername = neo4j\npassword = your-password\nconnection_pool_size = 100"
},
{
"path": "docker-build-push.sh",
"chars": 2011,
"preview": "#!/bin/bash\nset -e\n\n# Configuration\nIMAGE_NAME=\"ghcr.io/hkuds/lightrag\"\nDOCKERFILE=\"Dockerfile\"\nTAG=\"latest\"\n\n# Get vers"
},
{
"path": "docker-compose-full.yml",
"chars": 7139,
"preview": "# Full Docker Compose Deployment Sample Generated by Setup Wizard: `make base` and `make storage`\n# This Sample File req"
},
{
"path": "docker-compose.yml",
"chars": 679,
"preview": "services:\n lightrag:\n image: ghcr.io/hkuds/lightrag:latest\n build:\n context: .\n dockerfile: Dockerfile\n"
},
{
"path": "docs/Algorithm.md",
"chars": 544,
"preview": ":\n pm.install(\"pyvis\")\nif not pm.is_installed(\"networkx\"):\n "
},
{
"path": "examples/graph_visual_with_neo4j.py",
"chars": 6174,
"preview": "import os\nimport json\nimport xml.etree.ElementTree as ET\nfrom neo4j import GraphDatabase\n\n# Constants\nWORKING_DIR = \"./d"
},
{
"path": "examples/graph_visual_with_opensearch.py",
"chars": 5090,
"preview": "\"\"\"\nKnowledge Graph Visualization with OpenSearch + LightRAG WebUI\n\nThis script demonstrates two ways to visualize the k"
},
{
"path": "examples/insert_custom_kg.py",
"chars": 3667,
"preview": "import os\nfrom lightrag import LightRAG\nfrom lightrag.llm.openai import gpt_4o_mini_complete\n#########\n# Uncomment the b"
},
{
"path": "examples/lightrag_azure_openai_demo.py",
"chars": 3441,
"preview": "import os\nimport asyncio\nfrom lightrag import LightRAG, QueryParam\nfrom lightrag.utils import EmbeddingFunc\nimport numpy"
},
{
"path": "examples/lightrag_gemini_demo.py",
"chars": 3365,
"preview": "\"\"\"\nLightRAG Demo with Google Gemini Models\n\nThis example demonstrates how to use LightRAG with Google's Gemini 2.0 Flas"
},
{
"path": "examples/lightrag_gemini_postgres_demo.py",
"chars": 4991,
"preview": "\"\"\"\nLightRAG Demo with PostgreSQL + Google Gemini\n\nThis example demonstrates how to use LightRAG with:\n- Google Gemini ("
},
{
"path": "examples/lightrag_gemini_workspace_demo.py",
"chars": 4720,
"preview": "\"\"\"\nLightRAG Data Isolation Demo: Workspace Management\n\nThis example demonstrates how to maintain multiple isolated know"
},
{
"path": "examples/lightrag_ollama_demo.py",
"chars": 7477,
"preview": "import asyncio\nimport os\nimport inspect\nimport logging\nimport logging.config\nfrom functools import partial\nfrom lightrag"
},
{
"path": "examples/lightrag_openai_compatible_demo.py",
"chars": 7656,
"preview": "import os\nimport asyncio\nimport inspect\nimport logging\nimport logging.config\nfrom functools import partial\nfrom lightrag"
},
{
"path": "examples/lightrag_openai_demo.py",
"chars": 6069,
"preview": "import os\nimport asyncio\nimport logging\nimport logging.config\nfrom lightrag import LightRAG, QueryParam\nfrom lightrag.ll"
},
{
"path": "examples/lightrag_openai_mongodb_graph_demo.py",
"chars": 3085,
"preview": "import os\nimport asyncio\nfrom lightrag import LightRAG, QueryParam\nfrom lightrag.llm.openai import gpt_4o_mini_complete,"
},
{
"path": "examples/lightrag_openai_opensearch_graph_demo.py",
"chars": 5144,
"preview": "\"\"\"\nLightRAG Demo with OpenSearch + OpenAI\n\nThis example demonstrates how to use LightRAG with:\n- OpenAI (LLM + Embeddin"
},
{
"path": "examples/lightrag_vllm_demo.py",
"chars": 5378,
"preview": "\"\"\"\nLightRAG Demo with vLLM (LLM, Embeddings, and Reranker)\n\nThis example demonstrates how to use LightRAG with:\n- vLLM-"
},
{
"path": "examples/milvus_kwargs_configuration_demo.py",
"chars": 4775,
"preview": "\"\"\"\nExample: Configuring Milvus Index Parameters via vector_db_storage_cls_kwargs\n\nThis example demonstrates how to conf"
},
{
"path": "examples/modalprocessors_example.py",
"chars": 7028,
"preview": "\"\"\"\nExample of directly using modal processors\n\nThis example demonstrates how to use LightRAG's modal processors directl"
},
{
"path": "examples/opensearch_storage_demo.py",
"chars": 11598,
"preview": "\"\"\"\nIntegration test for OpenSearch Storage in LightRAG.\n\nTests all 4 storage types against a live OpenSearch cluster:\n-"
},
{
"path": "examples/raganything_example.py",
"chars": 9841,
"preview": "#!/usr/bin/env python\n\"\"\"\nExample script demonstrating the integration of MinerU parser with RAGAnything\n\nThis example s"
},
{
"path": "examples/rerank_example.py",
"chars": 7697,
"preview": "\"\"\"\nLightRAG Rerank Integration Example\n\nThis example demonstrates how to use rerank functionality with LightRAG\nto impr"
},
{
"path": "examples/unofficial-sample/copy_llm_cache_to_another_storage.py",
"chars": 3637,
"preview": "\"\"\"\nSometimes you need to switch a storage solution, but you want to save LLM token and time.\nThis handy script helps yo"
},
{
"path": "examples/unofficial-sample/lightrag_bedrock_demo.py",
"chars": 1353,
"preview": "\"\"\"\nLightRAG meets Amazon Bedrock ⛰️\n\"\"\"\n\nimport os\nimport logging\n\nfrom lightrag import LightRAG, QueryParam\nfrom light"
},
{
"path": "examples/unofficial-sample/lightrag_cloudflare_demo.py",
"chars": 11200,
"preview": "import asyncio\nimport os\nimport inspect\nimport logging\nimport logging.config\nfrom lightrag import LightRAG, QueryParam\nf"
},
{
"path": "examples/unofficial-sample/lightrag_hf_demo.py",
"chars": 1911,
"preview": "import os\n\nfrom lightrag import LightRAG, QueryParam\nfrom lightrag.llm.hf import hf_model_complete, hf_embed\nfrom lightr"
},
{
"path": "examples/unofficial-sample/lightrag_llamaindex_direct_demo.py",
"chars": 3782,
"preview": "import os\nfrom lightrag import LightRAG, QueryParam\nfrom lightrag.llm.llama_index_impl import (\n llama_index_complete"
},
{
"path": "examples/unofficial-sample/lightrag_llamaindex_litellm_demo.py",
"chars": 3930,
"preview": "import os\nfrom lightrag import LightRAG, QueryParam\nfrom lightrag.llm.llama_index_impl import (\n llama_index_complete"
},
{
"path": "examples/unofficial-sample/lightrag_llamaindex_litellm_opik_demo.py",
"chars": 4272,
"preview": "import os\nfrom lightrag import LightRAG, QueryParam\nfrom lightrag.llm.llama_index_impl import (\n llama_index_complete"
},
{
"path": "examples/unofficial-sample/lightrag_lmdeploy_demo.py",
"chars": 3014,
"preview": "import os\n\nfrom lightrag import LightRAG, QueryParam\nfrom lightrag.llm.lmdeploy import lmdeploy_model_if_cache\nfrom ligh"
},
{
"path": "examples/unofficial-sample/lightrag_nvidia_demo.py",
"chars": 5087,
"preview": "import os\nimport asyncio\nimport nest_asyncio\n\nfrom lightrag import LightRAG, QueryParam\nfrom lightrag.llm import (\n o"
},
{
"path": "examples/unofficial-sample/lightrag_openai_neo4j_milvus_redis_demo.py",
"chars": 2763,
"preview": "import os\nimport asyncio\nfrom lightrag import LightRAG, QueryParam\nfrom lightrag.llm.ollama import ollama_embed, openai_"
},
{
"path": "k8s-deploy/README-zh.md",
"chars": 4830,
"preview": "# LightRAG Helm Chart\n\n这是用于在Kubernetes集群上部署LightRAG服务的Helm chart。\n\nLightRAG有两种推荐的部署方法:\n1. **轻量级部署**:使用内置轻量级存储,适合测试和小规模使用"
},
{
"path": "k8s-deploy/README.md",
"chars": 7747,
"preview": "# LightRAG Helm Chart\n\nThis is the Helm chart for LightRAG, used to deploy LightRAG services on a Kubernetes cluster.\n\nT"
},
{
"path": "k8s-deploy/databases/00-config.sh",
"chars": 572,
"preview": "#!/bin/bash\n\n# Get the directory where this script is located\nDATABASE_SCRIPT_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\""
},
{
"path": "k8s-deploy/databases/01-prepare.sh",
"chars": 2042,
"preview": "#!/bin/bash\n\n# Get the directory where this script is located\nDATABASE_SCRIPT_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\""
},
{
"path": "k8s-deploy/databases/02-install-database.sh",
"chars": 3855,
"preview": "#!/bin/bash\n\n# Get the directory where this script is located\nDATABASE_SCRIPT_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\""
},
{
"path": "k8s-deploy/databases/03-uninstall-database.sh",
"chars": 1319,
"preview": "#!/bin/bash\n\n# Get the directory where this script is located\nDATABASE_SCRIPT_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\""
},
{
"path": "k8s-deploy/databases/04-cleanup.sh",
"chars": 1455,
"preview": "#!/bin/bash\n\n# Get the directory where this script is located\nDATABASE_SCRIPT_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\""
},
{
"path": "k8s-deploy/databases/README.md",
"chars": 6347,
"preview": "# Using KubeBlocks to Deploy and Manage Databases\n\nLearn how to quickly deploy and manage various databases in a Kuberne"
},
{
"path": "k8s-deploy/databases/elasticsearch/values.yaml",
"chars": 724,
"preview": "## description: The version of ElasticSearch.\n## default: 8.8.2\nversion: \"8.8.2\"\n\n## description: Mode for ElasticSearch"
},
{
"path": "k8s-deploy/databases/install-kubeblocks.sh",
"chars": 2368,
"preview": "#!/bin/bash\n\n# Get the directory where this script is located\nDATABASE_SCRIPT_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\""
},
{
"path": "k8s-deploy/databases/mongodb/values.yaml",
"chars": 705,
"preview": "## description: Cluster version.\n## default: 6.0.16\n## one of: [8.0.8, 8.0.6, 8.0.4, 7.0.19, 7.0.16, 7.0.12, 6.0.22, 6.0"
},
{
"path": "k8s-deploy/databases/neo4j/values.yaml",
"chars": 837,
"preview": "# Version\n# description: Cluster version.\n# default: 5.26.5\n# one of: [5.26.5, 4.4.42]\nversion: 5.26.5\n\n# Mode\n# descrip"
},
{
"path": "k8s-deploy/databases/postgresql/values.yaml",
"chars": 734,
"preview": "## description: service version.\n## default: 15.7.0\nversion: 16.4.0\n\n## mode postgresql cluster topology mode replicatio"
},
{
"path": "k8s-deploy/databases/qdrant/values.yaml",
"chars": 552,
"preview": "## description: The version of Qdrant.\n## default: 1.10.0\nversion: 1.10.0\n\n## description: The number of replicas.\n## de"
},
{
"path": "k8s-deploy/databases/redis/values.yaml",
"chars": 721,
"preview": "## description: Cluster version.\n## default: 7.2.7\nversion: 7.2.7\n\n## description: Cluster topology mode.\n## default: re"
},
{
"path": "k8s-deploy/databases/scripts/common.sh",
"chars": 912,
"preview": "#!/bin/bash\n\nprint_title() {\n echo \"============================================\"\n echo \"$1\"\n echo \"================="
},
{
"path": "k8s-deploy/databases/uninstall-kubeblocks.sh",
"chars": 2198,
"preview": "#!/bin/bash\n\n# Get the directory where this script is located\nDATABASE_SCRIPT_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\""
},
{
"path": "k8s-deploy/install_lightrag.sh",
"chars": 3945,
"preview": "#!/bin/bash\n\nNAMESPACE=rag\n\nSCRIPT_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" &> /dev/null && pwd )\"\n\nif [ -z \"$OPENA"
},
{
"path": "k8s-deploy/install_lightrag_dev.sh",
"chars": 2827,
"preview": "#!/bin/bash\n\nNAMESPACE=rag\n\nSCRIPT_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" &> /dev/null && pwd )\"\n\ncheck_dependenc"
},
{
"path": "k8s-deploy/lightrag/.helmignore",
"chars": 349,
"preview": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation"
},
{
"path": "k8s-deploy/lightrag/Chart.yaml",
"chars": 245,
"preview": "apiVersion: v2\nname: lightrag\ndescription: A Helm chart for LightRAG, an efficient and lightweight RAG system\ntype: appl"
},
{
"path": "k8s-deploy/lightrag/templates/NOTES.txt",
"chars": 2121,
"preview": "===========================================\n LightRAG has been successfully deployed!\n=================================="
},
{
"path": "k8s-deploy/lightrag/templates/_helpers.tpl",
"chars": 958,
"preview": "{{/*\nApplication name\n*/}}\n{{- define \"lightrag.name\" -}}\n{{- default .Chart.Name .Values.nameOverride | trunc 63 | trim"
},
{
"path": "k8s-deploy/lightrag/templates/deployment.yaml",
"chars": 2768,
"preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: {{ include \"lightrag.fullname\" . }}\n labels:\n {{- include \"li"
},
{
"path": "k8s-deploy/lightrag/templates/pvc.yaml",
"chars": 638,
"preview": "{{- if .Values.persistence.enabled }}\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: {{ include \"light"
},
{
"path": "k8s-deploy/lightrag/templates/secret.yaml",
"chars": 238,
"preview": "apiVersion: v1\nkind: Secret\nmetadata:\n name: {{ include \"lightrag.fullname\" . }}-env\n labels:\n {{- include \"lightra"
},
{
"path": "k8s-deploy/lightrag/templates/service.yaml",
"chars": 382,
"preview": "apiVersion: v1\nkind: Service\nmetadata:\n name: {{ include \"lightrag.fullname\" . }}\n labels:\n {{- include \"lightrag.l"
},
{
"path": "k8s-deploy/lightrag/values.yaml",
"chars": 2162,
"preview": "replicaCount: 1\n\nimage:\n repository: ghcr.io/hkuds/lightrag\n tag: latest\n # Optionally specify imagePullSecrets if yo"
},
{
"path": "k8s-deploy/uninstall_lightrag.sh",
"chars": 74,
"preview": "#!/bin/bash\n\nNAMESPACE=rag\nhelm uninstall lightrag --namespace $NAMESPACE\n"
},
{
"path": "k8s-deploy/uninstall_lightrag_dev.sh",
"chars": 78,
"preview": "#!/bin/bash\n\nNAMESPACE=rag\nhelm uninstall lightrag-dev --namespace $NAMESPACE\n"
},
{
"path": "lightrag/__init__.py",
"chars": 164,
"preview": "from .lightrag import LightRAG as LightRAG, QueryParam as QueryParam\n\n__version__ = \"1.4.11\"\n__author__ = \"Zirui Guo\"\n__"
},
{
"path": "lightrag/api/.gitignore",
"chars": 19,
"preview": "inputs\nrag_storage\n"
},
{
"path": "lightrag/api/README-zh.md",
"chars": 22025,
"preview": "# LightRAG 服务器和 WebUI\n\nLightRAG 服务器旨在提供 Web 界面和 API 支持。Web 界面便于文档索引、知识图谱探索和简单的 RAG 查询界面。LightRAG 服务器还提供了与 Ollama 兼容的接口,旨"
},
{
"path": "lightrag/api/README.md",
"chars": 41160,
"preview": "# LightRAG Server and WebUI\n\nThe LightRAG Server is designed to provide a Web UI and API support. The Web UI facilitates"
},
{
"path": "lightrag/api/__init__.py",
"chars": 25,
"preview": "__api_version__ = \"0276\"\n"
},
{
"path": "lightrag/api/auth.py",
"chars": 3455,
"preview": "from datetime import datetime, timedelta\n\nimport jwt\nfrom dotenv import load_dotenv\nfrom fastapi import HTTPException, s"
},
{
"path": "lightrag/api/config.py",
"chars": 20952,
"preview": "\"\"\"\nConfigs for the LightRAG API.\n\"\"\"\n\nimport os\nimport re\nimport argparse\nimport logging\nfrom dotenv import load_dotenv"
},
{
"path": "lightrag/api/gunicorn_config.py",
"chars": 5043,
"preview": "# gunicorn_config.py\nimport os\nimport logging\nfrom lightrag.kg.shared_storage import finalize_share_data\nfrom lightrag.u"
},
{
"path": "lightrag/api/lightrag_server.py",
"chars": 61726,
"preview": "\"\"\"\nLightRAG FastAPI Server\n\"\"\"\n\nfrom fastapi import FastAPI, Depends, HTTPException, Request\nfrom fastapi.exceptions im"
},
{
"path": "lightrag/api/routers/__init__.py",
"chars": 331,
"preview": "\"\"\"\nThis module contains all the routers for the LightRAG API.\n\"\"\"\n\nfrom .document_routes import router as document_rout"
},
{
"path": "lightrag/api/routers/document_routes.py",
"chars": 135525,
"preview": "\"\"\"\nThis module contains all document-related routes for the LightRAG API.\n\"\"\"\n\nimport asyncio\nfrom functools import lru"
},
{
"path": "lightrag/api/routers/graph_routes.py",
"chars": 28533,
"preview": "\"\"\"\nThis module contains all graph-related routes for the LightRAG API.\n\"\"\"\n\nfrom typing import Optional, Dict, Any\nimpo"
},
{
"path": "lightrag/api/routers/ollama_api.py",
"chars": 31987,
"preview": "from fastapi import APIRouter, HTTPException, Request\nfrom pydantic import BaseModel\nfrom typing import List, Dict, Any,"
},
{
"path": "lightrag/api/routers/query_routes.py",
"chars": 60266,
"preview": "\"\"\"\nThis module contains all query-related routes for the LightRAG API.\n\"\"\"\n\nimport json\nfrom typing import Any, Dict, L"
},
{
"path": "lightrag/api/run_with_gunicorn.py",
"chars": 10216,
"preview": "#!/usr/bin/env python\n\"\"\"\nStart LightRAG server with Gunicorn\n\"\"\"\n\nimport os\nimport sys\nimport platform\nimport pipmaster"
},
{
"path": "lightrag/api/runtime_validation.py",
"chars": 4105,
"preview": "\"\"\"Helpers for validating startup runtime expectations from `.env`.\"\"\"\n\nfrom __future__ import annotations\n\nimport os\nfr"
},
{
"path": "lightrag/api/static/swagger-ui/swagger-ui-bundle.js",
"chars": 1509189,
"preview": "/*! For license information please see swagger-ui-bundle.js.LICENSE.txt */\n!function webpackUniversalModuleDefinition(s,"
},
{
"path": "lightrag/api/static/swagger-ui/swagger-ui.css",
"chars": 155212,
"preview": ".swagger-ui{color:#3b4151;font-family:sans-serif}.swagger-ui html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-tex"
},
{
"path": "lightrag/api/utils_api.py",
"chars": 19208,
"preview": "\"\"\"\nUtility functions for the LightRAG API.\n\"\"\"\n\nimport os\nimport argparse\nfrom typing import Optional, List, Tuple\nimpo"
},
{
"path": "lightrag/base.py",
"chars": 30696,
"preview": "from __future__ import annotations\n\nfrom abc import ABC, abstractmethod\nfrom enum import Enum\nimport os\nfrom dotenv impo"
},
{
"path": "lightrag/constants.py",
"chars": 3944,
"preview": "\"\"\"\nCentralized configuration constants for LightRAG.\n\nThis module defines default values for configuration constants us"
},
{
"path": "lightrag/evaluation/README_EVALUASTION_RAGAS.md",
"chars": 16688,
"preview": "# 📊 RAGAS-based Evaluation Framework\n\n## What is RAGAS?\n\n**RAGAS** (Retrieval Augmented Generation Assessment) is a fram"
},
{
"path": "lightrag/evaluation/__init__.py",
"chars": 646,
"preview": "\"\"\"\nLightRAG Evaluation Module\n\nRAGAS-based evaluation framework for assessing RAG system quality.\n\nUsage:\n from ligh"
},
{
"path": "lightrag/evaluation/eval_rag_quality.py",
"chars": 39781,
"preview": "#!/usr/bin/env python3\n\"\"\"\nRAGAS Evaluation Script for LightRAG System\n\nEvaluates RAG response quality using RAGAS metri"
},
{
"path": "lightrag/evaluation/sample_dataset.json",
"chars": 3971,
"preview": "{\n \"test_cases\": [\n {\n \"question\": \"How does LightRAG solve the hallucination problem in large language models?"
},
{
"path": "lightrag/evaluation/sample_documents/01_lightrag_overview.md",
"chars": 1409,
"preview": "# LightRAG Framework Overview\n\n## What is LightRAG?\n\n**LightRAG** is a Simple and Fast Retrieval-Augmented Generation fr"
},
{
"path": "lightrag/evaluation/sample_documents/02_rag_architecture.md",
"chars": 1497,
"preview": "# RAG System Architecture\n\n## Main Components of RAG Systems\n\nA RAG system consists of three main components that work t"
},
{
"path": "lightrag/evaluation/sample_documents/03_lightrag_improvements.md",
"chars": 1580,
"preview": "# LightRAG Improvements Over Traditional RAG\n\n## Key Improvements\n\nLightRAG improves upon traditional RAG approaches in "
},
{
"path": "lightrag/evaluation/sample_documents/04_supported_databases.md",
"chars": 1916,
"preview": "# LightRAG Vector Database Support\n\n## Supported Vector Databases\n\nLightRAG supports multiple vector databases for flexi"
},
{
"path": "lightrag/evaluation/sample_documents/05_evaluation_and_deployment.md",
"chars": 2459,
"preview": "# RAG Evaluation Metrics and Deployment\n\n## Key RAG Evaluation Metrics\n\nRAG system quality is measured through four key "
},
{
"path": "lightrag/evaluation/sample_documents/README.md",
"chars": 813,
"preview": "# Sample Documents for Evaluation\n\nThese markdown files correspond to test questions in `../sample_dataset.json`.\n\n## Us"
},
{
"path": "lightrag/exceptions.py",
"chars": 4798,
"preview": "from __future__ import annotations\n\nimport httpx\nfrom typing import Literal\n\n\nclass APIStatusError(Exception):\n \"\"\"Ra"
},
{
"path": "lightrag/kg/__init__.py",
"chars": 5364,
"preview": "STORAGE_IMPLEMENTATIONS = {\n \"KV_STORAGE\": {\n \"implementations\": [\n \"JsonKVStorage\",\n \"R"
},
{
"path": "lightrag/kg/deprecated/chroma_impl.py",
"chars": 13221,
"preview": "import asyncio\nimport os\nfrom dataclasses import dataclass\nfrom typing import Any, final\nimport numpy as np\n\nfrom lightr"
},
{
"path": "lightrag/kg/faiss_impl.py",
"chars": 22387,
"preview": "import os\nimport time\nimport asyncio\nfrom typing import Any, final\nimport json\nimport numpy as np\nfrom dataclasses impor"
},
{
"path": "lightrag/kg/json_doc_status_impl.py",
"chars": 15790,
"preview": "from dataclasses import dataclass\nimport os\nfrom typing import Any, Union, final\n\nfrom lightrag.base import (\n DocPro"
},
{
"path": "lightrag/kg/json_kv_impl.py",
"chars": 11729,
"preview": "import os\nfrom dataclasses import dataclass\nfrom typing import Any, final\n\nfrom lightrag.base import (\n BaseKVStorage"
},
{
"path": "lightrag/kg/memgraph_impl.py",
"chars": 47479,
"preview": "import os\nimport asyncio\nimport random\nfrom dataclasses import dataclass\nfrom typing import final\nimport configparser\n\nf"
},
{
"path": "lightrag/kg/milvus_impl.py",
"chars": 71516,
"preview": "import asyncio\nimport os\nfrom typing import Any, final, Optional, Dict\nfrom dataclasses import dataclass, fields\nimport "
},
{
"path": "lightrag/kg/mongo_impl.py",
"chars": 96435,
"preview": "import os\nimport re\nimport time\nfrom dataclasses import dataclass, field\nimport numpy as np\nimport configparser\nimport a"
},
{
"path": "lightrag/kg/nano_vector_db_impl.py",
"chars": 16091,
"preview": "import asyncio\nimport base64\nimport os\nimport zlib\nfrom typing import Any, final\nfrom dataclasses import dataclass\nimpor"
},
{
"path": "lightrag/kg/neo4j_impl.py",
"chars": 82823,
"preview": "import os\nimport re\nfrom dataclasses import dataclass\nfrom typing import final\nimport configparser\n\n\nfrom tenacity impor"
},
{
"path": "lightrag/kg/networkx_impl.py",
"chars": 22552,
"preview": "import os\nfrom collections import deque\nfrom dataclasses import dataclass\nfrom typing import final\n\nfrom lightrag.types "
},
{
"path": "lightrag/kg/opensearch_impl.py",
"chars": 110053,
"preview": "\"\"\"\nOpenSearch Storage Implementation for LightRAG\n\nThis module provides OpenSearch-based storage backends for LightRAG,"
},
{
"path": "lightrag/kg/postgres_impl.py",
"chars": 248560,
"preview": "import asyncio\nimport hashlib\nimport json\nimport os\nimport re\nimport datetime\nfrom datetime import timezone\nfrom datacla"
},
{
"path": "lightrag/kg/qdrant_impl.py",
"chars": 41670,
"preview": "import asyncio\nimport configparser\nimport hashlib\nimport json\nimport os\nimport uuid\nfrom dataclasses import dataclass\nfr"
},
{
"path": "lightrag/kg/redis_impl.py",
"chars": 46410,
"preview": "import os\nimport logging\nfrom typing import Any, final, Union\nfrom dataclasses import dataclass\nimport pipmaster as pm\ni"
},
{
"path": "lightrag/kg/shared_storage.py",
"chars": 64402,
"preview": "import os\nimport sys\nimport asyncio\nimport multiprocessing as mp\nfrom multiprocessing.synchronize import Lock as Process"
},
{
"path": "lightrag/lightrag.py",
"chars": 181382,
"preview": "from __future__ import annotations\n\nimport traceback\nimport asyncio\nimport configparser\nimport inspect\nimport os\nimport "
},
{
"path": "lightrag/llm/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "lightrag/llm/anthropic.py",
"chars": 10280,
"preview": "from ..utils import verbose_debug, VERBOSE_DEBUG\nimport sys\nimport os\nimport logging\nimport numpy as np\nfrom typing impo"
},
{
"path": "lightrag/llm/azure_openai.py",
"chars": 630,
"preview": "\"\"\"\nAzure OpenAI compatibility layer.\n\nThis module provides backward compatibility by re-exporting Azure OpenAI function"
},
{
"path": "lightrag/llm/bedrock.py",
"chars": 17700,
"preview": "import copy\nimport os\nimport json\nimport logging\n\nimport pipmaster as pm # Pipmaster for dynamic library install\n\nif no"
},
{
"path": "lightrag/llm/binding_options.py",
"chars": 30751,
"preview": "\"\"\"\nModule that implements containers for specific LLM bindings.\n\nThis module provides container implementations for var"
},
{
"path": "lightrag/llm/deprecated/siliconcloud.py",
"chars": 1894,
"preview": "import sys\n\nif sys.version_info < (3, 9):\n pass\nelse:\n pass\nimport pipmaster as pm # Pipmaster for dynamic librar"
},
{
"path": "lightrag/llm/gemini.py",
"chars": 23406,
"preview": "\"\"\"\nGemini LLM binding for LightRAG.\n\nThis module provides asynchronous helpers that adapt Google's Gemini models\nto the"
},
{
"path": "lightrag/llm/hf.py",
"chars": 5438,
"preview": "import copy\nimport os\nfrom functools import lru_cache\n\nimport pipmaster as pm # Pipmaster for dynamic library install\n\n"
},
{
"path": "lightrag/llm/jina.py",
"chars": 5995,
"preview": "import os\nimport pipmaster as pm # Pipmaster for dynamic library install\n\n# install specific modules\nif not pm.is_insta"
},
{
"path": "lightrag/llm/llama_index_impl.py",
"chars": 5932,
"preview": "import pipmaster as pm\nfrom llama_index.core.llms import (\n ChatMessage,\n MessageRole,\n ChatResponse,\n)\nfrom ty"
},
{
"path": "lightrag/llm/lmdeploy.py",
"chars": 5058,
"preview": "import pipmaster as pm # Pipmaster for dynamic library install\n\n# install specific modules\nif not pm.is_installed(\"lmde"
},
{
"path": "lightrag/llm/lollms.py",
"chars": 5340,
"preview": "import sys\n\nif sys.version_info < (3, 9):\n from typing import AsyncIterator\nelse:\n from collections.abc import Asy"
},
{
"path": "lightrag/llm/nvidia_openai.py",
"chars": 1766,
"preview": "import sys\nimport os\n\nif sys.version_info < (3, 9):\n pass\nelse:\n pass\n\nimport pipmaster as pm # Pipmaster for dyn"
},
{
"path": "lightrag/llm/ollama.py",
"chars": 8184,
"preview": "from collections.abc import AsyncIterator\nimport os\nimport re\n\nimport pipmaster as pm\n\n# install specific modules\nif not"
},
{
"path": "lightrag/llm/openai.py",
"chars": 41112,
"preview": "from ..utils import verbose_debug, VERBOSE_DEBUG\nimport os\nimport logging\n\nfrom collections.abc import AsyncIterator\n\nim"
},
{
"path": "lightrag/llm/zhipu.py",
"chars": 8361,
"preview": "import sys\nimport re\nimport json\nfrom ..utils import verbose_debug\n\nif sys.version_info < (3, 9):\n pass\nelse:\n pas"
},
{
"path": "lightrag/namespace.py",
"chars": 892,
"preview": "from __future__ import annotations\n\nfrom typing import Iterable\n\n\n# All namespace should not be changed\nclass NameSpace:"
},
{
"path": "lightrag/operate.py",
"chars": 199736,
"preview": "from __future__ import annotations\nfrom functools import partial\nfrom pathlib import Path\n\nimport asyncio\nimport json\nim"
},
{
"path": "lightrag/prompt.py",
"chars": 29461,
"preview": "from __future__ import annotations\nfrom typing import Any\n\n\nPROMPTS: dict[str, Any] = {}\n\n# All delimiters must be forma"
},
{
"path": "lightrag/rerank.py",
"chars": 20298,
"preview": "from __future__ import annotations\n\nimport os\nimport aiohttp\nfrom typing import Any, List, Dict, Optional, Tuple\nfrom te"
},
{
"path": "lightrag/tools/README_CLEAN_LLM_QUERY_CACHE.md",
"chars": 18147,
"preview": "# LLM Query Cache Cleanup Tool - User Guide\n\n## Overview\n\nThis tool cleans up LightRAG's LLM query cache from KV storage"
},
{
"path": "lightrag/tools/README_MIGRATE_LLM_CACHE.md",
"chars": 14842,
"preview": "# LLM Cache Migration Tool - User Guide\n\n## Overview\n\nThis tool migrates LightRAG's LLM response cache between different"
},
{
"path": "lightrag/tools/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "lightrag/tools/check_initialization.py",
"chars": 5737,
"preview": "#!/usr/bin/env python3\n\"\"\"\nDiagnostic tool to check LightRAG initialization status.\n\nThis tool helps developers verify t"
},
{
"path": "lightrag/tools/clean_llm_query_cache.py",
"chars": 44964,
"preview": "#!/usr/bin/env python3\n\"\"\"\nLLM Query Cache Cleanup Tool for LightRAG\n\nThis tool cleans up LLM query cache (mix:*, hybrid"
},
{
"path": "lightrag/tools/download_cache.py",
"chars": 6820,
"preview": "\"\"\"\nDownload all necessary cache files for offline deployment.\n\nThis module provides a CLI command to download tiktoken "
},
{
"path": "lightrag/tools/lightrag_visualizer/README-zh.md",
"chars": 1526,
"preview": "# 3D GraphML Viewer\n\n一个基于 Dear ImGui 和 ModernGL 的交互式 3D 图可视化工具。\n\n## 功能特点\n\n- **3D 交互式可视化**: 使用 ModernGL 实现高性能的 3D 图形渲染\n- "
},
{
"path": "lightrag/tools/lightrag_visualizer/README.md",
"chars": 3716,
"preview": "# LightRAG 3D Graph Viewer\n\nAn interactive 3D graph visualization tool included in the LightRAG package for visualizing "
},
{
"path": "lightrag/tools/lightrag_visualizer/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "lightrag/tools/lightrag_visualizer/assets/LICENSE - Geist.txt",
"chars": 4368,
"preview": "Copyright (c) 2023 Vercel, in collaboration with basement.studio\n\nThis Font Software is licensed under the SIL Open Font"
},
{
"path": "lightrag/tools/lightrag_visualizer/assets/LICENSE - SmileySans.txt",
"chars": 4415,
"preview": "Copyright (c) 2022--2024, atelierAnchor <https://atelier-anchor.com>,\nwith Reserved Font Name <Smiley> and <得意黑>.\n\nThis "
},
{
"path": "lightrag/tools/lightrag_visualizer/assets/place_font_here",
"chars": 0,
"preview": ""
},
{
"path": "lightrag/tools/lightrag_visualizer/graph_visualizer.py",
"chars": 43192,
"preview": "from typing import Optional, Tuple, Dict, List\nimport numpy as np\nimport networkx as nx\nimport pipmaster as pm\n\n# Added "
},
{
"path": "lightrag/tools/lightrag_visualizer/requirements.txt",
"chars": 67,
"preview": "imgui_bundle\nmoderngl\nnetworkx\nnumpy\npyglm\npython-louvain\nscipy\ntk\n"
},
{
"path": "lightrag/tools/migrate_llm_cache.py",
"chars": 56473,
"preview": "#!/usr/bin/env python3\n\"\"\"\nLLM Cache Migration Tool for LightRAG\n\nThis tool migrates LLM response cache (default:extract"
},
{
"path": "lightrag/tools/prepare_qdrant_legacy_data.py",
"chars": 24102,
"preview": "#!/usr/bin/env python3\n\"\"\"\nQdrant Legacy Data Preparation Tool for LightRAG\n\nThis tool copies data from new collections "
},
{
"path": "lightrag/types.py",
"chars": 702,
"preview": "from __future__ import annotations\n\nfrom pydantic import BaseModel\nfrom typing import Any, Optional\n\n\nclass GPTKeywordEx"
},
{
"path": "lightrag/utils.py",
"chars": 122991,
"preview": "from __future__ import annotations\nimport weakref\n\nimport sys\n\nimport asyncio\nimport html\nimport csv\nimport inspect\nimpo"
},
{
"path": "lightrag/utils_graph.py",
"chars": 72882,
"preview": "from __future__ import annotations\n\nimport time\nimport asyncio\nfrom typing import Any, cast\n\nfrom .base import DeletionR"
},
{
"path": "lightrag.service.example",
"chars": 741,
"preview": "[Unit]\nDescription=LightRAG XYJ Service\nAfter=network.target\n\n[Service]\nType=simple\nUser=netman\n# Memory settings\nMemory"
},
{
"path": "lightrag_webui/.gitignore",
"chars": 253,
"preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndis"
},
{
"path": "lightrag_webui/.prettierrc.json",
"chars": 233,
"preview": "{\n \"$schema\": \"https://json.schemastore.org/prettierrc\",\n \"semi\": false,\n \"tabWidth\": 2,\n \"singleQuote\": true,\n \"pr"
},
{
"path": "lightrag_webui/README.md",
"chars": 2349,
"preview": "# LightRAG WebUI\n\nLightRAG WebUI is a React-based web interface for interacting with the LightRAG system. It provides a "
},
{
"path": "lightrag_webui/components.json",
"chars": 423,
"preview": "{\n \"$schema\": \"https://ui.shadcn.com/schema.json\",\n \"style\": \"new-york\",\n \"rsc\": false,\n \"tsx\": true,\n \"tailwind\": "
},
{
"path": "lightrag_webui/env.development.smaple",
"chars": 219,
"preview": "# Development environment configuration\nVITE_BACKEND_URL=http://localhost:9621\nVITE_API_PROXY=true\nVITE_API_ENDPOINTS=/a"
},
{
"path": "lightrag_webui/env.local.sample",
"chars": 171,
"preview": "VITE_BACKEND_URL=http://localhost:9621\nVITE_API_PROXY=true\nVITE_API_ENDPOINTS=/api,/documents,/graphs,/graph,/health,/qu"
},
{
"path": "lightrag_webui/eslint.config.js",
"chars": 1191,
"preview": "import js from '@eslint/js'\nimport globals from 'globals'\nimport reactHooks from 'eslint-plugin-react-hooks'\nimport reac"
},
{
"path": "lightrag_webui/index.html",
"chars": 539,
"preview": "<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta http-equiv=\"Cache-Control\" content=\"no-"
},
{
"path": "lightrag_webui/package.json",
"chars": 3693,
"preview": "{\n \"name\": \"lightrag-webui\",\n \"private\": true,\n \"version\": \"0.0.0\",\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vi"
}
]
// ... and 178 more files (download for full content)
About this extraction
This page contains the full source code of the HKUDS/LightRAG GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 378 files (6.2 MB), approximately 1.7M tokens, and a symbol index with 5562 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.