mojentic 0.8.3__py3-none-any.whl → 0.8.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mojentic/llm/gateways/openai.py +12 -3
- mojentic/llm/gateways/openai_spec.py +99 -0
- {mojentic-0.8.3.dist-info → mojentic-0.8.4.dist-info}/METADATA +3 -3
- {mojentic-0.8.3.dist-info → mojentic-0.8.4.dist-info}/RECORD +7 -6
- {mojentic-0.8.3.dist-info → mojentic-0.8.4.dist-info}/WHEEL +0 -0
- {mojentic-0.8.3.dist-info → mojentic-0.8.4.dist-info}/licenses/LICENSE.md +0 -0
- {mojentic-0.8.3.dist-info → mojentic-0.8.4.dist-info}/top_level.txt +0 -0
mojentic/llm/gateways/openai.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import os
|
|
2
3
|
from itertools import islice
|
|
3
4
|
from typing import Type, List, Iterable, Optional
|
|
4
5
|
|
|
@@ -23,11 +24,19 @@ class OpenAIGateway(LLMGateway):
|
|
|
23
24
|
|
|
24
25
|
Parameters
|
|
25
26
|
----------
|
|
26
|
-
api_key : str
|
|
27
|
-
The OpenAI API key to use.
|
|
27
|
+
api_key : str, optional
|
|
28
|
+
The OpenAI API key to use. If not provided, defaults to the value of the
|
|
29
|
+
OPENAI_API_KEY environment variable.
|
|
30
|
+
base_url : str, optional
|
|
31
|
+
The base URL for the OpenAI API. If not provided, defaults to the value of the
|
|
32
|
+
OPENAI_API_ENDPOINT environment variable, or None if not set.
|
|
28
33
|
"""
|
|
29
34
|
|
|
30
|
-
def __init__(self, api_key: str, base_url: Optional[str] = None):
|
|
35
|
+
def __init__(self, api_key: Optional[str] = None, base_url: Optional[str] = None):
|
|
36
|
+
if api_key is None:
|
|
37
|
+
api_key = os.getenv("OPENAI_API_KEY")
|
|
38
|
+
if base_url is None:
|
|
39
|
+
base_url = os.getenv("OPENAI_API_ENDPOINT")
|
|
31
40
|
self.client = OpenAI(api_key=api_key, base_url=base_url)
|
|
32
41
|
self.model_registry = get_model_registry()
|
|
33
42
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from unittest.mock import patch
|
|
3
|
+
|
|
4
|
+
from mojentic.llm.gateways.openai import OpenAIGateway
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class DescribeOpenAIGateway:
|
|
8
|
+
"""
|
|
9
|
+
Unit tests for the OpenAI gateway
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
class DescribeInitialization:
|
|
13
|
+
"""
|
|
14
|
+
Tests for OpenAI gateway initialization
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def should_initialize_with_api_key(self, mocker):
|
|
18
|
+
api_key = "test-api-key"
|
|
19
|
+
mock_openai = mocker.patch('mojentic.llm.gateways.openai.OpenAI')
|
|
20
|
+
|
|
21
|
+
gateway = OpenAIGateway(api_key=api_key)
|
|
22
|
+
|
|
23
|
+
mock_openai.assert_called_once_with(api_key=api_key, base_url=None)
|
|
24
|
+
assert gateway.client is not None
|
|
25
|
+
|
|
26
|
+
def should_initialize_with_api_key_and_base_url(self, mocker):
|
|
27
|
+
api_key = "test-api-key"
|
|
28
|
+
base_url = "https://custom.openai.com"
|
|
29
|
+
mock_openai = mocker.patch('mojentic.llm.gateways.openai.OpenAI')
|
|
30
|
+
|
|
31
|
+
gateway = OpenAIGateway(api_key=api_key, base_url=base_url)
|
|
32
|
+
|
|
33
|
+
mock_openai.assert_called_once_with(api_key=api_key, base_url=base_url)
|
|
34
|
+
assert gateway.client is not None
|
|
35
|
+
|
|
36
|
+
def should_read_api_key_from_environment_variable(self, mocker):
|
|
37
|
+
api_key = "test-api-key-from-env"
|
|
38
|
+
mock_openai = mocker.patch('mojentic.llm.gateways.openai.OpenAI')
|
|
39
|
+
|
|
40
|
+
with patch.dict(os.environ, {'OPENAI_API_KEY': api_key}):
|
|
41
|
+
gateway = OpenAIGateway()
|
|
42
|
+
|
|
43
|
+
mock_openai.assert_called_once_with(api_key=api_key, base_url=None)
|
|
44
|
+
assert gateway.client is not None
|
|
45
|
+
|
|
46
|
+
def should_read_base_url_from_environment_variable(self, mocker):
|
|
47
|
+
api_key = "test-api-key"
|
|
48
|
+
endpoint = "https://corporate.openai.com"
|
|
49
|
+
mock_openai = mocker.patch('mojentic.llm.gateways.openai.OpenAI')
|
|
50
|
+
|
|
51
|
+
with patch.dict(os.environ, {'OPENAI_API_ENDPOINT': endpoint}):
|
|
52
|
+
gateway = OpenAIGateway(api_key=api_key)
|
|
53
|
+
|
|
54
|
+
mock_openai.assert_called_once_with(api_key=api_key, base_url=endpoint)
|
|
55
|
+
assert gateway.client is not None
|
|
56
|
+
|
|
57
|
+
def should_read_both_from_environment_variables(self, mocker):
|
|
58
|
+
api_key = "test-api-key-from-env"
|
|
59
|
+
endpoint = "https://corporate.openai.com"
|
|
60
|
+
mock_openai = mocker.patch('mojentic.llm.gateways.openai.OpenAI')
|
|
61
|
+
|
|
62
|
+
with patch.dict(os.environ, {'OPENAI_API_KEY': api_key, 'OPENAI_API_ENDPOINT': endpoint}):
|
|
63
|
+
gateway = OpenAIGateway()
|
|
64
|
+
|
|
65
|
+
mock_openai.assert_called_once_with(api_key=api_key, base_url=endpoint)
|
|
66
|
+
assert gateway.client is not None
|
|
67
|
+
|
|
68
|
+
def should_prefer_explicit_api_key_over_environment_variable(self, mocker):
|
|
69
|
+
api_key_env = "test-api-key-from-env"
|
|
70
|
+
api_key_explicit = "test-api-key-explicit"
|
|
71
|
+
mock_openai = mocker.patch('mojentic.llm.gateways.openai.OpenAI')
|
|
72
|
+
|
|
73
|
+
with patch.dict(os.environ, {'OPENAI_API_KEY': api_key_env}):
|
|
74
|
+
gateway = OpenAIGateway(api_key=api_key_explicit)
|
|
75
|
+
|
|
76
|
+
mock_openai.assert_called_once_with(api_key=api_key_explicit, base_url=None)
|
|
77
|
+
assert gateway.client is not None
|
|
78
|
+
|
|
79
|
+
def should_prefer_explicit_base_url_over_environment_variable(self, mocker):
|
|
80
|
+
api_key = "test-api-key"
|
|
81
|
+
endpoint_env = "https://corporate.openai.com"
|
|
82
|
+
endpoint_explicit = "https://explicit.openai.com"
|
|
83
|
+
mock_openai = mocker.patch('mojentic.llm.gateways.openai.OpenAI')
|
|
84
|
+
|
|
85
|
+
with patch.dict(os.environ, {'OPENAI_API_ENDPOINT': endpoint_env}):
|
|
86
|
+
gateway = OpenAIGateway(api_key=api_key, base_url=endpoint_explicit)
|
|
87
|
+
|
|
88
|
+
mock_openai.assert_called_once_with(api_key=api_key, base_url=endpoint_explicit)
|
|
89
|
+
assert gateway.client is not None
|
|
90
|
+
|
|
91
|
+
def should_use_none_when_no_endpoint_specified(self, mocker):
|
|
92
|
+
api_key = "test-api-key"
|
|
93
|
+
mock_openai = mocker.patch('mojentic.llm.gateways.openai.OpenAI')
|
|
94
|
+
|
|
95
|
+
with patch.dict(os.environ, {}, clear=True):
|
|
96
|
+
gateway = OpenAIGateway(api_key=api_key)
|
|
97
|
+
|
|
98
|
+
mock_openai.assert_called_once_with(api_key=api_key, base_url=None)
|
|
99
|
+
assert gateway.client is not None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mojentic
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.4
|
|
4
4
|
Summary: Mojentic is an agentic framework that aims to provide a simple and flexible way to assemble teams of agents to solve complex problems.
|
|
5
5
|
Author-email: Stacey Vetzal <stacey@vetzal.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/svetzal/mojentic
|
|
@@ -170,9 +170,9 @@ pip install -e ".[dev]"
|
|
|
170
170
|
pytest
|
|
171
171
|
```
|
|
172
172
|
|
|
173
|
-
##
|
|
173
|
+
## ✅ Project Status
|
|
174
174
|
|
|
175
|
-
|
|
175
|
+
The agentic aspects of this framework are in the highest state of flux. The first layer has stabilized, as have the simpler parts of the second layer, and we're working on the stability of the asynchronous pubsub architecture. We expect Python 3.14 will be the real enabler for the async aspects of the second layer.
|
|
176
176
|
|
|
177
177
|
## 📄 License
|
|
178
178
|
|
|
@@ -87,11 +87,12 @@ mojentic/llm/gateways/models.py,sha256=OyIaMHKrrx6dHo5FbC8qOFct7PRql9wqbe_BJlgDS
|
|
|
87
87
|
mojentic/llm/gateways/ollama.py,sha256=OUUImBNzPte52Gsf-e7TBjDHRvYW5flU9ddxwG2zlzk,7909
|
|
88
88
|
mojentic/llm/gateways/ollama_messages_adapter.py,sha256=kUN_p2FyN88_trXMcL-Xsn9xPBU7pGKlJwTUEUCf6G4,1404
|
|
89
89
|
mojentic/llm/gateways/ollama_messages_adapter_spec.py,sha256=gVRbWDrHOa1EiZ0CkEWe0pGn-GKRqdGb-x56HBQeYSE,4981
|
|
90
|
-
mojentic/llm/gateways/openai.py,sha256=
|
|
90
|
+
mojentic/llm/gateways/openai.py,sha256=JNpbcGInAq97Hm4-GS_5IMNTRhUdSIJtIPdAn6fT_jo,14509
|
|
91
91
|
mojentic/llm/gateways/openai_message_adapter_spec.py,sha256=ITBSV5njldV_x0NPgjmg8Okf9KzevQJ8dTXM-t6ubcg,6612
|
|
92
92
|
mojentic/llm/gateways/openai_messages_adapter.py,sha256=Scal68JKKdBHB35ok1c5DeWYdD6Wra5oXSsPxJyyXSQ,3947
|
|
93
93
|
mojentic/llm/gateways/openai_model_registry.py,sha256=CPfbwBhdZ94jzLjmaH9dRXGZFk4OD2pOUlW6RFWVAPM,14101
|
|
94
94
|
mojentic/llm/gateways/openai_model_registry_spec.py,sha256=rCyXhiCOKMewkZjdZoawALoEk62yjENeYTpjYuMuXDM,6711
|
|
95
|
+
mojentic/llm/gateways/openai_spec.py,sha256=eazIk8bLQ2d9CNPGhcw0WedX7CZz-TEkmwGz74c39CM,4161
|
|
95
96
|
mojentic/llm/gateways/openai_temperature_handling_spec.py,sha256=PxQpI57RGaWpt1Dj6z2uLeFcP-dRZTHkai-igZTZc9M,9947
|
|
96
97
|
mojentic/llm/gateways/tokenizer_gateway.py,sha256=ztuqfunlJ6xmyUPPHcC_69-kegiNJD6jdSEde7hDh2w,485
|
|
97
98
|
mojentic/llm/registry/__init__.py,sha256=P2MHlptrtRPMSWbWl9ojXPmjMwkW0rIn6jwzCkSgnhE,164
|
|
@@ -138,8 +139,8 @@ mojentic/tracer/tracer_system.py,sha256=PqAHvG4mxUfkdCOiT0mCrzvPAgPNqiTov5TksEBG
|
|
|
138
139
|
mojentic/tracer/tracer_system_spec.py,sha256=TNm0f9LV__coBx0JGEKyzzNN9mFjCSG_SSrRISO8Xeg,8632
|
|
139
140
|
mojentic/utils/__init__.py,sha256=lqECkkoFvHFttDnafRE1vvh0Dmna_lwupMToP5VvX5k,115
|
|
140
141
|
mojentic/utils/formatting.py,sha256=bPrwwdluXdQ8TsFxfWtHNOeMWKNvAfABSoUnnA1g7c8,947
|
|
141
|
-
mojentic-0.8.
|
|
142
|
-
mojentic-0.8.
|
|
143
|
-
mojentic-0.8.
|
|
144
|
-
mojentic-0.8.
|
|
145
|
-
mojentic-0.8.
|
|
142
|
+
mojentic-0.8.4.dist-info/licenses/LICENSE.md,sha256=txSgV8n5zY1W3NiF5HHsCwlaW0e8We1cSC6TuJUqxXA,1060
|
|
143
|
+
mojentic-0.8.4.dist-info/METADATA,sha256=uwjgOm_Rbx2rFyeh_NDuVNYiSLvBJePbObI0rXelzcU,7039
|
|
144
|
+
mojentic-0.8.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
145
|
+
mojentic-0.8.4.dist-info/top_level.txt,sha256=Q-BvPQ8Eu1jnEqK8Xkr6A9C8Xa1z38oPZRHuA5MCTqg,19
|
|
146
|
+
mojentic-0.8.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|