From 3a4b81ba46c2d0d693594de32a15d04191924337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20MANSUY?= Date: Thu, 4 Dec 2025 19:19:03 +0800 Subject: [PATCH] cherry-pick 746c069a --- lightrag/api/config.py | 81 ++++++++++++++++++++++++++++++- lightrag/api/lightrag_server.py | 6 +++ lightrag/api/run_with_gunicorn.py | 5 ++ pyproject.toml | 1 + 4 files changed, 92 insertions(+), 1 deletion(-) diff --git a/lightrag/api/config.py b/lightrag/api/config.py index 92e81253..a02a1cae 100644 --- a/lightrag/api/config.py +++ b/lightrag/api/config.py @@ -432,4 +432,83 @@ def update_uvicorn_mode_config(): ) -global_args = parse_args() +# Global configuration with lazy initialization +_global_args = None +_initialized = False + + +def initialize_config(args=None, force=False): + """Initialize global configuration + + This function allows explicit initialization of the configuration, + which is useful for programmatic usage, testing, or embedding LightRAG + in other applications. + + Args: + args: Pre-parsed argparse.Namespace or None to parse from sys.argv + force: Force re-initialization even if already initialized + + Returns: + argparse.Namespace: The configured arguments + + Example: + # Use parsed command line arguments (default) + initialize_config() + + # Use custom configuration programmatically + custom_args = argparse.Namespace( + host='localhost', + port=8080, + working_dir='./custom_rag', + # ... other config + ) + initialize_config(custom_args) + """ + global _global_args, _initialized + + if _initialized and not force: + return _global_args + + _global_args = args if args is not None else parse_args() + _initialized = True + return _global_args + + +def get_config(): + """Get global configuration, auto-initializing if needed + + Returns: + argparse.Namespace: The configured arguments + """ + if not _initialized: + initialize_config() + return _global_args + + +class _GlobalArgsProxy: + """Proxy object that auto-initializes configuration on first access + + This maintains backward compatibility with existing code while + allowing programmatic control over initialization timing. + """ + + def __getattr__(self, name): + if not _initialized: + initialize_config() + return getattr(_global_args, name) + + def __setattr__(self, name, value): + if not _initialized: + initialize_config() + setattr(_global_args, name, value) + + def __repr__(self): + if not _initialized: + return "" + return repr(_global_args) + + +# Create proxy instance for backward compatibility +# Existing code like `from config import global_args` continues to work +# The proxy will auto-initialize on first attribute access +global_args = _GlobalArgsProxy() diff --git a/lightrag/api/lightrag_server.py b/lightrag/api/lightrag_server.py index 0ed20a28..6593f50c 100644 --- a/lightrag/api/lightrag_server.py +++ b/lightrag/api/lightrag_server.py @@ -1172,6 +1172,12 @@ def check_and_install_dependencies(): def main(): + # Explicitly initialize configuration for clarity + # (The proxy will auto-initialize anyway, but this makes intent clear) + from .config import initialize_config + + initialize_config() + # Check if running under Gunicorn if "GUNICORN_CMD_ARGS" in os.environ: # If started with Gunicorn, return directly as Gunicorn will call get_application diff --git a/lightrag/api/run_with_gunicorn.py b/lightrag/api/run_with_gunicorn.py index 1ce5418d..0de2ac36 100644 --- a/lightrag/api/run_with_gunicorn.py +++ b/lightrag/api/run_with_gunicorn.py @@ -35,6 +35,11 @@ def check_and_install_dependencies(): def main(): + # Explicitly initialize configuration for Gunicorn mode + from lightrag.api.config import initialize_config + + initialize_config() + # Set Gunicorn mode flag for lifespan cleanup detection os.environ["LIGHTRAG_GUNICORN_MODE"] = "1" diff --git a/pyproject.toml b/pyproject.toml index 38632833..38b51ca1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,6 +77,7 @@ api = [ "python-multipart", "pytz", "uvicorn", + "gunicorn", # Document processing dependencies (required for API document upload functionality) "openpyxl>=3.0.0,<4.0.0", # XLSX processing "pycryptodome>=3.0.0,<4.0.0", # PDF encryption support