-
Notifications
You must be signed in to change notification settings - Fork 0
fix: auto-detect OpenAI embedding provider when API key available (#72) #583
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -17,7 +17,7 @@ | |||||
|
|
||||||
| from __future__ import annotations | ||||||
|
|
||||||
| from pydantic import Field | ||||||
| from pydantic import Field, model_validator | ||||||
| from pydantic_settings import BaseSettings, SettingsConfigDict | ||||||
|
|
||||||
|
|
||||||
|
|
@@ -229,6 +229,24 @@ class CoreSettings(BaseSettings): | |||||
| # These are checked via os.environ in health.py | ||||||
|
|
||||||
| # ========================================================================== | ||||||
| # VALIDATORS | ||||||
| # ========================================================================== | ||||||
|
|
||||||
| @model_validator(mode="after") | ||||||
| def _auto_select_embedding_provider(self) -> CoreSettings: | ||||||
| """Auto-select openai embedding provider when API key is available.""" | ||||||
| # Only auto-select if no explicit provider was set (still default "local") | ||||||
| # and an OpenAI API key is available | ||||||
| if self.embedding_provider == "local" and self.openai_api_key: | ||||||
| import os | ||||||
|
|
||||||
| # Check if VALENCE_EMBEDDING_PROVIDER was explicitly set | ||||||
| if not os.environ.get("VALENCE_EMBEDDING_PROVIDER"): | ||||||
| self.embedding_provider = "openai" | ||||||
| return self | ||||||
|
|
||||||
| # ========================================================================== | ||||||
|
||||||
| # ========================================================================== | |
| # ========================================================================== |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -383,3 +383,39 @@ def test_int_coercion_seed_port(self, monkeypatch, clean_env): | |||||||||||||||||||||
| settings = CoreSettings() | ||||||||||||||||||||||
| assert settings.seed_port == 9000 | ||||||||||||||||||||||
| assert isinstance(settings.seed_port, int) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # ============================================================================ | ||||||||||||||||||||||
| # Embedding Provider Auto-Detection (#72) | ||||||||||||||||||||||
| # ============================================================================ | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| class TestEmbeddingProviderAutoDetect: | ||||||||||||||||||||||
| """Test auto-detection of embedding provider based on available API keys.""" | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def test_autoselects_openai_when_key_available(self, monkeypatch, clean_env): | ||||||||||||||||||||||
| """When OPENAI_API_KEY is set and VALENCE_EMBEDDING_PROVIDER is NOT set, | ||||||||||||||||||||||
| provider should auto-select to 'openai'.""" | ||||||||||||||||||||||
| monkeypatch.setenv("OPENAI_API_KEY", "sk-test-autodetect-key") | ||||||||||||||||||||||
| monkeypatch.delenv("VALENCE_EMBEDDING_PROVIDER", raising=False) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| settings = CoreSettings() | ||||||||||||||||||||||
| assert settings.embedding_provider == "openai" | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def test_explicit_local_override_respected(self, monkeypatch, clean_env): | ||||||||||||||||||||||
| """When VALENCE_EMBEDDING_PROVIDER is explicitly set to 'local', | ||||||||||||||||||||||
| it should stay 'local' even if OPENAI_API_KEY is set (user override).""" | ||||||||||||||||||||||
| monkeypatch.setenv("OPENAI_API_KEY", "sk-test-explicit-local") | ||||||||||||||||||||||
| monkeypatch.setenv("VALENCE_EMBEDDING_PROVIDER", "local") | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| settings = CoreSettings() | ||||||||||||||||||||||
| assert settings.embedding_provider == "local" | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
||||||||||||||||||||||
| def test_kwarg_local_override_respected(self, monkeypatch, clean_env): | |
| """When embedding_provider='local' is passed via kwargs, it should stay | |
| 'local' even if OPENAI_API_KEY is set (direct Python override).""" | |
| monkeypatch.setenv("OPENAI_API_KEY", "sk-test-kwarg-local") | |
| monkeypatch.delenv("VALENCE_EMBEDDING_PROVIDER", raising=False) | |
| settings = CoreSettings(embedding_provider="local") | |
| assert settings.embedding_provider == "local" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The explicit-configuration check relies on
os.environ.get("VALENCE_EMBEDDING_PROVIDER"), butBaseSettingsvalues can come from non-os.environsources (e.g., passingembedding_provider="local"toCoreSettings(...), or values loaded from an env_file in non-test runs). In those cases this validator can incorrectly override an explicitlocalsetting toopenai. Prefer detecting whether the field was provided via settings inputs (e.g., usingself.model_fields_setto see ifembedding_providerwas set) rather than inspectingos.environdirectly.