ommlds 0.0.0.dev475__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.
Files changed (71) hide show
  1. ommlds/.omlish-manifests.json +85 -1
  2. ommlds/__about__.py +1 -1
  3. ommlds/backends/groq/_marshal.py +23 -0
  4. ommlds/backends/groq/protocol.py +184 -0
  5. ommlds/cli/{sessions/chat/backends → backends}/catalog.py +35 -3
  6. ommlds/cli/backends/configs.py +9 -0
  7. ommlds/cli/backends/inject.py +31 -36
  8. ommlds/cli/{sessions/chat/backends → backends}/injection.py +1 -1
  9. ommlds/cli/{sessions/chat/backends → backends}/types.py +11 -1
  10. ommlds/cli/{sessions/chat/content → content}/messages.py +1 -1
  11. ommlds/cli/{sessions/chat/content → content}/strings.py +1 -1
  12. ommlds/cli/inject.py +0 -6
  13. ommlds/cli/inputs/asyncs.py +32 -0
  14. ommlds/cli/{sessions/chat/chat/user/inputs.py → inputs/sync.py} +0 -30
  15. ommlds/cli/main.py +267 -113
  16. ommlds/cli/rendering/__init__.py +0 -0
  17. ommlds/cli/rendering/configs.py +9 -0
  18. ommlds/cli/{sessions/chat/rendering → rendering}/inject.py +4 -5
  19. ommlds/cli/{sessions/chat/rendering → rendering}/markdown.py +1 -1
  20. ommlds/cli/{sessions/chat/rendering → rendering}/raw.py +1 -1
  21. ommlds/cli/{sessions/chat/rendering → rendering}/types.py +1 -1
  22. ommlds/cli/secrets.py +21 -0
  23. ommlds/cli/sessions/base.py +1 -1
  24. ommlds/cli/sessions/chat/chat/ai/configs.py +11 -0
  25. ommlds/cli/sessions/chat/chat/ai/inject.py +7 -11
  26. ommlds/cli/sessions/chat/chat/ai/rendering.py +4 -4
  27. ommlds/cli/sessions/chat/chat/ai/services.py +2 -2
  28. ommlds/cli/sessions/chat/chat/state/configs.py +11 -0
  29. ommlds/cli/sessions/chat/chat/state/inject.py +6 -10
  30. ommlds/cli/sessions/chat/chat/state/inmemory.py +1 -2
  31. ommlds/cli/sessions/chat/chat/state/storage.py +1 -2
  32. ommlds/cli/sessions/chat/chat/state/types.py +1 -1
  33. ommlds/cli/sessions/chat/chat/user/configs.py +17 -0
  34. ommlds/cli/sessions/chat/chat/user/inject.py +13 -19
  35. ommlds/cli/sessions/chat/chat/user/interactive.py +3 -3
  36. ommlds/cli/sessions/chat/configs.py +15 -26
  37. ommlds/cli/sessions/chat/inject.py +18 -35
  38. ommlds/cli/sessions/chat/session.py +1 -1
  39. ommlds/cli/sessions/chat/tools/configs.py +13 -0
  40. ommlds/cli/sessions/chat/tools/inject.py +6 -10
  41. ommlds/cli/sessions/chat/tools/injection.py +1 -0
  42. ommlds/cli/sessions/chat/tools/rendering.py +1 -1
  43. ommlds/cli/sessions/completion/configs.py +2 -2
  44. ommlds/cli/sessions/completion/inject.py +14 -0
  45. ommlds/cli/sessions/completion/session.py +7 -11
  46. ommlds/cli/sessions/embedding/configs.py +2 -2
  47. ommlds/cli/sessions/embedding/inject.py +14 -0
  48. ommlds/cli/sessions/embedding/session.py +7 -11
  49. ommlds/cli/state/storage.py +1 -1
  50. ommlds/minichain/backends/catalogs/strings.py +1 -1
  51. ommlds/minichain/backends/impls/groq/__init__.py +0 -0
  52. ommlds/minichain/backends/impls/groq/chat.py +69 -0
  53. ommlds/minichain/backends/impls/groq/names.py +35 -0
  54. ommlds/minichain/backends/impls/groq/protocol.py +46 -0
  55. ommlds/minichain/backends/impls/groq/stream.py +121 -0
  56. ommlds/minichain/backends/impls/openai/chat.py +3 -3
  57. ommlds/minichain/backends/impls/openai/names.py +27 -3
  58. ommlds/minichain/backends/impls/openai/stream.py +2 -2
  59. ommlds/wiki/utils/xml.py +5 -5
  60. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev476.dist-info}/METADATA +5 -5
  61. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev476.dist-info}/RECORD +68 -55
  62. ommlds/cli/backends/standard.py +0 -20
  63. ommlds/cli/main2.py +0 -220
  64. ommlds/cli/sessions/chat/backends/inject.py +0 -53
  65. /ommlds/{cli/sessions/chat/backends → backends/groq}/__init__.py +0 -0
  66. /ommlds/cli/{sessions/chat/content → content}/__init__.py +0 -0
  67. /ommlds/cli/{sessions/chat/rendering → inputs}/__init__.py +0 -0
  68. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev476.dist-info}/WHEEL +0 -0
  69. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev476.dist-info}/entry_points.txt +0 -0
  70. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev476.dist-info}/licenses/LICENSE +0 -0
  71. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev476.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,10 @@
1
- import typing as ta
2
-
3
1
  from omlish import inject as inj
4
2
  from omlish import lang
5
3
 
6
4
  from ...phases.injection import phase_callbacks
7
5
  from ...phases.types import ChatPhase
8
6
  from ...phases.types import ChatPhaseCallback
7
+ from .configs import StateConfig
9
8
 
10
9
 
11
10
  with lang.auto_proxy_import(globals()):
@@ -17,24 +16,21 @@ with lang.auto_proxy_import(globals()):
17
16
  ##
18
17
 
19
18
 
20
- def bind_state(
21
- *,
22
- state: ta.Literal['new', 'continue', 'ephemeral'] = 'continue',
23
- ) -> inj.Elements:
19
+ def bind_state(cfg: StateConfig = StateConfig()) -> inj.Elements:
24
20
  els: list[inj.Elemental] = []
25
21
 
26
- if state in ('continue', 'new'):
22
+ if cfg.state in ('continue', 'new'):
27
23
  els.append(inj.bind(_types.ChatStateManager, to_ctor=_storage.StateStorageChatStateManager, singleton=True))
28
24
 
29
- if state == 'new':
25
+ if cfg.state == 'new':
30
26
  els.append(phase_callbacks().bind_item(to_fn=lang.typed_lambda(cm=_types.ChatStateManager)(
31
27
  lambda cm: ChatPhaseCallback(ChatPhase.STARTING, cm.clear_state),
32
28
  )))
33
29
 
34
- elif state == 'ephemeral':
30
+ elif cfg.state == 'ephemeral':
35
31
  els.append(inj.bind(_types.ChatStateManager, to_ctor=_inmemory.InMemoryChatStateManager, singleton=True))
36
32
 
37
33
  else:
38
- raise TypeError(state)
34
+ raise TypeError(cfg.state)
39
35
 
40
36
  return inj.as_elements(*els)
@@ -1,5 +1,4 @@
1
- import dataclasses as dc
2
-
1
+ from omlish import dataclasses as dc
3
2
  from omlish import lang
4
3
 
5
4
  from ...... import minichain as mc
@@ -1,6 +1,5 @@
1
- import dataclasses as dc
2
-
3
1
  from omlish import check
2
+ from omlish import dataclasses as dc
4
3
  from omlish import lang
5
4
 
6
5
  from ...... import minichain as mc
@@ -1,8 +1,8 @@
1
1
  import abc
2
- import dataclasses as dc
3
2
  import datetime
4
3
  import typing as ta
5
4
 
5
+ from omlish import dataclasses as dc
6
6
  from omlish import lang
7
7
 
8
8
  from ...... import minichain as mc
@@ -0,0 +1,17 @@
1
+ import typing as ta
2
+
3
+ from omlish import dataclasses as dc
4
+
5
+ from ...... import minichain as mc
6
+
7
+
8
+ ##
9
+
10
+
11
+ @dc.dataclass(frozen=True, kw_only=True)
12
+ class UserConfig:
13
+ initial_system_content: ta.Optional['mc.Content'] = None
14
+ initial_user_content: ta.Optional['mc.Content'] = None
15
+
16
+ interactive: bool = False
17
+ use_readline: bool | ta.Literal['auto'] = 'auto'
@@ -1,5 +1,3 @@
1
- import typing as ta
2
-
3
1
  from omlish import inject as inj
4
2
  from omlish import lang
5
3
 
@@ -7,11 +5,13 @@ from ...... import minichain as mc
7
5
  from ...phases.injection import phase_callbacks
8
6
  from ...phases.types import ChatPhase
9
7
  from ...phases.types import ChatPhaseCallback
8
+ from .configs import UserConfig
10
9
 
11
10
 
12
11
  with lang.auto_proxy_import(globals()):
12
+ from .....inputs import asyncs as _inputs_asyncs
13
+ from .....inputs import sync as _inputs_sync
13
14
  from ..state import types as _state
14
- from . import inputs as _inputs
15
15
  from . import interactive as _interactive
16
16
  from . import oneshot as _oneshot
17
17
  from . import types as _types
@@ -20,28 +20,22 @@ with lang.auto_proxy_import(globals()):
20
20
  ##
21
21
 
22
22
 
23
- def bind_user(
24
- *,
25
- initial_system_content: ta.Optional['mc.Content'] = None,
26
- initial_user_content: ta.Optional['mc.Content'] = None,
27
- interactive: bool = False,
28
- use_readline: bool | ta.Literal['auto'] = False,
29
- ) -> inj.Elements:
23
+ def bind_user(cfg: UserConfig = UserConfig()) -> inj.Elements:
30
24
  els: list[inj.Elemental] = []
31
25
 
32
26
  # FIXME: barf
33
- if initial_system_content is not None:
27
+ if cfg.initial_system_content is not None:
34
28
  async def add_initial_system_content(cm: '_state.ChatStateManager') -> None:
35
- await cm.extend_chat([mc.SystemMessage(initial_system_content)])
29
+ await cm.extend_chat([mc.SystemMessage(cfg.initial_system_content)])
36
30
 
37
31
  els.append(phase_callbacks().bind_item(to_fn=lang.typed_lambda(cm=_state.ChatStateManager)(
38
32
  lambda cm: ChatPhaseCallback(ChatPhase.STARTED, lambda: add_initial_system_content(cm)),
39
33
  )))
40
34
 
41
- if interactive:
42
- if initial_user_content is not None:
35
+ if cfg.interactive:
36
+ if cfg.initial_user_content is not None:
43
37
  async def add_initial_user_content(cm: '_state.ChatStateManager') -> None:
44
- await cm.extend_chat([mc.UserMessage(initial_user_content)])
38
+ await cm.extend_chat([mc.UserMessage(cfg.initial_user_content)])
45
39
 
46
40
  els.append(phase_callbacks().bind_item(to_fn=lang.typed_lambda(cm=_state.ChatStateManager)(
47
41
  lambda cm: ChatPhaseCallback(ChatPhase.STARTED, lambda: add_initial_user_content(cm)),
@@ -52,16 +46,16 @@ def bind_user(
52
46
  els.append(inj.bind(_types.UserChatInput, to_ctor=_interactive.InteractiveUserChatInput, singleton=True))
53
47
 
54
48
  els.extend([
55
- inj.bind(_inputs.SyncStringInput, to_const=_inputs.InputSyncStringInput(use_readline=use_readline)), # noqa
56
- inj.bind(_inputs.AsyncStringInput, to_ctor=_inputs.ThreadAsyncStringInput, singleton=True),
49
+ inj.bind(_inputs_sync.SyncStringInput, to_const=_inputs_sync.InputSyncStringInput(use_readline=cfg.use_readline)), # noqa
50
+ inj.bind(_inputs_asyncs.AsyncStringInput, to_ctor=_inputs_asyncs.ThreadAsyncStringInput, singleton=True),
57
51
  ])
58
52
 
59
53
  else:
60
- if initial_user_content is None:
54
+ if cfg.initial_user_content is None:
61
55
  raise ValueError('Initial user content is required for non-interactive chat')
62
56
 
63
57
  els.extend([
64
- inj.bind(_oneshot.OneshotUserChatInputInitialChat, to_const=[mc.UserMessage(initial_user_content)]),
58
+ inj.bind(_oneshot.OneshotUserChatInputInitialChat, to_const=[mc.UserMessage(cfg.initial_user_content)]),
65
59
  inj.bind(_types.UserChatInput, to_ctor=_oneshot.OneshotUserChatInput, singleton=True),
66
60
  ])
67
61
 
@@ -1,9 +1,9 @@
1
1
  import typing as ta
2
2
 
3
3
  from ...... import minichain as mc
4
- from .inputs import AsyncStringInput
5
- from .inputs import InputSyncStringInput
6
- from .inputs import SyncAsyncStringInput
4
+ from .....inputs.asyncs import AsyncStringInput
5
+ from .....inputs.asyncs import SyncAsyncStringInput
6
+ from .....inputs.sync import InputSyncStringInput
7
7
  from .types import UserChatInput
8
8
 
9
9
 
@@ -1,38 +1,27 @@
1
- import dataclasses as dc
2
- import typing as ta
1
+ from omlish import dataclasses as dc
3
2
 
4
- from .... import minichain as mc
3
+ from ...backends.configs import BackendConfig
4
+ from ...rendering.configs import RenderingConfig
5
+ from .chat.ai.configs import AiConfig
6
+ from .chat.state.configs import StateConfig
7
+ from .chat.user.configs import UserConfig
8
+ from .tools.configs import ToolsConfig
5
9
 
6
10
 
7
11
  ##
8
12
 
9
13
 
10
- DEFAULT_CHAT_MODEL_BACKEND = 'openai'
14
+ DEFAULT_BACKEND = 'openai'
11
15
 
12
16
 
13
17
  ##
14
18
 
15
19
 
16
- @dc.dataclass(frozen=True)
20
+ @dc.dataclass(frozen=True, kw_only=True)
17
21
  class ChatConfig:
18
- _: dc.KW_ONLY
19
-
20
- backend: str | None = None
21
- model_name: str | None = None
22
-
23
- state: ta.Literal['new', 'continue', 'ephemeral'] = 'continue'
24
-
25
- initial_system_content: ta.Optional['mc.Content'] = None
26
- initial_user_content: ta.Optional['mc.Content'] = None
27
-
28
- interactive: bool = False
29
- use_readline: bool | ta.Literal['auto'] = 'auto'
30
-
31
- silent: bool = False
32
- markdown: bool = False
33
-
34
- stream: bool = False
35
-
36
- enable_tools: bool = False
37
- enabled_tools: ta.AbstractSet[str] | None = None
38
- dangerous_no_tool_confirmation: bool = False
22
+ backend: BackendConfig = BackendConfig()
23
+ ai: AiConfig = AiConfig()
24
+ state: StateConfig = StateConfig()
25
+ user: UserConfig = UserConfig()
26
+ rendering: RenderingConfig = RenderingConfig()
27
+ tools: ToolsConfig = ToolsConfig()
@@ -2,20 +2,21 @@ 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.types import DefaultBackendName
5
6
  from ..base import Session
6
- from .configs import DEFAULT_CHAT_MODEL_BACKEND
7
+ from .configs import DEFAULT_BACKEND
7
8
  from .configs import ChatConfig
8
9
 
9
10
 
10
11
  with lang.auto_proxy_import(globals()):
12
+ from ...backends import inject as _backends
13
+ from ...rendering import inject as _rendering
11
14
  from . import driver as _driver
12
15
  from . import session as _session
13
- from .backends import inject as _backends
14
16
  from .chat.ai import inject as _chat_ai
15
17
  from .chat.state import inject as _chat_state
16
18
  from .chat.user import inject as _chat_user
17
19
  from .phases import inject as _phases
18
- from .rendering import inject as _rendering
19
20
  from .tools import inject as _tools
20
21
 
21
22
 
@@ -28,42 +29,20 @@ def bind_chat(cfg: ChatConfig) -> inj.Elements:
28
29
  #
29
30
 
30
31
  els.extend([
31
- _backends.bind_backends(
32
- backend=cfg.backend or DEFAULT_CHAT_MODEL_BACKEND,
33
- ),
34
-
35
- _chat_ai.bind_ai(
36
- stream=cfg.stream,
37
- silent=cfg.silent,
38
- enable_tools=cfg.enable_tools,
39
- ),
40
-
41
- _chat_user.bind_user(
42
- initial_system_content=cfg.initial_system_content,
43
- initial_user_content=cfg.initial_user_content,
44
- interactive=cfg.interactive,
45
- use_readline=cfg.use_readline,
46
- ),
47
-
48
- _chat_state.bind_state(
49
- state=cfg.state,
50
- ),
32
+ _backends.bind_backends(cfg.backend),
51
33
 
52
- _phases.bind_phases(),
34
+ _chat_ai.bind_ai(cfg.ai),
53
35
 
54
- _rendering.bind_rendering(
55
- markdown=cfg.markdown,
56
- ),
57
- ])
36
+ _chat_user.bind_user(cfg.user),
58
37
 
59
- #
38
+ _chat_state.bind_state(cfg.state),
39
+
40
+ _phases.bind_phases(),
60
41
 
61
- if cfg.enable_tools:
62
- els.append(_tools.bind_tools(
63
- silent=cfg.silent,
64
- dangerous_no_confirmation=cfg.dangerous_no_tool_confirmation,
65
- enabled_tools=cfg.enabled_tools,
66
- ))
42
+ _rendering.bind_rendering(cfg.rendering),
43
+
44
+ _tools.bind_tools(cfg.tools),
45
+ ])
67
46
 
68
47
  #
69
48
 
@@ -80,4 +59,8 @@ def bind_chat(cfg: ChatConfig) -> inj.Elements:
80
59
 
81
60
  #
82
61
 
62
+ els.append(inj.bind(DefaultBackendName, to_const=DEFAULT_BACKEND))
63
+
64
+ #
65
+
83
66
  return inj.as_elements(*els)
@@ -1,4 +1,4 @@
1
- import dataclasses as dc
1
+ from omlish import dataclasses as dc
2
2
 
3
3
  from ..base import Session
4
4
  from .configs import ChatConfig
@@ -0,0 +1,13 @@
1
+ import typing as ta
2
+
3
+ from omlish import dataclasses as dc
4
+
5
+
6
+ ##
7
+
8
+
9
+ @dc.dataclass(frozen=True, kw_only=True)
10
+ class ToolsConfig:
11
+ silent: bool = False
12
+ dangerous_no_confirmation: bool = False
13
+ enabled_tools: ta.Iterable[str] | None = None
@@ -6,6 +6,7 @@ from omlish import inject as inj
6
6
  from omlish import lang
7
7
 
8
8
  from ..... import minichain as mc
9
+ from .configs import ToolsConfig
9
10
  from .injection import bind_tool_context_provider_to_key
10
11
  from .injection import tool_catalog_entries
11
12
  from .injection import tool_context_providers
@@ -90,12 +91,7 @@ def _bind_fs_tools() -> inj.Elements:
90
91
  ##
91
92
 
92
93
 
93
- def bind_tools(
94
- *,
95
- silent: bool = False,
96
- dangerous_no_confirmation: bool = False,
97
- enabled_tools: ta.Iterable[str] | None = None,
98
- ) -> inj.Elements:
94
+ def bind_tools(cfg: ToolsConfig = ToolsConfig()) -> inj.Elements:
99
95
  els: list[inj.Elemental] = []
100
96
 
101
97
  #
@@ -106,7 +102,7 @@ def bind_tools(
106
102
 
107
103
  els.append(tool_catalog_entries().bind_items_provider(singleton=True))
108
104
 
109
- for etn in check.not_isinstance(enabled_tools or [], str):
105
+ for etn in check.not_isinstance(cfg.enabled_tools or [], str):
110
106
  els.append(_TOOL_BINDERS[etn]())
111
107
 
112
108
  #
@@ -115,10 +111,10 @@ def bind_tools(
115
111
 
116
112
  els.append(exec_stack.push_bind(to_ctor=_execution.ToolUseExecutorImpl, singleton=True))
117
113
 
118
- if not silent:
114
+ if not cfg.silent:
119
115
  els.append(exec_stack.push_bind(to_ctor=_rendering.ResultRenderingToolUseExecutor, singleton=True))
120
116
 
121
- if dangerous_no_confirmation:
117
+ if cfg.dangerous_no_confirmation:
122
118
  els.append(exec_stack.push_bind(to_ctor=_rendering.ArgsRenderingToolUseExecutor, singleton=True))
123
119
 
124
120
  els.extend([
@@ -127,7 +123,7 @@ def bind_tools(
127
123
 
128
124
  #
129
125
 
130
- if not dangerous_no_confirmation:
126
+ if not cfg.dangerous_no_confirmation:
131
127
  els.append(inj.bind(_confirmation.ToolExecutionConfirmation, to_ctor=_confirmation.InteractiveToolExecutionConfirmation, singleton=True)) # noqa
132
128
 
133
129
  #
@@ -9,6 +9,7 @@ from ..... import minichain as mc
9
9
  with lang.auto_proxy_import(globals()):
10
10
  from . import execution as _execution
11
11
 
12
+
12
13
  ##
13
14
 
14
15
 
@@ -1,7 +1,7 @@
1
1
  import typing as ta
2
2
 
3
3
  from ..... import minichain as mc
4
- from ..rendering.types import ContentRendering
4
+ from ....rendering.types import ContentRendering
5
5
  from .execution import ToolUseExecutor
6
6
 
7
7
 
@@ -1,4 +1,4 @@
1
- import dataclasses as dc
1
+ from omlish import dataclasses as dc
2
2
 
3
3
  from .... import minichain as mc
4
4
 
@@ -6,7 +6,7 @@ from .... import minichain as mc
6
6
  ##
7
7
 
8
8
 
9
- DEFAULT_COMPLETION_MODEL_BACKEND = 'openai'
9
+ DEFAULT_BACKEND = 'openai'
10
10
 
11
11
 
12
12
  ##
@@ -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 CompletionConfig
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_completion(cfg: CompletionConfig) -> 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
1
  from omlish import check
4
- from omlish import lang
2
+ from omlish import dataclasses as dc
5
3
 
6
4
  from .... import minichain as mc
5
+ from ...backends.types import CompletionServiceBackendProvider
7
6
  from ..base import Session
8
- from .configs import DEFAULT_COMPLETION_MODEL_BACKEND
9
7
  from .configs import CompletionConfig
10
8
 
11
9
 
@@ -21,19 +19,17 @@ class CompletionSession(Session['CompletionSession.Config']):
21
19
  self,
22
20
  config: Config,
23
21
  *,
24
- backend_catalog: mc.BackendCatalog,
22
+ service_provider: CompletionServiceBackendProvider,
25
23
  ) -> None:
26
24
  super().__init__(config)
27
25
 
28
- self._backend_catalog = backend_catalog
26
+ self._service_provider = service_provider
29
27
 
30
28
  async def run(self) -> None:
31
29
  prompt = check.isinstance(self._config.content, str)
32
30
 
33
31
  mdl: mc.CompletionService
34
- async with lang.async_maybe_managing(self._backend_catalog.new_backend(
35
- mc.CompletionService,
36
- self._config.backend or DEFAULT_COMPLETION_MODEL_BACKEND,
37
- )) as mdl:
32
+ async with self._service_provider.provide_backend() as mdl:
38
33
  response = await mdl.invoke(mc.CompletionRequest(prompt))
39
- print(response.v.strip())
34
+
35
+ print(response.v.strip())
@@ -1,4 +1,4 @@
1
- import dataclasses as dc
1
+ from omlish import dataclasses as dc
2
2
 
3
3
  from .... import minichain as mc
4
4
 
@@ -6,7 +6,7 @@ from .... import minichain as mc
6
6
  ##
7
7
 
8
8
 
9
- DEFAULT_EMBEDDING_MODEL_BACKEND = 'openai'
9
+ DEFAULT_BACKEND = 'openai'
10
10
 
11
11
 
12
12
  ##
@@ -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
- backend_catalog: mc.BackendCatalog,
22
+ service_provider: EmbeddingServiceBackendProvider,
25
23
  ) -> None:
26
24
  super().__init__(config)
27
25
 
28
- self._backend_catalog = backend_catalog
26
+ self._service_provider = service_provider
29
27
 
30
28
  async def run(self) -> None:
31
29
  mdl: mc.EmbeddingService
32
- async with lang.async_maybe_managing(self._backend_catalog.new_backend(
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
- print(json.dumps_compact(list(map(float, response.v))))
32
+
33
+ print(json.dumps_compact(list(map(float, response.v))))
@@ -1,8 +1,8 @@
1
1
  import abc
2
- import dataclasses as dc
3
2
  import os.path
4
3
  import typing as ta
5
4
 
5
+ from omlish import dataclasses as dc
6
6
  from omlish import lang
7
7
  from omlish import marshal as msh
8
8
  from omlish.formats import json
@@ -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
+ 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))