ommlds 0.0.0.dev442__py3-none-any.whl → 0.0.0.dev443__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.

@@ -63,7 +63,7 @@
63
63
  "module": ".minichain.backends.impls.anthropic.stream",
64
64
  "attr": null,
65
65
  "file": "ommlds/minichain/backends/impls/anthropic/stream.py",
66
- "line": 34,
66
+ "line": 35,
67
67
  "value": {
68
68
  "!.minichain.registries.manifests.RegistryManifest": {
69
69
  "module": "ommlds.minichain.backends.impls.anthropic.stream",
@@ -184,7 +184,7 @@
184
184
  "module": ".minichain.backends.impls.llamacpp.stream",
185
185
  "attr": null,
186
186
  "file": "ommlds/minichain/backends/impls/llamacpp/stream.py",
187
- "line": 31,
187
+ "line": 32,
188
188
  "value": {
189
189
  "!.minichain.registries.manifests.RegistryManifest": {
190
190
  "module": "ommlds.minichain.backends.impls.llamacpp.stream",
@@ -341,7 +341,7 @@
341
341
  "module": ".minichain.backends.impls.openai.stream",
342
342
  "attr": null,
343
343
  "file": "ommlds/minichain/backends/impls/openai/stream.py",
344
- "line": 36,
344
+ "line": 37,
345
345
  "value": {
346
346
  "!.minichain.registries.manifests.RegistryManifest": {
347
347
  "module": "ommlds.minichain.backends.impls.openai.stream",
@@ -356,7 +356,7 @@
356
356
  "module": ".minichain.backends.impls.tinygrad.chat",
357
357
  "attr": null,
358
358
  "file": "ommlds/minichain/backends/impls/tinygrad/chat.py",
359
- "line": 113,
359
+ "line": 115,
360
360
  "value": {
361
361
  "!.minichain.registries.manifests.RegistryManifest": {
362
362
  "module": "ommlds.minichain.backends.impls.tinygrad.chat",
@@ -371,7 +371,7 @@
371
371
  "module": ".minichain.backends.impls.tinygrad.chat",
372
372
  "attr": null,
373
373
  "file": "ommlds/minichain/backends/impls/tinygrad/chat.py",
374
- "line": 133,
374
+ "line": 135,
375
375
  "value": {
376
376
  "!.minichain.registries.manifests.RegistryManifest": {
377
377
  "module": "ommlds.minichain.backends.impls.tinygrad.chat",
@@ -386,7 +386,7 @@
386
386
  "module": ".minichain.backends.impls.tinygrad.chat",
387
387
  "attr": null,
388
388
  "file": "ommlds/minichain/backends/impls/tinygrad/chat.py",
389
- "line": 159,
389
+ "line": 161,
390
390
  "value": {
391
391
  "!.minichain.backends.strings.manifests.BackendStringsManifest": {
392
392
  "service_cls_names": [
ommlds/__about__.py CHANGED
@@ -19,7 +19,7 @@ class Project(ProjectBase):
19
19
  'llama-cpp-python ~= 0.3',
20
20
 
21
21
  'mlx ~= 0.29',
22
- 'mlx-lm ~= 0.27; sys_platform == "darwin"',
22
+ 'mlx-lm ~= 0.28; sys_platform == "darwin"',
23
23
 
24
24
  # 'sentencepiece ~= 0.2', # FIXME: https://github.com/google/sentencepiece/issues/1121
25
25
 
@@ -54,7 +54,7 @@ class InteractiveChatSession(ChatSession['InteractiveChatSession.Config']):
54
54
  backend = DEFAULT_CHAT_MODEL_BACKEND
55
55
 
56
56
  mdl: mc.ChatChoicesService
57
- with lang.maybe_managing(self._backend_catalog.get_backend(
57
+ async with lang.async_maybe_managing(self._backend_catalog.get_backend(
58
58
  mc.ChatChoicesService,
59
59
  backend,
60
60
  *([mc.ModelName(mn)] if (mn := self._config.model_name) is not None else []),
@@ -70,17 +70,17 @@ class PromptChatSession(ChatSession['PromptChatSession.Config']):
70
70
  ]
71
71
 
72
72
  mdl: mc.ChatChoicesStreamService
73
- with lang.maybe_managing(self._backend_catalog.get_backend(
73
+ async with lang.async_maybe_managing(self._backend_catalog.get_backend(
74
74
  mc.ChatChoicesStreamService,
75
75
  self._config.backend or DEFAULT_CHAT_MODEL_BACKEND,
76
76
  *([mc.ModelName(mn)] if (mn := self._config.model_name) is not None else []),
77
77
  )) as mdl:
78
- with (await mdl.invoke(mc.ChatChoicesStreamRequest(
78
+ async with (await mdl.invoke(mc.ChatChoicesStreamRequest(
79
79
  [*state.chat, *new_chat],
80
80
  (self._chat_options or []),
81
81
  ))).v as st_resp:
82
82
  lst: list[str] = []
83
- for o in st_resp:
83
+ async for o in st_resp:
84
84
  if o:
85
85
  m = check.single(o).m
86
86
  if m.c is not None:
@@ -107,7 +107,7 @@ class PromptChatSession(ChatSession['PromptChatSession.Config']):
107
107
  ]
108
108
 
109
109
  mdl: mc.ChatChoicesService
110
- with lang.maybe_managing(self._backend_catalog.get_backend(
110
+ async with lang.async_maybe_managing(self._backend_catalog.get_backend(
111
111
  mc.ChatChoicesService,
112
112
  self._config.backend or DEFAULT_CHAT_MODEL_BACKEND,
113
113
  *([mc.ModelName(mn)] if (mn := self._config.model_name) is not None else []),
@@ -36,7 +36,7 @@ class CompletionSession(Session['CompletionSession.Config']):
36
36
  prompt = check.isinstance(self._config.content, str)
37
37
 
38
38
  mdl: mc.CompletionService
39
- with lang.maybe_managing(self._backend_catalog.get_backend(
39
+ async with lang.async_maybe_managing(self._backend_catalog.get_backend(
40
40
  mc.CompletionService,
41
41
  self._config.backend or DEFAULT_COMPLETION_MODEL_BACKEND,
42
42
  )) as mdl:
@@ -34,7 +34,7 @@ class EmbeddingSession(Session['EmbeddingSession.Config']):
34
34
 
35
35
  async def run(self) -> None:
36
36
  mdl: mc.EmbeddingService
37
- with lang.maybe_managing(self._backend_catalog.get_backend(
37
+ async with lang.async_maybe_managing(self._backend_catalog.get_backend(
38
38
  mc.EmbeddingService,
39
39
  self._config.backend or DEFAULT_EMBEDDING_MODEL_BACKEND,
40
40
  )) as mdl:
@@ -98,8 +98,6 @@ with _lang.auto_proxy_init(
98
98
  ChatChoicesStreamService,
99
99
  AbstractChatChoicesStreamService,
100
100
  static_check_is_chat_choices_stream_service,
101
-
102
- ChatChoicesStreamGenerator,
103
101
  )
104
102
 
105
103
  from .chat.stream.types import ( # noqa
@@ -322,7 +320,12 @@ with _lang.auto_proxy_init(
322
320
  StreamOption,
323
321
  StreamOptions,
324
322
 
325
- ResponseGenerator,
323
+ StreamResponseSink,
324
+ StreamResponseIterator,
325
+
326
+ StreamServiceCancelledError,
327
+ StreamServiceNotAwaitedError,
328
+
326
329
  StreamResponse,
327
330
  new_stream_response,
328
331
  )
@@ -23,6 +23,7 @@ from ....chat.stream.types import AiMessageDelta
23
23
  from ....configs import Config
24
24
  from ....resources import UseResources
25
25
  from ....standard import ApiKey
26
+ from ....stream.services import StreamResponseSink
26
27
  from ....stream.services import new_stream_response
27
28
  from .chat import AnthropicChatChoicesService
28
29
  from .names import MODEL_NAMES
@@ -83,11 +84,11 @@ class AnthropicChatChoicesStreamService:
83
84
  data=json.dumps(raw_request).encode('utf-8'),
84
85
  )
85
86
 
86
- with UseResources.or_new(request.options) as rs:
87
+ async with UseResources.or_new(request.options) as rs:
87
88
  http_client = rs.enter_context(http.client())
88
89
  http_response = rs.enter_context(http_client.stream_request(http_request))
89
90
 
90
- def yield_choices() -> ta.Generator[AiChoiceDeltas, None, ta.Sequence[ChatChoicesOutputs] | None]:
91
+ async def inner(sink: StreamResponseSink[AiChoiceDeltas]) -> ta.Sequence[ChatChoicesOutputs] | None:
91
92
  db = DelimitingBuffer([b'\r', b'\n', b'\r\n'])
92
93
  sd = sse.SseDecoder()
93
94
  ass = AnthropicSseMessageAssembler()
@@ -112,9 +113,9 @@ class AnthropicChatChoicesStreamService:
112
113
  for am in ass(ae):
113
114
  if isinstance(am, pt.Message):
114
115
  mt = check.isinstance(check.single(check.not_none(am.content)), pt.Text)
115
- yield [
116
+ await sink.emit([
116
117
  AiChoiceDelta(AiMessageDelta(mt.text)),
117
- ]
118
+ ])
118
119
 
119
120
  if not b:
120
121
  return []
@@ -122,4 +123,4 @@ class AnthropicChatChoicesStreamService:
122
123
  # raw_response = json.loads(check.not_none(http_response.data).decode('utf-8'))
123
124
  # return rh.build_response(raw_response)
124
125
 
125
- return new_stream_response(rs, yield_choices())
126
+ return await new_stream_response(rs, inner)
@@ -19,6 +19,7 @@ from ....chat.stream.types import AiMessageDelta
19
19
  from ....configs import Config
20
20
  from ....models.configs import ModelPath
21
21
  from ....resources import UseResources
22
+ from ....stream.services import StreamResponseSink
22
23
  from ....stream.services import new_stream_response
23
24
  from .chat import LlamacppChatChoicesService
24
25
  from .format import ROLES_MAP
@@ -52,7 +53,7 @@ class LlamacppChatChoicesStreamService(lang.ExitStacked):
52
53
  async def invoke(self, request: ChatChoicesStreamRequest) -> ChatChoicesStreamResponse:
53
54
  lcu.install_logging_hook()
54
55
 
55
- with UseResources.or_new(request.options) as rs:
56
+ async with UseResources.or_new(request.options) as rs:
56
57
  rs.enter_context(self._lock)
57
58
 
58
59
  model: ta.Any = self._load_model() # FIXME: the types are awful lol
@@ -74,7 +75,7 @@ class LlamacppChatChoicesStreamService(lang.ExitStacked):
74
75
 
75
76
  rs.enter_context(lang.defer(close_output))
76
77
 
77
- def yield_choices() -> ta.Generator[AiChoiceDeltas, None, ta.Sequence[ChatChoicesOutputs] | None]:
78
+ async def inner(sink: StreamResponseSink[AiChoiceDeltas]) -> ta.Sequence[ChatChoicesOutputs] | None:
78
79
  for chunk in output:
79
80
  check.state(chunk['object'] == 'chat.completion.chunk')
80
81
  l: list[AiChoiceDelta] = []
@@ -86,7 +87,7 @@ class LlamacppChatChoicesStreamService(lang.ExitStacked):
86
87
  if not (content := delta.get('content', '')):
87
88
  continue
88
89
  l.append(AiChoiceDelta(AiMessageDelta(content)))
89
- yield l
90
+ await sink.emit(l)
90
91
  return None
91
92
 
92
- return new_stream_response(rs, yield_choices())
93
+ return await new_stream_response(rs, inner)
@@ -24,6 +24,7 @@ from ....resources import ResourcesOption
24
24
  from ....resources import UseResources
25
25
  from ....standard import ApiKey
26
26
  from ....stream.services import StreamOption
27
+ from ....stream.services import StreamResponseSink
27
28
  from ....stream.services import new_stream_response
28
29
  from .chat import OpenaiChatChoicesService
29
30
  from .format import OpenaiChatRequestHandler
@@ -78,11 +79,11 @@ class OpenaiChatChoicesStreamService:
78
79
  data=json.dumps(raw_request).encode('utf-8'),
79
80
  )
80
81
 
81
- with UseResources.or_new(request.options) as rs:
82
+ async with UseResources.or_new(request.options) as rs:
82
83
  http_client = rs.enter_context(http.client())
83
84
  http_response = rs.enter_context(http_client.stream_request(http_request))
84
85
 
85
- def yield_choices() -> ta.Generator[AiChoiceDeltas, None, ta.Sequence[ChatChoicesOutputs] | None]:
86
+ async def inner(sink: StreamResponseSink[AiChoiceDeltas]) -> ta.Sequence[ChatChoicesOutputs]:
86
87
  db = DelimitingBuffer([b'\r', b'\n', b'\r\n'])
87
88
  sd = sse.SseDecoder()
88
89
  while True:
@@ -111,10 +112,10 @@ class OpenaiChatChoicesStreamService:
111
112
  if not sj['choices']:
112
113
  continue
113
114
 
114
- yield [
115
+ await sink.emit([
115
116
  AiChoiceDelta(rh.build_ai_message_delta(choice['delta']))
116
117
  for choice in sj['choices']
117
- ]
118
+ ])
118
119
 
119
120
  if not b:
120
121
  return []
@@ -122,4 +123,4 @@ class OpenaiChatChoicesStreamService:
122
123
  # raw_response = json.loads(check.not_none(http_response.data).decode('utf-8'))
123
124
  # return rh.build_response(raw_response)
124
125
 
125
- return new_stream_response(rs, yield_choices())
126
+ return await new_stream_response(rs, inner)
@@ -10,19 +10,21 @@ from ....chat.choices.services import ChatChoicesRequest
10
10
  from ....chat.choices.services import ChatChoicesResponse
11
11
  from ....chat.choices.services import static_check_is_chat_choices_service
12
12
  from ....chat.choices.types import AiChoice
13
+ from ....chat.choices.types import ChatChoicesOutputs
13
14
  from ....chat.messages import AiMessage
14
15
  from ....chat.messages import Chat
15
16
  from ....chat.messages import SystemMessage
16
17
  from ....chat.messages import UserMessage
17
- from ....chat.stream.services import ChatChoicesStreamGenerator
18
18
  from ....chat.stream.services import ChatChoicesStreamRequest
19
19
  from ....chat.stream.services import ChatChoicesStreamResponse
20
20
  from ....chat.stream.services import static_check_is_chat_choices_stream_service
21
21
  from ....chat.stream.types import AiChoiceDelta
22
+ from ....chat.stream.types import AiChoiceDeltas
22
23
  from ....chat.stream.types import AiMessageDelta
23
24
  from ....chat.types import ChatOption
24
25
  from ....llms.types import LlmOption
25
26
  from ....resources import UseResources
27
+ from ....stream.services import StreamResponseSink
26
28
  from ....stream.services import new_stream_response
27
29
 
28
30
 
@@ -137,7 +139,7 @@ class TinygradLlama3ChatChoicesService(BaseTinygradLlama3ChatService):
137
139
  @static_check_is_chat_choices_stream_service
138
140
  class TinygradLlama3ChatChoicesStreamService(BaseTinygradLlama3ChatService):
139
141
  async def invoke(self, request: ChatChoicesStreamRequest) -> ChatChoicesStreamResponse:
140
- with UseResources.or_new(request.options) as rs:
142
+ async with UseResources.or_new(request.options) as rs:
141
143
  llm = self._load_model()
142
144
  toks = _prepare_toks(
143
145
  llm,
@@ -145,12 +147,12 @@ class TinygradLlama3ChatChoicesStreamService(BaseTinygradLlama3ChatService):
145
147
  request.options.get_any((ChatOption, LlmOption)), # FIXME # noqa
146
148
  )
147
149
 
148
- def yield_choices() -> ChatChoicesStreamGenerator:
150
+ async def inner(sink: StreamResponseSink[AiChoiceDeltas]) -> ta.Sequence[ChatChoicesOutputs]:
149
151
  for s in tgl3.run_llm(llm, toks):
150
- yield [AiChoiceDelta(AiMessageDelta(s))]
152
+ await sink.emit([AiChoiceDelta(AiMessageDelta(s))])
151
153
  return []
152
154
 
153
- return new_stream_response(rs, yield_choices())
155
+ return await new_stream_response(rs, inner)
154
156
 
155
157
 
156
158
  ##
@@ -2,6 +2,7 @@ import typing as ta
2
2
 
3
3
  from omlish import check
4
4
  from omlish import dataclasses as dc
5
+ from omlish import lang
5
6
 
6
7
  from ...services import Response
7
8
  from ..choices.services import ChatChoicesRequest
@@ -33,10 +34,9 @@ class ChatChoicesStreamServiceChatChoicesService:
33
34
  ]:
34
35
  lst: list[ChatChoicesStreamServiceChatChoicesService._Choice] = []
35
36
 
36
- resp = await self.service.invoke(request)
37
- with resp.v as resp_v:
37
+ async with (resp := await self.service.invoke(request)).v as it: # noqa
38
38
  i = -1 # noqa
39
- for i, cs in enumerate(resp_v):
39
+ async for i, cs in lang.async_enumerate(it):
40
40
  if i == 0:
41
41
  for c in cs:
42
42
  m = c.m
@@ -56,7 +56,7 @@ class ChatChoicesStreamServiceChatChoicesService:
56
56
  # if m.tool_exec_requests:
57
57
  # ch.trs.extend(m.tool_exec_requests)
58
58
 
59
- check.state(resp_v.is_done)
59
+ # check.state(resp_v.is_done)
60
60
 
61
61
  ret: list[AiChoice] = []
62
62
  for ch in lst:
@@ -43,9 +43,3 @@ class AbstractChatChoicesStreamService(lang.Abstract):
43
43
  @abc.abstractmethod
44
44
  def invoke(self, request: ChatChoicesStreamRequest) -> ta.Awaitable[ChatChoicesStreamResponse]:
45
45
  raise NotImplementedError
46
-
47
-
48
- ##
49
-
50
-
51
- ChatChoicesStreamGenerator: ta.TypeAlias = ta.Generator[AiChoiceDeltas, None, ta.Sequence[ChatChoicesOutputs] | None]
@@ -3,7 +3,6 @@ TODO:
3
3
  - unify with omlish.sql.api.resources -> omlish.resources
4
4
  """
5
5
  import contextlib
6
- import threading
7
6
  import typing as ta
8
7
 
9
8
  from omlish import check
@@ -43,26 +42,25 @@ class Resources(lang.Final, lang.NotPicklable):
43
42
 
44
43
  self._no_autoclose = no_autoclose
45
44
 
46
- self._lock = threading.RLock()
47
-
48
45
  self._closed = False
49
46
 
50
47
  self._refs: ta.MutableSet[ResourcesRef] = col.IdentitySet()
51
48
 
52
- self._es = contextlib.ExitStack()
53
- self._es.__enter__()
49
+ self._aes = contextlib.AsyncExitStack()
54
50
 
55
51
  if init_ref is not None:
56
52
  self.add_ref(init_ref)
57
53
 
54
+ async def init(self) -> None:
55
+ await self._aes.__aenter__()
56
+
58
57
  @property
59
58
  def autoclose(self) -> bool:
60
59
  return not self._no_autoclose
61
60
 
62
61
  @property
63
62
  def num_refs(self) -> int:
64
- with self._lock:
65
- return len(self._refs)
63
+ return len(self._refs)
66
64
 
67
65
  @property
68
66
  def closed(self) -> bool:
@@ -77,15 +75,16 @@ class Resources(lang.Final, lang.NotPicklable):
77
75
  pass
78
76
 
79
77
  @classmethod
80
- def new(cls, **kwargs: ta.Any) -> ta.ContextManager['Resources']:
81
- @contextlib.contextmanager
82
- def inner():
78
+ def new(cls, **kwargs: ta.Any) -> ta.AsyncContextManager['Resources']:
79
+ @contextlib.asynccontextmanager
80
+ async def inner():
83
81
  init_ref = Resources._InitRef()
84
82
  res = Resources(init_ref=init_ref, **kwargs)
83
+ await res.init()
85
84
  try:
86
85
  yield res
87
86
  finally:
88
- res.remove_ref(init_ref)
87
+ await res.remove_ref(init_ref)
89
88
 
90
89
  return inner()
91
90
 
@@ -93,30 +92,30 @@ class Resources(lang.Final, lang.NotPicklable):
93
92
 
94
93
  def add_ref(self, ref: ResourcesRef) -> None:
95
94
  check.isinstance(ref, ResourcesRef)
96
- with self._lock:
97
- check.state(not self._closed)
98
- self._refs.add(ref)
95
+ check.state(not self._closed)
96
+ self._refs.add(ref)
99
97
 
100
98
  def has_ref(self, ref: ResourcesRef) -> bool:
101
- with self._lock:
102
- return ref in self._refs
99
+ return ref in self._refs
103
100
 
104
- def remove_ref(self, ref: ResourcesRef) -> None:
101
+ async def remove_ref(self, ref: ResourcesRef) -> None:
105
102
  check.isinstance(ref, ResourcesRef)
106
- with self._lock:
107
- try:
108
- self._refs.remove(ref)
109
- except KeyError:
110
- raise ResourcesRefNotRegisteredError(ref) from None
111
- if not self._no_autoclose and not self._refs:
112
- self.close()
103
+ try:
104
+ self._refs.remove(ref)
105
+ except KeyError:
106
+ raise ResourcesRefNotRegisteredError(ref) from None
107
+ if not self._no_autoclose and not self._refs:
108
+ await self.aclose()
113
109
 
114
110
  #
115
111
 
116
112
  def enter_context(self, cm: ta.ContextManager[T]) -> T:
117
- with self._lock:
118
- check.state(not self._closed)
119
- return self._es.enter_context(cm)
113
+ check.state(not self._closed)
114
+ return self._aes.enter_context(cm)
115
+
116
+ async def enter_async_context(self, cm: ta.AsyncContextManager[T]) -> T:
117
+ check.state(not self._closed)
118
+ return await self._aes.enter_async_context(cm)
120
119
 
121
120
  #
122
121
 
@@ -125,12 +124,11 @@ class Resources(lang.Final, lang.NotPicklable):
125
124
 
126
125
  #
127
126
 
128
- def close(self) -> None:
129
- with self._lock:
130
- try:
131
- self._es.__exit__(None, None, None)
132
- finally:
133
- self._closed = True
127
+ async def aclose(self) -> None:
128
+ try:
129
+ await self._aes.__aexit__(None, None, None)
130
+ finally:
131
+ self._closed = True
134
132
 
135
133
  def __del__(self) -> None:
136
134
  if not self._closed:
@@ -159,11 +157,11 @@ class ResourceManaged(ResourcesRef, lang.Final, lang.NotPicklable, ta.Generic[T]
159
157
  def __repr__(self) -> str:
160
158
  return f'{self.__class__.__name__}<{self._v!r}>'
161
159
 
162
- def __enter__(self) -> T:
160
+ async def __aenter__(self) -> T:
163
161
  return self._v
164
162
 
165
- def __exit__(self, exc_type, exc_val, exc_tb):
166
- self.__resources.remove_ref(self)
163
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
164
+ await self.__resources.remove_ref(self)
167
165
 
168
166
 
169
167
  ##
@@ -175,11 +173,11 @@ class ResourcesOption(Option, lang.Abstract):
175
173
 
176
174
  class UseResources(tv.UniqueScalarTypedValue[Resources], ResourcesOption, lang.Final):
177
175
  @classmethod
178
- @contextlib.contextmanager
179
- def or_new(cls, options: ta.Sequence[Option]) -> ta.Iterator[Resources]:
176
+ @contextlib.asynccontextmanager
177
+ async def or_new(cls, options: ta.Sequence[Option]) -> ta.AsyncGenerator[Resources]:
180
178
  if (ur := tv.as_collection(options).get(UseResources)) is not None:
181
- with ResourceManaged(ur.v, ur.v) as rs:
179
+ async with ResourceManaged(ur.v, ur.v) as rs:
182
180
  yield rs
183
181
  else:
184
- with Resources.new() as rs:
182
+ async with Resources.new() as rs:
185
183
  yield rs
@@ -1,4 +1,4 @@
1
- import contextlib
1
+ import abc
2
2
  import typing as ta
3
3
 
4
4
  from omlish import check
@@ -14,6 +14,8 @@ from ..types import Output
14
14
 
15
15
 
16
16
  V = ta.TypeVar('V')
17
+ V2 = ta.TypeVar('V2')
18
+
17
19
  OutputT = ta.TypeVar('OutputT', bound=Output)
18
20
  StreamOutputT = ta.TypeVar('StreamOutputT', bound=Output)
19
21
 
@@ -31,44 +33,143 @@ StreamOptions: ta.TypeAlias = StreamOption | ResourcesOption
31
33
  ##
32
34
 
33
35
 
34
- class ResponseGenerator(lang.Final, ta.Generic[V, OutputT]):
35
- def __init__(self, g: ta.Generator[V, None, ta.Sequence[OutputT] | None]) -> None:
36
- super().__init__()
36
+ class StreamResponseSink(lang.Abstract, ta.Generic[V]):
37
+ @abc.abstractmethod
38
+ def emit(self, value: V) -> ta.Awaitable[None]:
39
+ raise NotImplementedError
37
40
 
38
- self._g = g
39
- self._is_done = False
40
41
 
41
- def __repr__(self) -> str:
42
- return f'{self.__class__.__name__}<{self._g!r}>'
42
+ class StreamResponseIterator(lang.Abstract, ta.Generic[V, OutputT]):
43
+ @abc.abstractmethod
44
+ def __aenter__(self) -> ta.Awaitable[ta.Self]:
45
+ raise NotImplementedError
43
46
 
44
- _outputs: tv.TypedValues[OutputT]
47
+ @abc.abstractmethod
48
+ def __aexit__(self, exc_type, exc_val, exc_tb) -> ta.Awaitable[None]:
49
+ raise NotImplementedError
45
50
 
46
51
  @property
47
- def is_done(self) -> bool:
48
- return self._is_done
52
+ @abc.abstractmethod
53
+ def outputs(self) -> tv.TypedValues[OutputT]:
54
+ raise NotImplementedError
55
+
56
+ @ta.final
57
+ def __aiter__(self) -> ta.AsyncIterator[V]:
58
+ return self
59
+
60
+ @abc.abstractmethod
61
+ def __anext__(self) -> ta.Awaitable[V]:
62
+ raise NotImplementedError
63
+
64
+
65
+ ##
66
+
67
+
68
+ class StreamServiceCancelledError(BaseException):
69
+ pass
70
+
71
+
72
+ class StreamServiceNotAwaitedError(Exception):
73
+ pass
74
+
75
+
76
+ class _StreamServiceResponse(StreamResponseIterator[V, OutputT]):
77
+ def __init__(
78
+ self,
79
+ fn: ta.Callable[[StreamResponseSink[V]], ta.Awaitable[ta.Sequence[OutputT] | None]],
80
+ ) -> None:
81
+ super().__init__()
82
+
83
+ self._fn = fn
84
+
85
+ @ta.final
86
+ class _Emit(ta.Generic[V2]):
87
+ def __init__(self, ssr: '_StreamServiceResponse', value: V2) -> None:
88
+ self.ssr, self.value = ssr, value
89
+
90
+ done: bool = False
91
+
92
+ def __await__(self) -> ta.Generator['_StreamServiceResponse._Emit[V2]']:
93
+ if not self.done:
94
+ yield self
95
+ if not self.done:
96
+ raise StreamServiceNotAwaitedError
97
+
98
+ @ta.final
99
+ class _Sink(StreamResponseSink[V2]):
100
+ def __init__(self, ssr: '_StreamServiceResponse') -> None:
101
+ super().__init__()
102
+
103
+ self._ssr = ssr
104
+
105
+ def emit(self, item: V2) -> ta.Awaitable[None]:
106
+ return _StreamServiceResponse._Emit(self._ssr, item)
107
+
108
+ _state: ta.Literal['new', 'running', 'closed'] = 'new'
109
+ _sink: _Sink[V]
110
+ _a: ta.Any
111
+ _cr: ta.Any
112
+
113
+ async def __aenter__(self) -> ta.Self:
114
+ check.state(self._state == 'new')
115
+ self._state = 'running'
116
+ self._sink = _StreamServiceResponse._Sink(self)
117
+ self._cr = self._fn(self._sink)
118
+ self._a = self._cr.__await__()
119
+ self._g = iter(self._a)
120
+ return self
121
+
122
+ async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
123
+ old_state = self._state
124
+ self._state = 'closed'
125
+ if old_state != 'running':
126
+ return
127
+ if self._cr.cr_running:
128
+ cex = StreamServiceCancelledError()
129
+ try:
130
+ self._g.throw(cex)
131
+ except StreamServiceCancelledError as cex2:
132
+ if cex2 is not cex:
133
+ raise
134
+ if self._cr.cr_running:
135
+ raise RuntimeError(f'Coroutine {self._cr!r} not terminated')
136
+ if self._g is not self._a:
137
+ self._g.close()
138
+ self._a.close()
139
+ self._cr.close()
140
+
141
+ _outputs: tv.TypedValues[OutputT]
49
142
 
50
143
  @property
51
144
  def outputs(self) -> tv.TypedValues[OutputT]:
52
145
  return self._outputs
53
146
 
54
- def __iter__(self) -> ta.Iterator[V]:
55
- return self
147
+ async def __anext__(self) -> V:
148
+ check.state(self._state == 'running')
149
+ while True:
150
+ try:
151
+ x = self._g.send(None)
152
+ except StopIteration as e:
153
+ if e.value is not None:
154
+ self._outputs = tv.TypedValues(*check.isinstance(e.value, ta.Sequence))
155
+ else:
156
+ self._outputs = tv.TypedValues()
157
+ raise StopAsyncIteration from None
56
158
 
57
- def __next__(self) -> V:
58
- try:
59
- return next(self._g)
60
- except StopIteration as e:
61
- self._is_done = True
62
- if e.value is not None:
63
- self._outputs = tv.TypedValues(*check.isinstance(e.value, ta.Sequence))
64
- else:
65
- self._outputs = tv.TypedValues()
66
- raise
159
+ if isinstance(x, _StreamServiceResponse._Emit) and x.ssr is self:
160
+ check.state(not x.done)
161
+ x.done = True
162
+ return x.value
163
+
164
+ await x
165
+
166
+
167
+ ##
67
168
 
68
169
 
69
170
  StreamResponse: ta.TypeAlias = Response[
70
171
  ResourceManaged[
71
- ResponseGenerator[
172
+ StreamResponseIterator[
72
173
  V,
73
174
  OutputT,
74
175
  ],
@@ -77,18 +178,16 @@ StreamResponse: ta.TypeAlias = Response[
77
178
  ]
78
179
 
79
180
 
80
- def new_stream_response(
181
+ async def new_stream_response(
81
182
  rs: Resources,
82
- g: ta.Generator[V, None, ta.Sequence[OutputT] | None],
183
+ fn: ta.Callable[[StreamResponseSink[V]], ta.Awaitable[ta.Sequence[OutputT] | None]],
83
184
  outputs: ta.Sequence[StreamOutputT] | None = None,
84
185
  ) -> StreamResponse[V, OutputT, StreamOutputT]:
85
186
  return StreamResponse(
86
187
  rs.new_managed(
87
- ResponseGenerator(
88
- rs.enter_context(
89
- contextlib.closing(
90
- g,
91
- ),
188
+ await rs.enter_async_context(
189
+ _StreamServiceResponse(
190
+ fn,
92
191
  ),
93
192
  ),
94
193
  ),
@@ -5,8 +5,8 @@ from ..resources import Resources
5
5
  from ..services import Request
6
6
  from ..services import Service
7
7
  from ..types import Output
8
- from .services import ResponseGenerator
9
8
  from .services import StreamResponse
9
+ from .services import StreamResponseSink
10
10
  from .services import new_stream_response
11
11
 
12
12
 
@@ -29,36 +29,34 @@ class WrappedStreamService(ta.Generic[StreamRequestT, V, OutputT, StreamOutputT]
29
29
 
30
30
  #
31
31
 
32
- def _process_request(self, request: StreamRequestT) -> StreamRequestT:
32
+ async def _process_request(self, request: StreamRequestT) -> StreamRequestT:
33
33
  return request
34
34
 
35
- def _process_stream_outputs(self, outputs: ta.Sequence[StreamOutputT]) -> ta.Sequence[StreamOutputT]:
35
+ async def _process_stream_outputs(self, outputs: ta.Sequence[StreamOutputT]) -> ta.Sequence[StreamOutputT]:
36
36
  return outputs
37
37
 
38
- def _process_vs(self, vs: ta.Iterator[V]) -> ta.Iterator[V]:
39
- return vs
38
+ async def _process_value(self, v: V) -> ta.Iterable[V]:
39
+ return [v]
40
40
 
41
- def _process_outputs(self, outputs: ta.Sequence[OutputT]) -> ta.Sequence[OutputT]:
41
+ async def _process_outputs(self, outputs: ta.Sequence[OutputT]) -> ta.Sequence[OutputT]:
42
42
  return outputs
43
43
 
44
44
  #
45
45
 
46
46
  async def invoke(self, request: StreamRequestT) -> StreamResponse[V, OutputT, StreamOutputT]:
47
- with Resources.new() as rs:
48
- in_response = await self._inner.invoke(self._process_request(request))
49
- in_vs: ResponseGenerator[V, OutputT] = rs.enter_context(in_response.v)
50
- out_vs = self._process_vs(in_vs)
51
-
52
- def yield_vs() -> ta.Generator[V, None, ta.Sequence[OutputT] | None]:
53
- while True:
54
- try:
55
- out_v = next(out_vs)
56
- except StopIteration as se:
57
- return self._process_outputs(se.value)
58
- yield out_v
59
-
60
- return new_stream_response(
47
+ async with Resources.new() as rs:
48
+ in_resp = await self._inner.invoke(await self._process_request(request))
49
+ in_vs = await rs.enter_async_context(in_resp.v)
50
+
51
+ async def inner(sink: StreamResponseSink[V]) -> ta.Sequence[OutputT] | None:
52
+ async for in_v in in_vs:
53
+ for out_v in (await self._process_value(in_v)):
54
+ await sink.emit(out_v)
55
+
56
+ return await self._process_outputs(in_vs.outputs)
57
+
58
+ return await new_stream_response(
61
59
  rs,
62
- yield_vs(),
63
- self._process_stream_outputs(in_response.outputs),
60
+ inner,
61
+ await self._process_stream_outputs(in_resp.outputs),
64
62
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ommlds
3
- Version: 0.0.0.dev442
3
+ Version: 0.0.0.dev443
4
4
  Summary: ommlds
5
5
  Author: wrmsr
6
6
  License-Expression: BSD-3-Clause
@@ -14,12 +14,12 @@ 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.dev442
18
- Requires-Dist: omlish==0.0.0.dev442
17
+ Requires-Dist: omdev==0.0.0.dev443
18
+ Requires-Dist: omlish==0.0.0.dev443
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"
22
- Requires-Dist: mlx-lm~=0.27; sys_platform == "darwin" and extra == "all"
22
+ Requires-Dist: mlx-lm~=0.28; sys_platform == "darwin" and extra == "all"
23
23
  Requires-Dist: tiktoken~=0.11; extra == "all"
24
24
  Requires-Dist: tinygrad~=0.11; extra == "all"
25
25
  Requires-Dist: tokenizers~=0.22; extra == "all"
@@ -39,7 +39,7 @@ Requires-Dist: lxml>=5.3; python_version < "3.13" and extra == "all"
39
39
  Provides-Extra: backends
40
40
  Requires-Dist: llama-cpp-python~=0.3; extra == "backends"
41
41
  Requires-Dist: mlx~=0.29; extra == "backends"
42
- Requires-Dist: mlx-lm~=0.27; sys_platform == "darwin" and extra == "backends"
42
+ Requires-Dist: mlx-lm~=0.28; sys_platform == "darwin" and extra == "backends"
43
43
  Requires-Dist: tiktoken~=0.11; extra == "backends"
44
44
  Requires-Dist: tinygrad~=0.11; extra == "backends"
45
45
  Requires-Dist: tokenizers~=0.22; extra == "backends"
@@ -1,5 +1,5 @@
1
- ommlds/.omlish-manifests.json,sha256=mCv-0aH_AHhPPs4Uq8-3JmKJE1LXgspCmHvsAVQpNdY,17481
2
- ommlds/__about__.py,sha256=MNqSmD9ozY6rDorcO5skXSfyFHzOBT7A3r956u62tPs,1759
1
+ ommlds/.omlish-manifests.json,sha256=UfOa-wySWiPmKtp2MqM1dvOCDiyaxDOFK29yBFRzKPE,17481
2
+ ommlds/__about__.py,sha256=Z9VIVQnuNBbIYEtIm9XZU4T2QGRqMNjtmQX2OOTaUc0,1759
3
3
  ommlds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  ommlds/huggingface.py,sha256=JfEyfKOxU3-SY_ojtXBJFNeD-NIuKjvMe3GL3e93wNA,1175
5
5
  ommlds/_hacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -87,15 +87,15 @@ ommlds/cli/sessions/inject.py,sha256=sCwNFDhiyir1taxufFVEcHtaK_o14IcsQOvGUHWM9Jo
87
87
  ommlds/cli/sessions/chat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
88
88
  ommlds/cli/sessions/chat/base.py,sha256=GlDBXZ-KymSokNl1a7uwX1abswmRE67Q0zOIHjhZb_0,796
89
89
  ommlds/cli/sessions/chat/inject.py,sha256=zg26F-yDm9sH4COzS-3yZua2taeb3ogHCOZ34UEKI54,2661
90
- ommlds/cli/sessions/chat/interactive.py,sha256=AeZWJ0lI8pt9NqXOGm4KTAdWB1NYkec87LntVpZ6pVk,1972
90
+ ommlds/cli/sessions/chat/interactive.py,sha256=0Pt3H7uZl9nGXAvMqGxU8Ih65N-DrWSkLahRFmnkFw8,1984
91
91
  ommlds/cli/sessions/chat/printing.py,sha256=urlxuSBOisRVn1f_uDb343pyBps9ht2BznMWB_H0ti8,2321
92
- ommlds/cli/sessions/chat/prompt.py,sha256=d3KIMvyVviNr6zFHbhOQOaeXIanpGUXZ8_4BoOAEMAI,4511
92
+ ommlds/cli/sessions/chat/prompt.py,sha256=nEj2vwzwBJ4WTEwXwKkygrOktqqsoyGaJ46z-LYl1pQ,4547
93
93
  ommlds/cli/sessions/chat/state.py,sha256=en29yekINGqVqqMoqZxxIRMuU_j3Z7Qxvtr8q5igcgg,2621
94
94
  ommlds/cli/sessions/chat/tools.py,sha256=wEcpawpEj2Zgti9gWGjk_B9yfCM3SL-tFVb56cQnDso,2259
95
95
  ommlds/cli/sessions/completion/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
96
- ommlds/cli/sessions/completion/completion.py,sha256=Dhc1mShRPifRjLtFRFjgkdbA_aojRHnhU1NGPG3aSU0,1065
96
+ ommlds/cli/sessions/completion/completion.py,sha256=2ZrzmHBCF3mG13ABcoiHva6OUzPpdF7qzByteaLNsxk,1077
97
97
  ommlds/cli/sessions/embedding/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
98
- ommlds/cli/sessions/embedding/embedding.py,sha256=zh1nqSP9YYCFGPlbWUibiIaG_a-jxCW6R-Y584dyWuA,1039
98
+ ommlds/cli/sessions/embedding/embedding.py,sha256=9U5Maj-XI5nsrk7m-O3P2rZggey0z2p7onZn2QfQe38,1051
99
99
  ommlds/cli/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
100
100
  ommlds/cli/tools/config.py,sha256=fjdZAxs9r7aNN-YjYLQNU15KWOUtL5azX_3typf-ltQ,225
101
101
  ommlds/cli/tools/inject.py,sha256=dnS9OdYAGRE2QpWGAge3bu3UCmc7h5EUXVhnwL2zJsk,1447
@@ -103,7 +103,7 @@ ommlds/cli/tools/weather.py,sha256=FUPxPF5KBbbyK3voBtcRUOkuMO2zK5GFZoFTJMaM6LQ,3
103
103
  ommlds/datasets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
104
104
  ommlds/datasets/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
105
105
  ommlds/datasets/lib/movies.py,sha256=LmdfoXsZU9XMM_r-sxCLv_s06BFzwWO4xUj6sc9XVcI,1961
106
- ommlds/minichain/__init__.py,sha256=0C25ffuHRqsZ23pRjyORIsG89QxGHsMc0bojhGYz84o,10327
106
+ ommlds/minichain/__init__.py,sha256=6R-TOiDSx4PuK8_57XUWVmpG1bfzDx8pZxHSQWpMUtc,10400
107
107
  ommlds/minichain/_marshal.py,sha256=Lcib21J6jWyd-fkdQhUzij-TH2tnwylBChLRGrinWbk,892
108
108
  ommlds/minichain/_typedvalues.py,sha256=vPwVYGWtIJT_dclarnZlA-2sjP2o3L2HSDK5VDurYfM,2229
109
109
  ommlds/minichain/completion.py,sha256=lQ0LfCIYZsvDqteHhhDIv16D2_gn_xMfEL0ouywE5Yo,1033
@@ -111,7 +111,7 @@ ommlds/minichain/configs.py,sha256=WwrHxfkDAfo_RtuCqUgySthj-2W26lZbpuQoghUyGNw,1
111
111
  ommlds/minichain/envs.py,sha256=vE2CSeT6KYxOpPY72VbFLzGUnBERYdhfiEUlvSRHkXE,225
112
112
  ommlds/minichain/json.py,sha256=hfI9TMhgmhECIi-CFGnezsvOGeYWIHbZGfDDBeiUmB4,177
113
113
  ommlds/minichain/metadata.py,sha256=2jik8gEm_VMnknPuPwqRssTg0MClRFUrXz_IsyEgUt4,878
114
- ommlds/minichain/resources.py,sha256=4p2EhzxVK4kp8mgZ7PKXFYQQV-H28eTzV4HL0QMIm0Y,4358
114
+ ommlds/minichain/resources.py,sha256=HfcydnyFmXVRspYw-32-lvM_OfrZQdPEebAt3ivLev0,4436
115
115
  ommlds/minichain/search.py,sha256=azRzWcYhcm9IgSHquqLwtbwowtYCRAtPLSm7Gvt9iNo,1262
116
116
  ommlds/minichain/standard.py,sha256=uKXvdUNLxdUu7suCBsVOjJtnYVC2hjD_tmz3Ra7H6Jg,2510
117
117
  ommlds/minichain/types.py,sha256=K6RRjpUi17UEG0cqPrrvbVANU0iRVh3WLiH-y6oEWFI,414
@@ -126,7 +126,7 @@ ommlds/minichain/backends/impls/sqlite.py,sha256=NOFm_fgr-OZ8mo7etj0zwvxsDnidRwK
126
126
  ommlds/minichain/backends/impls/anthropic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
127
127
  ommlds/minichain/backends/impls/anthropic/chat.py,sha256=eyh7hWADTcQiMAHjYgjwoZZcpVxHLUhqSJhuraw27K8,3712
128
128
  ommlds/minichain/backends/impls/anthropic/names.py,sha256=CNZzE0EQwdIPGV0JNr5YbpuM1lf0l5AN1Su6XpwJ-LM,1098
129
- ommlds/minichain/backends/impls/anthropic/stream.py,sha256=8-wvfC1Gg_wlnV4-bb8VukE9ptT6nN52gx-mkn8bwog,5344
129
+ ommlds/minichain/backends/impls/anthropic/stream.py,sha256=I95OVhJ6y1AiZDwxRzK9W8pyNvzFIFmfyqhT4KmAQV0,5410
130
130
  ommlds/minichain/backends/impls/duckduckgo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
131
131
  ommlds/minichain/backends/impls/duckduckgo/search.py,sha256=igzeU9P9b1MMiu4KAJVS9H6KLIoPm68wXi4Kx3_DHyQ,940
132
132
  ommlds/minichain/backends/impls/google/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -140,7 +140,7 @@ ommlds/minichain/backends/impls/llamacpp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5
140
140
  ommlds/minichain/backends/impls/llamacpp/chat.py,sha256=X7B_H4PdsNX7rZ2LvldOv2oUDUnYLcvPAdqVVkWcb4A,5403
141
141
  ommlds/minichain/backends/impls/llamacpp/completion.py,sha256=oJ2I6wUoIPXYLm9Vc7dwOPgqbevatTjNBZ-jXeM24tQ,2372
142
142
  ommlds/minichain/backends/impls/llamacpp/format.py,sha256=lKO88-IbqWD7vTWoerLiPBdKKCLq86cbBJO96A7wMbE,702
143
- ommlds/minichain/backends/impls/llamacpp/stream.py,sha256=nmKCb_DdrgSbNb_1l7Sf8J1wA4s8pOr7ygoHmhcBZAI,3276
143
+ ommlds/minichain/backends/impls/llamacpp/stream.py,sha256=1AOtwPelxKpPRTJZjv1xkK5LYfySGe7uo0uazxM7BbM,3342
144
144
  ommlds/minichain/backends/impls/mlx/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
145
145
  ommlds/minichain/backends/impls/mlx/chat.py,sha256=DzR86VcrYx7gMxAAQ40Wf7IuBI4F0mxNvuEykotufPI,4556
146
146
  ommlds/minichain/backends/impls/openai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -149,11 +149,11 @@ ommlds/minichain/backends/impls/openai/completion.py,sha256=0XTC08mZzbW23Y2DNW2x
149
149
  ommlds/minichain/backends/impls/openai/embedding.py,sha256=kkDJ3_0EqwQ_E0eXsSH1TuWXQmRqaijK8zG90fnlf3s,1582
150
150
  ommlds/minichain/backends/impls/openai/format.py,sha256=ooUwI3UA7zeWOGFAAlFAM49lUDmtEJ3P3fPlwJ0_fNA,6423
151
151
  ommlds/minichain/backends/impls/openai/names.py,sha256=b74t8FwSbGEveVtVz4SqM5tiRDyTKNlUKlseV6AX3Yo,1211
152
- ommlds/minichain/backends/impls/openai/stream.py,sha256=88yEVdOuzxGNT1mnUg769IjHQVGZoPmzh7JAPX30qDg,4984
152
+ ommlds/minichain/backends/impls/openai/stream.py,sha256=uEn4gLiS6Ep9CzvA3GMsgD_pu610P5wAs3p4xhr7p7E,5043
153
153
  ommlds/minichain/backends/impls/sentencepiece/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
154
154
  ommlds/minichain/backends/impls/sentencepiece/tokens.py,sha256=tUEBKyBgkTowssS_AdcAuPkyFzfyDfE935x4JG8PXM0,1602
155
155
  ommlds/minichain/backends/impls/tinygrad/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
156
- ommlds/minichain/backends/impls/tinygrad/chat.py,sha256=vx6ZSv5_un1tFmJIubR9a-Thr2Yxu05W2vdP_xcye3Q,4630
156
+ ommlds/minichain/backends/impls/tinygrad/chat.py,sha256=teCEuTiqQRd0RXhY_j8XRiryKHYJUwPvYntmBGYt1Ao,4776
157
157
  ommlds/minichain/backends/impls/tokenizers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
158
158
  ommlds/minichain/backends/impls/tokenizers/tokens.py,sha256=_8Q49k5YroG5wQI0cuK6kOJ3XYwjhpaAS04ejhzBsWw,1500
159
159
  ommlds/minichain/backends/impls/transformers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -178,8 +178,8 @@ ommlds/minichain/chat/choices/adapters.py,sha256=gI6Vh4m-lz8dFagz7-mBAERDdd0G7uJ
178
178
  ommlds/minichain/chat/choices/services.py,sha256=p_FsCZEsGJun8epzAHoeNdjwJ86ZwihIhvFMsfdafeA,1041
179
179
  ommlds/minichain/chat/choices/types.py,sha256=GzkzaLnRKrugmjOfF0SvwHChc5pE88-HrADshswQLEE,730
180
180
  ommlds/minichain/chat/stream/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
181
- ommlds/minichain/chat/stream/adapters.py,sha256=RPHV9NDkCsiw2qI4QT19Q0p2WlbEPwOguNqzIMjDlnc,2217
182
- ommlds/minichain/chat/stream/services.py,sha256=O4hERji7TmpEWNrXd9gb7cXspIO2T6ftz-VVWI--H8Q,1375
181
+ ommlds/minichain/chat/stream/adapters.py,sha256=Xd82qvr73RHDSQiqyIpMA43LpMSc6JQp844Ii8oLxw0,2256
182
+ ommlds/minichain/chat/stream/services.py,sha256=XAj4CZvpxPrfjbkV6iN0651bj19fkec00wgTkAqDxJk,1250
183
183
  ommlds/minichain/chat/stream/types.py,sha256=XqeTQBTCW-aXaI_L3v64dWe96HF6DCPAVvf6-j3b90I,1302
184
184
  ommlds/minichain/chat/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
185
185
  ommlds/minichain/chat/tools/execution.py,sha256=a44cvJsmrXRqyg-3p5oaeI54HGjhOCDEtL9CMg-p1ic,540
@@ -241,8 +241,8 @@ ommlds/minichain/services/requests.py,sha256=VAfKbYu4T0CZTWVQmZ2LUmYU7DNm6IerYMN
241
241
  ommlds/minichain/services/responses.py,sha256=4W6Z4Fx4_GFqKgle27OeLr0zzjVTA0pkZrlsZiFQNdo,1534
242
242
  ommlds/minichain/services/services.py,sha256=WjkQNYIp87SflLSReOHMkG2qIVAOem6vsrs_2NxWN_M,325
243
243
  ommlds/minichain/stream/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
244
- ommlds/minichain/stream/services.py,sha256=4I3DaiJGAbvzBDs1uGAMkabO8opc5CbkqxvxOxd3EFs,2186
245
- ommlds/minichain/stream/wrap.py,sha256=bA4YMgxGSB-B9woUCR5tpkhOMjF1NUOZzuU1F71Du0U,2062
244
+ ommlds/minichain/stream/services.py,sha256=oOdJ-GpkeXpb-kqEY7FZi_J0NzbVJk5VpPUk7ZIRFt4,5020
245
+ ommlds/minichain/stream/wrap.py,sha256=B9jyUBmeD6KTan6XD4kNe_khjr0w0juck9FyBtR-HI8,2009
246
246
  ommlds/minichain/text/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
247
247
  ommlds/minichain/text/applypatch.py,sha256=YIN5JChJ0FXyK1I6OiAHQmE7BT-exHfaAMM9ay7ylyc,17705
248
248
  ommlds/minichain/text/toolparsing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -299,9 +299,9 @@ ommlds/wiki/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
299
299
  ommlds/wiki/utils/io.py,sha256=UKgDJGtmpnWvIqVd2mJc2QNPOqlToEY1GEveNp6_pMo,7088
300
300
  ommlds/wiki/utils/progress.py,sha256=EhvKcMFYtsarCQhIahlO6f0SboyAKP3UwUyrnVnP-Vk,3222
301
301
  ommlds/wiki/utils/xml.py,sha256=vVV8Ctn13aaRM9eYfs9Wd6rHn5WOCEUzQ44fIhOvJdg,3754
302
- ommlds-0.0.0.dev442.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
303
- ommlds-0.0.0.dev442.dist-info/METADATA,sha256=z4nqdm1N90RMFDn4PYH8WUpT12PiK8cAQSbmaE-3WRw,3224
304
- ommlds-0.0.0.dev442.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
305
- ommlds-0.0.0.dev442.dist-info/entry_points.txt,sha256=Z5YWtX7ClfiCKdW-dd_CSVvM0h4yQpJPi-2G3q6gNFo,35
306
- ommlds-0.0.0.dev442.dist-info/top_level.txt,sha256=Rbnk5d5wi58vnAXx13WFZqdQ4VX8hBCS2hEL3WeXOhY,7
307
- ommlds-0.0.0.dev442.dist-info/RECORD,,
302
+ ommlds-0.0.0.dev443.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
303
+ ommlds-0.0.0.dev443.dist-info/METADATA,sha256=7kkg5qkXPTJymBKRtYsIJAoxGsciQx_I7MDodtdXano,3224
304
+ ommlds-0.0.0.dev443.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
305
+ ommlds-0.0.0.dev443.dist-info/entry_points.txt,sha256=Z5YWtX7ClfiCKdW-dd_CSVvM0h4yQpJPi-2G3q6gNFo,35
306
+ ommlds-0.0.0.dev443.dist-info/top_level.txt,sha256=Rbnk5d5wi58vnAXx13WFZqdQ4VX8hBCS2hEL3WeXOhY,7
307
+ ommlds-0.0.0.dev443.dist-info/RECORD,,