ommlds 0.0.0.dev475__py3-none-any.whl → 0.0.0.dev477__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 (83) 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 +249 -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 +22 -0
  40. ommlds/cli/sessions/chat/tools/fs/__init__.py +0 -0
  41. ommlds/cli/sessions/chat/tools/fs/configs.py +12 -0
  42. ommlds/cli/sessions/chat/tools/fs/inject.py +35 -0
  43. ommlds/cli/sessions/chat/tools/inject.py +17 -74
  44. ommlds/cli/sessions/chat/tools/injection.py +15 -0
  45. ommlds/cli/sessions/chat/tools/rendering.py +1 -1
  46. ommlds/cli/sessions/chat/tools/todo/__init__.py +0 -0
  47. ommlds/cli/sessions/chat/tools/todo/configs.py +12 -0
  48. ommlds/cli/sessions/chat/tools/todo/inject.py +31 -0
  49. ommlds/cli/sessions/chat/tools/weather/__init__.py +0 -0
  50. ommlds/cli/sessions/chat/tools/weather/configs.py +12 -0
  51. ommlds/cli/sessions/chat/tools/weather/inject.py +22 -0
  52. ommlds/cli/sessions/chat/tools/{weather.py → weather/tools.py} +1 -1
  53. ommlds/cli/sessions/completion/configs.py +2 -2
  54. ommlds/cli/sessions/completion/inject.py +14 -0
  55. ommlds/cli/sessions/completion/session.py +7 -11
  56. ommlds/cli/sessions/embedding/configs.py +2 -2
  57. ommlds/cli/sessions/embedding/inject.py +14 -0
  58. ommlds/cli/sessions/embedding/session.py +7 -11
  59. ommlds/cli/state/storage.py +1 -1
  60. ommlds/minichain/backends/catalogs/strings.py +1 -1
  61. ommlds/minichain/backends/impls/groq/__init__.py +0 -0
  62. ommlds/minichain/backends/impls/groq/chat.py +75 -0
  63. ommlds/minichain/backends/impls/groq/names.py +48 -0
  64. ommlds/minichain/backends/impls/groq/protocol.py +143 -0
  65. ommlds/minichain/backends/impls/groq/stream.py +125 -0
  66. ommlds/minichain/backends/impls/openai/chat.py +3 -3
  67. ommlds/minichain/backends/impls/openai/names.py +27 -3
  68. ommlds/minichain/backends/impls/openai/stream.py +2 -2
  69. ommlds/minichain/chat/stream/joining.py +1 -0
  70. ommlds/minichain/tools/reflect.py +5 -1
  71. ommlds/wiki/utils/xml.py +5 -5
  72. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev477.dist-info}/METADATA +5 -5
  73. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev477.dist-info}/RECORD +80 -58
  74. ommlds/cli/backends/standard.py +0 -20
  75. ommlds/cli/main2.py +0 -220
  76. ommlds/cli/sessions/chat/backends/inject.py +0 -53
  77. /ommlds/{cli/sessions/chat/backends → backends/groq}/__init__.py +0 -0
  78. /ommlds/cli/{sessions/chat/content → content}/__init__.py +0 -0
  79. /ommlds/cli/{sessions/chat/rendering → inputs}/__init__.py +0 -0
  80. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev477.dist-info}/WHEEL +0 -0
  81. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev477.dist-info}/entry_points.txt +0 -0
  82. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev477.dist-info}/licenses/LICENSE +0 -0
  83. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev477.dist-info}/top_level.txt +0 -0
@@ -194,6 +194,60 @@
194
194
  }
195
195
  }
196
196
  },
197
+ {
198
+ "module": ".minichain.backends.impls.groq.chat",
199
+ "attr": null,
200
+ "file": "ommlds/minichain/backends/impls/groq/chat.py",
201
+ "line": 26,
202
+ "value": {
203
+ "!.minichain.registries.manifests.RegistryManifest": {
204
+ "module": "ommlds.minichain.backends.impls.groq.chat",
205
+ "attr": "GroqChatChoicesService",
206
+ "name": "groq",
207
+ "aliases": null,
208
+ "type": "ChatChoicesService"
209
+ }
210
+ }
211
+ },
212
+ {
213
+ "module": ".minichain.backends.impls.groq.names",
214
+ "attr": "_BACKEND_STRINGS_MANIFEST",
215
+ "file": "ommlds/minichain/backends/impls/groq/names.py",
216
+ "line": 40,
217
+ "value": {
218
+ "!.minichain.backends.strings.manifests.BackendStringsManifest": {
219
+ "service_cls_names": [
220
+ "ChatChoicesService",
221
+ "ChatChoicesStreamService"
222
+ ],
223
+ "backend_name": "groq",
224
+ "model_names": {
225
+ "default": "gpt-oss-120b",
226
+ "aliases": {
227
+ "gpt-oss-120b": "openai/gpt-oss-120b",
228
+ "openai/gpt-oss-120b": null,
229
+ "gpt-oss-20b": "openai/gpt-oss-20b",
230
+ "openai/gpt-oss-20b": null
231
+ }
232
+ }
233
+ }
234
+ }
235
+ },
236
+ {
237
+ "module": ".minichain.backends.impls.groq.stream",
238
+ "attr": null,
239
+ "file": "ommlds/minichain/backends/impls/groq/stream.py",
240
+ "line": 33,
241
+ "value": {
242
+ "!.minichain.registries.manifests.RegistryManifest": {
243
+ "module": "ommlds.minichain.backends.impls.groq.stream",
244
+ "attr": "GroqChatChoicesStreamService",
245
+ "name": "groq",
246
+ "aliases": null,
247
+ "type": "ChatChoicesStreamService"
248
+ }
249
+ }
250
+ },
197
251
  {
198
252
  "module": ".minichain.backends.impls.huggingface.repos",
199
253
  "attr": null,
@@ -440,7 +494,7 @@
440
494
  },
441
495
  {
442
496
  "module": ".minichain.backends.impls.openai.names",
443
- "attr": "_BACKEND_STRINGS_MANIFEST",
497
+ "attr": "_CHAT_BACKEND_STRINGS_MANIFEST",
444
498
  "file": "ommlds/minichain/backends/impls/openai/names.py",
445
499
  "line": 63,
446
500
  "value": {
@@ -490,6 +544,36 @@
490
544
  }
491
545
  }
492
546
  },
547
+ {
548
+ "module": ".minichain.backends.impls.openai.names",
549
+ "attr": "_COMPLETION_BACKEND_STRINGS_MANIFEST",
550
+ "file": "ommlds/minichain/backends/impls/openai/names.py",
551
+ "line": 77,
552
+ "value": {
553
+ "!.minichain.backends.strings.manifests.BackendStringsManifest": {
554
+ "service_cls_names": [
555
+ "CompletionService"
556
+ ],
557
+ "backend_name": "openai",
558
+ "model_names": null
559
+ }
560
+ }
561
+ },
562
+ {
563
+ "module": ".minichain.backends.impls.openai.names",
564
+ "attr": "_EMBEDDING_BACKEND_STRINGS_MANIFEST",
565
+ "file": "ommlds/minichain/backends/impls/openai/names.py",
566
+ "line": 89,
567
+ "value": {
568
+ "!.minichain.backends.strings.manifests.BackendStringsManifest": {
569
+ "service_cls_names": [
570
+ "EmbeddingService"
571
+ ],
572
+ "backend_name": "openai",
573
+ "model_names": null
574
+ }
575
+ }
576
+ },
493
577
  {
494
578
  "module": ".minichain.backends.impls.openai.stream",
495
579
  "attr": null,
ommlds/__about__.py CHANGED
@@ -60,7 +60,7 @@ class Project(ProjectBase):
60
60
  ],
61
61
 
62
62
  'search': [
63
- 'ddgs ~= 9.8',
63
+ 'ddgs ~= 9.9',
64
64
  ],
65
65
 
66
66
  'wiki': [
@@ -0,0 +1,23 @@
1
+ from omlish import lang
2
+ from omlish import marshal as msh
3
+
4
+ from .protocol import ChatCompletionRequest
5
+
6
+
7
+ ##
8
+
9
+
10
+ @lang.static_init
11
+ def _install_standard_marshaling() -> None:
12
+ for root_cls, tag_field in [
13
+ (ChatCompletionRequest.Message, 'role'),
14
+ ]:
15
+ msh.install_standard_factories(*msh.standard_polymorphism_factories(
16
+ msh.polymorphism_from_subclasses(
17
+ root_cls,
18
+ naming=msh.Naming.SNAKE,
19
+ strip_suffix=msh.AutoStripSuffix,
20
+ ),
21
+ msh.FieldTypeTagging(tag_field),
22
+ unions='partial',
23
+ ))
@@ -0,0 +1,249 @@
1
+ """
2
+ https://console.groq.com/docs/api-reference#chat-create
3
+ """
4
+ import typing as ta
5
+
6
+ from omlish import dataclasses as dc
7
+ from omlish import lang
8
+ from omlish import marshal as msh
9
+
10
+
11
+ ##
12
+
13
+
14
+ def _set_class_marshal_options(cls):
15
+ msh.update_object_metadata(
16
+ cls,
17
+ field_defaults=msh.FieldMetadata(
18
+ options=msh.FieldOptions(
19
+ omit_if=lang.is_none,
20
+ ),
21
+ ),
22
+ )
23
+
24
+ return cls
25
+
26
+
27
+ ##
28
+
29
+
30
+ @dc.dataclass(frozen=True, kw_only=True)
31
+ @_set_class_marshal_options
32
+ class ChatCompletionRequest(lang.Final):
33
+ @dc.dataclass(frozen=True, kw_only=True)
34
+ class Message(lang.Sealed, lang.Abstract):
35
+ pass
36
+
37
+ @dc.dataclass(frozen=True, kw_only=True)
38
+ @_set_class_marshal_options
39
+ class SystemMessage(Message, lang.Final):
40
+ content: str | ta.Sequence[str]
41
+ name: str | None = None
42
+ role: ta.Literal['system'] = 'system'
43
+
44
+ @dc.dataclass(frozen=True, kw_only=True)
45
+ @_set_class_marshal_options
46
+ class UserMessage(Message, lang.Final):
47
+ content: str | ta.Sequence[str]
48
+ name: str | None = None
49
+ role: ta.Literal['user'] = 'user'
50
+
51
+ @dc.dataclass(frozen=True, kw_only=True)
52
+ @_set_class_marshal_options
53
+ class AssistantMessage(Message, lang.Final):
54
+ content: str | ta.Sequence[str] | None = None
55
+ name: str | None = None
56
+ reasoning: str | None = None
57
+ role: ta.Literal['assistant'] = 'assistant'
58
+
59
+ @dc.dataclass(frozen=True, kw_only=True)
60
+ @_set_class_marshal_options
61
+ class ToolCall(lang.Final):
62
+ @dc.dataclass(frozen=True, kw_only=True)
63
+ @_set_class_marshal_options
64
+ class Function(lang.Final):
65
+ arguments: str
66
+ name: str
67
+
68
+ function: Function
69
+ id: str
70
+ type: ta.Literal['function'] = 'function'
71
+
72
+ tool_calls: ta.Sequence[ToolCall] | None = None
73
+
74
+ @dc.dataclass(frozen=True, kw_only=True)
75
+ @_set_class_marshal_options
76
+ class ToolMessage(Message, lang.Final):
77
+ content: str | ta.Sequence[str]
78
+ role: ta.Literal['tool'] = 'tool'
79
+ tool_call_id: str
80
+
81
+ messages: ta.Sequence[Message]
82
+ model: str
83
+ citation_options: ta.Literal['enabled', 'disabled'] | None = None
84
+ compound_custom: ta.Mapping[str, ta.Any] | None = None
85
+ disable_tool_validation: bool | None = None
86
+ documents: ta.Sequence[ta.Mapping[str, ta.Any]] | None = None
87
+ frequency_penalty: float | None = None
88
+ include_reasoning: bool | None = None
89
+ logit_bias: ta.Mapping[str, ta.Any] | None = None
90
+ logprobs: bool | None = None
91
+ max_completion_tokens: int | None = None
92
+ n: int | None = None
93
+ parallel_tool_calls: bool | None = None
94
+ presence_penalty: float | None = None
95
+ reasoning_effort: ta.Literal['none', 'default', 'low', 'medium', 'high'] | None = None
96
+ reasoning_format: ta.Literal['hidden', 'raw', 'parsed'] | None = None
97
+ response_format: ta.Any | None = None
98
+ search_settings: ta.Mapping[str, ta.Any] | None = None
99
+ seed: int | None = None
100
+ service_tier: ta.Literal['auto', 'on_demand', 'flex', 'performance', 'null'] | None = None
101
+ stop: str | ta.Sequence[str] | None = None
102
+ store: bool | None = None
103
+ stream: bool | None = None
104
+ stream_options: ta.Mapping[str, ta.Any] | None = None
105
+ temperature: float | None = None
106
+ ool_choice: str | None = None
107
+
108
+ @dc.dataclass(frozen=True, kw_only=True)
109
+ @_set_class_marshal_options
110
+ class Tool(lang.Final):
111
+ @dc.dataclass(frozen=True, kw_only=True)
112
+ @_set_class_marshal_options
113
+ class Function(lang.Final):
114
+ description: str | None = None
115
+ name: str
116
+ parameters: ta.Mapping[str, ta.Any] | None = None # json schema
117
+ strict: bool | None = None
118
+
119
+ function: Function
120
+ type: ta.Literal['function', 'browser_search', 'code_interpreter'] = 'function'
121
+
122
+ tools: ta.Sequence[Tool] | None = None
123
+
124
+ top_logprobs: int | None = None
125
+ top_p: float | None = None
126
+ user: str | None = None
127
+
128
+
129
+ @dc.dataclass(frozen=True, kw_only=True)
130
+ @_set_class_marshal_options
131
+ class ExecutedTool(lang.Final):
132
+ arguments: str
133
+ index: int
134
+ type: str
135
+ browser_results: ta.Sequence[ta.Any] | None = None
136
+ code_results: ta.Sequence[ta.Any] | None = None
137
+ output: str | None = None
138
+ search_results: ta.Any | None = None
139
+
140
+
141
+ @dc.dataclass(frozen=True, kw_only=True)
142
+ @_set_class_marshal_options
143
+ class ChatCompletionResponse(lang.Final):
144
+ @dc.dataclass(frozen=True, kw_only=True)
145
+ @_set_class_marshal_options
146
+ class Choice(lang.Final):
147
+ finish_reason: ta.Literal['stop', 'length', 'tool_calls', 'function_call']
148
+ index: int
149
+ logprobs: ta.Mapping[str, ta.Any] | None = None
150
+
151
+ @dc.dataclass(frozen=True, kw_only=True)
152
+ @_set_class_marshal_options
153
+ class Message(lang.Final):
154
+ annotations: ta.Sequence[ta.Mapping[str, ta.Any]] | None = None
155
+ content: str | None = None
156
+
157
+ executed_tools: ta.Sequence[ExecutedTool] | None = None
158
+
159
+ reasoning: str | None = None
160
+ role: ta.Literal['assistant'] = 'assistant'
161
+
162
+ @dc.dataclass(frozen=True, kw_only=True)
163
+ @_set_class_marshal_options
164
+ class ToolCall(lang.Final):
165
+ id: str
166
+
167
+ @dc.dataclass(frozen=True, kw_only=True)
168
+ @_set_class_marshal_options
169
+ class Function(lang.Final):
170
+ arguments: str
171
+ name: str
172
+
173
+ function: Function
174
+ type: ta.Literal['function'] = 'function'
175
+
176
+ tool_calls: ta.Sequence[ToolCall] | None = None
177
+
178
+ message: Message
179
+
180
+ choices: ta.Sequence[Choice]
181
+ created: int
182
+ id: str
183
+ model: str
184
+ object: ta.Literal['chat.completion'] = 'chat.completion'
185
+ system_fingerprint: str
186
+ usage: ta.Mapping[str, ta.Any] | None = None
187
+ usage_breakdown: ta.Mapping[str, ta.Any] | None = None
188
+ x_groq: ta.Mapping[str, ta.Any] | None = None
189
+ service_tier: str | None = None
190
+
191
+
192
+ @dc.dataclass(frozen=True, kw_only=True)
193
+ @_set_class_marshal_options
194
+ class ChatCompletionChunk(lang.Final):
195
+ id: str
196
+ object: ta.Literal['chat.completion.chunk'] = 'chat.completion.chunk'
197
+ created: int
198
+ model: str
199
+ system_fingerprint: str
200
+
201
+ @dc.dataclass(frozen=True, kw_only=True)
202
+ @_set_class_marshal_options
203
+ class Choice(lang.Final):
204
+ index: int
205
+
206
+ @dc.dataclass(frozen=True, kw_only=True)
207
+ @_set_class_marshal_options
208
+ class Delta(lang.Final):
209
+ role: str | None = None
210
+ content: str | None = None
211
+
212
+ channel: str | None = None
213
+ reasoning: str | None = None
214
+
215
+ @dc.dataclass(frozen=True, kw_only=True)
216
+ @_set_class_marshal_options
217
+ class ToolCall(lang.Final):
218
+ index: int
219
+ id: str | None = None
220
+
221
+ @dc.dataclass(frozen=True, kw_only=True)
222
+ @_set_class_marshal_options
223
+ class Function(lang.Final):
224
+ arguments: str | None = None
225
+ name: str | None = None
226
+
227
+ function: Function | None = None
228
+
229
+ type: ta.Literal['function'] = 'function'
230
+
231
+ tool_calls: ta.Sequence[ToolCall] | None = None
232
+
233
+ executed_tools: ta.Sequence[ExecutedTool] | None = None
234
+
235
+ delta: Delta
236
+ logprobs: ta.Mapping[str, ta.Any] | None = None
237
+ finish_reason: ta.Literal['stop', 'length', 'tool_calls', 'function_call'] | None = None
238
+
239
+ choices: ta.Sequence[Choice]
240
+
241
+ x_groq: ta.Mapping[str, ta.Any] | None = None
242
+ service_tier: str | None = None
243
+ usage: ta.Mapping[str, ta.Any] | None = None
244
+
245
+
246
+ ##
247
+
248
+
249
+ msh.register_global_module_import('._marshal', __package__)
@@ -3,12 +3,15 @@ import typing as ta
3
3
 
4
4
  from omlish import lang
5
5
 
6
- from ..... import minichain as mc
6
+ from ... import minichain as mc
7
7
  from .types import BackendConfigs
8
8
  from .types import BackendName
9
9
  from .types import BackendProvider
10
10
  from .types import ChatChoicesServiceBackendProvider
11
11
  from .types import ChatChoicesStreamServiceBackendProvider
12
+ from .types import CompletionServiceBackendProvider
13
+ from .types import DefaultBackendName
14
+ from .types import EmbeddingServiceBackendProvider
12
15
  from .types import ServiceT
13
16
 
14
17
 
@@ -22,7 +25,8 @@ class CatalogBackendProvider(BackendProvider[ServiceT], lang.Abstract):
22
25
  def __init__(
23
26
  self,
24
27
  *,
25
- name: BackendName,
28
+ name: BackendName | None = None,
29
+ default_name: DefaultBackendName | None = None,
26
30
  catalog: 'mc.BackendCatalog',
27
31
  configs: BackendConfigs | None = None,
28
32
  instantiator: Instantiator | None = None,
@@ -30,6 +34,7 @@ class CatalogBackendProvider(BackendProvider[ServiceT], lang.Abstract):
30
34
  super().__init__()
31
35
 
32
36
  self._name = name
37
+ self._default_name = default_name
33
38
  self._catalog = catalog
34
39
  self._configs = configs
35
40
  if instantiator is None:
@@ -38,13 +43,24 @@ class CatalogBackendProvider(BackendProvider[ServiceT], lang.Abstract):
38
43
 
39
44
  @contextlib.asynccontextmanager
40
45
  async def _provide_backend(self, cls: type[ServiceT]) -> ta.AsyncIterator[ServiceT]:
41
- be = self._catalog.get_backend(cls, self._name)
46
+ name: str
47
+ if self._name is not None:
48
+ name = self._name
49
+ elif self._default_name is not None:
50
+ name = self._default_name
51
+ else:
52
+ raise RuntimeError('No backend name specified')
53
+
54
+ be = self._catalog.get_backend(cls, name)
42
55
 
43
56
  service: ServiceT
44
57
  async with lang.async_or_sync_maybe_managing(await self._instantiator(be, self._configs)) as service:
45
58
  yield service
46
59
 
47
60
 
61
+ ##
62
+
63
+
48
64
  class CatalogChatChoicesServiceBackendProvider(
49
65
  CatalogBackendProvider['mc.ChatChoicesService'],
50
66
  ChatChoicesServiceBackendProvider,
@@ -59,3 +75,19 @@ class CatalogChatChoicesStreamServiceBackendProvider(
59
75
  ):
60
76
  def provide_backend(self) -> ta.AsyncContextManager['mc.ChatChoicesStreamService']:
61
77
  return self._provide_backend(mc.ChatChoicesStreamService) # type: ignore[type-abstract]
78
+
79
+
80
+ class CatalogCompletionServiceBackendProvider(
81
+ CatalogBackendProvider['mc.CompletionService'],
82
+ CompletionServiceBackendProvider,
83
+ ):
84
+ def provide_backend(self) -> ta.AsyncContextManager['mc.CompletionService']:
85
+ return self._provide_backend(mc.CompletionService) # type: ignore[type-abstract]
86
+
87
+
88
+ class CatalogEmbeddingServiceBackendProvider(
89
+ CatalogBackendProvider['mc.EmbeddingService'],
90
+ EmbeddingServiceBackendProvider,
91
+ ):
92
+ def provide_backend(self) -> ta.AsyncContextManager['mc.EmbeddingService']:
93
+ return self._provide_backend(mc.EmbeddingService) # type: ignore[type-abstract]
@@ -0,0 +1,9 @@
1
+ from omlish import dataclasses as dc
2
+
3
+
4
+ ##
5
+
6
+
7
+ @dc.dataclass(frozen=True, kw_only=True)
8
+ class BackendConfig:
9
+ backend: str | None = None
@@ -2,69 +2,64 @@ import typing as ta
2
2
 
3
3
  from omlish import inject as inj
4
4
  from omlish import lang
5
+ from omlish import typedvalues as tv
5
6
 
6
7
  from ... import minichain as mc
8
+ from .configs import BackendConfig
9
+ from .injection import backend_configs
10
+
11
+
12
+ with lang.auto_proxy_import(globals()):
13
+ from ...minichain.backends.impls.huggingface import repos as hf_repos
14
+ from . import catalog as _catalog
15
+ from . import types as _types
7
16
 
8
17
 
9
18
  ##
10
19
 
11
20
 
12
- def bind_strings_backends() -> inj.Elements:
21
+ def bind_backends(cfg: BackendConfig = BackendConfig()) -> inj.Elements:
13
22
  lst: list[inj.Elemental] = []
14
23
 
24
+ #
25
+
15
26
  lst.extend([
16
27
  inj.bind(mc.BackendStringBackendCatalog, singleton=True),
17
28
  inj.bind(mc.BackendCatalog, to_key=mc.BackendStringBackendCatalog),
18
29
  ])
19
30
 
20
- from ...minichain.backends.impls.huggingface.repos import HuggingfaceModelRepoResolver
21
-
22
31
  lst.extend([
23
- inj.bind(HuggingfaceModelRepoResolver, singleton=True),
24
- inj.bind(mc.ModelRepoResolver, to_key=HuggingfaceModelRepoResolver),
32
+ inj.bind(hf_repos.HuggingfaceModelRepoResolver, singleton=True),
33
+ inj.bind(mc.ModelRepoResolver, to_key=hf_repos.HuggingfaceModelRepoResolver),
25
34
 
26
35
  ])
27
36
 
28
- return inj.as_elements(*lst)
29
-
30
-
31
- def bind_simple_backends() -> inj.Elements:
32
- lst: list[inj.Elemental] = []
37
+ #
33
38
 
34
- lst.extend([
35
- inj.set_binder[mc.SimpleBackendCatalogEntry](),
36
- inj.bind(
37
- lang.typed_lambda(mc.SimpleBackendCatalogEntries, s=ta.AbstractSet[mc.SimpleBackendCatalogEntry])(
38
- lambda s: list(s),
39
- ),
40
- singleton=True,
41
- ),
42
- ])
39
+ lst.append(backend_configs().bind_items_provider(singleton=True))
43
40
 
44
- lst.extend([
45
- inj.bind(mc.SimpleBackendCatalog, singleton=True),
46
- inj.bind(mc.BackendCatalog, to_key=mc.SimpleBackendCatalog),
47
- ])
41
+ #
48
42
 
49
- from .standard import STANDARD_BACKEND_CATALOG_ENTRIES
43
+ if cfg.backend is not None:
44
+ lst.append(inj.bind(_types.BackendName, to_const=cfg.backend))
50
45
 
51
46
  lst.extend([
52
- inj.bind_set_entry_const(ta.AbstractSet[mc.SimpleBackendCatalogEntry], e)
53
- for e in STANDARD_BACKEND_CATALOG_ENTRIES
47
+ inj.bind(_types.ChatChoicesServiceBackendProvider, to_ctor=_catalog.CatalogChatChoicesServiceBackendProvider, singleton=True), # noqa
48
+ inj.bind(_types.ChatChoicesStreamServiceBackendProvider, to_ctor=_catalog.CatalogChatChoicesStreamServiceBackendProvider, singleton=True), # noqa
49
+ inj.bind(_types.CompletionServiceBackendProvider, to_ctor=_catalog.CatalogCompletionServiceBackendProvider, singleton=True), # noqa
50
+ inj.bind(_types.EmbeddingServiceBackendProvider, to_ctor=_catalog.CatalogEmbeddingServiceBackendProvider, singleton=True), # noqa
54
51
  ])
55
52
 
56
- return inj.as_elements(*lst)
53
+ #
57
54
 
55
+ async def catalog_backend_instantiator_provider(injector: inj.AsyncInjector) -> _catalog.CatalogBackendProvider.Instantiator: # noqa
56
+ async def inner(be: 'mc.BackendCatalog.Backend', cfgs: _types.BackendConfigs | None) -> ta.Any:
57
+ kwt = inj.build_kwargs_target(be.factory, non_strict=True)
58
+ kw = await injector.provide_kwargs(kwt)
59
+ return be.factory(*tv.collect(*(be.configs or []), *(cfgs or []), override=True), **kw)
58
60
 
59
- def bind_backends(
60
- *,
61
- enable_backend_strings: bool = False,
62
- ) -> inj.Elements:
63
- lst: list[inj.Elemental] = []
61
+ return _catalog.CatalogBackendProvider.Instantiator(inner)
64
62
 
65
- if enable_backend_strings:
66
- lst.append(bind_strings_backends())
67
- else:
68
- lst.append(bind_simple_backends())
63
+ lst.append(inj.bind(_catalog.CatalogBackendProvider.Instantiator, to_async_fn=catalog_backend_instantiator_provider)) # noqa
69
64
 
70
65
  return inj.as_elements(*lst)
@@ -1,7 +1,7 @@
1
1
  from omlish import inject as inj
2
2
  from omlish import lang
3
3
 
4
- from ..... import minichain as mc
4
+ from ... import minichain as mc
5
5
 
6
6
 
7
7
  with lang.auto_proxy_import(globals()):
@@ -3,7 +3,7 @@ import typing as ta
3
3
 
4
4
  from omlish import lang
5
5
 
6
- from ..... import minichain as mc
6
+ from ... import minichain as mc
7
7
 
8
8
 
9
9
  ServiceT = ta.TypeVar('ServiceT', bound=mc.Service)
@@ -13,6 +13,8 @@ ServiceT = ta.TypeVar('ServiceT', bound=mc.Service)
13
13
 
14
14
 
15
15
  BackendName = ta.NewType('BackendName', str)
16
+ DefaultBackendName = ta.NewType('DefaultBackendName', str)
17
+
16
18
  BackendConfigs = ta.NewType('BackendConfigs', ta.Sequence['mc.Config'])
17
19
 
18
20
 
@@ -34,3 +36,11 @@ class ChatChoicesServiceBackendProvider(BackendProvider['mc.ChatChoicesService']
34
36
 
35
37
  class ChatChoicesStreamServiceBackendProvider(BackendProvider['mc.ChatChoicesStreamService'], lang.Abstract):
36
38
  pass
39
+
40
+
41
+ class CompletionServiceBackendProvider(BackendProvider['mc.CompletionService'], lang.Abstract):
42
+ pass
43
+
44
+
45
+ class EmbeddingServiceBackendProvider(BackendProvider['mc.EmbeddingService'], lang.Abstract):
46
+ pass
@@ -4,7 +4,7 @@ import typing as ta
4
4
  from omlish import check
5
5
  from omlish import lang
6
6
 
7
- from ..... import minichain as mc
7
+ from ... import minichain as mc
8
8
 
9
9
 
10
10
  ##
@@ -4,7 +4,7 @@ import typing as ta
4
4
  from omlish import lang
5
5
  from omlish.formats import json
6
6
 
7
- from ..... import minichain as mc
7
+ from ... import minichain as mc
8
8
 
9
9
 
10
10
  ##
ommlds/cli/inject.py CHANGED
@@ -6,7 +6,6 @@ from omlish import lang
6
6
 
7
7
  with lang.auto_proxy_import(globals()):
8
8
  from . import asyncs
9
- from .backends import inject as _backends
10
9
  from .sessions import inject as _sessions
11
10
  from .state import inject as _state
12
11
 
@@ -17,17 +16,12 @@ with lang.auto_proxy_import(globals()):
17
16
  def bind_main(
18
17
  *,
19
18
  session_cfg: ta.Any,
20
- enable_backend_strings: bool = False,
21
19
  ) -> inj.Elements:
22
20
  els: list[inj.Elemental] = []
23
21
 
24
22
  #
25
23
 
26
24
  els.extend([
27
- _backends.bind_backends(
28
- enable_backend_strings=enable_backend_strings,
29
- ),
30
-
31
25
  _sessions.bind_sessions(session_cfg),
32
26
 
33
27
  _state.bind_state(),