From 626b42bc409378ecb8a9983171cede3f7d04f579 Mon Sep 17 00:00:00 2001 From: anouarbm Date: Sat, 1 Nov 2025 21:40:22 +0100 Subject: [PATCH 1/4] feat: add optional Langfuse observability integration This contribution adds optional Langfuse support for LLM observability and tracing. Langfuse provides a drop-in replacement for the OpenAI client that automatically tracks all LLM interactions without requiring code changes. Features: - Optional Langfuse integration with graceful fallback - Automatic LLM request/response tracing - Token usage tracking - Latency metrics - Error tracking - Zero code changes required for existing functionality Implementation: - Modified lightrag/llm/openai.py to conditionally use Langfuse's AsyncOpenAI - Falls back to standard OpenAI client if Langfuse is not installed - Logs observability status on import Configuration: To enable Langfuse tracing, install the observability extras and set environment variables: ```bash pip install lightrag-hku[observability] export LANGFUSE_PUBLIC_KEY="your_public_key" export LANGFUSE_SECRET_KEY="your_secret_key" export LANGFUSE_HOST="https://cloud.langfuse.com" # or your self-hosted instance ``` If Langfuse is not installed or environment variables are not set, LightRAG will use the standard OpenAI client without any functionality changes. Changes: - Modified lightrag/llm/openai.py (added optional Langfuse import) - Updated pyproject.toml with optional 'observability' dependencies Dependencies (optional): - langfuse>=3.8.1 --- lightrag/llm/openai.py | 12 +++++++++++- pyproject.toml | 5 +++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lightrag/llm/openai.py b/lightrag/llm/openai.py index d367abc7..07942101 100644 --- a/lightrag/llm/openai.py +++ b/lightrag/llm/openai.py @@ -10,8 +10,18 @@ import pipmaster as pm if not pm.is_installed("openai"): pm.install("openai") +# Try to import Langfuse for LLM observability (optional) +# Falls back to standard OpenAI client if not available +try: + from langfuse.openai import AsyncOpenAI + LANGFUSE_ENABLED = True + logger.info("Langfuse observability enabled for OpenAI client") +except ImportError: + from openai import AsyncOpenAI + LANGFUSE_ENABLED = False + logger.debug("Langfuse not available, using standard OpenAI client") + from openai import ( - AsyncOpenAI, APIConnectionError, RateLimitError, APITimeoutError, diff --git a/pyproject.toml b/pyproject.toml index 57e1b765..8eabb37c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -113,6 +113,11 @@ offline = [ "lightrag-hku[offline-docs,offline-storage,offline-llm]", ] +observability = [ + # LLM observability and tracing dependencies + "langfuse>=3.8.1", +] + [project.scripts] lightrag-server = "lightrag.api.lightrag_server:main" lightrag-gunicorn = "lightrag.api.run_with_gunicorn:main" From 7b8223daaddfec31a1847a133315d5fde13b63fb Mon Sep 17 00:00:00 2001 From: yangdx Date: Mon, 3 Nov 2025 04:02:40 +0800 Subject: [PATCH 2/4] Update env.example with host/endpoint clarifications for LLM/embedding --- env.example | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/env.example b/env.example index 90977e6e..f60ba29d 100644 --- a/env.example +++ b/env.example @@ -166,10 +166,11 @@ MAX_PARALLEL_INSERT=2 ### Num of chunks send to Embedding in single request # EMBEDDING_BATCH_NUM=10 -########################################################### +########################################################################### ### LLM Configuration ### LLM_BINDING type: openai, ollama, lollms, azure_openai, aws_bedrock -########################################################### +### LLM_BINDING_HOST: host only for Ollama, endpoint for other LLM service +########################################################################### ### LLM request timeout setting for all llm (0 means no timeout for Ollma) # LLM_TIMEOUT=180 @@ -224,10 +225,11 @@ OLLAMA_LLM_NUM_CTX=32768 ### Bedrock Specific Parameters # BEDROCK_LLM_TEMPERATURE=1.0 -#################################################################################### +####################################################################################### ### Embedding Configuration (Should not be changed after the first file processed) ### EMBEDDING_BINDING: ollama, openai, azure_openai, jina, lollms, aws_bedrock -#################################################################################### +### EMBEDDING_BINDING_HOST: host only for Ollama, endpoint for other Embedding service +####################################################################################### # EMBEDDING_TIMEOUT=30 EMBEDDING_BINDING=ollama EMBEDDING_MODEL=bge-m3:latest From 9495778c2d396113339fd0e4681d70ec22350545 Mon Sep 17 00:00:00 2001 From: anouarbm Date: Mon, 3 Nov 2025 05:27:41 +0100 Subject: [PATCH 3/4] refactor: reorder Langfuse import logic for improved clarity Moved logger import before Langfuse block to fix NameError. --- lightrag/llm/openai.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lightrag/llm/openai.py b/lightrag/llm/openai.py index 07942101..1eaf3bd5 100644 --- a/lightrag/llm/openai.py +++ b/lightrag/llm/openai.py @@ -10,17 +10,6 @@ import pipmaster as pm if not pm.is_installed("openai"): pm.install("openai") -# Try to import Langfuse for LLM observability (optional) -# Falls back to standard OpenAI client if not available -try: - from langfuse.openai import AsyncOpenAI - LANGFUSE_ENABLED = True - logger.info("Langfuse observability enabled for OpenAI client") -except ImportError: - from openai import AsyncOpenAI - LANGFUSE_ENABLED = False - logger.debug("Langfuse not available, using standard OpenAI client") - from openai import ( APIConnectionError, RateLimitError, @@ -37,6 +26,19 @@ from lightrag.utils import ( safe_unicode_decode, logger, ) + +# Try to import Langfuse for LLM observability (optional) +# Falls back to standard OpenAI client if not available +try: + from langfuse.openai import AsyncOpenAI + + LANGFUSE_ENABLED = True + logger.info("Langfuse observability enabled for OpenAI client") +except ImportError: + from openai import AsyncOpenAI + + LANGFUSE_ENABLED = False + logger.debug("Langfuse not available, using standard OpenAI client") from lightrag.types import GPTKeywordExtractionFormat from lightrag.api import __api_version__ From e0966b6511ab498bda9ad76be40616e1181602b0 Mon Sep 17 00:00:00 2001 From: yangdx Date: Mon, 3 Nov 2025 12:40:30 +0800 Subject: [PATCH 4/4] Add BuildKit cache mounts to optimize Docker build performance - Enable BuildKit syntax directive - Cache UV and Bun package downloads - Update docs for cache optimization - Improve rebuild efficiency --- Dockerfile | 14 ++++++++++---- Dockerfile.lite | 14 ++++++++++---- docs/DockerDeployment.md | 24 +++++++++++++++++++----- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index 67aa92b6..aaa3c84b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1 + # Frontend build stage FROM oven/bun:1 AS frontend-builder @@ -7,7 +9,8 @@ WORKDIR /app COPY lightrag_webui/ ./lightrag_webui/ # Build frontend assets for inclusion in the API package -RUN cd lightrag_webui \ +RUN --mount=type=cache,target=/root/.bun/install/cache \ + cd lightrag_webui \ && bun install --frozen-lockfile \ && bun run build @@ -40,7 +43,8 @@ COPY setup.py . COPY uv.lock . # Install base, API, and offline extras without the project to improve caching -RUN uv sync --frozen --no-dev --extra api --extra offline --no-install-project --no-editable +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/ @@ -49,7 +53,8 @@ COPY lightrag/ ./lightrag/ 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 uv sync --frozen --no-dev --extra api --extra offline --no-editable \ +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 @@ -81,7 +86,8 @@ 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 uv sync --frozen --no-dev --extra api --extra offline --no-editable \ +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 diff --git a/Dockerfile.lite b/Dockerfile.lite index 25ec8fe5..3f488886 100644 --- a/Dockerfile.lite +++ b/Dockerfile.lite @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1 + # Frontend build stage FROM oven/bun:1 AS frontend-builder @@ -7,7 +9,8 @@ WORKDIR /app COPY lightrag_webui/ ./lightrag_webui/ # Build frontend assets for inclusion in the API package -RUN cd lightrag_webui \ +RUN --mount=type=cache,target=/root/.bun/install/cache \ + cd lightrag_webui \ && bun install --frozen-lockfile \ && bun run build @@ -40,7 +43,8 @@ COPY setup.py . COPY uv.lock . # Install project dependencies (base + API extras) without the project to improve caching -RUN uv sync --frozen --no-dev --extra api --no-install-project --no-editable +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/ @@ -49,7 +53,8 @@ COPY lightrag/ ./lightrag/ 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 uv sync --frozen --no-dev --extra api --no-editable \ +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 @@ -81,7 +86,8 @@ 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 uv sync --frozen --no-dev --extra api --no-editable \ +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 diff --git a/docs/DockerDeployment.md b/docs/DockerDeployment.md index 968a8ec7..575359b4 100644 --- a/docs/DockerDeployment.md +++ b/docs/DockerDeployment.md @@ -59,10 +59,19 @@ LightRAG can be configured using environment variables in the `.env` file: Docker instructions work the same on all platforms with Docker Desktop installed. +### Build Optimization + +The Dockerfile uses BuildKit cache mounts to significantly improve build performance: + +- **Automatic cache management**: BuildKit is automatically enabled via `# syntax=docker/dockerfile:1` directive +- **Faster rebuilds**: Only downloads changed dependencies when `uv.lock` or `bun.lock` files are modified +- **Efficient package caching**: UV and Bun package downloads are cached across builds +- **No manual configuration needed**: Works out of the box in Docker Compose and GitHub Actions + ### Start LightRAG server: ```bash -docker-compose up -d +docker compose up -d ``` LightRAG Server uses the following paths for data storage: @@ -77,9 +86,9 @@ data/ To update the Docker container: ```bash -docker-compose pull -docker-compose down -docker-compose up +docker compose pull +docker compose down +docker compose up ``` ### Offline deployment @@ -91,10 +100,15 @@ Software packages requiring `transformers`, `torch`, or `cuda` will is not prein ### For local development and testing ```bash -# Build and run with docker-compose +# Build and run with Docker Compose (BuildKit automatically enabled) docker compose up --build + +# Or explicitly enable BuildKit if needed +DOCKER_BUILDKIT=1 docker compose up --build ``` +**Note**: BuildKit is automatically enabled by the `# syntax=docker/dockerfile:1` directive in the Dockerfile, ensuring optimal caching performance. + ### For production release **multi-architecture build and push**: