ommlds 0.0.0.dev469__py3-none-any.whl → 0.0.0.dev470__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.
Potentially problematic release.
This version of ommlds might be problematic. Click here for more details.
- ommlds/.omlish-manifests.json +1 -1
- ommlds/cli/sessions/chat/backends/catalog.py +13 -8
- ommlds/cli/sessions/chat/backends/inject.py +15 -0
- ommlds/minichain/backends/catalogs/base.py +7 -1
- ommlds/minichain/backends/impls/anthropic/chat.py +5 -1
- ommlds/minichain/backends/impls/anthropic/stream.py +10 -4
- ommlds/minichain/backends/impls/google/chat.py +9 -2
- ommlds/minichain/backends/impls/google/search.py +6 -1
- ommlds/minichain/backends/impls/google/stream.py +10 -4
- ommlds/minichain/backends/impls/mistral.py +9 -2
- ommlds/minichain/backends/impls/ollama/chat.py +1 -1
- ommlds/minichain/backends/impls/openai/chat.py +9 -2
- ommlds/minichain/backends/impls/openai/completion.py +9 -2
- ommlds/minichain/backends/impls/openai/embedding.py +9 -2
- ommlds/minichain/backends/impls/openai/stream.py +10 -4
- ommlds/tools/git.py +4 -1
- {ommlds-0.0.0.dev469.dist-info → ommlds-0.0.0.dev470.dist-info}/METADATA +3 -3
- {ommlds-0.0.0.dev469.dist-info → ommlds-0.0.0.dev470.dist-info}/RECORD +22 -22
- {ommlds-0.0.0.dev469.dist-info → ommlds-0.0.0.dev470.dist-info}/WHEEL +0 -0
- {ommlds-0.0.0.dev469.dist-info → ommlds-0.0.0.dev470.dist-info}/entry_points.txt +0 -0
- {ommlds-0.0.0.dev469.dist-info → ommlds-0.0.0.dev470.dist-info}/licenses/LICENSE +0 -0
- {ommlds-0.0.0.dev469.dist-info → ommlds-0.0.0.dev470.dist-info}/top_level.txt +0 -0
ommlds/.omlish-manifests.json
CHANGED
|
@@ -15,33 +15,38 @@ from .types import ServiceT
|
|
|
15
15
|
##
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
class
|
|
18
|
+
class CatalogBackendProvider(BackendProvider[ServiceT], lang.Abstract):
|
|
19
|
+
class Instantiator(lang.Func2['mc.BackendCatalog.Backend', BackendConfigs | None, ta.Awaitable[ta.Any]]):
|
|
20
|
+
pass
|
|
21
|
+
|
|
19
22
|
def __init__(
|
|
20
23
|
self,
|
|
21
24
|
*,
|
|
22
25
|
name: BackendName,
|
|
23
26
|
catalog: 'mc.BackendCatalog',
|
|
24
27
|
configs: BackendConfigs | None = None,
|
|
28
|
+
instantiator: Instantiator | None = None,
|
|
25
29
|
) -> None:
|
|
26
30
|
super().__init__()
|
|
27
31
|
|
|
28
32
|
self._name = name
|
|
29
33
|
self._catalog = catalog
|
|
30
34
|
self._configs = configs
|
|
35
|
+
if instantiator is None:
|
|
36
|
+
instantiator = CatalogBackendProvider.Instantiator(lang.as_async(lambda be, cfgs: be.factory(*cfgs or [])))
|
|
37
|
+
self._instantiator = instantiator
|
|
31
38
|
|
|
32
39
|
@contextlib.asynccontextmanager
|
|
33
40
|
async def _provide_backend(self, cls: type[ServiceT]) -> ta.AsyncIterator[ServiceT]:
|
|
41
|
+
be = self._catalog.get_backend(cls, self._name)
|
|
42
|
+
|
|
34
43
|
service: ServiceT
|
|
35
|
-
async with lang.async_or_sync_maybe_managing(self.
|
|
36
|
-
cls,
|
|
37
|
-
self._name,
|
|
38
|
-
*(self._configs or []),
|
|
39
|
-
)) as service:
|
|
44
|
+
async with lang.async_or_sync_maybe_managing(await self._instantiator(be, self._configs)) as service:
|
|
40
45
|
yield service
|
|
41
46
|
|
|
42
47
|
|
|
43
48
|
class CatalogChatChoicesServiceBackendProvider(
|
|
44
|
-
|
|
49
|
+
CatalogBackendProvider['mc.ChatChoicesService'],
|
|
45
50
|
ChatChoicesServiceBackendProvider,
|
|
46
51
|
):
|
|
47
52
|
def provide_backend(self) -> ta.AsyncContextManager['mc.ChatChoicesService']:
|
|
@@ -49,7 +54,7 @@ class CatalogChatChoicesServiceBackendProvider(
|
|
|
49
54
|
|
|
50
55
|
|
|
51
56
|
class CatalogChatChoicesStreamServiceBackendProvider(
|
|
52
|
-
|
|
57
|
+
CatalogBackendProvider['mc.ChatChoicesStreamService'],
|
|
53
58
|
ChatChoicesStreamServiceBackendProvider,
|
|
54
59
|
):
|
|
55
60
|
def provide_backend(self) -> ta.AsyncContextManager['mc.ChatChoicesStreamService']:
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
1
3
|
from omlish import inject as inj
|
|
2
4
|
from omlish import lang
|
|
3
5
|
|
|
6
|
+
from ..... import minichain as mc
|
|
4
7
|
from .injection import backend_configs
|
|
5
8
|
|
|
6
9
|
|
|
@@ -34,4 +37,16 @@ def bind_backends(
|
|
|
34
37
|
|
|
35
38
|
#
|
|
36
39
|
|
|
40
|
+
async def catalog_backend_instantiator_provider(injector: inj.AsyncInjector) -> _catalog.CatalogBackendProvider.Instantiator: # noqa
|
|
41
|
+
async def inner(be: 'mc.BackendCatalog.Backend', cfgs: _types.BackendConfigs | None) -> ta.Any:
|
|
42
|
+
kwt = inj.build_kwargs_target(be.factory, non_strict=True)
|
|
43
|
+
kw = await injector.provide_kwargs(kwt)
|
|
44
|
+
return be.factory(*cfgs or [], **kw)
|
|
45
|
+
|
|
46
|
+
return _catalog.CatalogBackendProvider.Instantiator(inner)
|
|
47
|
+
|
|
48
|
+
els.append(inj.bind(_catalog.CatalogBackendProvider.Instantiator, to_async_fn=catalog_backend_instantiator_provider)) # noqa
|
|
49
|
+
|
|
50
|
+
#
|
|
51
|
+
|
|
37
52
|
return inj.as_elements(*els)
|
|
@@ -21,7 +21,13 @@ class BackendCatalog(lang.Abstract):
|
|
|
21
21
|
def get_backend(self, service_cls: type[T], name: str) -> Backend:
|
|
22
22
|
raise NotImplementedError
|
|
23
23
|
|
|
24
|
-
def new_backend(
|
|
24
|
+
def new_backend(
|
|
25
|
+
self,
|
|
26
|
+
service_cls: ta.Any,
|
|
27
|
+
name: str,
|
|
28
|
+
*args: ta.Any,
|
|
29
|
+
**kwargs: ta.Any,
|
|
30
|
+
) -> ta.Any:
|
|
25
31
|
be = self.get_backend(service_cls, name)
|
|
26
32
|
return be.factory(*be.configs or [], *args, **kwargs)
|
|
27
33
|
|
|
@@ -46,9 +46,12 @@ class AnthropicChatChoicesService:
|
|
|
46
46
|
def __init__(
|
|
47
47
|
self,
|
|
48
48
|
*configs: ApiKey | ModelName,
|
|
49
|
+
http_client: http.AsyncHttpClient | None = None,
|
|
49
50
|
) -> None:
|
|
50
51
|
super().__init__()
|
|
51
52
|
|
|
53
|
+
self._http_client = http_client
|
|
54
|
+
|
|
52
55
|
with tv.consume(*configs) as cc:
|
|
53
56
|
self._api_key = check.not_none(ApiKey.pop_secret(cc, env='ANTHROPIC_API_KEY'))
|
|
54
57
|
self._model_name = cc.pop(self.DEFAULT_MODEL_NAME)
|
|
@@ -88,7 +91,7 @@ class AnthropicChatChoicesService:
|
|
|
88
91
|
|
|
89
92
|
raw_request = msh.marshal(a_req)
|
|
90
93
|
|
|
91
|
-
raw_response = http.
|
|
94
|
+
raw_response = await http.async_request(
|
|
92
95
|
'https://api.anthropic.com/v1/messages',
|
|
93
96
|
headers={
|
|
94
97
|
http.consts.HEADER_CONTENT_TYPE: http.consts.CONTENT_TYPE_JSON,
|
|
@@ -96,6 +99,7 @@ class AnthropicChatChoicesService:
|
|
|
96
99
|
b'anthropic-version': b'2023-06-01',
|
|
97
100
|
},
|
|
98
101
|
data=json.dumps(raw_request).encode('utf-8'),
|
|
102
|
+
client=self._http_client,
|
|
99
103
|
)
|
|
100
104
|
|
|
101
105
|
response = json.loads(check.not_none(raw_response.data).decode('utf-8'))
|
|
@@ -39,9 +39,15 @@ from .protocol import build_protocol_tool
|
|
|
39
39
|
# )
|
|
40
40
|
@static_check_is_chat_choices_stream_service
|
|
41
41
|
class AnthropicChatChoicesStreamService:
|
|
42
|
-
def __init__(
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
*configs: Config,
|
|
45
|
+
http_client: http.AsyncHttpClient | None = None,
|
|
46
|
+
) -> None:
|
|
43
47
|
super().__init__()
|
|
44
48
|
|
|
49
|
+
self._http_client = http_client
|
|
50
|
+
|
|
45
51
|
with tv.consume(*configs) as cc:
|
|
46
52
|
self._model_name = cc.pop(AnthropicChatChoicesService.DEFAULT_MODEL_NAME)
|
|
47
53
|
self._api_key = check.not_none(ApiKey.pop_secret(cc, env='ANTHROPIC_API_KEY'))
|
|
@@ -84,8 +90,8 @@ class AnthropicChatChoicesStreamService:
|
|
|
84
90
|
)
|
|
85
91
|
|
|
86
92
|
async with UseResources.or_new(request.options) as rs:
|
|
87
|
-
http_client = rs.
|
|
88
|
-
http_response = rs.
|
|
93
|
+
http_client = await rs.enter_async_context(http.manage_async_client(self._http_client))
|
|
94
|
+
http_response = await rs.enter_async_context(await http_client.stream_request(http_request))
|
|
89
95
|
|
|
90
96
|
async def inner(sink: StreamResponseSink[AiChoicesDeltas]) -> ta.Sequence[ChatChoicesOutputs] | None:
|
|
91
97
|
msg_start: AnthropicSseDecoderEvents.MessageStart | None = None
|
|
@@ -95,7 +101,7 @@ class AnthropicChatChoicesStreamService:
|
|
|
95
101
|
db = DelimitingBuffer([b'\r', b'\n', b'\r\n'])
|
|
96
102
|
sd = sse.SseDecoder()
|
|
97
103
|
while True:
|
|
98
|
-
b = http_response.stream.read1(self.READ_CHUNK_SIZE)
|
|
104
|
+
b = await http_response.stream.read1(self.READ_CHUNK_SIZE)
|
|
99
105
|
for l in db.feed(b):
|
|
100
106
|
if isinstance(l, DelimitingBuffer.Incomplete):
|
|
101
107
|
# FIXME: handle
|
|
@@ -40,9 +40,15 @@ from .tools import build_tool_spec_schema
|
|
|
40
40
|
class GoogleChatChoicesService:
|
|
41
41
|
DEFAULT_MODEL_NAME: ta.ClassVar[ModelName] = ModelName(check.not_none(MODEL_NAMES.default))
|
|
42
42
|
|
|
43
|
-
def __init__(
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
*configs: ApiKey | ModelName,
|
|
46
|
+
http_client: http.AsyncHttpClient | None = None,
|
|
47
|
+
) -> None:
|
|
44
48
|
super().__init__()
|
|
45
49
|
|
|
50
|
+
self._http_client = http_client
|
|
51
|
+
|
|
46
52
|
with tv.consume(*configs) as cc:
|
|
47
53
|
self._model_name = cc.pop(self.DEFAULT_MODEL_NAME)
|
|
48
54
|
self._api_key = ApiKey.pop_secret(cc, env='GEMINI_API_KEY')
|
|
@@ -149,11 +155,12 @@ class GoogleChatChoicesService:
|
|
|
149
155
|
|
|
150
156
|
model_name = MODEL_NAMES.resolve(self._model_name.v)
|
|
151
157
|
|
|
152
|
-
resp = http.
|
|
158
|
+
resp = await http.async_request(
|
|
153
159
|
f'{self.BASE_URL.rstrip("/")}/{model_name}:generateContent?key={key}',
|
|
154
160
|
headers={'Content-Type': 'application/json'},
|
|
155
161
|
data=json.dumps_compact(req_dct).encode('utf-8'),
|
|
156
162
|
method='POST',
|
|
163
|
+
client=self._http_client,
|
|
157
164
|
)
|
|
158
165
|
|
|
159
166
|
resp_dct = json.loads(check.not_none(resp.data).decode('utf-8'))
|
|
@@ -82,12 +82,16 @@ class CseSearchService:
|
|
|
82
82
|
self,
|
|
83
83
|
cse_id: str | None = None,
|
|
84
84
|
cse_api_key: str | None = None,
|
|
85
|
+
*,
|
|
86
|
+
http_client: http.AsyncHttpClient | None = None,
|
|
85
87
|
) -> None:
|
|
86
88
|
super().__init__()
|
|
87
89
|
|
|
88
90
|
self._cse_id = cse_id
|
|
89
91
|
self._cse_api_key = cse_api_key
|
|
90
92
|
|
|
93
|
+
self._http_client = http_client
|
|
94
|
+
|
|
91
95
|
async def invoke(
|
|
92
96
|
self,
|
|
93
97
|
request: SearchRequest,
|
|
@@ -97,8 +101,9 @@ class CseSearchService:
|
|
|
97
101
|
cx=check.non_empty_str(self._cse_id),
|
|
98
102
|
q=request.v,
|
|
99
103
|
))
|
|
100
|
-
resp = http.
|
|
104
|
+
resp = await http.async_request(
|
|
101
105
|
f'https://www.googleapis.com/customsearch/v1?{qs}',
|
|
106
|
+
client=self._http_client,
|
|
102
107
|
)
|
|
103
108
|
out = check.not_none(resp.data)
|
|
104
109
|
|
|
@@ -46,9 +46,15 @@ from .tools import build_tool_spec_schema
|
|
|
46
46
|
class GoogleChatChoicesStreamService:
|
|
47
47
|
DEFAULT_MODEL_NAME: ta.ClassVar[ModelName] = ModelName(check.not_none(MODEL_NAMES.default))
|
|
48
48
|
|
|
49
|
-
def __init__(
|
|
49
|
+
def __init__(
|
|
50
|
+
self,
|
|
51
|
+
*configs: ApiKey | ModelName,
|
|
52
|
+
http_client: http.AsyncHttpClient | None = None,
|
|
53
|
+
) -> None:
|
|
50
54
|
super().__init__()
|
|
51
55
|
|
|
56
|
+
self._http_client = http_client
|
|
57
|
+
|
|
52
58
|
with tv.consume(*configs) as cc:
|
|
53
59
|
self._model_name = cc.pop(self.DEFAULT_MODEL_NAME)
|
|
54
60
|
self._api_key = ApiKey.pop_secret(cc, env='GEMINI_API_KEY')
|
|
@@ -163,13 +169,13 @@ class GoogleChatChoicesStreamService:
|
|
|
163
169
|
)
|
|
164
170
|
|
|
165
171
|
async with UseResources.or_new(request.options) as rs:
|
|
166
|
-
http_client = rs.
|
|
167
|
-
http_response = rs.
|
|
172
|
+
http_client = await rs.enter_async_context(http.manage_async_client(self._http_client))
|
|
173
|
+
http_response = await rs.enter_async_context(await http_client.stream_request(http_request))
|
|
168
174
|
|
|
169
175
|
async def inner(sink: StreamResponseSink[AiChoicesDeltas]) -> ta.Sequence[ChatChoicesOutputs] | None:
|
|
170
176
|
db = DelimitingBuffer([b'\r', b'\n', b'\r\n'])
|
|
171
177
|
while True:
|
|
172
|
-
b = http_response.stream.read1(self.READ_CHUNK_SIZE)
|
|
178
|
+
b = await http_response.stream.read1(self.READ_CHUNK_SIZE)
|
|
173
179
|
for bl in db.feed(b):
|
|
174
180
|
if isinstance(bl, DelimitingBuffer.Incomplete):
|
|
175
181
|
# FIXME: handle
|
|
@@ -40,10 +40,16 @@ class MistralChatChoicesService:
|
|
|
40
40
|
AiMessage: 'assistant',
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
def __init__(
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
*,
|
|
46
|
+
api_key: str | None = None,
|
|
47
|
+
http_client: http.AsyncHttpClient | None = None,
|
|
48
|
+
) -> None:
|
|
44
49
|
super().__init__()
|
|
45
50
|
|
|
46
51
|
self._api_key = api_key
|
|
52
|
+
self._http_client = http_client
|
|
47
53
|
|
|
48
54
|
def _get_msg_content(self, m: Message) -> str | None:
|
|
49
55
|
if isinstance(m, AiMessage):
|
|
@@ -73,7 +79,7 @@ class MistralChatChoicesService:
|
|
|
73
79
|
],
|
|
74
80
|
}
|
|
75
81
|
|
|
76
|
-
resp = http.
|
|
82
|
+
resp = await http.async_request(
|
|
77
83
|
'https://api.mistral.ai/v1/chat/completions',
|
|
78
84
|
method='POST',
|
|
79
85
|
data=json.dumps_compact(req_dct).encode('utf-8'),
|
|
@@ -82,6 +88,7 @@ class MistralChatChoicesService:
|
|
|
82
88
|
'Accept': 'application/json',
|
|
83
89
|
'Authorization': f'Bearer {key}',
|
|
84
90
|
},
|
|
91
|
+
client=self._http_client,
|
|
85
92
|
)
|
|
86
93
|
|
|
87
94
|
if resp.status == 429:
|
|
@@ -66,7 +66,7 @@ class BaseOllamaChatChoicesService(lang.Abstract):
|
|
|
66
66
|
|
|
67
67
|
#
|
|
68
68
|
|
|
69
|
-
ROLE_MAP: ta.ClassVar[ta.Mapping[type[Message], pt.Role]] = {
|
|
69
|
+
ROLE_MAP: ta.ClassVar[ta.Mapping[type[Message], pt.Role]] = { # noqa
|
|
70
70
|
SystemMessage: 'system',
|
|
71
71
|
UserMessage: 'user',
|
|
72
72
|
AiMessage: 'assistant',
|
|
@@ -42,9 +42,15 @@ from .names import MODEL_NAMES
|
|
|
42
42
|
class OpenaiChatChoicesService:
|
|
43
43
|
DEFAULT_MODEL_NAME: ta.ClassVar[ModelName] = ModelName(check.not_none(MODEL_NAMES.default))
|
|
44
44
|
|
|
45
|
-
def __init__(
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
*configs: ApiKey | ModelName | DefaultOptions,
|
|
48
|
+
http_client: http.AsyncHttpClient | None = None,
|
|
49
|
+
) -> None:
|
|
46
50
|
super().__init__()
|
|
47
51
|
|
|
52
|
+
self._http_client = http_client
|
|
53
|
+
|
|
48
54
|
with tv.consume(*configs) as cc:
|
|
49
55
|
self._model_name = cc.pop(self.DEFAULT_MODEL_NAME)
|
|
50
56
|
self._api_key = ApiKey.pop_secret(cc, env='OPENAI_API_KEY')
|
|
@@ -68,13 +74,14 @@ class OpenaiChatChoicesService:
|
|
|
68
74
|
|
|
69
75
|
raw_request = msh.marshal(rh.oai_request())
|
|
70
76
|
|
|
71
|
-
http_response = http.
|
|
77
|
+
http_response = await http.async_request(
|
|
72
78
|
'https://api.openai.com/v1/chat/completions',
|
|
73
79
|
headers={
|
|
74
80
|
http.consts.HEADER_CONTENT_TYPE: http.consts.CONTENT_TYPE_JSON,
|
|
75
81
|
http.consts.HEADER_AUTH: http.consts.format_bearer_auth_header(check.not_none(self._api_key).reveal()),
|
|
76
82
|
},
|
|
77
83
|
data=json.dumps(raw_request).encode('utf-8'),
|
|
84
|
+
client=self._http_client,
|
|
78
85
|
)
|
|
79
86
|
|
|
80
87
|
raw_response = json.loads(check.not_none(http_response.data).decode('utf-8'))
|
|
@@ -23,9 +23,15 @@ from ....standard import ApiKey
|
|
|
23
23
|
class OpenaiCompletionService:
|
|
24
24
|
DEFAULT_MODEL_NAME: ta.ClassVar[str] = 'gpt-3.5-turbo-instruct'
|
|
25
25
|
|
|
26
|
-
def __init__(
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
*configs: Config,
|
|
29
|
+
http_client: http.AsyncHttpClient | None = None,
|
|
30
|
+
) -> None:
|
|
27
31
|
super().__init__()
|
|
28
32
|
|
|
33
|
+
self._http_client = http_client
|
|
34
|
+
|
|
29
35
|
with tv.consume(*configs) as cc:
|
|
30
36
|
self._api_key = ApiKey.pop_secret(cc, env='OPENAI_API_KEY')
|
|
31
37
|
|
|
@@ -41,13 +47,14 @@ class OpenaiCompletionService:
|
|
|
41
47
|
stream=False,
|
|
42
48
|
)
|
|
43
49
|
|
|
44
|
-
raw_response = http.
|
|
50
|
+
raw_response = await http.async_request(
|
|
45
51
|
'https://api.openai.com/v1/completions',
|
|
46
52
|
headers={
|
|
47
53
|
http.consts.HEADER_CONTENT_TYPE: http.consts.CONTENT_TYPE_JSON,
|
|
48
54
|
http.consts.HEADER_AUTH: http.consts.format_bearer_auth_header(check.not_none(self._api_key).reveal()),
|
|
49
55
|
},
|
|
50
56
|
data=json.dumps(raw_request).encode('utf-8'),
|
|
57
|
+
client=self._http_client,
|
|
51
58
|
)
|
|
52
59
|
|
|
53
60
|
response = json.loads(check.not_none(raw_response.data).decode('utf-8'))
|
|
@@ -22,9 +22,15 @@ from ....vectors.types import Vector
|
|
|
22
22
|
class OpenaiEmbeddingService:
|
|
23
23
|
model = 'text-embedding-3-small'
|
|
24
24
|
|
|
25
|
-
def __init__(
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
*configs: Config,
|
|
28
|
+
http_client: http.AsyncHttpClient | None = None,
|
|
29
|
+
) -> None:
|
|
26
30
|
super().__init__()
|
|
27
31
|
|
|
32
|
+
self._http_client = http_client
|
|
33
|
+
|
|
28
34
|
with tv.consume(*configs) as cc:
|
|
29
35
|
self._api_key = ApiKey.pop_secret(cc, env='OPENAI_API_KEY')
|
|
30
36
|
|
|
@@ -34,13 +40,14 @@ class OpenaiEmbeddingService:
|
|
|
34
40
|
input=check.isinstance(request.v, str),
|
|
35
41
|
)
|
|
36
42
|
|
|
37
|
-
raw_response = http.
|
|
43
|
+
raw_response = await http.async_request(
|
|
38
44
|
'https://api.openai.com/v1/embeddings',
|
|
39
45
|
headers={
|
|
40
46
|
http.consts.HEADER_CONTENT_TYPE: http.consts.CONTENT_TYPE_JSON,
|
|
41
47
|
http.consts.HEADER_AUTH: http.consts.format_bearer_auth_header(check.not_none(self._api_key).reveal()),
|
|
42
48
|
},
|
|
43
49
|
data=json.dumps(raw_request).encode('utf-8'),
|
|
50
|
+
client=self._http_client,
|
|
44
51
|
)
|
|
45
52
|
|
|
46
53
|
response = json.loads(check.not_none(raw_response.data).decode('utf-8'))
|
|
@@ -41,9 +41,15 @@ from .names import MODEL_NAMES
|
|
|
41
41
|
# )
|
|
42
42
|
@static_check_is_chat_choices_stream_service
|
|
43
43
|
class OpenaiChatChoicesStreamService:
|
|
44
|
-
def __init__(
|
|
44
|
+
def __init__(
|
|
45
|
+
self,
|
|
46
|
+
*configs: Config,
|
|
47
|
+
http_client: http.AsyncHttpClient | None = None,
|
|
48
|
+
) -> None:
|
|
45
49
|
super().__init__()
|
|
46
50
|
|
|
51
|
+
self._http_client = http_client
|
|
52
|
+
|
|
47
53
|
with tv.consume(*configs) as cc:
|
|
48
54
|
self._model_name = cc.pop(OpenaiChatChoicesService.DEFAULT_MODEL_NAME)
|
|
49
55
|
self._api_key = ApiKey.pop_secret(cc, env='OPENAI_API_KEY')
|
|
@@ -81,14 +87,14 @@ class OpenaiChatChoicesStreamService:
|
|
|
81
87
|
)
|
|
82
88
|
|
|
83
89
|
async with UseResources.or_new(request.options) as rs:
|
|
84
|
-
http_client = rs.
|
|
85
|
-
http_response = rs.
|
|
90
|
+
http_client = await rs.enter_async_context(http.manage_async_client(self._http_client))
|
|
91
|
+
http_response = await rs.enter_async_context(await http_client.stream_request(http_request))
|
|
86
92
|
|
|
87
93
|
async def inner(sink: StreamResponseSink[AiChoicesDeltas]) -> ta.Sequence[ChatChoicesOutputs]:
|
|
88
94
|
db = DelimitingBuffer([b'\r', b'\n', b'\r\n'])
|
|
89
95
|
sd = sse.SseDecoder()
|
|
90
96
|
while True:
|
|
91
|
-
b = http_response.stream.read1(self.READ_CHUNK_SIZE)
|
|
97
|
+
b = await http_response.stream.read1(self.READ_CHUNK_SIZE)
|
|
92
98
|
for l in db.feed(b):
|
|
93
99
|
if isinstance(l, DelimitingBuffer.Incomplete):
|
|
94
100
|
# FIXME: handle
|
ommlds/tools/git.py
CHANGED
|
@@ -16,6 +16,7 @@ from omdev.tools.git.messages import GitMessageGenerator
|
|
|
16
16
|
from omlish import check
|
|
17
17
|
from omlish import lang
|
|
18
18
|
from omlish.configs.classes import Configurable
|
|
19
|
+
from omlish.http import all as http
|
|
19
20
|
from omlish.subprocesses.sync import subprocesses
|
|
20
21
|
|
|
21
22
|
from .. import minichain as mc
|
|
@@ -76,7 +77,9 @@ class OpenaiGitAiBackend(GitAiBackend['OpenaiGitAiBackend.Config']):
|
|
|
76
77
|
if (sec := load_secrets().try_get(key.lower())) is not None:
|
|
77
78
|
os.environ[key] = sec.reveal()
|
|
78
79
|
|
|
79
|
-
llm = OpenaiChatChoicesService(
|
|
80
|
+
llm = OpenaiChatChoicesService(
|
|
81
|
+
http_client=http.SyncAsyncHttpClient(http.client()),
|
|
82
|
+
)
|
|
80
83
|
|
|
81
84
|
resp = lang.sync_await(llm.invoke(mc.ChatChoicesRequest(
|
|
82
85
|
[mc.UserMessage(prompt)],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ommlds
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev470
|
|
4
4
|
Summary: ommlds
|
|
5
5
|
Author: wrmsr
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -14,8 +14,8 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
14
14
|
Requires-Python: >=3.13
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
License-File: LICENSE
|
|
17
|
-
Requires-Dist: omdev==0.0.0.
|
|
18
|
-
Requires-Dist: omlish==0.0.0.
|
|
17
|
+
Requires-Dist: omdev==0.0.0.dev470
|
|
18
|
+
Requires-Dist: omlish==0.0.0.dev470
|
|
19
19
|
Provides-Extra: all
|
|
20
20
|
Requires-Dist: llama-cpp-python~=0.3; extra == "all"
|
|
21
21
|
Requires-Dist: mlx~=0.29; extra == "all"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
ommlds/.omlish-manifests.json,sha256=
|
|
1
|
+
ommlds/.omlish-manifests.json,sha256=nVhqSv9iQ2zu3MpOtJC2mFH5ORyzIC2K8kCAwDEdzGE,21555
|
|
2
2
|
ommlds/__about__.py,sha256=t2rQF0yXpWFcCb2dvgzGR3I35HKGvGSn-EfhaUWVl5s,1759
|
|
3
3
|
ommlds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
ommlds/huggingface.py,sha256=JfEyfKOxU3-SY_ojtXBJFNeD-NIuKjvMe3GL3e93wNA,1175
|
|
@@ -99,8 +99,8 @@ ommlds/cli/sessions/chat/driver.py,sha256=ddnCYTKqWiPxV8U4UbFwb7E3yi81ItjZ9j3AJd
|
|
|
99
99
|
ommlds/cli/sessions/chat/inject.py,sha256=7Yg6wUs2Oej4UjNZCAWCJCEsDJZWvT4G8XvkvVUMC7U,1928
|
|
100
100
|
ommlds/cli/sessions/chat/session.py,sha256=eqwelLE74JFC-fBpk_hdwMD2nP4pLv3ZPwUn99200B8,521
|
|
101
101
|
ommlds/cli/sessions/chat/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
102
|
-
ommlds/cli/sessions/chat/backends/catalog.py,sha256
|
|
103
|
-
ommlds/cli/sessions/chat/backends/inject.py,sha256=
|
|
102
|
+
ommlds/cli/sessions/chat/backends/catalog.py,sha256=hIY0L1zewuJX0_xxcMcy4gylSLiQENB3YxgYJEoKgrU,2109
|
|
103
|
+
ommlds/cli/sessions/chat/backends/inject.py,sha256=v_kw6lOMo5XoAf2dyIld2oBjg7lVbS2ndmdPQv4F464,1558
|
|
104
104
|
ommlds/cli/sessions/chat/backends/injection.py,sha256=GCn5OvNIEowgB70kQVuU84z3i8lLA4vOVkTZlQG8s0o,327
|
|
105
105
|
ommlds/cli/sessions/chat/backends/types.py,sha256=5eImYHXLKqbC5MDrN443eMGamP9snCmV1n7LtAsqgPk,696
|
|
106
106
|
ommlds/cli/sessions/chat/chat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -170,24 +170,24 @@ ommlds/minichain/types.py,sha256=K6RRjpUi17UEG0cqPrrvbVANU0iRVh3WLiH-y6oEWFI,414
|
|
|
170
170
|
ommlds/minichain/utils.py,sha256=NTsBu_pSZnLdZc1R1Se70rb_9J-IoB6VRwjhwzh3PwY,490
|
|
171
171
|
ommlds/minichain/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
172
172
|
ommlds/minichain/backends/catalogs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
173
|
-
ommlds/minichain/backends/catalogs/base.py,sha256=
|
|
173
|
+
ommlds/minichain/backends/catalogs/base.py,sha256=6ThxF-OozMm0aGHAo3UyKUcNA3TVda0w_QLpbz7XmEU,1306
|
|
174
174
|
ommlds/minichain/backends/catalogs/simple.py,sha256=T6GeY902XPRjNnwX1AivunpkirLyxFg5rG2V2LA0Puo,1501
|
|
175
175
|
ommlds/minichain/backends/catalogs/strings.py,sha256=IHid5yRbHvkU5O5ypSMWAPcETLlvj1CXeIJ3mHrDyi8,1768
|
|
176
176
|
ommlds/minichain/backends/impls/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
177
|
-
ommlds/minichain/backends/impls/mistral.py,sha256=
|
|
177
|
+
ommlds/minichain/backends/impls/mistral.py,sha256=nC0aqabg-I7JJyxHHMZASASksqV1at7nJWZHGtCwfio,2843
|
|
178
178
|
ommlds/minichain/backends/impls/sqlite.py,sha256=NOFm_fgr-OZ8mo7etj0zwvxsDnidRwKzhdDom58e6ks,2157
|
|
179
179
|
ommlds/minichain/backends/impls/anthropic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
180
|
-
ommlds/minichain/backends/impls/anthropic/chat.py,sha256
|
|
180
|
+
ommlds/minichain/backends/impls/anthropic/chat.py,sha256=-qGr_DZgGe-dr1AKb6WLtCq_I2E9635X1rQZSJqOb04,4318
|
|
181
181
|
ommlds/minichain/backends/impls/anthropic/names.py,sha256=GPPeYt0CcDcDCR8I6BMd7bMjC_Zk_bjnLLpF9ClwXcg,1099
|
|
182
182
|
ommlds/minichain/backends/impls/anthropic/protocol.py,sha256=whPVYuKShKiMCzasHl77sCIiymhzXj8mFZXEyhZvld8,3292
|
|
183
|
-
ommlds/minichain/backends/impls/anthropic/stream.py,sha256=
|
|
183
|
+
ommlds/minichain/backends/impls/anthropic/stream.py,sha256=ePgAz1QyuUcqSLiJTmP2IeW7jZagOMYceWmnvTTHBa8,8779
|
|
184
184
|
ommlds/minichain/backends/impls/duckduckgo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
185
185
|
ommlds/minichain/backends/impls/duckduckgo/search.py,sha256=igzeU9P9b1MMiu4KAJVS9H6KLIoPm68wXi4Kx3_DHyQ,940
|
|
186
186
|
ommlds/minichain/backends/impls/google/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
187
|
-
ommlds/minichain/backends/impls/google/chat.py,sha256=
|
|
187
|
+
ommlds/minichain/backends/impls/google/chat.py,sha256=lGb5blGLlcBlt9xeDZJvbh5SlV7fgfezd5_As_SPBXo,6499
|
|
188
188
|
ommlds/minichain/backends/impls/google/names.py,sha256=HxHJ31HeKZg6aW1C_Anqp-gamCXpq9pOdKj8_yVgE8Y,871
|
|
189
|
-
ommlds/minichain/backends/impls/google/search.py,sha256=
|
|
190
|
-
ommlds/minichain/backends/impls/google/stream.py,sha256=
|
|
189
|
+
ommlds/minichain/backends/impls/google/search.py,sha256=y5_6seSRU8CFnLA_Ja8XEMbIBWSgwBzE1iBf-qyz0tA,3427
|
|
190
|
+
ommlds/minichain/backends/impls/google/stream.py,sha256=lAxPZkFLkeBB8rNvnv5wEvK6aPqAfyAssukMA8QQz7s,8002
|
|
191
191
|
ommlds/minichain/backends/impls/google/tools.py,sha256=Tty0gsyx7-PbeoNqMuql_ewQ6q-ZsDaDdsD5ShinGVY,5089
|
|
192
192
|
ommlds/minichain/backends/impls/huggingface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
193
193
|
ommlds/minichain/backends/impls/huggingface/configs.py,sha256=6jsBtPNXOP57PcpxNTVLGWLc-18Iwn_lDbGouwCJTIQ,258
|
|
@@ -200,14 +200,14 @@ ommlds/minichain/backends/impls/llamacpp/stream.py,sha256=uzrXr2HhshgFe3Z0g8KTPc
|
|
|
200
200
|
ommlds/minichain/backends/impls/mlx/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
201
201
|
ommlds/minichain/backends/impls/mlx/chat.py,sha256=sMlhgiFZrxAC-kKkLSJ6c-2uJn0IHZXH4EiPET_-CKI,7458
|
|
202
202
|
ommlds/minichain/backends/impls/ollama/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
203
|
-
ommlds/minichain/backends/impls/ollama/chat.py,sha256=
|
|
203
|
+
ommlds/minichain/backends/impls/ollama/chat.py,sha256=3fuIAsIW20aEAOLLfM21d5ju27igr6N-3Lf9nNUWcoY,6598
|
|
204
204
|
ommlds/minichain/backends/impls/openai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
205
|
-
ommlds/minichain/backends/impls/openai/chat.py,sha256=
|
|
206
|
-
ommlds/minichain/backends/impls/openai/completion.py,sha256=
|
|
207
|
-
ommlds/minichain/backends/impls/openai/embedding.py,sha256=
|
|
205
|
+
ommlds/minichain/backends/impls/openai/chat.py,sha256=QcQZO78p4UUzI4QU1K-057OEZGKIYxjXENhkifsSuaI,2841
|
|
206
|
+
ommlds/minichain/backends/impls/openai/completion.py,sha256=4Mi4Zvrq5fCqUd0asL3WiCbCdmxOdo0NFkoZMfdsYXY,1939
|
|
207
|
+
ommlds/minichain/backends/impls/openai/embedding.py,sha256=BNtvKYLTsnQwQR9Tv3Fr8zCYN1kr1UNdJ15lcsjz6X0,1765
|
|
208
208
|
ommlds/minichain/backends/impls/openai/format.py,sha256=teGX8mNU3sXNWP4YWGD8d59M4X9_r75ImSzfTJgtNCM,7351
|
|
209
209
|
ommlds/minichain/backends/impls/openai/names.py,sha256=b74t8FwSbGEveVtVz4SqM5tiRDyTKNlUKlseV6AX3Yo,1211
|
|
210
|
-
ommlds/minichain/backends/impls/openai/stream.py,sha256=
|
|
210
|
+
ommlds/minichain/backends/impls/openai/stream.py,sha256=pm-iUNjw5o94LrnrbAWttfbpxStnq0vDvrE7FV9fdsM,5399
|
|
211
211
|
ommlds/minichain/backends/impls/sentencepiece/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
212
212
|
ommlds/minichain/backends/impls/sentencepiece/tokens.py,sha256=tUEBKyBgkTowssS_AdcAuPkyFzfyDfE935x4JG8PXM0,1602
|
|
213
213
|
ommlds/minichain/backends/impls/tinygrad/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -363,7 +363,7 @@ ommlds/server/client.py,sha256=4CeYj43nHwUmuxwD4lkAZjcaPlrWw7MDdenldj377IU,1735
|
|
|
363
363
|
ommlds/server/server.py,sha256=8l6jPEvUMrTd7iLUOGcUUzXWYA7l1ZzI2lkA8XqGOBA,4205
|
|
364
364
|
ommlds/server/service.py,sha256=WleUNyWqcnvZ_CNk6h1WVSTy1_xT9wJg4dduiJilGDY,2282
|
|
365
365
|
ommlds/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
366
|
-
ommlds/tools/git.py,sha256=
|
|
366
|
+
ommlds/tools/git.py,sha256=ILvsOFXbdDQvAHvGCSbd2fY4fswmDRXaB8yVDQymLY0,8205
|
|
367
367
|
ommlds/tools/ocr.py,sha256=UP2XK4-ELyhK2BnuBr7-DwUbkDIcX9xdvfXVimM19Y8,1839
|
|
368
368
|
ommlds/wiki/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
369
369
|
ommlds/wiki/analyze.py,sha256=38SvHF0X_z8OkjvbBc5tLj35e9pvqi53yg9tls-ay5A,9544
|
|
@@ -377,9 +377,9 @@ ommlds/wiki/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
|
|
|
377
377
|
ommlds/wiki/utils/io.py,sha256=UKgDJGtmpnWvIqVd2mJc2QNPOqlToEY1GEveNp6_pMo,7088
|
|
378
378
|
ommlds/wiki/utils/progress.py,sha256=EhvKcMFYtsarCQhIahlO6f0SboyAKP3UwUyrnVnP-Vk,3222
|
|
379
379
|
ommlds/wiki/utils/xml.py,sha256=vVV8Ctn13aaRM9eYfs9Wd6rHn5WOCEUzQ44fIhOvJdg,3754
|
|
380
|
-
ommlds-0.0.0.
|
|
381
|
-
ommlds-0.0.0.
|
|
382
|
-
ommlds-0.0.0.
|
|
383
|
-
ommlds-0.0.0.
|
|
384
|
-
ommlds-0.0.0.
|
|
385
|
-
ommlds-0.0.0.
|
|
380
|
+
ommlds-0.0.0.dev470.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
|
381
|
+
ommlds-0.0.0.dev470.dist-info/METADATA,sha256=hfCH2nU4I_NYHxvuAOZAIClqqcXGrJXIJiGuZ5HBknk,3224
|
|
382
|
+
ommlds-0.0.0.dev470.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
383
|
+
ommlds-0.0.0.dev470.dist-info/entry_points.txt,sha256=Z5YWtX7ClfiCKdW-dd_CSVvM0h4yQpJPi-2G3q6gNFo,35
|
|
384
|
+
ommlds-0.0.0.dev470.dist-info/top_level.txt,sha256=Rbnk5d5wi58vnAXx13WFZqdQ4VX8hBCS2hEL3WeXOhY,7
|
|
385
|
+
ommlds-0.0.0.dev470.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|