ommlds 0.0.0.dev474__py3-none-any.whl → 0.0.0.dev476__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.
- ommlds/.omlish-manifests.json +131 -1
- ommlds/__about__.py +1 -1
- ommlds/backends/groq/_marshal.py +23 -0
- ommlds/backends/groq/protocol.py +184 -0
- ommlds/backends/tinygrad/models/llama3/__init__.py +22 -14
- ommlds/cli/asyncs.py +30 -0
- ommlds/cli/{sessions/chat/backends → backends}/catalog.py +35 -3
- ommlds/cli/backends/configs.py +9 -0
- ommlds/cli/backends/inject.py +31 -36
- ommlds/cli/{sessions/chat/backends → backends}/injection.py +1 -1
- ommlds/cli/{sessions/chat/backends → backends}/types.py +11 -1
- ommlds/cli/{sessions/chat/content → content}/messages.py +1 -1
- ommlds/cli/{sessions/chat/content → content}/strings.py +1 -1
- ommlds/cli/inject.py +7 -6
- ommlds/cli/inputs/asyncs.py +32 -0
- ommlds/cli/inputs/sync.py +75 -0
- ommlds/cli/main.py +266 -124
- ommlds/cli/rendering/__init__.py +0 -0
- ommlds/cli/rendering/configs.py +9 -0
- ommlds/cli/{sessions/chat/rendering → rendering}/inject.py +4 -5
- ommlds/cli/{sessions/chat/rendering → rendering}/markdown.py +1 -1
- ommlds/cli/{sessions/chat/rendering → rendering}/raw.py +1 -1
- ommlds/cli/{sessions/chat/rendering → rendering}/types.py +1 -1
- ommlds/cli/secrets.py +21 -0
- ommlds/cli/sessions/base.py +1 -1
- ommlds/cli/sessions/chat/chat/ai/configs.py +11 -0
- ommlds/cli/sessions/chat/chat/ai/inject.py +7 -11
- ommlds/cli/sessions/chat/chat/ai/rendering.py +4 -4
- ommlds/cli/sessions/chat/chat/ai/services.py +2 -2
- ommlds/cli/sessions/chat/chat/state/configs.py +11 -0
- ommlds/cli/sessions/chat/chat/state/inject.py +6 -10
- ommlds/cli/sessions/chat/chat/state/inmemory.py +1 -2
- ommlds/cli/sessions/chat/chat/state/storage.py +1 -2
- ommlds/cli/sessions/chat/chat/state/types.py +1 -1
- ommlds/cli/sessions/chat/chat/user/configs.py +17 -0
- ommlds/cli/sessions/chat/chat/user/inject.py +16 -15
- ommlds/cli/sessions/chat/chat/user/interactive.py +7 -5
- ommlds/cli/sessions/chat/configs.py +15 -24
- ommlds/cli/sessions/chat/inject.py +18 -34
- ommlds/cli/sessions/chat/session.py +1 -1
- ommlds/cli/sessions/chat/tools/configs.py +13 -0
- ommlds/cli/sessions/chat/tools/inject.py +6 -10
- ommlds/cli/sessions/chat/tools/injection.py +1 -0
- ommlds/cli/sessions/chat/tools/rendering.py +1 -1
- ommlds/cli/sessions/completion/configs.py +2 -2
- ommlds/cli/sessions/completion/inject.py +14 -0
- ommlds/cli/sessions/completion/session.py +7 -11
- ommlds/cli/sessions/embedding/configs.py +2 -2
- ommlds/cli/sessions/embedding/inject.py +14 -0
- ommlds/cli/sessions/embedding/session.py +7 -11
- ommlds/cli/state/storage.py +1 -1
- ommlds/minichain/backends/catalogs/strings.py +1 -1
- ommlds/minichain/backends/impls/dummy/__init__.py +0 -0
- ommlds/minichain/backends/impls/dummy/chat.py +69 -0
- ommlds/minichain/backends/impls/groq/__init__.py +0 -0
- ommlds/minichain/backends/impls/groq/chat.py +69 -0
- ommlds/minichain/backends/impls/groq/names.py +35 -0
- ommlds/minichain/backends/impls/groq/protocol.py +46 -0
- ommlds/minichain/backends/impls/groq/stream.py +121 -0
- ommlds/minichain/backends/impls/openai/chat.py +3 -3
- ommlds/minichain/backends/impls/openai/names.py +27 -3
- ommlds/minichain/backends/impls/openai/stream.py +2 -2
- ommlds/wiki/analyze.py +2 -2
- ommlds/wiki/utils/xml.py +5 -5
- {ommlds-0.0.0.dev474.dist-info → ommlds-0.0.0.dev476.dist-info}/METADATA +5 -5
- {ommlds-0.0.0.dev474.dist-info → ommlds-0.0.0.dev476.dist-info}/RECORD +73 -55
- ommlds/cli/backends/standard.py +0 -20
- ommlds/cli/sessions/chat/backends/inject.py +0 -53
- /ommlds/{cli/sessions/chat/backends → backends/groq}/__init__.py +0 -0
- /ommlds/cli/{sessions/chat/content → content}/__init__.py +0 -0
- /ommlds/cli/{sessions/chat/rendering → inputs}/__init__.py +0 -0
- {ommlds-0.0.0.dev474.dist-info → ommlds-0.0.0.dev476.dist-info}/WHEEL +0 -0
- {ommlds-0.0.0.dev474.dist-info → ommlds-0.0.0.dev476.dist-info}/entry_points.txt +0 -0
- {ommlds-0.0.0.dev474.dist-info → ommlds-0.0.0.dev476.dist-info}/licenses/LICENSE +0 -0
- {ommlds-0.0.0.dev474.dist-info → ommlds-0.0.0.dev476.dist-info}/top_level.txt +0 -0
|
@@ -2,11 +2,15 @@ from omlish import dataclasses as dc
|
|
|
2
2
|
from omlish import inject as inj
|
|
3
3
|
from omlish import lang
|
|
4
4
|
|
|
5
|
+
from ...backends.configs import BackendConfig
|
|
6
|
+
from ...backends.types import DefaultBackendName
|
|
5
7
|
from ..base import Session
|
|
8
|
+
from .configs import DEFAULT_BACKEND
|
|
6
9
|
from .configs import EmbeddingConfig
|
|
7
10
|
|
|
8
11
|
|
|
9
12
|
with lang.auto_proxy_import(globals()):
|
|
13
|
+
from ...backends import inject as _backends
|
|
10
14
|
from . import session as _session
|
|
11
15
|
|
|
12
16
|
|
|
@@ -25,4 +29,14 @@ def bind_embedding(cfg: EmbeddingConfig) -> inj.Elements:
|
|
|
25
29
|
|
|
26
30
|
#
|
|
27
31
|
|
|
32
|
+
els.extend([
|
|
33
|
+
_backends.bind_backends(BackendConfig(
|
|
34
|
+
backend=cfg.backend,
|
|
35
|
+
)),
|
|
36
|
+
|
|
37
|
+
inj.bind(DefaultBackendName, to_const=DEFAULT_BACKEND),
|
|
38
|
+
])
|
|
39
|
+
|
|
40
|
+
#
|
|
41
|
+
|
|
28
42
|
return inj.as_elements(*els)
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import dataclasses as dc
|
|
2
|
-
|
|
3
|
-
from omlish import lang
|
|
1
|
+
from omlish import dataclasses as dc
|
|
4
2
|
from omlish.formats import json
|
|
5
3
|
|
|
6
4
|
from .... import minichain as mc
|
|
5
|
+
from ...backends.types import EmbeddingServiceBackendProvider
|
|
7
6
|
from ..base import Session
|
|
8
|
-
from .configs import DEFAULT_EMBEDDING_MODEL_BACKEND
|
|
9
7
|
from .configs import EmbeddingConfig
|
|
10
8
|
|
|
11
9
|
|
|
@@ -21,17 +19,15 @@ class EmbeddingSession(Session['EmbeddingSession.Config']):
|
|
|
21
19
|
self,
|
|
22
20
|
config: Config,
|
|
23
21
|
*,
|
|
24
|
-
|
|
22
|
+
service_provider: EmbeddingServiceBackendProvider,
|
|
25
23
|
) -> None:
|
|
26
24
|
super().__init__(config)
|
|
27
25
|
|
|
28
|
-
self.
|
|
26
|
+
self._service_provider = service_provider
|
|
29
27
|
|
|
30
28
|
async def run(self) -> None:
|
|
31
29
|
mdl: mc.EmbeddingService
|
|
32
|
-
async with
|
|
33
|
-
mc.EmbeddingService,
|
|
34
|
-
self._config.backend or DEFAULT_EMBEDDING_MODEL_BACKEND,
|
|
35
|
-
)) as mdl:
|
|
30
|
+
async with self._service_provider.provide_backend() as mdl:
|
|
36
31
|
response = await mdl.invoke(mc.EmbeddingRequest(self._config.content))
|
|
37
|
-
|
|
32
|
+
|
|
33
|
+
print(json.dumps_compact(list(map(float, response.v))))
|
ommlds/cli/state/storage.py
CHANGED
|
@@ -39,7 +39,7 @@ class BackendStringBackendCatalog(BackendCatalog):
|
|
|
39
39
|
|
|
40
40
|
al: list = list(rs.args or [])
|
|
41
41
|
|
|
42
|
-
# FIXME: lol
|
|
42
|
+
# FIXME: lol - move *into* local model classes as an injected dep?
|
|
43
43
|
if al and isinstance(al[0], ModelRepo):
|
|
44
44
|
[mr] = al
|
|
45
45
|
mrr = check.not_none(self._model_repo_resolver)
|
|
File without changes
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# ruff: noqa: PERF402
|
|
2
|
+
import typing as ta
|
|
3
|
+
|
|
4
|
+
from omlish.text.lorem import LOREM
|
|
5
|
+
|
|
6
|
+
from ....chat.choices.services import ChatChoicesRequest
|
|
7
|
+
from ....chat.choices.services import ChatChoicesResponse
|
|
8
|
+
from ....chat.choices.services import static_check_is_chat_choices_service
|
|
9
|
+
from ....chat.choices.types import AiChoice
|
|
10
|
+
from ....chat.choices.types import ChatChoicesOutputs
|
|
11
|
+
from ....chat.messages import AiMessage
|
|
12
|
+
from ....chat.stream.services import ChatChoicesStreamRequest
|
|
13
|
+
from ....chat.stream.services import ChatChoicesStreamResponse
|
|
14
|
+
from ....chat.stream.services import static_check_is_chat_choices_stream_service
|
|
15
|
+
from ....chat.stream.types import AiChoiceDeltas
|
|
16
|
+
from ....chat.stream.types import AiChoicesDeltas
|
|
17
|
+
from ....chat.stream.types import ContentAiChoiceDelta
|
|
18
|
+
from ....resources import UseResources
|
|
19
|
+
from ....stream.services import StreamResponseSink
|
|
20
|
+
from ....stream.services import new_stream_response
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# @omlish-manifest $.minichain.registries.manifests.RegistryManifest(
|
|
27
|
+
# name='dummy',
|
|
28
|
+
# type='ChatChoicesService',
|
|
29
|
+
# )
|
|
30
|
+
@static_check_is_chat_choices_service
|
|
31
|
+
class DummyChatChoicesService:
|
|
32
|
+
async def invoke(self, request: ChatChoicesRequest) -> ChatChoicesResponse:
|
|
33
|
+
return ChatChoicesResponse([AiChoice([AiMessage(LOREM)])])
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
##
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# @omlish-manifest $.minichain.registries.manifests.RegistryManifest(
|
|
40
|
+
# name='dummy',
|
|
41
|
+
# type='ChatChoicesStreamService',
|
|
42
|
+
# )
|
|
43
|
+
@static_check_is_chat_choices_stream_service
|
|
44
|
+
class DummyChatChoicesStreamService:
|
|
45
|
+
async def invoke(self, request: ChatChoicesStreamRequest) -> ChatChoicesStreamResponse:
|
|
46
|
+
async with UseResources.or_new(request.options) as rs:
|
|
47
|
+
async def inner(sink: StreamResponseSink[AiChoicesDeltas]) -> ta.Sequence[ChatChoicesOutputs]:
|
|
48
|
+
for s in LOREM:
|
|
49
|
+
await sink.emit(AiChoicesDeltas([
|
|
50
|
+
AiChoiceDeltas([
|
|
51
|
+
ContentAiChoiceDelta(s),
|
|
52
|
+
]),
|
|
53
|
+
]))
|
|
54
|
+
|
|
55
|
+
return []
|
|
56
|
+
|
|
57
|
+
return await new_stream_response(rs, inner)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
##
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# @omlish-manifest $.minichain.backends.strings.manifests.BackendStringsManifest(
|
|
64
|
+
# [
|
|
65
|
+
# 'ChatChoicesService',
|
|
66
|
+
# 'ChatChoicesStreamService',
|
|
67
|
+
# ],
|
|
68
|
+
# 'dummy',
|
|
69
|
+
# )
|
|
File without changes
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from omlish import check
|
|
4
|
+
from omlish import marshal as msh
|
|
5
|
+
from omlish import typedvalues as tv
|
|
6
|
+
from omlish.formats import json
|
|
7
|
+
from omlish.http import all as http
|
|
8
|
+
|
|
9
|
+
from .....backends.groq import protocol as pt
|
|
10
|
+
from ....chat.choices.services import ChatChoicesRequest
|
|
11
|
+
from ....chat.choices.services import ChatChoicesResponse
|
|
12
|
+
from ....chat.choices.services import static_check_is_chat_choices_service
|
|
13
|
+
from ....models.configs import ModelName
|
|
14
|
+
from ....standard import ApiKey
|
|
15
|
+
from ....standard import DefaultOptions
|
|
16
|
+
from .names import MODEL_NAMES
|
|
17
|
+
from .protocol import build_gq_request_message
|
|
18
|
+
from .protocol import build_mc_choices_response
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# @omlish-manifest $.minichain.registries.manifests.RegistryManifest(
|
|
25
|
+
# name='groq',
|
|
26
|
+
# type='ChatChoicesService',
|
|
27
|
+
# )
|
|
28
|
+
@static_check_is_chat_choices_service
|
|
29
|
+
class GroqChatChoicesService:
|
|
30
|
+
DEFAULT_MODEL_NAME: ta.ClassVar[ModelName] = ModelName(check.not_none(MODEL_NAMES.default))
|
|
31
|
+
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
*configs: ApiKey | ModelName | DefaultOptions,
|
|
35
|
+
http_client: http.AsyncHttpClient | None = None,
|
|
36
|
+
) -> None:
|
|
37
|
+
super().__init__()
|
|
38
|
+
|
|
39
|
+
self._http_client = http_client
|
|
40
|
+
|
|
41
|
+
with tv.consume(*configs) as cc:
|
|
42
|
+
self._model_name = cc.pop(self.DEFAULT_MODEL_NAME)
|
|
43
|
+
self._api_key = ApiKey.pop_secret(cc, env='GROQ_API_KEY')
|
|
44
|
+
self._default_options: tv.TypedValues = DefaultOptions.pop(cc)
|
|
45
|
+
|
|
46
|
+
async def invoke(self, request: ChatChoicesRequest) -> ChatChoicesResponse:
|
|
47
|
+
gq_request = pt.ChatCompletionRequest(
|
|
48
|
+
messages=[
|
|
49
|
+
build_gq_request_message(m)
|
|
50
|
+
for m in request.v
|
|
51
|
+
],
|
|
52
|
+
model=MODEL_NAMES.resolve(self._model_name.v),
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
raw_request = msh.marshal(gq_request)
|
|
56
|
+
|
|
57
|
+
http_response = await http.async_request(
|
|
58
|
+
'https://api.groq.com/openai/v1/chat/completions',
|
|
59
|
+
headers={
|
|
60
|
+
http.consts.HEADER_CONTENT_TYPE: http.consts.CONTENT_TYPE_JSON,
|
|
61
|
+
http.consts.HEADER_AUTH: http.consts.format_bearer_auth_header(check.not_none(self._api_key).reveal()),
|
|
62
|
+
},
|
|
63
|
+
data=json.dumps(raw_request).encode('utf-8'),
|
|
64
|
+
client=self._http_client,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
raw_response = json.loads(check.not_none(http_response.data).decode('utf-8'))
|
|
68
|
+
|
|
69
|
+
return build_mc_choices_response(msh.unmarshal(raw_response, pt.ChatCompletionResponse))
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""
|
|
2
|
+
https://console.groq.com/docs/models
|
|
3
|
+
|
|
4
|
+
curl -X GET "https://api.groq.com/openai/v1/models" \
|
|
5
|
+
-H "Authorization: Bearer $GROQ_API_KEY" \
|
|
6
|
+
-H "Content-Type: application/json"
|
|
7
|
+
"""
|
|
8
|
+
from ....models.names import ModelNameCollection
|
|
9
|
+
from ...strings.manifests import BackendStringsManifest
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
MODEL_NAMES = ModelNameCollection(
|
|
16
|
+
default='gpt-oss-120b',
|
|
17
|
+
aliases={
|
|
18
|
+
'gpt-oss-120b': 'openai/gpt-oss-120b',
|
|
19
|
+
'openai/gpt-oss-120b': None,
|
|
20
|
+
|
|
21
|
+
'gpt-oss-20b': 'openai/gpt-oss-20b',
|
|
22
|
+
'openai/gpt-oss-20b': None,
|
|
23
|
+
},
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# @omlish-manifest
|
|
28
|
+
_BACKEND_STRINGS_MANIFEST = BackendStringsManifest(
|
|
29
|
+
[
|
|
30
|
+
'ChatChoicesService',
|
|
31
|
+
'ChatChoicesStreamService',
|
|
32
|
+
],
|
|
33
|
+
'groq',
|
|
34
|
+
model_names=MODEL_NAMES,
|
|
35
|
+
)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from omlish import check
|
|
2
|
+
|
|
3
|
+
from .....backends.groq import protocol as pt
|
|
4
|
+
from ....chat.choices.services import ChatChoicesResponse
|
|
5
|
+
from ....chat.choices.types import AiChoice
|
|
6
|
+
from ....chat.messages import AiMessage
|
|
7
|
+
from ....chat.messages import Message
|
|
8
|
+
from ....chat.messages import SystemMessage
|
|
9
|
+
from ....chat.messages import UserMessage
|
|
10
|
+
from ....chat.stream.types import AiChoiceDeltas
|
|
11
|
+
from ....chat.stream.types import ContentAiChoiceDelta
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
##
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def build_gq_request_message(mc_msg: Message) -> pt.ChatCompletionRequest.Message:
|
|
18
|
+
if isinstance(mc_msg, SystemMessage):
|
|
19
|
+
return pt.ChatCompletionRequest.SystemMessage(
|
|
20
|
+
content=check.isinstance(mc_msg.c, str),
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
elif isinstance(mc_msg, UserMessage):
|
|
24
|
+
return pt.ChatCompletionRequest.UserMessage(
|
|
25
|
+
content=check.isinstance(mc_msg.c, str),
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
else:
|
|
29
|
+
raise TypeError(mc_msg)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def build_mc_choices_response(gq_resp: pt.ChatCompletionResponse) -> ChatChoicesResponse:
|
|
33
|
+
return ChatChoicesResponse([
|
|
34
|
+
AiChoice([AiMessage(
|
|
35
|
+
check.isinstance(gq_choice.message.content, str),
|
|
36
|
+
)])
|
|
37
|
+
for gq_choice in gq_resp.choices
|
|
38
|
+
])
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def build_mc_ai_choice_deltas(delta: pt.ChatCompletionChunk.Choice.Delta) -> AiChoiceDeltas:
|
|
42
|
+
if delta.role in (None, 'assistant') and delta.content is not None:
|
|
43
|
+
return AiChoiceDeltas([ContentAiChoiceDelta(delta.content)])
|
|
44
|
+
|
|
45
|
+
else:
|
|
46
|
+
return AiChoiceDeltas([])
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from omlish import check
|
|
4
|
+
from omlish import marshal as msh
|
|
5
|
+
from omlish import typedvalues as tv
|
|
6
|
+
from omlish.formats import json
|
|
7
|
+
from omlish.http import all as http
|
|
8
|
+
from omlish.http import sse
|
|
9
|
+
from omlish.io.buffers import DelimitingBuffer
|
|
10
|
+
|
|
11
|
+
from .....backends.groq import protocol as pt
|
|
12
|
+
from ....chat.choices.services import ChatChoicesOutputs
|
|
13
|
+
from ....chat.stream.services import ChatChoicesStreamRequest
|
|
14
|
+
from ....chat.stream.services import ChatChoicesStreamResponse
|
|
15
|
+
from ....chat.stream.services import static_check_is_chat_choices_stream_service
|
|
16
|
+
from ....chat.stream.types import AiChoicesDeltas
|
|
17
|
+
from ....configs import Config
|
|
18
|
+
from ....resources import UseResources
|
|
19
|
+
from ....standard import ApiKey
|
|
20
|
+
from ....stream.services import StreamResponseSink
|
|
21
|
+
from ....stream.services import new_stream_response
|
|
22
|
+
from .chat import GroqChatChoicesService
|
|
23
|
+
from .names import MODEL_NAMES
|
|
24
|
+
from .protocol import build_gq_request_message
|
|
25
|
+
from .protocol import build_mc_ai_choice_deltas
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# @omlish-manifest $.minichain.registries.manifests.RegistryManifest(
|
|
32
|
+
# name='groq',
|
|
33
|
+
# type='ChatChoicesStreamService',
|
|
34
|
+
# )
|
|
35
|
+
@static_check_is_chat_choices_stream_service
|
|
36
|
+
class GroqChatChoicesStreamService:
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
*configs: Config,
|
|
40
|
+
http_client: http.AsyncHttpClient | None = None,
|
|
41
|
+
) -> None:
|
|
42
|
+
super().__init__()
|
|
43
|
+
|
|
44
|
+
self._http_client = http_client
|
|
45
|
+
|
|
46
|
+
with tv.consume(*configs) as cc:
|
|
47
|
+
self._model_name = cc.pop(GroqChatChoicesService.DEFAULT_MODEL_NAME)
|
|
48
|
+
self._api_key = ApiKey.pop_secret(cc, env='GROQ_API_KEY')
|
|
49
|
+
|
|
50
|
+
READ_CHUNK_SIZE: ta.ClassVar[int] = -1
|
|
51
|
+
|
|
52
|
+
async def invoke(self, request: ChatChoicesStreamRequest) -> ChatChoicesStreamResponse:
|
|
53
|
+
# check.isinstance(request, ChatRequest)
|
|
54
|
+
|
|
55
|
+
gq_request = pt.ChatCompletionRequest(
|
|
56
|
+
messages=[
|
|
57
|
+
build_gq_request_message(m)
|
|
58
|
+
for m in request.v
|
|
59
|
+
],
|
|
60
|
+
model=MODEL_NAMES.resolve(self._model_name.v),
|
|
61
|
+
stream=True,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
raw_request = msh.marshal(gq_request)
|
|
65
|
+
|
|
66
|
+
http_request = http.HttpRequest(
|
|
67
|
+
'https://api.groq.com/openai/v1/chat/completions',
|
|
68
|
+
headers={
|
|
69
|
+
http.consts.HEADER_CONTENT_TYPE: http.consts.CONTENT_TYPE_JSON,
|
|
70
|
+
http.consts.HEADER_AUTH: http.consts.format_bearer_auth_header(check.not_none(self._api_key).reveal()),
|
|
71
|
+
},
|
|
72
|
+
data=json.dumps(raw_request).encode('utf-8'),
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
async with UseResources.or_new(request.options) as rs:
|
|
76
|
+
http_client = await rs.enter_async_context(http.manage_async_client(self._http_client))
|
|
77
|
+
http_response = await rs.enter_async_context(await http_client.stream_request(http_request))
|
|
78
|
+
|
|
79
|
+
async def inner(sink: StreamResponseSink[AiChoicesDeltas]) -> ta.Sequence[ChatChoicesOutputs]:
|
|
80
|
+
db = DelimitingBuffer([b'\r', b'\n', b'\r\n'])
|
|
81
|
+
sd = sse.SseDecoder()
|
|
82
|
+
while True:
|
|
83
|
+
b = await http_response.stream.read1(self.READ_CHUNK_SIZE)
|
|
84
|
+
for l in db.feed(b):
|
|
85
|
+
if isinstance(l, DelimitingBuffer.Incomplete):
|
|
86
|
+
# FIXME: handle
|
|
87
|
+
return []
|
|
88
|
+
|
|
89
|
+
# FIXME: https://platform.openai.com/docs/guides/function-calling?api-mode=responses#streaming
|
|
90
|
+
for so in sd.process_line(l):
|
|
91
|
+
if isinstance(so, sse.SseEvent) and so.type == b'message':
|
|
92
|
+
ss = so.data.decode('utf-8')
|
|
93
|
+
if ss == '[DONE]':
|
|
94
|
+
return []
|
|
95
|
+
|
|
96
|
+
sj = json.loads(ss) # ChatCompletionChunk
|
|
97
|
+
|
|
98
|
+
check.state(sj['object'] == 'chat.completion.chunk')
|
|
99
|
+
|
|
100
|
+
ccc = msh.unmarshal(sj, pt.ChatCompletionChunk)
|
|
101
|
+
|
|
102
|
+
# FIXME: stop reason
|
|
103
|
+
if not ccc.choices:
|
|
104
|
+
continue
|
|
105
|
+
|
|
106
|
+
if any(choice.finish_reason for choice in ccc.choices):
|
|
107
|
+
check.state(all(choice.finish_reason for choice in ccc.choices))
|
|
108
|
+
break
|
|
109
|
+
|
|
110
|
+
await sink.emit(AiChoicesDeltas([
|
|
111
|
+
build_mc_ai_choice_deltas(choice.delta)
|
|
112
|
+
for choice in ccc.choices
|
|
113
|
+
]))
|
|
114
|
+
|
|
115
|
+
if not b:
|
|
116
|
+
return []
|
|
117
|
+
|
|
118
|
+
# raw_response = json.loads(check.not_none(http_response.data).decode('utf-8'))
|
|
119
|
+
# return rh.build_response(raw_response)
|
|
120
|
+
|
|
121
|
+
return await new_stream_response(rs, inner)
|
|
@@ -28,7 +28,7 @@ from ....standard import ApiKey
|
|
|
28
28
|
from ....standard import DefaultOptions
|
|
29
29
|
from .format import OpenaiChatRequestHandler
|
|
30
30
|
from .format import build_mc_choices_response
|
|
31
|
-
from .names import
|
|
31
|
+
from .names import CHAT_MODEL_NAMES
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
##
|
|
@@ -40,7 +40,7 @@ from .names import MODEL_NAMES
|
|
|
40
40
|
# )
|
|
41
41
|
@static_check_is_chat_choices_service
|
|
42
42
|
class OpenaiChatChoicesService:
|
|
43
|
-
DEFAULT_MODEL_NAME: ta.ClassVar[ModelName] = ModelName(check.not_none(
|
|
43
|
+
DEFAULT_MODEL_NAME: ta.ClassVar[ModelName] = ModelName(check.not_none(CHAT_MODEL_NAMES.default))
|
|
44
44
|
|
|
45
45
|
def __init__(
|
|
46
46
|
self,
|
|
@@ -66,7 +66,7 @@ class OpenaiChatChoicesService:
|
|
|
66
66
|
*request.options,
|
|
67
67
|
override=True,
|
|
68
68
|
),
|
|
69
|
-
model=
|
|
69
|
+
model=CHAT_MODEL_NAMES.resolve(self._model_name.v),
|
|
70
70
|
mandatory_kwargs=dict(
|
|
71
71
|
stream=False,
|
|
72
72
|
),
|
|
@@ -33,7 +33,7 @@ _GPT_MODEL_NAMES = [
|
|
|
33
33
|
]
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
CHAT_MODEL_NAMES = ModelNameCollection(
|
|
37
37
|
default='gpt',
|
|
38
38
|
aliases={
|
|
39
39
|
**{
|
|
@@ -61,11 +61,35 @@ MODEL_NAMES = ModelNameCollection(
|
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
# @omlish-manifest
|
|
64
|
-
|
|
64
|
+
_CHAT_BACKEND_STRINGS_MANIFEST = BackendStringsManifest(
|
|
65
65
|
[
|
|
66
66
|
'ChatChoicesService',
|
|
67
67
|
'ChatChoicesStreamService',
|
|
68
68
|
],
|
|
69
69
|
'openai',
|
|
70
|
-
model_names=
|
|
70
|
+
model_names=CHAT_MODEL_NAMES,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
##
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# @omlish-manifest
|
|
78
|
+
_COMPLETION_BACKEND_STRINGS_MANIFEST = BackendStringsManifest(
|
|
79
|
+
[
|
|
80
|
+
'CompletionService',
|
|
81
|
+
],
|
|
82
|
+
'openai',
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
##
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# @omlish-manifest
|
|
90
|
+
_EMBEDDING_BACKEND_STRINGS_MANIFEST = BackendStringsManifest(
|
|
91
|
+
[
|
|
92
|
+
'EmbeddingService',
|
|
93
|
+
],
|
|
94
|
+
'openai',
|
|
71
95
|
)
|
|
@@ -29,7 +29,7 @@ from ....stream.services import new_stream_response
|
|
|
29
29
|
from .chat import OpenaiChatChoicesService
|
|
30
30
|
from .format import OpenaiChatRequestHandler
|
|
31
31
|
from .format import build_mc_ai_choice_delta
|
|
32
|
-
from .names import
|
|
32
|
+
from .names import CHAT_MODEL_NAMES
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
##
|
|
@@ -66,7 +66,7 @@ class OpenaiChatChoicesStreamService:
|
|
|
66
66
|
for o in request.options
|
|
67
67
|
if not isinstance(o, (ChatChoicesStreamOption, StreamOption, ResourcesOption))
|
|
68
68
|
],
|
|
69
|
-
model=
|
|
69
|
+
model=CHAT_MODEL_NAMES.resolve(self._model_name.v),
|
|
70
70
|
mandatory_kwargs=dict(
|
|
71
71
|
stream=True,
|
|
72
72
|
stream_options=pt.ChatCompletionRequest.StreamOptions(
|
ommlds/wiki/analyze.py
CHANGED
|
@@ -213,7 +213,7 @@ class FileAnalyzer:
|
|
|
213
213
|
self.verbose and print()
|
|
214
214
|
return True
|
|
215
215
|
|
|
216
|
-
@logs.
|
|
216
|
+
@logs.exception_logging(log)
|
|
217
217
|
def run(self, file_name: str) -> None:
|
|
218
218
|
log.info(f'{self._ctx.deathpact=} {file_name}') # noqa
|
|
219
219
|
|
|
@@ -268,7 +268,7 @@ class FileAnalyzer:
|
|
|
268
268
|
self._flush_rows()
|
|
269
269
|
|
|
270
270
|
|
|
271
|
-
@logs.
|
|
271
|
+
@logs.exception_logging(log)
|
|
272
272
|
def analyze_file(
|
|
273
273
|
file_name: str,
|
|
274
274
|
db_url: str,
|
ommlds/wiki/utils/xml.py
CHANGED
|
@@ -24,7 +24,7 @@ else:
|
|
|
24
24
|
|
|
25
25
|
T = ta.TypeVar('T')
|
|
26
26
|
|
|
27
|
-
Element: ta.TypeAlias = ta.Union[ET.Element, 'lxml_etree.Element']
|
|
27
|
+
Element: ta.TypeAlias = ta.Union[ET.Element, 'lxml_etree.Element'] # type: ignore[valid-type]
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
##
|
|
@@ -83,8 +83,8 @@ class ElementToKwargs:
|
|
|
83
83
|
raise KeyError(k)
|
|
84
84
|
kw[k] = v
|
|
85
85
|
|
|
86
|
-
if el.attrib:
|
|
87
|
-
for k, v in el.attrib.items():
|
|
86
|
+
if el.attrib: # type: ignore
|
|
87
|
+
for k, v in el.attrib.items(): # type: ignore
|
|
88
88
|
k = strip_ns(k)
|
|
89
89
|
|
|
90
90
|
if k in self.attrs:
|
|
@@ -99,7 +99,7 @@ class ElementToKwargs:
|
|
|
99
99
|
else:
|
|
100
100
|
raise KeyError(k)
|
|
101
101
|
|
|
102
|
-
for cel in el:
|
|
102
|
+
for cel in el: # type: ignore
|
|
103
103
|
k = strip_ns(cel.tag)
|
|
104
104
|
|
|
105
105
|
if k in self.scalars:
|
|
@@ -123,7 +123,7 @@ class ElementToKwargs:
|
|
|
123
123
|
raise KeyError(k)
|
|
124
124
|
|
|
125
125
|
if self.text is not None:
|
|
126
|
-
set_kw(self.text, el.text)
|
|
126
|
+
set_kw(self.text, el.text) # type: ignore
|
|
127
127
|
|
|
128
128
|
return kw
|
|
129
129
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ommlds
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev476
|
|
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.dev476
|
|
18
|
+
Requires-Dist: omlish==0.0.0.dev476
|
|
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"
|
|
@@ -33,7 +33,7 @@ Requires-Dist: numpy>=1.26; extra == "all"
|
|
|
33
33
|
Requires-Dist: pytesseract~=0.3; extra == "all"
|
|
34
34
|
Requires-Dist: rapidocr-onnxruntime~=1.4; extra == "all"
|
|
35
35
|
Requires-Dist: pillow~=12.0; extra == "all"
|
|
36
|
-
Requires-Dist: ddgs~=9.
|
|
36
|
+
Requires-Dist: ddgs~=9.9; extra == "all"
|
|
37
37
|
Requires-Dist: mwparserfromhell~=0.7; extra == "all"
|
|
38
38
|
Requires-Dist: wikitextparser~=0.56; extra == "all"
|
|
39
39
|
Requires-Dist: lxml>=5.3; python_version < "3.13" and extra == "all"
|
|
@@ -60,7 +60,7 @@ Requires-Dist: rapidocr-onnxruntime~=1.4; extra == "ocr"
|
|
|
60
60
|
Provides-Extra: pillow
|
|
61
61
|
Requires-Dist: pillow~=12.0; extra == "pillow"
|
|
62
62
|
Provides-Extra: search
|
|
63
|
-
Requires-Dist: ddgs~=9.
|
|
63
|
+
Requires-Dist: ddgs~=9.9; extra == "search"
|
|
64
64
|
Provides-Extra: wiki
|
|
65
65
|
Requires-Dist: mwparserfromhell~=0.7; extra == "wiki"
|
|
66
66
|
Requires-Dist: wikitextparser~=0.56; extra == "wiki"
|