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
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import abc
|
|
2
|
-
import typing as ta
|
|
3
|
-
|
|
4
|
-
from omdev.tui import rich
|
|
5
|
-
from omlish import check
|
|
6
|
-
from omlish import lang
|
|
7
|
-
from omlish.formats import json
|
|
8
|
-
|
|
9
|
-
from .... import minichain as mc
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
##
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class ChatSessionPrinter(lang.Abstract):
|
|
16
|
-
@abc.abstractmethod
|
|
17
|
-
def print(self, obj: mc.Message | mc.Content) -> None:
|
|
18
|
-
raise NotImplementedError
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
#
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class StringChatSessionPrinter(ChatSessionPrinter, lang.Abstract):
|
|
25
|
-
@abc.abstractmethod
|
|
26
|
-
def _print_str(self, s: str) -> None:
|
|
27
|
-
raise NotImplementedError
|
|
28
|
-
|
|
29
|
-
def print(self, obj: mc.Message | mc.Content) -> None:
|
|
30
|
-
if obj is None:
|
|
31
|
-
pass
|
|
32
|
-
|
|
33
|
-
elif isinstance(obj, mc.Message):
|
|
34
|
-
if isinstance(obj, mc.SystemMessage):
|
|
35
|
-
if obj.c is not None:
|
|
36
|
-
self._print_str(check.isinstance(obj.c, str))
|
|
37
|
-
elif isinstance(obj, mc.UserMessage):
|
|
38
|
-
if obj.c is not None:
|
|
39
|
-
self._print_str(check.isinstance(obj.c, str))
|
|
40
|
-
elif isinstance(obj, mc.AiMessage):
|
|
41
|
-
if obj.c is not None:
|
|
42
|
-
self._print_str(check.isinstance(obj.c, str))
|
|
43
|
-
elif isinstance(obj, mc.ToolUseResultMessage):
|
|
44
|
-
self._print_str(check.isinstance(obj.tur.c, str))
|
|
45
|
-
else:
|
|
46
|
-
raise TypeError(obj)
|
|
47
|
-
|
|
48
|
-
elif isinstance(obj, mc.JsonContent):
|
|
49
|
-
self._print_str(json.dumps_pretty(obj.v))
|
|
50
|
-
|
|
51
|
-
elif isinstance(obj, str):
|
|
52
|
-
self._print_str(obj)
|
|
53
|
-
|
|
54
|
-
else:
|
|
55
|
-
raise TypeError(obj)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
#
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
class SimpleStringChatSessionPrinter(StringChatSessionPrinter):
|
|
62
|
-
def __init__(
|
|
63
|
-
self,
|
|
64
|
-
*,
|
|
65
|
-
str_printer: ta.Callable[[str], None] | None = None,
|
|
66
|
-
) -> None:
|
|
67
|
-
super().__init__()
|
|
68
|
-
|
|
69
|
-
if str_printer is None:
|
|
70
|
-
str_printer = print
|
|
71
|
-
self._str_printer = str_printer
|
|
72
|
-
|
|
73
|
-
def _print_str(self, s: str) -> None:
|
|
74
|
-
s = s.strip()
|
|
75
|
-
if not s:
|
|
76
|
-
return
|
|
77
|
-
|
|
78
|
-
self._str_printer(s)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
#
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
class MarkdownStringChatSessionPrinter(StringChatSessionPrinter):
|
|
85
|
-
def _print_str(self, s: str) -> None:
|
|
86
|
-
s = s.strip()
|
|
87
|
-
if not s:
|
|
88
|
-
return
|
|
89
|
-
|
|
90
|
-
rich.Console().print(rich.Markdown(s))
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
##
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
class StreamPrinter(lang.ExitStacked, lang.Abstract):
|
|
97
|
-
@abc.abstractmethod
|
|
98
|
-
def feed(self, s: str) -> None:
|
|
99
|
-
raise NotImplementedError
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
#
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
class SimpleStreamPrinter(StreamPrinter):
|
|
106
|
-
def feed(self, s: str) -> None:
|
|
107
|
-
print(s, end='', flush=True)
|
|
108
|
-
|
|
109
|
-
def _exit_contexts(self) -> None:
|
|
110
|
-
super()._exit_contexts()
|
|
111
|
-
print(flush=True)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
#
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
class MarkdownStreamPrinter(StreamPrinter):
|
|
118
|
-
def __init__(self) -> None:
|
|
119
|
-
super().__init__()
|
|
120
|
-
|
|
121
|
-
def _enter_contexts(self) -> None:
|
|
122
|
-
super()._enter_contexts()
|
|
123
|
-
self._ir: rich.MarkdownLiveStream = self._enter_context(rich.IncrementalMarkdownLiveStream())
|
|
124
|
-
|
|
125
|
-
def feed(self, s: str) -> None:
|
|
126
|
-
self._ir.feed(s)
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
import dataclasses as dc
|
|
2
|
-
import os
|
|
3
|
-
|
|
4
|
-
from omlish import check
|
|
5
|
-
from omlish import lang
|
|
6
|
-
|
|
7
|
-
from .... import minichain as mc
|
|
8
|
-
from .base import DEFAULT_CHAT_MODEL_BACKEND
|
|
9
|
-
from .base import ChatOptions
|
|
10
|
-
from .base import ChatSession
|
|
11
|
-
from .printing import ChatSessionPrinter
|
|
12
|
-
from .printing import MarkdownStreamPrinter
|
|
13
|
-
from .printing import SimpleStreamPrinter
|
|
14
|
-
from .printing import StreamPrinter
|
|
15
|
-
from .state import ChatStateManager
|
|
16
|
-
from .tools import ToolUseExecutor
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
##
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class ToolExecutionRequestDeniedError(Exception):
|
|
23
|
-
pass
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class PromptChatSession(ChatSession['PromptChatSession.Config']):
|
|
27
|
-
@dc.dataclass(frozen=True)
|
|
28
|
-
class Config(ChatSession.Config): # noqa
|
|
29
|
-
content: mc.Content
|
|
30
|
-
|
|
31
|
-
_: dc.KW_ONLY
|
|
32
|
-
|
|
33
|
-
new: bool = False
|
|
34
|
-
|
|
35
|
-
backend: str | None = None
|
|
36
|
-
model_name: str | None = None
|
|
37
|
-
|
|
38
|
-
stream: bool = False
|
|
39
|
-
|
|
40
|
-
def __init__(
|
|
41
|
-
self,
|
|
42
|
-
config: Config,
|
|
43
|
-
*,
|
|
44
|
-
state_manager: ChatStateManager,
|
|
45
|
-
chat_options: ChatOptions | None = None,
|
|
46
|
-
printer: ChatSessionPrinter,
|
|
47
|
-
backend_catalog: mc.BackendCatalog,
|
|
48
|
-
tool_exec_request_executor: ToolUseExecutor,
|
|
49
|
-
) -> None:
|
|
50
|
-
super().__init__(config)
|
|
51
|
-
|
|
52
|
-
self._state_manager = state_manager
|
|
53
|
-
self._chat_options = chat_options
|
|
54
|
-
self._printer = printer
|
|
55
|
-
self._backend_catalog = backend_catalog
|
|
56
|
-
self._tool_exec_request_executor = tool_exec_request_executor
|
|
57
|
-
|
|
58
|
-
async def run(self) -> None:
|
|
59
|
-
if self._config.stream:
|
|
60
|
-
await self._run_stream()
|
|
61
|
-
else:
|
|
62
|
-
await self._run_immediate()
|
|
63
|
-
|
|
64
|
-
async def _run_stream(self) -> None:
|
|
65
|
-
prompt = check.isinstance(self._config.content, str)
|
|
66
|
-
|
|
67
|
-
if self._config.new:
|
|
68
|
-
state = self._state_manager.clear_state()
|
|
69
|
-
else:
|
|
70
|
-
state = self._state_manager.get_state()
|
|
71
|
-
|
|
72
|
-
new_chat: list[mc.Message] = [
|
|
73
|
-
mc.UserMessage(prompt),
|
|
74
|
-
]
|
|
75
|
-
|
|
76
|
-
mdl: mc.ChatChoicesStreamService
|
|
77
|
-
async with lang.async_maybe_managing(self._backend_catalog.get_backend(
|
|
78
|
-
mc.ChatChoicesStreamService,
|
|
79
|
-
self._config.backend or DEFAULT_CHAT_MODEL_BACKEND,
|
|
80
|
-
*([mc.ModelName(mn)] if (mn := self._config.model_name) is not None else []),
|
|
81
|
-
)) as mdl:
|
|
82
|
-
async with (await mdl.invoke(mc.ChatChoicesStreamRequest(
|
|
83
|
-
[*state.chat, *new_chat],
|
|
84
|
-
(self._chat_options or []),
|
|
85
|
-
))).v as st_resp:
|
|
86
|
-
lst: list[str] = []
|
|
87
|
-
|
|
88
|
-
sp_cls: type[StreamPrinter]
|
|
89
|
-
if self._config.markdown:
|
|
90
|
-
sp_cls = MarkdownStreamPrinter
|
|
91
|
-
else:
|
|
92
|
-
sp_cls = SimpleStreamPrinter
|
|
93
|
-
with sp_cls() as sp:
|
|
94
|
-
async for o in st_resp:
|
|
95
|
-
if o:
|
|
96
|
-
c = check.isinstance(check.single(check.single(o.choices).deltas), mc.ContentAiChoiceDelta).c # noqa
|
|
97
|
-
if c is not None:
|
|
98
|
-
s = check.isinstance(c, str)
|
|
99
|
-
sp.feed(s)
|
|
100
|
-
lst.append(s)
|
|
101
|
-
|
|
102
|
-
resp_m = mc.AiMessage(''.join(lst))
|
|
103
|
-
new_chat.append(resp_m)
|
|
104
|
-
|
|
105
|
-
self._state_manager.extend_chat(new_chat)
|
|
106
|
-
|
|
107
|
-
async def _run_immediate(self) -> None:
|
|
108
|
-
prompt = check.isinstance(self._config.content, str)
|
|
109
|
-
|
|
110
|
-
if self._config.new:
|
|
111
|
-
state = self._state_manager.clear_state()
|
|
112
|
-
else:
|
|
113
|
-
state = self._state_manager.get_state()
|
|
114
|
-
|
|
115
|
-
new_chat: list[mc.Message] = [
|
|
116
|
-
mc.UserMessage(prompt),
|
|
117
|
-
]
|
|
118
|
-
|
|
119
|
-
mdl: mc.ChatChoicesService
|
|
120
|
-
async with lang.async_maybe_managing(self._backend_catalog.get_backend(
|
|
121
|
-
mc.ChatChoicesService,
|
|
122
|
-
self._config.backend or DEFAULT_CHAT_MODEL_BACKEND,
|
|
123
|
-
*([mc.ModelName(mn)] if (mn := self._config.model_name) is not None else []),
|
|
124
|
-
)) as mdl:
|
|
125
|
-
response: mc.ChatChoicesResponse = await mdl.invoke(mc.ChatChoicesRequest(
|
|
126
|
-
[*state.chat, *new_chat],
|
|
127
|
-
(self._chat_options or []),
|
|
128
|
-
))
|
|
129
|
-
|
|
130
|
-
for resp_m in response.v[0].ms:
|
|
131
|
-
new_chat.append(resp_m)
|
|
132
|
-
|
|
133
|
-
if isinstance(resp_m, mc.AiMessage):
|
|
134
|
-
self._printer.print(resp_m)
|
|
135
|
-
|
|
136
|
-
elif isinstance(resp_m, mc.ToolUseMessage):
|
|
137
|
-
tr: mc.ToolUse = resp_m.tu
|
|
138
|
-
|
|
139
|
-
# FIXME: lol
|
|
140
|
-
from ....minichain.lib.fs.context import FsContext
|
|
141
|
-
|
|
142
|
-
trm = await self._tool_exec_request_executor.execute_tool_use(
|
|
143
|
-
tr,
|
|
144
|
-
FsContext(root_dir=os.getcwd()),
|
|
145
|
-
)
|
|
146
|
-
|
|
147
|
-
print(trm.tur.c)
|
|
148
|
-
new_chat.append(trm)
|
|
149
|
-
|
|
150
|
-
response = await mdl.invoke(mc.ChatChoicesRequest(
|
|
151
|
-
[*state.chat, *new_chat],
|
|
152
|
-
(self._chat_options or []),
|
|
153
|
-
))
|
|
154
|
-
|
|
155
|
-
resp_m = check.isinstance(check.single(response.v[0].ms), mc.AiMessage)
|
|
156
|
-
new_chat.append(resp_m)
|
|
157
|
-
|
|
158
|
-
else:
|
|
159
|
-
raise TypeError(resp_m)
|
|
160
|
-
|
|
161
|
-
self._state_manager.extend_chat(new_chat)
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import abc
|
|
2
|
-
import dataclasses as dc
|
|
3
|
-
import datetime
|
|
4
|
-
|
|
5
|
-
from omlish import check
|
|
6
|
-
from omlish import lang
|
|
7
|
-
|
|
8
|
-
from .... import minichain as mc
|
|
9
|
-
from ...state import StateStorage
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
##
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@dc.dataclass(frozen=True)
|
|
16
|
-
class ChatState:
|
|
17
|
-
name: str | None = None
|
|
18
|
-
|
|
19
|
-
created_at: datetime.datetime = dc.field(default_factory=lang.utcnow)
|
|
20
|
-
updated_at: datetime.datetime = dc.field(default_factory=lang.utcnow)
|
|
21
|
-
|
|
22
|
-
chat: mc.Chat = ()
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
##
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class ChatStateManager(lang.Abstract):
|
|
29
|
-
@abc.abstractmethod
|
|
30
|
-
def get_state(self) -> ChatState:
|
|
31
|
-
raise NotImplementedError
|
|
32
|
-
|
|
33
|
-
@abc.abstractmethod
|
|
34
|
-
def clear_state(self) -> ChatState:
|
|
35
|
-
raise NotImplementedError
|
|
36
|
-
|
|
37
|
-
@abc.abstractmethod
|
|
38
|
-
def extend_chat(self, chat_additions: mc.Chat) -> ChatState:
|
|
39
|
-
raise NotImplementedError
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
##
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
class InMemoryChatStateManager(ChatStateManager):
|
|
46
|
-
def __init__(self, initial_state: ChatState | None = None) -> None:
|
|
47
|
-
super().__init__()
|
|
48
|
-
|
|
49
|
-
if initial_state is None:
|
|
50
|
-
initial_state = ChatState()
|
|
51
|
-
self._state = initial_state
|
|
52
|
-
|
|
53
|
-
def get_state(self) -> ChatState:
|
|
54
|
-
return self._state
|
|
55
|
-
|
|
56
|
-
def clear_state(self) -> ChatState:
|
|
57
|
-
self._state = ChatState()
|
|
58
|
-
return self._state
|
|
59
|
-
|
|
60
|
-
def extend_chat(self, chat_additions: mc.Chat) -> ChatState:
|
|
61
|
-
self._state = dc.replace(
|
|
62
|
-
self._state,
|
|
63
|
-
chat=[*self._state.chat, *chat_additions],
|
|
64
|
-
updated_at=lang.utcnow(),
|
|
65
|
-
)
|
|
66
|
-
return self._state
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
##
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
class StateStorageChatStateManager(ChatStateManager):
|
|
73
|
-
def __init__(
|
|
74
|
-
self,
|
|
75
|
-
*,
|
|
76
|
-
storage: StateStorage,
|
|
77
|
-
key: str = 'chat',
|
|
78
|
-
) -> None:
|
|
79
|
-
super().__init__()
|
|
80
|
-
|
|
81
|
-
self._storage = storage
|
|
82
|
-
self._key = check.non_empty_str(key)
|
|
83
|
-
|
|
84
|
-
self._state: ChatState | None = None
|
|
85
|
-
|
|
86
|
-
def get_state(self) -> ChatState:
|
|
87
|
-
if self._state is not None:
|
|
88
|
-
return self._state
|
|
89
|
-
state: ChatState | None = lang.sync_await(self._storage.load_state(self._key, ChatState))
|
|
90
|
-
if state is None:
|
|
91
|
-
state = ChatState()
|
|
92
|
-
self._state = state
|
|
93
|
-
return state
|
|
94
|
-
|
|
95
|
-
def clear_state(self) -> ChatState:
|
|
96
|
-
state = ChatState()
|
|
97
|
-
lang.sync_await(self._storage.save_state(self._key, state, ChatState))
|
|
98
|
-
self._state = state
|
|
99
|
-
return state
|
|
100
|
-
|
|
101
|
-
def extend_chat(self, chat_additions: mc.Chat) -> ChatState:
|
|
102
|
-
state = self.get_state()
|
|
103
|
-
state = dc.replace(
|
|
104
|
-
state,
|
|
105
|
-
chat=[*state.chat, *chat_additions],
|
|
106
|
-
updated_at=lang.utcnow(),
|
|
107
|
-
)
|
|
108
|
-
lang.sync_await(self._storage.save_state(self._key, state, ChatState))
|
|
109
|
-
self._state = state
|
|
110
|
-
return state
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import abc
|
|
2
|
-
import typing as ta
|
|
3
|
-
|
|
4
|
-
from omlish import check
|
|
5
|
-
from omlish import lang
|
|
6
|
-
from omlish.formats import json
|
|
7
|
-
from omlish.term.confirm import confirm_action
|
|
8
|
-
|
|
9
|
-
from .... import minichain as mc
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
##
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class ToolExecutionRequestDeniedError(Exception):
|
|
16
|
-
pass
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class ToolExecutionConfirmation(lang.Abstract):
|
|
20
|
-
@abc.abstractmethod
|
|
21
|
-
def confirm_tool_execution_or_raise(
|
|
22
|
-
self,
|
|
23
|
-
tr: mc.ToolUse,
|
|
24
|
-
tce: mc.ToolCatalogEntry,
|
|
25
|
-
) -> ta.Awaitable[None]:
|
|
26
|
-
raise NotImplementedError
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class NopToolExecutionConfirmation(ToolExecutionConfirmation):
|
|
30
|
-
async def confirm_tool_execution_or_raise(
|
|
31
|
-
self,
|
|
32
|
-
tr: mc.ToolUse,
|
|
33
|
-
tce: mc.ToolCatalogEntry,
|
|
34
|
-
) -> None:
|
|
35
|
-
pass
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
class AskingToolExecutionConfirmation(ToolExecutionConfirmation):
|
|
39
|
-
async def confirm_tool_execution_or_raise(
|
|
40
|
-
self,
|
|
41
|
-
tr: mc.ToolUse,
|
|
42
|
-
tce: mc.ToolCatalogEntry,
|
|
43
|
-
) -> None:
|
|
44
|
-
tr_dct = dict(
|
|
45
|
-
id=tr.id,
|
|
46
|
-
name=tce.spec.name,
|
|
47
|
-
args=tr.args,
|
|
48
|
-
# spec=msh.marshal(tce.spec),
|
|
49
|
-
)
|
|
50
|
-
cr = confirm_action(f'Execute requested tool?\n\n{json.dumps_pretty(tr_dct)}') # FIXME: async lol
|
|
51
|
-
|
|
52
|
-
if not cr:
|
|
53
|
-
raise ToolExecutionRequestDeniedError
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
##
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class ToolUseExecutor(lang.Abstract):
|
|
60
|
-
@abc.abstractmethod
|
|
61
|
-
def execute_tool_use(
|
|
62
|
-
self,
|
|
63
|
-
tr: mc.ToolUse,
|
|
64
|
-
*ctx_items: ta.Any,
|
|
65
|
-
) -> ta.Awaitable[mc.ToolUseResultMessage]:
|
|
66
|
-
raise NotImplementedError
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
class ToolUseExecutorImpl(ToolUseExecutor):
|
|
70
|
-
def __init__(
|
|
71
|
-
self,
|
|
72
|
-
*,
|
|
73
|
-
catalog: mc.ToolCatalog,
|
|
74
|
-
confirmation: ToolExecutionConfirmation,
|
|
75
|
-
) -> None:
|
|
76
|
-
super().__init__()
|
|
77
|
-
|
|
78
|
-
self._catalog = catalog
|
|
79
|
-
self._confirmation = confirmation
|
|
80
|
-
|
|
81
|
-
async def execute_tool_use(
|
|
82
|
-
self,
|
|
83
|
-
tr: mc.ToolUse,
|
|
84
|
-
*ctx_items: ta.Any,
|
|
85
|
-
) -> mc.ToolUseResultMessage:
|
|
86
|
-
tce = self._catalog.by_name[check.non_empty_str(tr.name)]
|
|
87
|
-
|
|
88
|
-
await self._confirmation.confirm_tool_execution_or_raise(tr, tce)
|
|
89
|
-
|
|
90
|
-
return await mc.execute_tool_use(
|
|
91
|
-
mc.ToolContext(
|
|
92
|
-
tr,
|
|
93
|
-
*ctx_items,
|
|
94
|
-
),
|
|
95
|
-
tce.executor(),
|
|
96
|
-
tr,
|
|
97
|
-
)
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
from omlish import lang
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
with lang.auto_proxy_init(globals()):
|
|
5
|
-
from .backends.catalog import ( # noqa
|
|
6
|
-
CatalogChatChoicesServiceBackendProvider,
|
|
7
|
-
CatalogChatChoicesStreamServiceBackendProvider,
|
|
8
|
-
)
|
|
9
|
-
|
|
10
|
-
from .backends.types import ( # noqa
|
|
11
|
-
BackendName,
|
|
12
|
-
BackendConfigs,
|
|
13
|
-
BackendProvider,
|
|
14
|
-
ChatChoicesServiceBackendProvider,
|
|
15
|
-
ChatChoicesStreamServiceBackendProvider,
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
from .chat.ai.rendering import ( # noqa
|
|
19
|
-
RenderingAiChatGenerator,
|
|
20
|
-
RenderingStreamAiChatGenerator,
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
from .chat.ai.services import ( # noqa
|
|
24
|
-
ChatChoicesServiceOptions,
|
|
25
|
-
ChatChoicesServiceAiChatGenerator,
|
|
26
|
-
ChatChoicesStreamServiceStreamAiChatGenerator,
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
from .chat.ai.types import ( # noqa
|
|
30
|
-
AiChatGenerator,
|
|
31
|
-
StreamAiChatGenerator,
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
from .chat.state.inmemory import ( # noqa
|
|
35
|
-
InMemoryChatStateManager,
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
from .chat.state.storage import ( # noqa
|
|
39
|
-
StateStorageChatStateManager,
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
from .chat.state.types import ( # noqa
|
|
43
|
-
ChatState,
|
|
44
|
-
ChatStateManager,
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
from .chat.user.interactive import ( # noqa
|
|
48
|
-
InteractiveUserChatInput,
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
from .chat.user.oneshot import ( # noqa
|
|
52
|
-
OneshotUserChatInputInitialChat,
|
|
53
|
-
OneshotUserChatInput,
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
from .chat.user.types import ( # noqa
|
|
57
|
-
UserChatInput,
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
from .content.messages import ( # noqa
|
|
61
|
-
MessageContentExtractor,
|
|
62
|
-
MessageContentExtractorImpl,
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
from .content.strings import ( # noqa
|
|
66
|
-
ContentStringifier,
|
|
67
|
-
ContentStringifierImpl,
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
from .rendering.markdown import ( # noqa
|
|
71
|
-
MarkdownContentRendering,
|
|
72
|
-
MarkdownStreamContentRendering,
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
from .rendering.raw import ( # noqa
|
|
76
|
-
RawContentRendering,
|
|
77
|
-
RawContentStreamRendering,
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
from .rendering.types import ( # noqa
|
|
81
|
-
ContentRendering,
|
|
82
|
-
StreamContentRendering,
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
from .tools.confirmation import ( # noqa
|
|
86
|
-
ToolExecutionRequestDeniedError,
|
|
87
|
-
ToolExecutionConfirmation,
|
|
88
|
-
InteractiveToolExecutionConfirmation,
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
from .tools.execution import ( # noqa
|
|
92
|
-
ToolUseExecutor,
|
|
93
|
-
ToolUseExecutorImpl,
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
from .driver import ( # noqa
|
|
97
|
-
ChatDriver,
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
from .phases import ( # noqa
|
|
101
|
-
ChatPhase,
|
|
102
|
-
ChatPhaseCallback,
|
|
103
|
-
ChatPhaseCallbacks,
|
|
104
|
-
ChatPhaseManager,
|
|
105
|
-
)
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import typing as ta
|
|
2
|
-
|
|
3
|
-
from omlish import check
|
|
4
|
-
|
|
5
|
-
from ...... import minichain as mc
|
|
6
|
-
from ...backends.types import ChatChoicesServiceBackendProvider
|
|
7
|
-
from .types import AiChatGenerator
|
|
8
|
-
from .types import StreamAiChatGenerator
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
ChatChoicesServiceOptions = ta.NewType('ChatChoicesServiceOptions', ta.Sequence[mc.ChatChoicesOptions])
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
##
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class ChatChoicesServiceAiChatGenerator(AiChatGenerator):
|
|
21
|
-
def __init__(
|
|
22
|
-
self,
|
|
23
|
-
service_provider: ChatChoicesServiceBackendProvider,
|
|
24
|
-
*,
|
|
25
|
-
options: ChatChoicesServiceOptions | None = None,
|
|
26
|
-
) -> None:
|
|
27
|
-
super().__init__()
|
|
28
|
-
|
|
29
|
-
self._service_provider = service_provider
|
|
30
|
-
self._options = options
|
|
31
|
-
|
|
32
|
-
async def get_next_ai_messages(self, chat: mc.Chat) -> mc.AiChat:
|
|
33
|
-
async with self._service_provider.provide_backend() as service:
|
|
34
|
-
resp = await service.invoke(mc.ChatChoicesRequest(chat, self._options or []))
|
|
35
|
-
|
|
36
|
-
return check.single(resp.v).ms
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class ChatChoicesStreamServiceStreamAiChatGenerator(StreamAiChatGenerator):
|
|
40
|
-
def __init__(
|
|
41
|
-
self,
|
|
42
|
-
service: mc.ChatChoicesStreamService,
|
|
43
|
-
*,
|
|
44
|
-
options: ChatChoicesServiceOptions | None = None,
|
|
45
|
-
) -> None:
|
|
46
|
-
super().__init__()
|
|
47
|
-
|
|
48
|
-
self._service = service
|
|
49
|
-
self._options = options
|
|
50
|
-
|
|
51
|
-
async def get_next_ai_messages_streamed(
|
|
52
|
-
self,
|
|
53
|
-
chat: mc.Chat,
|
|
54
|
-
delta_callback: ta.Callable[[mc.AiChoiceDelta], ta.Awaitable[None]] | None = None,
|
|
55
|
-
) -> mc.AiChat:
|
|
56
|
-
lst: list[str] = []
|
|
57
|
-
|
|
58
|
-
async with (await self._service.invoke(mc.ChatChoicesStreamRequest(chat, self._options or []))).v as st_resp:
|
|
59
|
-
async for o in st_resp:
|
|
60
|
-
choice = check.single(o.choices)
|
|
61
|
-
|
|
62
|
-
for delta in choice.deltas:
|
|
63
|
-
if delta_callback is not None:
|
|
64
|
-
await delta_callback(delta)
|
|
65
|
-
|
|
66
|
-
c = check.isinstance(delta, mc.ContentAiChoiceDelta).c # noqa
|
|
67
|
-
if c is not None:
|
|
68
|
-
lst.append(check.isinstance(c, str))
|
|
69
|
-
|
|
70
|
-
return [mc.AiMessage(''.join(lst))]
|