From 0b696d9629070f73f6554bd01d85e04dcdbdf3c7 Mon Sep 17 00:00:00 2001 From: Yiorgis Gozadinos Date: Fri, 7 Nov 2025 10:54:32 +0200 Subject: [PATCH] Remove deprecated use of env variables for configuration --- CHANGELOG.md | 4 ++ docs/configuration.md | 29 ++++----- haiku_rag_slim/haiku/rag/cli.py | 34 +++-------- haiku_rag_slim/haiku/rag/config/__init__.py | 2 - haiku_rag_slim/haiku/rag/config/loader.py | 56 ----------------- tests/test_config_loader.py | 66 ++++----------------- 6 files changed, 34 insertions(+), 157 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 295ef9ca..2df0a506 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ - Updated CLI documentation to clarify global vs per-command options - **BREAKING**: Standardized configuration filename to `haiku.rag.yaml` in user directories (was incorrectly using `config.yaml`). Users with existing `config.yaml` in their user directory will need to rename it to `haiku.rag.yaml` +### Removed + +- **BREAKING**: Removed deprecated `.env`-based configuration system. The `haiku-rag init-config --from-env` command and `load_config_from_env()` function have been removed. All configuration must now be done via YAML files. Environment variables for API keys (e.g., `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`) and service URLs (e.g., `OLLAMA_BASE_URL`) are still supported and can be set via `.env` files. + ## [0.14.1] - 2025-11-06 ### Added diff --git a/docs/configuration.md b/docs/configuration.md index 224f9e02..41f85975 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -15,15 +15,6 @@ haiku-rag init-config This creates a `haiku.rag.yaml` file in your current directory with all available settings. -!!! warning "Deprecation Notice" - Environment variable configuration via `.env` files is deprecated and will be removed in future versions. Please migrate to YAML configuration. - - To migrate from environment variables (`.env` file): - - ```bash - haiku-rag init-config --from-env - ``` - ## Configuration File Locations `haiku.rag` searches for configuration files in this order: @@ -219,14 +210,7 @@ embeddings: vector_dim: 1024 ``` -The Ollama base URL can be configured via environment variable or config file: - -```bash -# Via environment variable (recommended) -export OLLAMA_BASE_URL=http://localhost:11434 -``` - -Or in your config file: +The Ollama base URL can be configured in your config file or via environment variable: ```yaml providers: @@ -234,7 +218,16 @@ providers: base_url: http://localhost:11434 ``` -If neither is set, it defaults to `http://localhost:11434`. +Or via environment variable: + +```bash +export OLLAMA_BASE_URL=http://localhost:11434 +``` + +If not configured, it defaults to `http://localhost:11434`. + +!!! note + You can use a `.env` file in your project directory to set environment variables like `OLLAMA_BASE_URL` and API keys (e.g., `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`). These will be automatically loaded when running `haiku-rag` commands. ### VoyageAI diff --git a/haiku_rag_slim/haiku/rag/cli.py b/haiku_rag_slim/haiku/rag/cli.py index 86802004..6274cb00 100644 --- a/haiku_rag_slim/haiku/rag/cli.py +++ b/haiku_rag_slim/haiku/rag/cli.py @@ -6,14 +6,7 @@ from pathlib import Path from typing import Any import typer - -# Load environment variables from .env file before importing Config -try: - from dotenv import load_dotenv - - load_dotenv() -except ImportError: - pass +from dotenv import load_dotenv from haiku.rag.app import HaikuRAGApp from haiku.rag.config import ( @@ -26,6 +19,9 @@ from haiku.rag.config import ( from haiku.rag.logging import configure_cli_logging from haiku.rag.utils import is_up_to_date +# Load environment variables from .env file for API keys and service URLs +load_dotenv() + cli = typer.Typer( context_settings={"help_option_names": ["-h", "--help"]}, no_args_is_help=True ) @@ -326,16 +322,11 @@ def init_config( Path("haiku.rag.yaml"), help="Output path for the config file", ), - from_env: bool = typer.Option( - False, - "--from-env", - help="Migrate settings from .env file", - ), ): - """Generate a YAML configuration file with defaults or from .env.""" + """Generate a YAML configuration file with defaults.""" import yaml - from haiku.rag.config.loader import generate_default_config, load_config_from_env + from haiku.rag.config.loader import generate_default_config if output.exists(): typer.echo( @@ -343,18 +334,7 @@ def init_config( ) raise typer.Exit(1) - if from_env: - # Load from environment variables (including .env if present) - from dotenv import load_dotenv - - load_dotenv() - config_data = load_config_from_env() - if not config_data: - typer.echo("Warning: No environment variables found to migrate.") - typer.echo("Generating default configuration instead.") - config_data = generate_default_config() - else: - config_data = generate_default_config() + config_data = generate_default_config() # Write YAML with comments with open(output, "w") as f: diff --git a/haiku_rag_slim/haiku/rag/config/__init__.py b/haiku_rag_slim/haiku/rag/config/__init__.py index 779510e8..6e9d9aed 100644 --- a/haiku_rag_slim/haiku/rag/config/__init__.py +++ b/haiku_rag_slim/haiku/rag/config/__init__.py @@ -3,7 +3,6 @@ import os from haiku.rag.config.loader import ( find_config_file, generate_default_config, - load_config_from_env, load_yaml_config, ) from haiku.rag.config.models import ( @@ -40,7 +39,6 @@ __all__ = [ "find_config_file", "load_yaml_config", "generate_default_config", - "load_config_from_env", "get_config", "set_config", ] diff --git a/haiku_rag_slim/haiku/rag/config/loader.py b/haiku_rag_slim/haiku/rag/config/loader.py index 1317d41f..4b6f9500 100644 --- a/haiku_rag_slim/haiku/rag/config/loader.py +++ b/haiku_rag_slim/haiku/rag/config/loader.py @@ -86,59 +86,3 @@ def generate_default_config() -> dict: }, "a2a": {"max_contexts": 1000}, } - - -def load_config_from_env() -> dict: - """Load current config from environment variables (for migration).""" - result = {} - - env_mappings = { - "ENV": "environment", - "DEFAULT_DATA_DIR": ("storage", "data_dir"), - "MONITOR_DIRECTORIES": ("monitor", "directories"), - "DISABLE_DB_AUTOCREATE": ("storage", "disable_autocreate"), - "VACUUM_RETENTION_SECONDS": ("storage", "vacuum_retention_seconds"), - "LANCEDB_URI": ("lancedb", "uri"), - "LANCEDB_API_KEY": ("lancedb", "api_key"), - "LANCEDB_REGION": ("lancedb", "region"), - "EMBEDDINGS_PROVIDER": ("embeddings", "provider"), - "EMBEDDINGS_MODEL": ("embeddings", "model"), - "EMBEDDINGS_VECTOR_DIM": ("embeddings", "vector_dim"), - "RERANK_PROVIDER": ("reranking", "provider"), - "RERANK_MODEL": ("reranking", "model"), - "QA_PROVIDER": ("qa", "provider"), - "QA_MODEL": ("qa", "model"), - "RESEARCH_PROVIDER": ("research", "provider"), - "RESEARCH_MODEL": ("research", "model"), - "CHUNK_SIZE": ("processing", "chunk_size"), - "CONTEXT_CHUNK_RADIUS": ("processing", "context_chunk_radius"), - "MARKDOWN_PREPROCESSOR": ("processing", "markdown_preprocessor"), - "OLLAMA_BASE_URL": ("providers", "ollama", "base_url"), - "VLLM_EMBEDDINGS_BASE_URL": ("providers", "vllm", "embeddings_base_url"), - "VLLM_RERANK_BASE_URL": ("providers", "vllm", "rerank_base_url"), - "VLLM_QA_BASE_URL": ("providers", "vllm", "qa_base_url"), - "VLLM_RESEARCH_BASE_URL": ("providers", "vllm", "research_base_url"), - "A2A_MAX_CONTEXTS": ("a2a", "max_contexts"), - } - - for env_var, path in env_mappings.items(): - value = os.getenv(env_var) - if value is not None: - # Special handling for MONITOR_DIRECTORIES - parse comma-separated list - if env_var == "MONITOR_DIRECTORIES": - if value.strip(): - value = [p.strip() for p in value.split(",") if p.strip()] - else: - value = [] - - if isinstance(path, tuple): - current = result - for key in path[:-1]: - if key not in current: - current[key] = {} - current = current[key] - current[path[-1]] = value - else: - result[path] = value - - return result diff --git a/tests/test_config_loader.py b/tests/test_config_loader.py index 1063dab8..62611f5f 100644 --- a/tests/test_config_loader.py +++ b/tests/test_config_loader.py @@ -1,11 +1,8 @@ -import os - import pytest from haiku.rag.config.loader import ( find_config_file, generate_default_config, - load_config_from_env, load_yaml_config, ) @@ -50,7 +47,7 @@ def test_find_config_file_user_config(tmp_path, monkeypatch): "haiku.rag.utils.get_default_data_dir", mock_get_default_data_dir ) - config_file = tmp_path / "config.yaml" + config_file = tmp_path / "haiku.rag.yaml" config_file.write_text("environment: production") found = find_config_file() @@ -114,68 +111,29 @@ def test_generate_default_config(): assert config["embeddings"]["vector_dim"] == 4096 -def test_load_config_from_env(monkeypatch): - """Test loading config from environment variables.""" - monkeypatch.setenv("ENV", "development") - monkeypatch.setenv("EMBEDDINGS_PROVIDER", "openai") - monkeypatch.setenv("EMBEDDINGS_MODEL", "text-embedding-3-small") - monkeypatch.setenv("EMBEDDINGS_VECTOR_DIM", "1536") - monkeypatch.setenv("QA_PROVIDER", "anthropic") - monkeypatch.setenv("QA_MODEL", "claude-3-haiku") - - config = load_config_from_env() - - assert config["environment"] == "development" - assert config["embeddings"]["provider"] == "openai" - assert config["embeddings"]["model"] == "text-embedding-3-small" - assert config["embeddings"]["vector_dim"] == "1536" - assert config["qa"]["provider"] == "anthropic" - assert config["qa"]["model"] == "claude-3-haiku" - - -def test_load_config_from_env_empty(): - """Test loading from env when no relevant vars set.""" - # Clear any env vars that might be set - env_vars = [ - "ENV", - "EMBEDDINGS_PROVIDER", - "QA_PROVIDER", - "OPENAI_API_KEY", - ] - original_values = {} - for var in env_vars: - original_values[var] = os.environ.get(var) - if var in os.environ: - del os.environ[var] - - try: - config = load_config_from_env() - # Should return empty or minimal dict - assert isinstance(config, dict) - finally: - # Restore original values - for var, value in original_values.items(): - if value is not None: - os.environ[var] = value - - def test_config_precedence_cwd_over_user(tmp_path, monkeypatch): """Test that cwd config takes precedence over user config.""" - monkeypatch.chdir(tmp_path) + # Create separate directories for cwd and user config + cwd_dir = tmp_path / "cwd" + cwd_dir.mkdir() + user_dir = tmp_path / "user" + user_dir.mkdir() - # Mock get_default_data_dir to return tmp_path + monkeypatch.chdir(cwd_dir) + + # Mock get_default_data_dir to return user_dir def mock_get_default_data_dir(): - return tmp_path + return user_dir monkeypatch.setattr( "haiku.rag.utils.get_default_data_dir", mock_get_default_data_dir ) # Create both configs - cwd_config = tmp_path / "haiku.rag.yaml" + cwd_config = cwd_dir / "haiku.rag.yaml" cwd_config.write_text("environment: from-cwd") - user_config = tmp_path / "config.yaml" + user_config = user_dir / "haiku.rag.yaml" user_config.write_text("environment: from-user") found = find_config_file()