Skip to content

Commit

Permalink
feat: improve CLI parameter handling and cleanup unused code (langflo…
Browse files Browse the repository at this point in the history
…w-ai#4002)

* chore: remove envvar parameter from CLI option

* chore: add show_default=False flag to CLI option

* chore: update argument type to accept None

* feat: add missing Settings to CLI options

* feat: add default path value for components

* chore: rename CLI parameters to match Settings

* feat: update function to enforce parameter hierarchy

CLI > specific env_file > default env_file

* fix: adjust CLI parameter code to pass unit tests

* fix: mypy error arg-type

* fix: little ajustments
  • Loading branch information
italojohnny authored Oct 3, 2024
1 parent b8e7a77 commit ed7ec6a
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 59 deletions.
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -243,15 +243,15 @@ start:

ifeq ($(open_browser),false)
@make install_backend && uv run langflow run \
--path $(path) \
--frontend-path $(path) \
--log-level $(log_level) \
--host $(host) \
--port $(port) \
--env-file $(env) \
--no-open-browser
else
@make install_backend && uv run langflow run \
--path $(path) \
--frontend-path $(path) \
--log-level $(log_level) \
--host $(host) \
--port $(port) \
Expand All @@ -262,7 +262,7 @@ setup_devcontainer: ## set up the development container
make install_backend
make install_frontend
make build_frontend
uv run langflow --path src/frontend/build
uv run langflow --frontend-path src/frontend/build

setup_env: ## set up the environment
@sh ./scripts/setup/setup_env.sh
Expand Down
127 changes: 71 additions & 56 deletions src/backend/base/langflow/__main__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import inspect
import platform
import socket
import sys
Expand Down Expand Up @@ -28,7 +29,6 @@
from langflow.services.deps import get_db_service, get_settings_service, session_scope
from langflow.services.settings.constants import DEFAULT_SUPERUSER
from langflow.services.utils import initialize_services
from langflow.utils.util import update_settings
from langflow.utils.version import fetch_latest_version, get_version_info
from langflow.utils.version import is_pre_release as langflow_is_pre_release

Expand Down Expand Up @@ -79,69 +79,73 @@ def set_var_for_macos_issue():

@app.command()
def run(
host: str = typer.Option("127.0.0.1", help="Host to bind the server to.", envvar="LANGFLOW_HOST"),
workers: int = typer.Option(1, help="Number of worker processes.", envvar="LANGFLOW_WORKERS"),
timeout: int = typer.Option(300, help="Worker timeout in seconds.", envvar="LANGFLOW_WORKER_TIMEOUT"),
port: int = typer.Option(7860, help="Port to listen on.", envvar="LANGFLOW_PORT"),
host: str | None = typer.Option(None, help="Host to bind the server to.", show_default=False),
workers: int | None = typer.Option(None, help="Number of worker processes.", show_default=False),
worker_timeout: int | None = typer.Option(None, help="Worker timeout in seconds.", show_default=False),
port: int | None = typer.Option(None, help="Port to listen on.", show_default=False),
components_path: Path | None = typer.Option(
Path(__file__).parent / "components",
help="Path to the directory containing custom components.",
envvar="LANGFLOW_COMPONENTS_PATH",
show_default=False,
),
# .env file param
env_file: Path = typer.Option(None, help="Path to the .env file containing environment variables."),
log_level: str = typer.Option("critical", help="Logging level.", envvar="LANGFLOW_LOG_LEVEL"),
log_file: Path = typer.Option("logs/langflow.log", help="Path to the log file.", envvar="LANGFLOW_LOG_FILE"),
env_file: Path | None = typer.Option(
None,
help="Path to the .env file containing environment variables.",
show_default=False,
),
log_level: str | None = typer.Option(None, help="Logging level.", show_default=False),
log_file: Path | None = typer.Option(None, help="Path to the log file.", show_default=False),
cache: str | None = typer.Option(
envvar="LANGFLOW_LANGCHAIN_CACHE",
None,
help="Type of cache to use. (InMemoryCache, SQLiteCache)",
default=None,
show_default=False,
),
dev: bool = typer.Option(False, help="Run in development mode (may contain bugs)"),
path: str = typer.Option(
dev: bool | None = typer.Option(None, help="Run in development mode (may contain bugs)", show_default=False),
frontend_path: str | None = typer.Option(
None,
help="Path to the frontend directory containing build files. This is for development purposes only.",
envvar="LANGFLOW_FRONTEND_PATH",
show_default=False,
),
open_browser: bool = typer.Option(
True,
open_browser: bool | None = typer.Option(
None,
help="Open the browser after starting the server.",
envvar="LANGFLOW_OPEN_BROWSER",
show_default=False,
),
remove_api_keys: bool = typer.Option(
False,
remove_api_keys: bool | None = typer.Option(
None,
help="Remove API keys from the projects saved in the database.",
envvar="LANGFLOW_REMOVE_API_KEYS",
show_default=False,
),
backend_only: bool = typer.Option(
False,
backend_only: bool | None = typer.Option(
None,
help="Run only the backend server without the frontend.",
envvar="LANGFLOW_BACKEND_ONLY",
show_default=False,
),
store: bool = typer.Option(
True,
store: bool | None = typer.Option(
None,
help="Enables the store features.",
envvar="LANGFLOW_STORE",
show_default=False,
),
auto_saving: bool = typer.Option(
True,
auto_saving: bool | None = typer.Option(
None,
help="Defines if the auto save is enabled.",
envvar="LANGFLOW_AUTO_SAVING",
show_default=False,
),
auto_saving_interval: int = typer.Option(
1000,
auto_saving_interval: int | None = typer.Option(
None,
help="Defines the debounce time for the auto save.",
envvar="LANGFLOW_AUTO_SAVING_INTERVAL",
show_default=False,
),
health_check_max_retries: bool = typer.Option(
True,
health_check_max_retries: bool | None = typer.Option(
None,
help="Defines the number of retries for the health check.",
envvar="LANGFLOW_HEALTH_CHECK_MAX_RETRIES",
show_default=False,
),
max_file_size_upload: int = typer.Option(
100,
max_file_size_upload: int | None = typer.Option(
None,
help="Defines the maximum file size for the upload in MB.",
envvar="LANGFLOW_MAX_FILE_SIZE_UPLOAD",
show_default=False,
),
):
"""
Expand All @@ -153,33 +157,44 @@ def run(

if env_file:
load_dotenv(env_file, override=True)
logger.debug(f"Loading config from file: '{env_file}'")

update_settings(
dev=dev,
remove_api_keys=remove_api_keys,
cache=cache,
components_path=components_path,
store=store,
auto_saving=auto_saving,
auto_saving_interval=auto_saving_interval,
health_check_max_retries=health_check_max_retries,
max_file_size_upload=max_file_size_upload,
)
# create path object if path is provided
static_files_dir: Path | None = Path(path) if path else None
settings_service = get_settings_service()
settings_service.set("backend_only", backend_only)

frame = inspect.currentframe()
valid_args: list = []
values: dict = {}
if frame is not None:
arguments, _, _, values = inspect.getargvalues(frame)
valid_args = [arg for arg in arguments if values[arg] is not None]

for arg in valid_args:
if arg == "components_path":
settings_service.settings.update_settings(components_path=components_path)
elif hasattr(settings_service.settings, arg):
settings_service.set(arg, values[arg])
logger.debug(f"Loading config from cli parameter '{arg}': '{values[arg]}'")

host = settings_service.settings.host
port = settings_service.settings.port
workers = settings_service.settings.workers
worker_timeout = settings_service.settings.worker_timeout
log_level = settings_service.settings.log_level
frontend_path = settings_service.settings.frontend_path
backend_only = settings_service.settings.backend_only

# create path object if frontend_path is provided
static_files_dir: Path | None = Path(frontend_path) if frontend_path else None

app = setup_app(static_files_dir=static_files_dir, backend_only=backend_only)
# check if port is being used
if is_port_in_use(port, host):
port = get_free_port(port)

settings_service.set("worker_timeout", timeout)

options = {
"bind": f"{host}:{port}",
"workers": get_number_of_workers(workers),
"timeout": timeout,
"timeout": worker_timeout,
}

# Define an env variable to know if we are just testing the server
Expand Down Expand Up @@ -472,7 +487,7 @@ def migration(

@app.command()
def api_key(
log_level: str = typer.Option("error", help="Logging level.", envvar="LANGFLOW_LOG_LEVEL"),
log_level: str = typer.Option("error", help="Logging level."),
):
"""
Creates an API key for the default superuser if AUTO_LOGIN is enabled.
Expand Down
14 changes: 14 additions & 0 deletions src/backend/base/langflow/services/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,20 @@ class Settings(BaseSettings):
"""If set to True, Langflow will keep track of each vertex builds (outputs) in the UI for any flow."""

# Config
host: str = "127.0.0.1"
"""The host on which Langflow will run."""
port: int = 7860
"""The port on which Langflow will run."""
workers: int = 1
"""The number of workers to run."""
log_level: str = "critical"
"""The log level for Langflow."""
log_file: str | None = "logs/langflow.log"
"""The path to log file for Langflow."""
frontend_path: str | None = None
"""The path to the frontend directory containing build files. This is for development purposes only.."""
open_browser: bool = False
"""If set to True, Langflow will open the browser on startup."""
auto_saving: bool = True
"""If set to True, Langflow will auto save flows."""
auto_saving_interval: int = 1000
Expand Down

0 comments on commit ed7ec6a

Please sign in to comment.