Skip to content

Commit 89c0528

Browse files
committed
fix: resolve merge conflict, bump to 2.19.2
2 parents 52ef529 + 642f6be commit 89c0528

File tree

9 files changed

+66
-15
lines changed

9 files changed

+66
-15
lines changed

CHANGELOG.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10-
## [2.19.1] - 2026-02-14
10+
## [2.19.2] - 2026-02-14
1111

1212
### Fixed
1313

@@ -18,6 +18,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818
- Direct `api_key` and `base_url` parameters on `create_text_to_speech()` — use `config={"api_key": "...", "base_url": "..."}` instead.
1919
- Removed `api_key` parameter from `create_tts()` deprecated alias.
2020

21+
## [2.19.1] - 2026-02-12
22+
23+
### Fixed
24+
25+
- **Config Dict API Key Resolution in Embedding Providers** - Fixed embedding providers ignoring `api_key` passed via config dict
26+
- Affected providers: OpenAI, Google, Jina, Voyage (embedding)
27+
- Providers now correctly honor API keys resolved from config before env fallback
28+
- Added regression tests to ensure `config={"api_key": "..."}` works consistently
29+
2130
## [2.19.0] - 2026-02-07
2231

2332
### Added

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "esperanto"
3-
version = "2.19.1"
3+
version = "2.19.2"
44
description = "A light-weight, production-ready, unified interface for various AI model providers"
55
authors = [
66
{ name = "LUIS NOVO", email = "lfnovo@gmail.com" }

src/esperanto/providers/embedding/google.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ def __init__(self, **kwargs):
3333

3434
# Get API key
3535
self.api_key = (
36-
kwargs.get("api_key")
36+
self.api_key
37+
or kwargs.get("api_key")
38+
or (self.config or {}).get("api_key")
3739
or os.getenv("GOOGLE_API_KEY")
3840
or os.getenv("GEMINI_API_KEY")
3941
)

src/esperanto/providers/embedding/jina.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,23 @@ def __init__(self, **kwargs):
3939
- config: Dict with task_type, late_chunking, output_dimensions, etc.
4040
"""
4141
super().__init__(**kwargs)
42-
self.api_key = kwargs.get("api_key") or os.getenv("JINA_API_KEY")
42+
self.api_key = (
43+
self.api_key
44+
or kwargs.get("api_key")
45+
or (self.config or {}).get("api_key")
46+
or os.getenv("JINA_API_KEY")
47+
)
4348
if not self.api_key:
4449
raise ValueError(
4550
"Jina API key not found. Please set the JINA_API_KEY environment "
4651
"variable or pass it as 'api_key' parameter."
4752
)
48-
self.base_url = kwargs.get("base_url", "https://api.jina.ai/v1/embeddings")
53+
self.base_url = (
54+
self.base_url
55+
or kwargs.get("base_url")
56+
or (self.config or {}).get("base_url")
57+
or "https://api.jina.ai/v1/embeddings"
58+
)
4959

5060
# Initialize HTTP clients with configurable timeout
5161
self._create_http_clients()
@@ -256,4 +266,4 @@ def _get_models(self) -> List[Model]:
256266

257267
def _get_default_model(self) -> str:
258268
"""Get the default model name."""
259-
return "jina-embeddings-v3"
269+
return "jina-embeddings-v3"

src/esperanto/providers/embedding/openai.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,24 @@ class OpenAIEmbeddingModel(EmbeddingModel):
1212

1313
def __init__(self, **kwargs):
1414
super().__init__(**kwargs)
15-
15+
1616
# Get API key
17-
self.api_key = kwargs.get("api_key") or os.getenv("OPENAI_API_KEY")
17+
self.api_key = (
18+
self.api_key
19+
or kwargs.get("api_key")
20+
or (self.config or {}).get("api_key")
21+
or os.getenv("OPENAI_API_KEY")
22+
)
1823
if not self.api_key:
1924
raise ValueError("OpenAI API key not found")
20-
25+
2126
# Set base URL
2227
self.base_url = self.base_url or "https://api.openai.com/v1"
23-
28+
2429
# Update config with model_name if provided
2530
if "model_name" in kwargs:
2631
self._config["model_name"] = kwargs["model_name"]
27-
32+
2833
# Initialize HTTP clients with configurable timeout
2934
self._create_http_clients()
3035

src/esperanto/providers/embedding/voyage.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,17 @@ def __init__(self, **kwargs):
2020
super().__init__(**kwargs)
2121

2222
# Get API key
23-
self.api_key = kwargs.get("api_key") or os.getenv("VOYAGE_API_KEY")
23+
self.api_key = (
24+
self.api_key
25+
or kwargs.get("api_key")
26+
or (self.config or {}).get("api_key")
27+
or os.getenv("VOYAGE_API_KEY")
28+
)
2429
if not self.api_key:
2530
raise ValueError("Voyage API key not found")
2631

2732
# Set base URL
28-
self.base_url = "https://api.voyageai.com/v1"
33+
self.base_url = self.base_url or "https://api.voyageai.com/v1"
2934

3035
# Initialize HTTP clients with configurable timeout
3136
self._create_http_clients()

tests/providers/embedding/test_embedding_providers.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,11 @@ def test_openai_initialization_with_api_key():
323323
assert model.api_key == "test-key"
324324

325325

326+
def test_openai_initialization_with_config_api_key():
327+
model = OpenAIEmbeddingModel(config={"api_key": "config-test-key"})
328+
assert model.api_key == "config-test-key"
329+
330+
326331
def test_openai_initialization_with_env_var():
327332
with patch.dict(os.environ, {"OPENAI_API_KEY": "env-test-key"}):
328333
model = OpenAIEmbeddingModel()
@@ -540,6 +545,11 @@ def test_google_initialization_with_api_key():
540545
assert model.api_key == "test-key"
541546

542547

548+
def test_google_initialization_with_config_api_key():
549+
model = GoogleEmbeddingModel(config={"api_key": "config-test-key"})
550+
assert model.api_key == "config-test-key"
551+
552+
543553
def test_google_initialization_with_env_var():
544554
with patch.dict(os.environ, {"GOOGLE_API_KEY": "env-test-key"}):
545555
model = GoogleEmbeddingModel()

tests/providers/embedding/test_jina.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ def test_init_with_env_var(self):
2626
model = JinaEmbeddingModel()
2727
assert model.api_key == "env-key"
2828

29+
def test_init_with_config_api_key(self):
30+
"""Test initialization with API key from config."""
31+
model = JinaEmbeddingModel(config={"api_key": "config-key"})
32+
assert model.api_key == "config-key"
33+
2934
def test_init_without_api_key(self):
3035
"""Test initialization without API key raises error."""
3136
with patch.dict(os.environ, {}, clear=True):
@@ -235,4 +240,4 @@ def test_native_late_chunking(self):
235240
# The method should return unchanged texts
236241
texts = ["very long text " * 100]
237242
chunked = model._apply_late_chunking(texts)
238-
assert chunked == texts # No chunking applied
243+
assert chunked == texts # No chunking applied

tests/providers/embedding/test_voyage_provider.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ def test_init_with_env_api_key():
6565
model = VoyageEmbeddingModel()
6666
assert model.api_key == "test-key"
6767

68+
def test_init_with_config_api_key():
69+
"""Test initialization with API key from config."""
70+
model = VoyageEmbeddingModel(config={"api_key": "config-test-key"})
71+
assert model.api_key == "config-test-key"
72+
6873

6974
def test_init_without_api_key():
7075
"""Test initialization without API key raises error."""
@@ -168,4 +173,4 @@ def test_text_cleaning(voyage_model):
168173
# Check that the input was cleaned
169174
call_args = voyage_model.client.post.call_args
170175
json_payload = call_args[1]["json"]
171-
assert json_payload["input"] == ["Hello World", "Test Text"]
176+
assert json_payload["input"] == ["Hello World", "Test Text"]

0 commit comments

Comments
 (0)