ommlds 0.0.0.dev463__py3-none-any.whl → 0.0.0.dev464__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ommlds might be problematic. Click here for more details.
- ommlds/cli/inject.py +0 -5
- ommlds/cli/main.py +26 -54
- ommlds/cli/sessions/{chat2 → chat}/backends/catalog.py +5 -5
- ommlds/cli/sessions/chat/backends/inject.py +37 -0
- ommlds/cli/sessions/chat/backends/injection.py +16 -0
- ommlds/cli/sessions/{chat2 → chat}/backends/types.py +3 -3
- ommlds/cli/sessions/chat/chat/ai/inject.py +81 -0
- ommlds/cli/sessions/chat/chat/ai/injection.py +14 -0
- ommlds/cli/sessions/{chat2 → chat}/chat/ai/rendering.py +13 -10
- ommlds/cli/sessions/chat/chat/ai/services.py +81 -0
- ommlds/cli/sessions/chat/chat/ai/tools.py +44 -0
- ommlds/cli/sessions/{chat2 → chat}/chat/ai/types.py +5 -5
- ommlds/cli/sessions/chat/chat/state/inject.py +40 -0
- ommlds/cli/sessions/{chat2 → chat}/chat/state/inmemory.py +1 -1
- ommlds/cli/sessions/{chat2 → chat}/chat/state/storage.py +1 -1
- ommlds/cli/sessions/{chat2 → chat}/chat/state/types.py +1 -1
- ommlds/cli/sessions/chat/chat/user/inject.py +61 -0
- ommlds/cli/sessions/{chat2 → chat}/chat/user/interactive.py +1 -1
- ommlds/cli/sessions/{chat2 → chat}/chat/user/oneshot.py +1 -1
- ommlds/cli/sessions/{chat2 → chat}/chat/user/types.py +1 -1
- ommlds/cli/sessions/{chat2 → chat}/configs.py +4 -1
- ommlds/cli/sessions/{chat2 → chat}/content/messages.py +6 -2
- ommlds/cli/sessions/{chat2 → chat}/content/strings.py +2 -2
- ommlds/cli/sessions/{chat2 → chat}/driver.py +2 -2
- ommlds/cli/sessions/chat/inject.py +40 -66
- ommlds/cli/sessions/chat/phases/inject.py +27 -0
- ommlds/cli/sessions/chat/phases/injection.py +14 -0
- ommlds/cli/sessions/{chat2/phases.py → chat/phases/manager.py} +2 -28
- ommlds/cli/sessions/chat/phases/types.py +29 -0
- ommlds/cli/sessions/chat/rendering/inject.py +32 -0
- ommlds/cli/sessions/{chat2 → chat}/rendering/markdown.py +2 -2
- ommlds/cli/sessions/{chat2 → chat}/rendering/raw.py +6 -6
- ommlds/cli/sessions/{chat2 → chat}/rendering/types.py +1 -1
- ommlds/cli/sessions/{chat2 → chat}/session.py +1 -1
- ommlds/cli/sessions/{chat2 → chat}/tools/confirmation.py +4 -4
- ommlds/cli/sessions/{chat2 → chat}/tools/execution.py +18 -5
- ommlds/cli/sessions/chat/tools/inject.py +145 -0
- ommlds/cli/sessions/chat/tools/injection.py +29 -0
- ommlds/cli/sessions/chat/tools/rendering.py +58 -0
- ommlds/cli/{tools → sessions/chat/tools}/weather.py +1 -1
- ommlds/cli/sessions/inject.py +2 -7
- {ommlds-0.0.0.dev463.dist-info → ommlds-0.0.0.dev464.dist-info}/METADATA +3 -3
- {ommlds-0.0.0.dev463.dist-info → ommlds-0.0.0.dev464.dist-info}/RECORD +56 -54
- ommlds/cli/sessions/chat/base.py +0 -42
- ommlds/cli/sessions/chat/code.py +0 -125
- ommlds/cli/sessions/chat/interactive.py +0 -70
- ommlds/cli/sessions/chat/printing.py +0 -126
- ommlds/cli/sessions/chat/prompt.py +0 -161
- ommlds/cli/sessions/chat/state.py +0 -110
- ommlds/cli/sessions/chat/tools.py +0 -97
- ommlds/cli/sessions/chat2/_inject.py +0 -105
- ommlds/cli/sessions/chat2/chat/ai/services.py +0 -70
- ommlds/cli/sessions/chat2/inject.py +0 -143
- ommlds/cli/tools/__init__.py +0 -0
- ommlds/cli/tools/config.py +0 -14
- ommlds/cli/tools/inject.py +0 -75
- /ommlds/cli/sessions/{chat2 → chat/backends}/__init__.py +0 -0
- /ommlds/cli/sessions/{chat2/backends → chat/chat}/__init__.py +0 -0
- /ommlds/cli/sessions/{chat2/chat → chat/chat/ai}/__init__.py +0 -0
- /ommlds/cli/sessions/{chat2/chat/ai → chat/chat/state}/__init__.py +0 -0
- /ommlds/cli/sessions/{chat2/chat/state → chat/chat/user}/__init__.py +0 -0
- /ommlds/cli/sessions/{chat2/chat/user → chat/content}/__init__.py +0 -0
- /ommlds/cli/sessions/{chat2/content → chat/phases}/__init__.py +0 -0
- /ommlds/cli/sessions/{chat2 → chat}/rendering/__init__.py +0 -0
- /ommlds/cli/sessions/{chat2 → chat}/tools/__init__.py +0 -0
- {ommlds-0.0.0.dev463.dist-info → ommlds-0.0.0.dev464.dist-info}/WHEEL +0 -0
- {ommlds-0.0.0.dev463.dist-info → ommlds-0.0.0.dev464.dist-info}/entry_points.txt +0 -0
- {ommlds-0.0.0.dev463.dist-info → ommlds-0.0.0.dev464.dist-info}/licenses/LICENSE +0 -0
- {ommlds-0.0.0.dev463.dist-info → ommlds-0.0.0.dev464.dist-info}/top_level.txt +0 -0
ommlds/cli/inject.py
CHANGED
|
@@ -10,8 +10,6 @@ with lang.auto_proxy_import(globals()):
|
|
|
10
10
|
from .backends import inject as backends_inj
|
|
11
11
|
from .sessions import base as sessions_base
|
|
12
12
|
from .sessions import inject as sessions_inj
|
|
13
|
-
from .tools import config as tools_cfg
|
|
14
|
-
from .tools import inject as tools_inj
|
|
15
13
|
|
|
16
14
|
|
|
17
15
|
##
|
|
@@ -33,7 +31,6 @@ def _provide_state_storage() -> 'state.StateStorage':
|
|
|
33
31
|
def bind_main(
|
|
34
32
|
*,
|
|
35
33
|
session_cfg: 'sessions_base.Session.Config',
|
|
36
|
-
tools_config: 'tools_cfg.ToolsConfig',
|
|
37
34
|
enable_backend_strings: bool = False,
|
|
38
35
|
) -> inj.Elements:
|
|
39
36
|
els: list[inj.Elemental] = [
|
|
@@ -42,8 +39,6 @@ def bind_main(
|
|
|
42
39
|
),
|
|
43
40
|
|
|
44
41
|
sessions_inj.bind_sessions(session_cfg),
|
|
45
|
-
|
|
46
|
-
tools_inj.bind_tools(tools_config),
|
|
47
42
|
]
|
|
48
43
|
|
|
49
44
|
#
|
ommlds/cli/main.py
CHANGED
|
@@ -24,13 +24,9 @@ from omlish.subprocesses.sync import subprocesses
|
|
|
24
24
|
from .. import minichain as mc
|
|
25
25
|
from .inject import bind_main
|
|
26
26
|
from .sessions.base import Session
|
|
27
|
-
from .sessions.chat.
|
|
28
|
-
from .sessions.chat.interactive import InteractiveChatSession
|
|
29
|
-
from .sessions.chat.prompt import PromptChatSession
|
|
30
|
-
from .sessions.chat2.session import Chat2Session
|
|
27
|
+
from .sessions.chat.session import ChatSession
|
|
31
28
|
from .sessions.completion.completion import CompletionSession
|
|
32
29
|
from .sessions.embedding.embedding import EmbeddingSession
|
|
33
|
-
from .tools.config import ToolsConfig
|
|
34
30
|
|
|
35
31
|
|
|
36
32
|
if ta.TYPE_CHECKING:
|
|
@@ -57,6 +53,7 @@ async def _a_main(args: ta.Any = None) -> None:
|
|
|
57
53
|
parser.add_argument('-C', '--completion', action='store_true')
|
|
58
54
|
|
|
59
55
|
parser.add_argument('-n', '--new', action='store_true')
|
|
56
|
+
parser.add_argument('--ephemeral', action='store_true')
|
|
60
57
|
|
|
61
58
|
parser.add_argument('-e', '--editor', action='store_true')
|
|
62
59
|
parser.add_argument('-i', '--interactive', action='store_true')
|
|
@@ -67,8 +64,6 @@ async def _a_main(args: ta.Any = None) -> None:
|
|
|
67
64
|
parser.add_argument('-E', '--embed', action='store_true')
|
|
68
65
|
parser.add_argument('-j', '--image', action='store_true')
|
|
69
66
|
|
|
70
|
-
parser.add_argument('-2', '--two', action='store_true')
|
|
71
|
-
|
|
72
67
|
parser.add_argument('--enable-fs-tools', action='store_true')
|
|
73
68
|
parser.add_argument('--enable-todo-tools', action='store_true')
|
|
74
69
|
parser.add_argument('--enable-unsafe-tools-do-not-use-lol', action='store_true')
|
|
@@ -93,6 +88,7 @@ async def _a_main(args: ta.Any = None) -> None:
|
|
|
93
88
|
elif args.interactive:
|
|
94
89
|
if args.prompt:
|
|
95
90
|
raise ValueError('Must not provide prompt')
|
|
91
|
+
content = None
|
|
96
92
|
|
|
97
93
|
elif args.code:
|
|
98
94
|
if args.prompt:
|
|
@@ -131,34 +127,7 @@ async def _a_main(args: ta.Any = None) -> None:
|
|
|
131
127
|
|
|
132
128
|
session_cfg: Session.Config
|
|
133
129
|
|
|
134
|
-
if args.
|
|
135
|
-
session_cfg = Chat2Session.Config(
|
|
136
|
-
backend=args.backend,
|
|
137
|
-
model_name=args.model_name,
|
|
138
|
-
state='ephemeral',
|
|
139
|
-
initial_content=content, # noqa
|
|
140
|
-
# dangerous_no_tool_confirmation=bool(args.dangerous_no_tool_confirmation),
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
elif args.interactive:
|
|
144
|
-
session_cfg = InteractiveChatSession.Config(
|
|
145
|
-
backend=args.backend,
|
|
146
|
-
model_name=args.model_name,
|
|
147
|
-
new=bool(args.new),
|
|
148
|
-
dangerous_no_tool_confirmation=bool(args.dangerous_no_tool_confirmation),
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
elif args.code:
|
|
152
|
-
session_cfg = CodeChatSession.Config(
|
|
153
|
-
backend=args.backend,
|
|
154
|
-
model_name=args.model_name,
|
|
155
|
-
new=bool(args.new),
|
|
156
|
-
dangerous_no_tool_confirmation=bool(args.dangerous_no_tool_confirmation),
|
|
157
|
-
initial_message=content, # noqa
|
|
158
|
-
markdown=bool(args.markdown),
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
elif args.embed:
|
|
130
|
+
if args.embed:
|
|
162
131
|
session_cfg = EmbeddingSession.Config(
|
|
163
132
|
check.not_none(content), # noqa
|
|
164
133
|
backend=args.backend,
|
|
@@ -171,35 +140,38 @@ async def _a_main(args: ta.Any = None) -> None:
|
|
|
171
140
|
)
|
|
172
141
|
|
|
173
142
|
else:
|
|
174
|
-
|
|
175
|
-
|
|
143
|
+
from ..minichain.lib.code.prompts import CODE_AGENT_SYSTEM_PROMPT
|
|
144
|
+
|
|
145
|
+
session_cfg = ChatSession.Config(
|
|
176
146
|
backend=args.backend,
|
|
177
147
|
model_name=args.model_name,
|
|
178
|
-
|
|
179
|
-
|
|
148
|
+
state='ephemeral' if args.ephemeral else 'new' if args.new else 'continue',
|
|
149
|
+
initial_system_content=CODE_AGENT_SYSTEM_PROMPT if args.new and args.code else None,
|
|
150
|
+
initial_user_content=content, # noqa
|
|
151
|
+
interactive=args.interactive,
|
|
180
152
|
markdown=bool(args.markdown),
|
|
153
|
+
stream=bool(args.stream),
|
|
154
|
+
enable_tools=(
|
|
155
|
+
args.enable_fs_tools or
|
|
156
|
+
args.enable_todo_tools or
|
|
157
|
+
args.enable_unsafe_tools_do_not_use_lol or
|
|
158
|
+
args.enable_test_weather_tool or
|
|
159
|
+
args.code
|
|
160
|
+
),
|
|
161
|
+
enabled_tools={
|
|
162
|
+
*(['fs'] if args.enable_fs_tools else []),
|
|
163
|
+
*(['todo'] if args.enable_todo_tools else []),
|
|
164
|
+
*(['weather'] if args.enable_test_weather_tool else []),
|
|
165
|
+
# FIXME: enable_unsafe_tools_do_not_use_lol
|
|
166
|
+
},
|
|
181
167
|
dangerous_no_tool_confirmation=bool(args.dangerous_no_tool_confirmation),
|
|
182
168
|
)
|
|
183
169
|
|
|
184
170
|
#
|
|
185
171
|
|
|
186
|
-
tools_config = ToolsConfig(
|
|
187
|
-
enable_fs_tools=args.enable_fs_tools or args.code,
|
|
188
|
-
enable_todo_tools=args.enable_todo_tools or args.code,
|
|
189
|
-
enable_unsafe_tools_do_not_use_lol=args.enable_unsafe_tools_do_not_use_lol,
|
|
190
|
-
enable_test_weather_tool=args.enable_test_weather_tool,
|
|
191
|
-
)
|
|
192
|
-
|
|
193
|
-
#
|
|
194
|
-
|
|
195
172
|
with inj.create_managed_injector(bind_main(
|
|
196
173
|
session_cfg=session_cfg,
|
|
197
|
-
|
|
198
|
-
enable_backend_strings=isinstance(session_cfg, (
|
|
199
|
-
Chat2Session.Config,
|
|
200
|
-
CodeChatSession.Config,
|
|
201
|
-
PromptChatSession.Config,
|
|
202
|
-
)),
|
|
174
|
+
enable_backend_strings=isinstance(session_cfg, ChatSession.Config),
|
|
203
175
|
)) as injector:
|
|
204
176
|
await injector[Session].run()
|
|
205
177
|
|
|
@@ -20,7 +20,7 @@ class _CatalogBackendProvider(BackendProvider[ServiceT], lang.Abstract):
|
|
|
20
20
|
self,
|
|
21
21
|
*,
|
|
22
22
|
name: BackendName,
|
|
23
|
-
catalog: mc.BackendCatalog,
|
|
23
|
+
catalog: 'mc.BackendCatalog',
|
|
24
24
|
configs: BackendConfigs | None = None,
|
|
25
25
|
) -> None:
|
|
26
26
|
super().__init__()
|
|
@@ -41,16 +41,16 @@ class _CatalogBackendProvider(BackendProvider[ServiceT], lang.Abstract):
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
class CatalogChatChoicesServiceBackendProvider(
|
|
44
|
-
_CatalogBackendProvider[mc.ChatChoicesService],
|
|
44
|
+
_CatalogBackendProvider['mc.ChatChoicesService'],
|
|
45
45
|
ChatChoicesServiceBackendProvider,
|
|
46
46
|
):
|
|
47
|
-
def provide_backend(self) -> ta.AsyncContextManager[mc.ChatChoicesService]:
|
|
47
|
+
def provide_backend(self) -> ta.AsyncContextManager['mc.ChatChoicesService']:
|
|
48
48
|
return self._provide_backend(mc.ChatChoicesService) # type: ignore[type-abstract]
|
|
49
49
|
|
|
50
50
|
|
|
51
51
|
class CatalogChatChoicesStreamServiceBackendProvider(
|
|
52
|
-
_CatalogBackendProvider[mc.ChatChoicesStreamService],
|
|
52
|
+
_CatalogBackendProvider['mc.ChatChoicesStreamService'],
|
|
53
53
|
ChatChoicesStreamServiceBackendProvider,
|
|
54
54
|
):
|
|
55
|
-
def provide_backend(self) -> ta.AsyncContextManager[mc.ChatChoicesStreamService]:
|
|
55
|
+
def provide_backend(self) -> ta.AsyncContextManager['mc.ChatChoicesStreamService']:
|
|
56
56
|
return self._provide_backend(mc.ChatChoicesStreamService) # type: ignore[type-abstract]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from omlish import inject as inj
|
|
2
|
+
from omlish import lang
|
|
3
|
+
|
|
4
|
+
from .injection import backend_configs
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
with lang.auto_proxy_import(globals()):
|
|
8
|
+
from . import catalog as _catalog
|
|
9
|
+
from . import types as _types
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def bind_backends(
|
|
16
|
+
*,
|
|
17
|
+
backend: str | None = None,
|
|
18
|
+
) -> inj.Elements:
|
|
19
|
+
els: list[inj.Elemental] = []
|
|
20
|
+
|
|
21
|
+
#
|
|
22
|
+
|
|
23
|
+
els.append(backend_configs().bind_items_provider(singleton=True))
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
|
|
27
|
+
if backend is not None:
|
|
28
|
+
els.append(inj.bind(_types.BackendName, to_const=backend))
|
|
29
|
+
|
|
30
|
+
els.extend([
|
|
31
|
+
inj.bind(_types.ChatChoicesServiceBackendProvider, to_ctor=_catalog.CatalogChatChoicesServiceBackendProvider, singleton=True), # noqa
|
|
32
|
+
inj.bind(_types.ChatChoicesStreamServiceBackendProvider, to_ctor=_catalog.CatalogChatChoicesStreamServiceBackendProvider, singleton=True), # noqa
|
|
33
|
+
])
|
|
34
|
+
|
|
35
|
+
#
|
|
36
|
+
|
|
37
|
+
return inj.as_elements(*els)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from omlish import inject as inj
|
|
2
|
+
from omlish import lang
|
|
3
|
+
|
|
4
|
+
from ..... import minichain as mc
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
with lang.auto_proxy_import(globals()):
|
|
8
|
+
from . import types as _types
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@lang.cached_function
|
|
15
|
+
def backend_configs() -> 'inj.ItemsBinderHelper[mc.Config]':
|
|
16
|
+
return inj.items_binder_helper[mc.Config](_types.BackendConfigs)
|
|
@@ -13,7 +13,7 @@ ServiceT = ta.TypeVar('ServiceT', bound=mc.Service)
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
BackendName = ta.NewType('BackendName', str)
|
|
16
|
-
BackendConfigs = ta.NewType('BackendConfigs', ta.Sequence[mc.Config])
|
|
16
|
+
BackendConfigs = ta.NewType('BackendConfigs', ta.Sequence['mc.Config'])
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
##
|
|
@@ -28,9 +28,9 @@ class BackendProvider(lang.Abstract, ta.Generic[ServiceT]):
|
|
|
28
28
|
##
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
class ChatChoicesServiceBackendProvider(BackendProvider[mc.ChatChoicesService], lang.Abstract):
|
|
31
|
+
class ChatChoicesServiceBackendProvider(BackendProvider['mc.ChatChoicesService'], lang.Abstract):
|
|
32
32
|
pass
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
class ChatChoicesStreamServiceBackendProvider(BackendProvider[mc.ChatChoicesStreamService], lang.Abstract):
|
|
35
|
+
class ChatChoicesStreamServiceBackendProvider(BackendProvider['mc.ChatChoicesStreamService'], lang.Abstract):
|
|
36
36
|
pass
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from omlish import inject as inj
|
|
2
|
+
from omlish import lang
|
|
3
|
+
|
|
4
|
+
from ...... import minichain as mc
|
|
5
|
+
from .injection import chat_options_providers
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
with lang.auto_proxy_import(globals()):
|
|
9
|
+
from . import rendering as _rendering
|
|
10
|
+
from . import services as _services
|
|
11
|
+
from . import tools as _tools
|
|
12
|
+
from . import types as _types
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def bind_ai(
|
|
19
|
+
*,
|
|
20
|
+
stream: bool = False,
|
|
21
|
+
silent: bool = False,
|
|
22
|
+
enable_tools: bool = False,
|
|
23
|
+
) -> inj.Elements:
|
|
24
|
+
els: list[inj.Elemental] = []
|
|
25
|
+
|
|
26
|
+
#
|
|
27
|
+
|
|
28
|
+
els.append(chat_options_providers().bind_items_provider(singleton=True))
|
|
29
|
+
|
|
30
|
+
def _provide_chat_choices_options_provider(
|
|
31
|
+
ps: _services.ChatChoicesServiceOptionsProviders,
|
|
32
|
+
) -> _services.ChatChoicesServiceOptionsProvider:
|
|
33
|
+
return _services.ChatChoicesServiceOptionsProvider(lambda: [o for p in ps for o in p()])
|
|
34
|
+
|
|
35
|
+
els.append(inj.bind(_provide_chat_choices_options_provider, singleton=True))
|
|
36
|
+
|
|
37
|
+
#
|
|
38
|
+
|
|
39
|
+
if stream:
|
|
40
|
+
ai_stack = inj.wrapper_binder_helper(_types.StreamAiChatGenerator)
|
|
41
|
+
|
|
42
|
+
els.append(ai_stack.push_bind(to_ctor=_services.ChatChoicesStreamServiceStreamAiChatGenerator, singleton=True))
|
|
43
|
+
|
|
44
|
+
if not silent:
|
|
45
|
+
els.append(ai_stack.push_bind(to_ctor=_rendering.RenderingStreamAiChatGenerator, singleton=True))
|
|
46
|
+
|
|
47
|
+
if enable_tools:
|
|
48
|
+
raise NotImplementedError
|
|
49
|
+
|
|
50
|
+
els.extend([
|
|
51
|
+
inj.bind(_types.StreamAiChatGenerator, to_key=ai_stack.top),
|
|
52
|
+
inj.bind(_types.AiChatGenerator, to_key=_types.StreamAiChatGenerator),
|
|
53
|
+
])
|
|
54
|
+
|
|
55
|
+
else:
|
|
56
|
+
ai_stack = inj.wrapper_binder_helper(_types.AiChatGenerator)
|
|
57
|
+
|
|
58
|
+
els.append(ai_stack.push_bind(to_ctor=_services.ChatChoicesServiceAiChatGenerator, singleton=True))
|
|
59
|
+
|
|
60
|
+
if not silent:
|
|
61
|
+
els.append(ai_stack.push_bind(to_ctor=_rendering.RenderingAiChatGenerator, singleton=True))
|
|
62
|
+
|
|
63
|
+
if enable_tools:
|
|
64
|
+
els.append(ai_stack.push_bind(to_ctor=_tools.ToolExecutingAiChatGenerator, singleton=True))
|
|
65
|
+
|
|
66
|
+
els.append(inj.bind(_types.AiChatGenerator, to_key=ai_stack.top))
|
|
67
|
+
|
|
68
|
+
#
|
|
69
|
+
|
|
70
|
+
if enable_tools:
|
|
71
|
+
def _provide_tools_chat_choices_options_provider(tc: mc.ToolCatalog) -> _services.ChatChoicesServiceOptionsProvider: # noqa
|
|
72
|
+
return _services.ChatChoicesServiceOptionsProvider(lambda: [
|
|
73
|
+
mc.Tool(tce.spec)
|
|
74
|
+
for tce in tc.by_name.values()
|
|
75
|
+
])
|
|
76
|
+
|
|
77
|
+
els.append(chat_options_providers().bind_item(to_fn=_provide_tools_chat_choices_options_provider, singleton=True)) # noqa
|
|
78
|
+
|
|
79
|
+
#
|
|
80
|
+
|
|
81
|
+
return inj.as_elements(*els)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from omlish import inject as inj
|
|
2
|
+
from omlish import lang
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
with lang.auto_proxy_import(globals()):
|
|
6
|
+
from . import services as _services
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@lang.cached_function
|
|
13
|
+
def chat_options_providers() -> 'inj.ItemsBinderHelper[_services.ChatChoicesServiceOptionsProvider]':
|
|
14
|
+
return inj.items_binder_helper[_services.ChatChoicesServiceOptionsProvider](_services.ChatChoicesServiceOptionsProviders) # noqa
|
|
@@ -4,6 +4,7 @@ from ...... import minichain as mc
|
|
|
4
4
|
from ...content.messages import MessageContentExtractor
|
|
5
5
|
from ...content.messages import MessageContentExtractorImpl
|
|
6
6
|
from ...rendering.types import ContentRendering
|
|
7
|
+
from ...rendering.types import StreamContentRendering
|
|
7
8
|
from .types import AiChatGenerator
|
|
8
9
|
from .types import StreamAiChatGenerator
|
|
9
10
|
|
|
@@ -27,7 +28,7 @@ class RenderingAiChatGenerator(AiChatGenerator):
|
|
|
27
28
|
self._extractor = extractor
|
|
28
29
|
self._renderer = renderer
|
|
29
30
|
|
|
30
|
-
async def get_next_ai_messages(self, chat: mc.Chat) -> mc.
|
|
31
|
+
async def get_next_ai_messages(self, chat: 'mc.Chat') -> 'mc.Chat':
|
|
31
32
|
out = await self._wrapped.get_next_ai_messages(chat)
|
|
32
33
|
|
|
33
34
|
for msg in out:
|
|
@@ -43,7 +44,7 @@ class RenderingStreamAiChatGenerator(StreamAiChatGenerator):
|
|
|
43
44
|
*,
|
|
44
45
|
wrapped: StreamAiChatGenerator,
|
|
45
46
|
extractor: MessageContentExtractor | None = None,
|
|
46
|
-
renderer:
|
|
47
|
+
renderer: StreamContentRendering,
|
|
47
48
|
) -> None:
|
|
48
49
|
super().__init__()
|
|
49
50
|
|
|
@@ -55,13 +56,15 @@ class RenderingStreamAiChatGenerator(StreamAiChatGenerator):
|
|
|
55
56
|
|
|
56
57
|
async def get_next_ai_messages_streamed(
|
|
57
58
|
self,
|
|
58
|
-
chat: mc.Chat,
|
|
59
|
-
delta_callback: ta.Callable[[mc.AiChoiceDelta], ta.Awaitable[None]] | None = None,
|
|
60
|
-
) -> mc.
|
|
61
|
-
async
|
|
62
|
-
|
|
59
|
+
chat: 'mc.Chat',
|
|
60
|
+
delta_callback: ta.Callable[['mc.AiChoiceDelta'], ta.Awaitable[None]] | None = None,
|
|
61
|
+
) -> mc.Chat:
|
|
62
|
+
async with self._renderer.create_context() as renderer:
|
|
63
|
+
async def inner(delta: mc.AiChoiceDelta) -> None:
|
|
64
|
+
if isinstance(delta, mc.ContentAiChoiceDelta):
|
|
65
|
+
await renderer.render_content(delta.c)
|
|
63
66
|
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
if delta_callback is not None:
|
|
68
|
+
await delta_callback(delta)
|
|
66
69
|
|
|
67
|
-
|
|
70
|
+
return await self._wrapped.get_next_ai_messages_streamed(chat, delta_callback=inner)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from omlish import check
|
|
4
|
+
from omlish import lang
|
|
5
|
+
|
|
6
|
+
from ...... import minichain as mc
|
|
7
|
+
from ...backends.types import ChatChoicesServiceBackendProvider
|
|
8
|
+
from ...backends.types import ChatChoicesStreamServiceBackendProvider
|
|
9
|
+
from .types import AiChatGenerator
|
|
10
|
+
from .types import StreamAiChatGenerator
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ChatChoicesServiceOptionsProvider(lang.Func0[ta.Sequence['mc.ChatChoicesOptions']]):
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
ChatChoicesServiceOptionsProviders = ta.NewType('ChatChoicesServiceOptionsProviders', ta.Sequence[ChatChoicesServiceOptionsProvider]) # noqa
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ChatChoicesServiceAiChatGenerator(AiChatGenerator):
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
service_provider: ChatChoicesServiceBackendProvider,
|
|
30
|
+
*,
|
|
31
|
+
options: ChatChoicesServiceOptionsProvider | None = None,
|
|
32
|
+
) -> None:
|
|
33
|
+
super().__init__()
|
|
34
|
+
|
|
35
|
+
self._service_provider = service_provider
|
|
36
|
+
self._options = options
|
|
37
|
+
|
|
38
|
+
async def get_next_ai_messages(self, chat: 'mc.Chat') -> 'mc.Chat':
|
|
39
|
+
opts = self._options() if self._options is not None else []
|
|
40
|
+
|
|
41
|
+
async with self._service_provider.provide_backend() as service:
|
|
42
|
+
resp = await service.invoke(mc.ChatChoicesRequest(chat, opts))
|
|
43
|
+
|
|
44
|
+
return check.single(resp.v).ms
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class ChatChoicesStreamServiceStreamAiChatGenerator(StreamAiChatGenerator):
|
|
48
|
+
def __init__(
|
|
49
|
+
self,
|
|
50
|
+
service_provider: ChatChoicesStreamServiceBackendProvider,
|
|
51
|
+
*,
|
|
52
|
+
options: ChatChoicesServiceOptionsProvider | None = None,
|
|
53
|
+
) -> None:
|
|
54
|
+
super().__init__()
|
|
55
|
+
|
|
56
|
+
self._service_provider = service_provider
|
|
57
|
+
self._options = options
|
|
58
|
+
|
|
59
|
+
async def get_next_ai_messages_streamed(
|
|
60
|
+
self,
|
|
61
|
+
chat: 'mc.Chat',
|
|
62
|
+
delta_callback: ta.Callable[['mc.AiChoiceDelta'], ta.Awaitable[None]] | None = None,
|
|
63
|
+
) -> mc.AiChat:
|
|
64
|
+
opts = self._options() if self._options is not None else []
|
|
65
|
+
|
|
66
|
+
lst: list[str] = []
|
|
67
|
+
|
|
68
|
+
async with self._service_provider.provide_backend() as service:
|
|
69
|
+
async with (await service.invoke(mc.ChatChoicesStreamRequest(chat, opts))).v as st_resp:
|
|
70
|
+
async for o in st_resp:
|
|
71
|
+
choice = check.single(o.choices)
|
|
72
|
+
|
|
73
|
+
for delta in choice.deltas:
|
|
74
|
+
if delta_callback is not None:
|
|
75
|
+
await delta_callback(delta)
|
|
76
|
+
|
|
77
|
+
c = check.isinstance(delta, mc.ContentAiChoiceDelta).c # noqa
|
|
78
|
+
if c is not None:
|
|
79
|
+
lst.append(check.isinstance(c, str))
|
|
80
|
+
|
|
81
|
+
return [mc.AiMessage(''.join(lst))]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from ...... import minichain as mc
|
|
2
|
+
from ...tools.execution import ToolUseExecutor
|
|
3
|
+
from .types import AiChatGenerator
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ToolExecutingAiChatGenerator(AiChatGenerator):
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
*,
|
|
13
|
+
wrapped: AiChatGenerator,
|
|
14
|
+
executor: ToolUseExecutor,
|
|
15
|
+
) -> None:
|
|
16
|
+
super().__init__()
|
|
17
|
+
|
|
18
|
+
self._wrapped = wrapped
|
|
19
|
+
self._executor = executor
|
|
20
|
+
|
|
21
|
+
async def get_next_ai_messages(self, chat: 'mc.Chat') -> 'mc.Chat':
|
|
22
|
+
out: list[mc.Message] = []
|
|
23
|
+
|
|
24
|
+
while True:
|
|
25
|
+
new = await self._wrapped.get_next_ai_messages([*chat, *out])
|
|
26
|
+
|
|
27
|
+
out.extend(new)
|
|
28
|
+
|
|
29
|
+
cont = False
|
|
30
|
+
|
|
31
|
+
for msg in new:
|
|
32
|
+
if isinstance(msg, mc.ToolUseMessage):
|
|
33
|
+
trm = await self._executor.execute_tool_use(
|
|
34
|
+
msg.tu,
|
|
35
|
+
# fs_tool_context,
|
|
36
|
+
# todo_tool_context, # noqa
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
out.append(trm)
|
|
40
|
+
|
|
41
|
+
cont = True
|
|
42
|
+
|
|
43
|
+
if not cont:
|
|
44
|
+
return out
|
|
@@ -11,18 +11,18 @@ from ...... import minichain as mc
|
|
|
11
11
|
|
|
12
12
|
class AiChatGenerator(lang.Abstract):
|
|
13
13
|
@abc.abstractmethod
|
|
14
|
-
def get_next_ai_messages(self, chat: mc.Chat) -> ta.Awaitable[mc.
|
|
14
|
+
def get_next_ai_messages(self, chat: 'mc.Chat') -> ta.Awaitable['mc.Chat']:
|
|
15
15
|
raise NotImplementedError
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class StreamAiChatGenerator(AiChatGenerator, lang.Abstract):
|
|
19
|
-
def get_next_ai_messages(self, chat: mc.Chat) -> ta.Awaitable[mc.
|
|
19
|
+
def get_next_ai_messages(self, chat: 'mc.Chat') -> ta.Awaitable['mc.Chat']:
|
|
20
20
|
return self.get_next_ai_messages_streamed(chat)
|
|
21
21
|
|
|
22
22
|
@abc.abstractmethod
|
|
23
23
|
def get_next_ai_messages_streamed(
|
|
24
24
|
self,
|
|
25
|
-
chat: mc.Chat,
|
|
26
|
-
delta_callback: ta.Callable[[mc.AiChoiceDelta], ta.Awaitable[None]] | None = None,
|
|
27
|
-
) -> ta.Awaitable[mc.
|
|
25
|
+
chat: 'mc.Chat',
|
|
26
|
+
delta_callback: ta.Callable[['mc.AiChoiceDelta'], ta.Awaitable[None]] | None = None,
|
|
27
|
+
) -> ta.Awaitable['mc.Chat']:
|
|
28
28
|
raise NotImplementedError
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from omlish import inject as inj
|
|
4
|
+
from omlish import lang
|
|
5
|
+
|
|
6
|
+
from ...phases.injection import phase_callbacks
|
|
7
|
+
from ...phases.types import ChatPhase
|
|
8
|
+
from ...phases.types import ChatPhaseCallback
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
with lang.auto_proxy_import(globals()):
|
|
12
|
+
from . import inmemory as _inmemory
|
|
13
|
+
from . import storage as _storage
|
|
14
|
+
from . import types as _types
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def bind_state(
|
|
21
|
+
*,
|
|
22
|
+
state: ta.Literal['new', 'continue', 'ephemeral'] = 'continue',
|
|
23
|
+
) -> inj.Elements:
|
|
24
|
+
els: list[inj.Elemental] = []
|
|
25
|
+
|
|
26
|
+
if state in ('continue', 'new'):
|
|
27
|
+
els.append(inj.bind(_types.ChatStateManager, to_ctor=_storage.StateStorageChatStateManager, singleton=True))
|
|
28
|
+
|
|
29
|
+
if state == 'new':
|
|
30
|
+
els.append(phase_callbacks().bind_item(to_fn=lang.typed_lambda(cm=_types.ChatStateManager)(
|
|
31
|
+
lambda cm: ChatPhaseCallback(ChatPhase.STARTING, cm.clear_state),
|
|
32
|
+
)))
|
|
33
|
+
|
|
34
|
+
elif state == 'ephemeral':
|
|
35
|
+
els.append(inj.bind(_types.ChatStateManager, to_ctor=_inmemory.InMemoryChatStateManager, singleton=True))
|
|
36
|
+
|
|
37
|
+
else:
|
|
38
|
+
raise TypeError(state)
|
|
39
|
+
|
|
40
|
+
return inj.as_elements(*els)
|
|
@@ -25,7 +25,7 @@ class InMemoryChatStateManager(ChatStateManager):
|
|
|
25
25
|
self._state = ChatState()
|
|
26
26
|
return self._state
|
|
27
27
|
|
|
28
|
-
async def extend_chat(self, chat_additions: mc.Chat) -> ChatState:
|
|
28
|
+
async def extend_chat(self, chat_additions: 'mc.Chat') -> ChatState:
|
|
29
29
|
self._state = dc.replace(
|
|
30
30
|
self._state,
|
|
31
31
|
chat=[*self._state.chat, *chat_additions],
|
|
@@ -41,7 +41,7 @@ class StateStorageChatStateManager(ChatStateManager):
|
|
|
41
41
|
self._state = state
|
|
42
42
|
return state
|
|
43
43
|
|
|
44
|
-
async def extend_chat(self, chat_additions: mc.Chat) -> ChatState:
|
|
44
|
+
async def extend_chat(self, chat_additions: 'mc.Chat') -> ChatState:
|
|
45
45
|
state = await self.get_state()
|
|
46
46
|
state = dc.replace(
|
|
47
47
|
state,
|
|
@@ -34,5 +34,5 @@ class ChatStateManager(lang.Abstract):
|
|
|
34
34
|
raise NotImplementedError
|
|
35
35
|
|
|
36
36
|
@abc.abstractmethod
|
|
37
|
-
def extend_chat(self, chat_additions: mc.Chat) -> ta.Awaitable[ChatState]:
|
|
37
|
+
def extend_chat(self, chat_additions: 'mc.Chat') -> ta.Awaitable[ChatState]:
|
|
38
38
|
raise NotImplementedError
|