ommlds 0.0.0.dev456__py3-none-any.whl → 0.0.0.dev485__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. ommlds/.omlish-manifests.json +314 -33
  2. ommlds/__about__.py +15 -9
  3. ommlds/_hacks/__init__.py +4 -0
  4. ommlds/_hacks/funcs.py +110 -0
  5. ommlds/_hacks/names.py +158 -0
  6. ommlds/_hacks/params.py +73 -0
  7. ommlds/_hacks/patches.py +0 -3
  8. ommlds/backends/anthropic/protocol/__init__.py +13 -1
  9. ommlds/backends/anthropic/protocol/_dataclasses.py +1625 -0
  10. ommlds/backends/anthropic/protocol/sse/assemble.py +22 -6
  11. ommlds/backends/anthropic/protocol/sse/events.py +13 -0
  12. ommlds/backends/google/protocol/__init__.py +13 -0
  13. ommlds/backends/google/protocol/_dataclasses.py +5997 -0
  14. ommlds/backends/google/protocol/types.py +5 -1
  15. ommlds/backends/groq/__init__.py +7 -0
  16. ommlds/backends/groq/_dataclasses.py +3901 -0
  17. ommlds/backends/groq/_marshal.py +23 -0
  18. ommlds/backends/groq/protocol.py +249 -0
  19. ommlds/backends/llamacpp/logging.py +4 -1
  20. ommlds/backends/mlx/caching.py +7 -3
  21. ommlds/backends/mlx/cli.py +10 -7
  22. ommlds/backends/mlx/generation.py +18 -16
  23. ommlds/backends/mlx/limits.py +10 -6
  24. ommlds/backends/mlx/loading.py +65 -5
  25. ommlds/backends/ollama/__init__.py +7 -0
  26. ommlds/backends/ollama/_dataclasses.py +3458 -0
  27. ommlds/backends/ollama/protocol.py +170 -0
  28. ommlds/backends/openai/protocol/__init__.py +15 -1
  29. ommlds/backends/openai/protocol/_dataclasses.py +7708 -0
  30. ommlds/backends/tavily/__init__.py +7 -0
  31. ommlds/backends/tavily/_dataclasses.py +1734 -0
  32. ommlds/backends/tavily/protocol.py +301 -0
  33. ommlds/backends/tinygrad/models/llama3/__init__.py +22 -14
  34. ommlds/backends/transformers/__init__.py +14 -0
  35. ommlds/backends/transformers/filecache.py +109 -0
  36. ommlds/backends/transformers/streamers.py +73 -0
  37. ommlds/cli/__init__.py +7 -0
  38. ommlds/cli/_dataclasses.py +2562 -0
  39. ommlds/cli/asyncs.py +30 -0
  40. ommlds/cli/backends/catalog.py +93 -0
  41. ommlds/cli/backends/configs.py +9 -0
  42. ommlds/cli/backends/inject.py +31 -36
  43. ommlds/cli/backends/injection.py +16 -0
  44. ommlds/cli/backends/types.py +46 -0
  45. ommlds/cli/content/messages.py +34 -0
  46. ommlds/cli/content/strings.py +42 -0
  47. ommlds/cli/inject.py +15 -32
  48. ommlds/cli/inputs/__init__.py +0 -0
  49. ommlds/cli/inputs/asyncs.py +32 -0
  50. ommlds/cli/inputs/sync.py +75 -0
  51. ommlds/cli/main.py +267 -128
  52. ommlds/cli/rendering/__init__.py +0 -0
  53. ommlds/cli/rendering/configs.py +9 -0
  54. ommlds/cli/rendering/inject.py +31 -0
  55. ommlds/cli/rendering/markdown.py +52 -0
  56. ommlds/cli/rendering/raw.py +73 -0
  57. ommlds/cli/rendering/types.py +21 -0
  58. ommlds/cli/secrets.py +21 -0
  59. ommlds/cli/sessions/base.py +1 -1
  60. ommlds/cli/sessions/chat/chat/__init__.py +0 -0
  61. ommlds/cli/sessions/chat/chat/ai/__init__.py +0 -0
  62. ommlds/cli/sessions/chat/chat/ai/configs.py +11 -0
  63. ommlds/cli/sessions/chat/chat/ai/inject.py +74 -0
  64. ommlds/cli/sessions/chat/chat/ai/injection.py +14 -0
  65. ommlds/cli/sessions/chat/chat/ai/rendering.py +70 -0
  66. ommlds/cli/sessions/chat/chat/ai/services.py +79 -0
  67. ommlds/cli/sessions/chat/chat/ai/tools.py +44 -0
  68. ommlds/cli/sessions/chat/chat/ai/types.py +28 -0
  69. ommlds/cli/sessions/chat/chat/state/__init__.py +0 -0
  70. ommlds/cli/sessions/chat/chat/state/configs.py +11 -0
  71. ommlds/cli/sessions/chat/chat/state/inject.py +36 -0
  72. ommlds/cli/sessions/chat/chat/state/inmemory.py +33 -0
  73. ommlds/cli/sessions/chat/chat/state/storage.py +52 -0
  74. ommlds/cli/sessions/chat/chat/state/types.py +38 -0
  75. ommlds/cli/sessions/chat/chat/user/__init__.py +0 -0
  76. ommlds/cli/sessions/chat/chat/user/configs.py +17 -0
  77. ommlds/cli/sessions/chat/chat/user/inject.py +62 -0
  78. ommlds/cli/sessions/chat/chat/user/interactive.py +31 -0
  79. ommlds/cli/sessions/chat/chat/user/oneshot.py +25 -0
  80. ommlds/cli/sessions/chat/chat/user/types.py +15 -0
  81. ommlds/cli/sessions/chat/configs.py +27 -0
  82. ommlds/cli/sessions/chat/driver.py +43 -0
  83. ommlds/cli/sessions/chat/inject.py +33 -65
  84. ommlds/cli/sessions/chat/phases/__init__.py +0 -0
  85. ommlds/cli/sessions/chat/phases/inject.py +27 -0
  86. ommlds/cli/sessions/chat/phases/injection.py +14 -0
  87. ommlds/cli/sessions/chat/phases/manager.py +29 -0
  88. ommlds/cli/sessions/chat/phases/types.py +29 -0
  89. ommlds/cli/sessions/chat/session.py +27 -0
  90. ommlds/cli/sessions/chat/tools/__init__.py +0 -0
  91. ommlds/cli/sessions/chat/tools/configs.py +22 -0
  92. ommlds/cli/sessions/chat/tools/confirmation.py +46 -0
  93. ommlds/cli/sessions/chat/tools/execution.py +66 -0
  94. ommlds/cli/sessions/chat/tools/fs/__init__.py +0 -0
  95. ommlds/cli/sessions/chat/tools/fs/configs.py +12 -0
  96. ommlds/cli/sessions/chat/tools/fs/inject.py +35 -0
  97. ommlds/cli/sessions/chat/tools/inject.py +88 -0
  98. ommlds/cli/sessions/chat/tools/injection.py +44 -0
  99. ommlds/cli/sessions/chat/tools/rendering.py +58 -0
  100. ommlds/cli/sessions/chat/tools/todo/__init__.py +0 -0
  101. ommlds/cli/sessions/chat/tools/todo/configs.py +12 -0
  102. ommlds/cli/sessions/chat/tools/todo/inject.py +31 -0
  103. ommlds/cli/sessions/chat/tools/weather/__init__.py +0 -0
  104. ommlds/cli/sessions/chat/tools/weather/configs.py +12 -0
  105. ommlds/cli/sessions/chat/tools/weather/inject.py +22 -0
  106. ommlds/cli/{tools/weather.py → sessions/chat/tools/weather/tools.py} +1 -1
  107. ommlds/cli/sessions/completion/configs.py +21 -0
  108. ommlds/cli/sessions/completion/inject.py +42 -0
  109. ommlds/cli/sessions/completion/session.py +35 -0
  110. ommlds/cli/sessions/embedding/configs.py +21 -0
  111. ommlds/cli/sessions/embedding/inject.py +42 -0
  112. ommlds/cli/sessions/embedding/session.py +33 -0
  113. ommlds/cli/sessions/inject.py +28 -11
  114. ommlds/cli/state/__init__.py +0 -0
  115. ommlds/cli/state/inject.py +28 -0
  116. ommlds/cli/{state.py → state/storage.py} +41 -24
  117. ommlds/minichain/__init__.py +46 -17
  118. ommlds/minichain/_dataclasses.py +15401 -0
  119. ommlds/minichain/backends/catalogs/base.py +20 -1
  120. ommlds/minichain/backends/catalogs/simple.py +2 -2
  121. ommlds/minichain/backends/catalogs/strings.py +10 -8
  122. ommlds/minichain/backends/impls/anthropic/chat.py +31 -65
  123. ommlds/minichain/backends/impls/anthropic/names.py +3 -4
  124. ommlds/minichain/backends/impls/anthropic/protocol.py +109 -0
  125. ommlds/minichain/backends/impls/anthropic/stream.py +53 -31
  126. ommlds/minichain/backends/impls/duckduckgo/search.py +5 -1
  127. ommlds/minichain/backends/impls/dummy/__init__.py +0 -0
  128. ommlds/minichain/backends/impls/dummy/chat.py +69 -0
  129. ommlds/minichain/backends/impls/google/chat.py +9 -2
  130. ommlds/minichain/backends/impls/google/search.py +6 -1
  131. ommlds/minichain/backends/impls/google/stream.py +122 -32
  132. ommlds/minichain/backends/impls/groq/__init__.py +0 -0
  133. ommlds/minichain/backends/impls/groq/chat.py +75 -0
  134. ommlds/minichain/backends/impls/groq/names.py +48 -0
  135. ommlds/minichain/backends/impls/groq/protocol.py +143 -0
  136. ommlds/minichain/backends/impls/groq/stream.py +125 -0
  137. ommlds/minichain/backends/impls/huggingface/repos.py +1 -5
  138. ommlds/minichain/backends/impls/llamacpp/chat.py +15 -3
  139. ommlds/minichain/backends/impls/llamacpp/completion.py +7 -3
  140. ommlds/minichain/backends/impls/llamacpp/stream.py +38 -19
  141. ommlds/minichain/backends/impls/mistral.py +9 -2
  142. ommlds/minichain/backends/impls/mlx/chat.py +100 -23
  143. ommlds/minichain/backends/impls/ollama/__init__.py +0 -0
  144. ommlds/minichain/backends/impls/ollama/chat.py +199 -0
  145. ommlds/minichain/backends/impls/openai/chat.py +14 -7
  146. ommlds/minichain/backends/impls/openai/completion.py +9 -2
  147. ommlds/minichain/backends/impls/openai/embedding.py +9 -2
  148. ommlds/minichain/backends/impls/openai/format.py +115 -109
  149. ommlds/minichain/backends/impls/openai/names.py +31 -5
  150. ommlds/minichain/backends/impls/openai/stream.py +33 -27
  151. ommlds/minichain/backends/impls/sentencepiece/tokens.py +9 -6
  152. ommlds/minichain/backends/impls/tavily.py +66 -0
  153. ommlds/minichain/backends/impls/tinygrad/chat.py +17 -14
  154. ommlds/minichain/backends/impls/tokenizers/tokens.py +9 -6
  155. ommlds/minichain/backends/impls/transformers/sentence.py +5 -2
  156. ommlds/minichain/backends/impls/transformers/tokens.py +10 -7
  157. ommlds/minichain/backends/impls/transformers/transformers.py +139 -20
  158. ommlds/minichain/backends/strings/parsing.py +1 -1
  159. ommlds/minichain/backends/strings/resolving.py +4 -1
  160. ommlds/minichain/chat/choices/stream/__init__.py +0 -0
  161. ommlds/minichain/chat/choices/stream/adapters.py +35 -0
  162. ommlds/minichain/chat/choices/stream/joining.py +31 -0
  163. ommlds/minichain/chat/choices/stream/services.py +45 -0
  164. ommlds/minichain/chat/choices/stream/types.py +43 -0
  165. ommlds/minichain/chat/stream/_marshal.py +4 -4
  166. ommlds/minichain/chat/stream/joining.py +85 -0
  167. ommlds/minichain/chat/stream/services.py +15 -15
  168. ommlds/minichain/chat/stream/types.py +24 -18
  169. ommlds/minichain/llms/types.py +4 -0
  170. ommlds/minichain/registries/globals.py +18 -4
  171. ommlds/minichain/resources.py +28 -3
  172. ommlds/minichain/search.py +1 -1
  173. ommlds/minichain/standard.py +8 -0
  174. ommlds/minichain/stream/services.py +19 -16
  175. ommlds/minichain/tools/reflect.py +5 -1
  176. ommlds/nanochat/LICENSE +21 -0
  177. ommlds/nanochat/__init__.py +0 -0
  178. ommlds/nanochat/rustbpe/LICENSE +21 -0
  179. ommlds/nanochat/tokenizers.py +406 -0
  180. ommlds/specs/__init__.py +0 -0
  181. ommlds/specs/mcp/__init__.py +0 -0
  182. ommlds/specs/mcp/_marshal.py +23 -0
  183. ommlds/specs/mcp/clients.py +146 -0
  184. ommlds/specs/mcp/protocol.py +371 -0
  185. ommlds/tools/git.py +13 -6
  186. ommlds/tools/ocr.py +1 -8
  187. ommlds/wiki/analyze.py +2 -2
  188. ommlds/wiki/text/mfh.py +1 -5
  189. ommlds/wiki/text/wtp.py +1 -3
  190. ommlds/wiki/utils/xml.py +5 -5
  191. {ommlds-0.0.0.dev456.dist-info → ommlds-0.0.0.dev485.dist-info}/METADATA +22 -19
  192. {ommlds-0.0.0.dev456.dist-info → ommlds-0.0.0.dev485.dist-info}/RECORD +198 -95
  193. ommlds/cli/backends/standard.py +0 -20
  194. ommlds/cli/sessions/chat/base.py +0 -42
  195. ommlds/cli/sessions/chat/code.py +0 -129
  196. ommlds/cli/sessions/chat/interactive.py +0 -71
  197. ommlds/cli/sessions/chat/printing.py +0 -97
  198. ommlds/cli/sessions/chat/prompt.py +0 -151
  199. ommlds/cli/sessions/chat/state.py +0 -110
  200. ommlds/cli/sessions/chat/tools.py +0 -100
  201. ommlds/cli/sessions/completion/completion.py +0 -44
  202. ommlds/cli/sessions/embedding/embedding.py +0 -42
  203. ommlds/cli/tools/config.py +0 -14
  204. ommlds/cli/tools/inject.py +0 -75
  205. ommlds/minichain/backends/impls/openai/format2.py +0 -210
  206. ommlds/minichain/chat/stream/adapters.py +0 -80
  207. /ommlds/{huggingface.py → backends/huggingface.py} +0 -0
  208. /ommlds/cli/{tools → content}/__init__.py +0 -0
  209. {ommlds-0.0.0.dev456.dist-info → ommlds-0.0.0.dev485.dist-info}/WHEEL +0 -0
  210. {ommlds-0.0.0.dev456.dist-info → ommlds-0.0.0.dev485.dist-info}/entry_points.txt +0 -0
  211. {ommlds-0.0.0.dev456.dist-info → ommlds-0.0.0.dev485.dist-info}/licenses/LICENSE +0 -0
  212. {ommlds-0.0.0.dev456.dist-info → ommlds-0.0.0.dev485.dist-info}/top_level.txt +0 -0
@@ -1,42 +0,0 @@
1
- import dataclasses as dc
2
-
3
- from omlish import lang
4
- from omlish.formats import json
5
-
6
- from .... import minichain as mc
7
- from ..base import Session
8
-
9
-
10
- ##
11
-
12
-
13
- DEFAULT_EMBEDDING_MODEL_BACKEND = 'openai'
14
-
15
-
16
- class EmbeddingSession(Session['EmbeddingSession.Config']):
17
- @dc.dataclass(frozen=True)
18
- class Config(Session.Config):
19
- content: mc.Content
20
-
21
- _: dc.KW_ONLY
22
-
23
- backend: str | None = None
24
-
25
- def __init__(
26
- self,
27
- config: Config,
28
- *,
29
- backend_catalog: mc.BackendCatalog,
30
- ) -> None:
31
- super().__init__(config)
32
-
33
- self._backend_catalog = backend_catalog
34
-
35
- async def run(self) -> None:
36
- mdl: mc.EmbeddingService
37
- async with lang.async_maybe_managing(self._backend_catalog.get_backend(
38
- mc.EmbeddingService,
39
- self._config.backend or DEFAULT_EMBEDDING_MODEL_BACKEND,
40
- )) as mdl:
41
- response = await mdl.invoke(mc.EmbeddingRequest(self._config.content))
42
- print(json.dumps_compact(list(map(float, response.v))))
@@ -1,14 +0,0 @@
1
- from omlish import dataclasses as dc
2
-
3
-
4
- ##
5
-
6
-
7
- @dc.dataclass(frozen=True, kw_only=True)
8
- class ToolsConfig:
9
- enable_fs_tools: bool = False
10
- enable_todo_tools: bool = False
11
-
12
- enable_unsafe_tools_do_not_use_lol: bool = False
13
-
14
- enable_test_weather_tool: bool = False
@@ -1,75 +0,0 @@
1
- import dataclasses as dc
2
- import typing as ta
3
-
4
- from omlish import inject as inj
5
- from omlish import lang
6
-
7
- from ... import minichain as mc
8
- from ..sessions.chat.inject import bind_chat_options
9
- from .config import ToolsConfig
10
- from .weather import WEATHER_TOOL
11
-
12
-
13
- ##
14
-
15
-
16
- @dc.dataclass(frozen=True, eq=False)
17
- class _InjectedTool:
18
- tce: mc.ToolCatalogEntry
19
-
20
-
21
- def bind_tool(tce: mc.ToolCatalogEntry) -> inj.Element | inj.Elements:
22
- return inj.as_elements(
23
- inj.bind_set_entry_const(ta.AbstractSet[_InjectedTool], _InjectedTool(tce)),
24
-
25
- bind_chat_options(mc.Tool(tce.spec)),
26
- )
27
-
28
-
29
- ##
30
-
31
-
32
- def bind_tools(tools_config: ToolsConfig) -> inj.Elements:
33
- els: list[inj.Elemental] = [
34
- inj.bind(tools_config),
35
-
36
- inj.bind(mc.ToolCatalog, singleton=True),
37
-
38
- inj.set_binder[_InjectedTool](),
39
- inj.bind(
40
- lang.typed_lambda(mc.ToolCatalogEntries, s=ta.AbstractSet[_InjectedTool])(
41
- lambda s: [it.tce for it in s],
42
- ),
43
- singleton=True,
44
- ),
45
- ]
46
-
47
- #
48
-
49
- if tools_config.enable_fs_tools:
50
- from ...minichain.lib.fs.tools.ls import ls_tool
51
- els.append(bind_tool(ls_tool()))
52
-
53
- from ...minichain.lib.fs.tools.read import read_tool
54
- els.append(bind_tool(read_tool()))
55
-
56
- if tools_config.enable_todo_tools:
57
- from ...minichain.lib.todo.tools.read import todo_read_tool
58
- els.append(bind_tool(todo_read_tool()))
59
-
60
- from ...minichain.lib.todo.tools.write import todo_write_tool
61
- els.append(bind_tool(todo_write_tool()))
62
-
63
- if tools_config.enable_unsafe_tools_do_not_use_lol:
64
- from ...minichain.lib.bash import bash_tool
65
- els.append(bind_tool(bash_tool()))
66
-
67
- from ...minichain.lib.fs.tools.edit import edit_tool
68
- els.append(bind_tool(edit_tool()))
69
-
70
- if tools_config.enable_test_weather_tool:
71
- els.append(bind_tool(WEATHER_TOOL))
72
-
73
- #
74
-
75
- return inj.as_elements(*els)
@@ -1,210 +0,0 @@
1
- import typing as ta
2
-
3
- from omlish import cached
4
- from omlish import check
5
- from omlish import typedvalues as tv
6
- from omlish.formats import json
7
-
8
- from .....backends.openai import protocol as pt
9
- from ....chat.choices.services import ChatChoicesResponse
10
- from ....chat.choices.types import AiChoice
11
- from ....chat.choices.types import AiChoices
12
- from ....chat.choices.types import ChatChoicesOptions
13
- from ....chat.messages import AiMessage
14
- from ....chat.messages import AnyAiMessage
15
- from ....chat.messages import Chat
16
- from ....chat.messages import SystemMessage
17
- from ....chat.messages import ToolUseMessage
18
- from ....chat.messages import ToolUseResultMessage
19
- from ....chat.messages import UserMessage
20
- from ....chat.tools.types import Tool
21
- from ....content.json import JsonContent
22
- from ....content.prepare import prepare_content_str
23
- from ....llms.types import MaxTokens
24
- from ....llms.types import Temperature
25
- from ....llms.types import TokenUsage
26
- from ....llms.types import TokenUsageOutput
27
- from ....tools.jsonschema import build_tool_spec_params_json_schema
28
- from ....tools.types import ToolSpec
29
- from ....tools.types import ToolUse
30
- from ....types import Option
31
-
32
-
33
- ##
34
-
35
-
36
- def build_oai_request_msgs(mc_chat: Chat) -> ta.Sequence[pt.ChatCompletionMessage]:
37
- oai_msgs: list[pt.ChatCompletionMessage] = []
38
-
39
- for mc_msg in mc_chat:
40
- if isinstance(mc_msg, SystemMessage):
41
- oai_msgs.append(pt.SystemChatCompletionMessage(
42
- content=check.isinstance(mc_msg.c, str),
43
- ))
44
-
45
- elif isinstance(mc_msg, AiMessage):
46
- oai_msgs.append(pt.AssistantChatCompletionMessage(
47
- content=check.isinstance(mc_msg.c, (str, None)),
48
- ))
49
-
50
- elif isinstance(mc_msg, ToolUseMessage):
51
- oai_msgs.append(pt.AssistantChatCompletionMessage(
52
- tool_calls=[pt.AssistantChatCompletionMessage.ToolCall(
53
- id=check.not_none(mc_msg.tu.id),
54
- function=pt.AssistantChatCompletionMessage.ToolCall.Function(
55
- arguments=check.not_none(mc_msg.tu.raw_args),
56
- name=mc_msg.tu.name,
57
- ),
58
- )],
59
- ))
60
-
61
- elif isinstance(mc_msg, UserMessage):
62
- oai_msgs.append(pt.UserChatCompletionMessage(
63
- content=prepare_content_str(mc_msg.c),
64
- ))
65
-
66
- elif isinstance(mc_msg, ToolUseResultMessage):
67
- tc: str
68
- if isinstance(mc_msg.tur.c, str):
69
- tc = mc_msg.tur.c
70
- elif isinstance(mc_msg.tur.c, JsonContent):
71
- tc = json.dumps_compact(mc_msg.tur.c)
72
- else:
73
- raise TypeError(mc_msg.tur.c)
74
- oai_msgs.append(pt.ToolChatCompletionMessage(
75
- tool_call_id=check.not_none(mc_msg.tur.id),
76
- content=tc,
77
- ))
78
-
79
- else:
80
- raise TypeError(mc_msg)
81
-
82
- return oai_msgs
83
-
84
-
85
- #
86
-
87
-
88
- def build_mc_ai_choice(oai_choice: pt.ChatCompletionResponseChoice) -> AiChoice:
89
- cur: list[AnyAiMessage] = []
90
-
91
- oai_msg = oai_choice.message
92
-
93
- if (oai_c := oai_msg.content) is not None:
94
- cur.append(AiMessage(check.isinstance(oai_c, str)))
95
-
96
- for oai_tc in oai_msg.tool_calls or []:
97
- cur.append(ToolUseMessage(ToolUse(
98
- id=oai_tc.id,
99
- name=oai_tc.function.name,
100
- args=json.loads(oai_tc.function.arguments or '{}'),
101
- raw_args=oai_tc.function.arguments,
102
- )))
103
-
104
- return AiChoice(cur)
105
-
106
-
107
- def build_mc_ai_choices(oai_resp: pt.ChatCompletionResponse) -> AiChoices:
108
- return [
109
- build_mc_ai_choice(oai_choice)
110
- for oai_choice in oai_resp.choices
111
- ]
112
-
113
-
114
- def build_mc_choices_response(oai_resp: pt.ChatCompletionResponse) -> ChatChoicesResponse:
115
- return ChatChoicesResponse(
116
- build_mc_ai_choices(oai_resp),
117
-
118
- tv.TypedValues(
119
- *([TokenUsageOutput(TokenUsage(
120
- input=tu.prompt_tokens,
121
- output=tu.completion_tokens,
122
- total=tu.total_tokens,
123
- ))] if (tu := oai_resp.usage) is not None else []),
124
- ),
125
- )
126
-
127
-
128
- ##
129
-
130
-
131
- class OpenaiChatRequestHandler:
132
- def __init__(
133
- self,
134
- chat: Chat,
135
- *options: ChatChoicesOptions,
136
- model: str,
137
- mandatory_kwargs: ta.Mapping[str, ta.Any] | None = None,
138
- ) -> None:
139
- super().__init__()
140
-
141
- self._chat = chat
142
- self._options = options
143
- self._model = model
144
- self._mandatory_kwargs = mandatory_kwargs
145
-
146
- DEFAULT_OPTIONS: ta.ClassVar[tv.TypedValues[Option]] = tv.TypedValues[Option](
147
- Temperature(0.),
148
- MaxTokens(1024),
149
- )
150
-
151
- _OPTION_KWARG_NAMES_MAP: ta.ClassVar[ta.Mapping[str, type[ChatChoicesOptions]]] = dict(
152
- temperature=Temperature,
153
- max_tokens=MaxTokens,
154
- )
155
-
156
- class _ProcessedOptions(ta.NamedTuple):
157
- kwargs: dict[str, ta.Any]
158
- tools_by_name: dict[str, ToolSpec]
159
-
160
- @cached.function
161
- def _process_options(self) -> _ProcessedOptions:
162
- kwargs: dict = dict(
163
- temperature=0,
164
- max_tokens=1024,
165
- )
166
-
167
- tools_by_name: dict[str, ToolSpec] = {}
168
-
169
- with tv.TypedValues(*self._options).consume() as oc:
170
- kwargs.update(oc.pop_scalar_kwargs(**self._OPTION_KWARG_NAMES_MAP))
171
-
172
- for t in oc.pop(Tool, []):
173
- if t.spec.name in tools_by_name:
174
- raise NameError(t.spec.name)
175
- tools_by_name[check.non_empty_str(t.spec.name)] = t.spec
176
-
177
- if (mk := self._mandatory_kwargs):
178
- for k, v in mk.items():
179
- check.not_in(k, kwargs)
180
- kwargs[k] = v
181
-
182
- return self._ProcessedOptions(
183
- kwargs=kwargs,
184
- tools_by_name=tools_by_name,
185
- )
186
-
187
- @cached.function
188
- def oai_request(self) -> pt.ChatCompletionRequest:
189
- po = self._process_options()
190
-
191
- tools: list[pt.ChatCompletionRequestTool] = [
192
- pt.ChatCompletionRequestTool(
193
- function=pt.ChatCompletionRequestTool.Function(
194
- name=check.not_none(ts.name),
195
- description=prepare_content_str(ts.desc),
196
- parameters=build_tool_spec_params_json_schema(ts),
197
- ),
198
- )
199
- for ts in po.tools_by_name.values()
200
- ]
201
-
202
- return pt.ChatCompletionRequest(
203
- model=self._model,
204
- messages=build_oai_request_msgs(self._chat),
205
- top_p=1,
206
- tools=tools or None,
207
- frequency_penalty=0.0,
208
- presence_penalty=0.0,
209
- **po.kwargs,
210
- )
@@ -1,80 +0,0 @@
1
- from omlish import check
2
- from omlish import dataclasses as dc
3
- from omlish import lang
4
-
5
- from ...services import Response
6
- from ...tools.types import ToolUse
7
- from ..choices.services import ChatChoicesRequest
8
- from ..choices.services import static_check_is_chat_choices_service
9
- from ..choices.types import AiChoice
10
- from ..choices.types import AiChoices
11
- from ..messages import AiMessage
12
- from ..messages import AnyAiMessage
13
- from ..messages import ToolUseMessage
14
- from .services import ChatChoicesOutputs
15
- from .services import ChatChoicesStreamOutputs
16
- from .services import ChatChoicesStreamService
17
- from .types import AiChoiceDelta
18
- from .types import ContentAiChoiceDelta
19
- from .types import ToolUseAiChoiceDelta
20
-
21
-
22
- ##
23
-
24
-
25
- @static_check_is_chat_choices_service
26
- @dc.dataclass(frozen=True)
27
- class ChatChoicesStreamServiceChatChoicesService:
28
- service: ChatChoicesStreamService
29
-
30
- async def invoke(self, request: ChatChoicesRequest) -> Response[
31
- AiChoices,
32
- ChatChoicesOutputs | ChatChoicesStreamOutputs,
33
- ]:
34
- choice_lsts: list[list[list[str] | ToolUse]] = []
35
-
36
- def add(l: list[list[str] | ToolUse], d: AiChoiceDelta) -> None:
37
- if isinstance(d, ContentAiChoiceDelta):
38
- s = check.isinstance(d.c, str)
39
- if l and isinstance(l[-1], list):
40
- l[-1].append(s)
41
- else:
42
- l.append([s])
43
-
44
- elif isinstance(d, ToolUseAiChoiceDelta):
45
- l.append(d.tu)
46
-
47
- else:
48
- raise TypeError(d)
49
-
50
- async with (resp := await self.service.invoke(request)).v as it: # noqa
51
- i = -1 # noqa
52
- l: list[list[str] | ToolUse]
53
- async for i, cs in lang.async_enumerate(it):
54
- if i == 0:
55
- for c in cs.choices:
56
- choice_lsts.append(l := [])
57
- for d in c.deltas:
58
- add(l, d)
59
-
60
- else:
61
- for l, c in zip(choice_lsts, cs.choices, strict=True):
62
- for d in c.deltas:
63
- add(l, d)
64
-
65
- # check.state(resp_v.is_done)
66
-
67
- ret: list[AiChoice] = []
68
- for cl in choice_lsts:
69
- cc: list[AnyAiMessage] = []
70
- for e in cl:
71
- if isinstance(e, list):
72
- cc.append(AiMessage(''.join(e)))
73
- elif isinstance(e, ToolUse):
74
- cc.append(ToolUseMessage(e))
75
- else:
76
- raise TypeError(e)
77
- ret.append(AiChoice(cc))
78
-
79
- # FIXME: outputs lol
80
- return Response(ret)
File without changes
File without changes