ommlds 0.0.0.dev466__py3-none-any.whl → 0.0.0.dev512__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.
- ommlds/.omlish-manifests.json +404 -31
- ommlds/README.md +11 -0
- ommlds/__about__.py +21 -12
- ommlds/_hacks/__init__.py +4 -0
- ommlds/_hacks/funcs.py +110 -0
- ommlds/_hacks/names.py +158 -0
- ommlds/_hacks/params.py +73 -0
- ommlds/_hacks/patches.py +0 -3
- ommlds/backends/anthropic/protocol/__init__.py +13 -1
- ommlds/backends/anthropic/protocol/_dataclasses.py +1625 -0
- ommlds/backends/anthropic/protocol/sse/events.py +2 -0
- ommlds/backends/anthropic/protocol/types.py +5 -7
- ommlds/backends/cerebras/__init__.py +7 -0
- ommlds/backends/cerebras/_dataclasses.py +4254 -0
- ommlds/backends/cerebras/_marshal.py +24 -0
- ommlds/backends/cerebras/clients.py +9 -0
- ommlds/backends/cerebras/protocol.py +310 -0
- ommlds/backends/google/protocol/__init__.py +13 -0
- ommlds/backends/google/protocol/_dataclasses.py +5997 -0
- ommlds/backends/google/protocol/types.py +6 -8
- ommlds/backends/groq/__init__.py +7 -0
- ommlds/backends/groq/_dataclasses.py +3901 -0
- ommlds/backends/groq/_marshal.py +23 -0
- ommlds/backends/groq/clients.py +9 -0
- ommlds/backends/groq/protocol.py +247 -0
- ommlds/{huggingface.py → backends/huggingface/cache.py} +1 -6
- ommlds/backends/huggingface/cli.py +208 -0
- ommlds/backends/llamacpp/logging.py +4 -1
- ommlds/backends/mlx/caching.py +7 -3
- ommlds/backends/mlx/cli.py +10 -7
- ommlds/backends/mlx/generation.py +18 -16
- ommlds/backends/mlx/limits.py +10 -6
- ommlds/backends/mlx/loading.py +7 -4
- ommlds/backends/ollama/__init__.py +7 -0
- ommlds/backends/ollama/_dataclasses.py +3940 -0
- ommlds/backends/ollama/cli.py +36 -0
- ommlds/backends/ollama/protocol.py +201 -0
- ommlds/backends/openai/protocol/__init__.py +15 -1
- ommlds/backends/openai/protocol/_common.py +3 -5
- ommlds/backends/openai/protocol/_dataclasses.py +7708 -0
- ommlds/backends/tavily/__init__.py +7 -0
- ommlds/backends/tavily/_dataclasses.py +1734 -0
- ommlds/backends/tavily/protocol.py +299 -0
- ommlds/backends/tinygrad/models/llama3/__init__.py +22 -14
- ommlds/backends/torch/backends.py +1 -1
- ommlds/backends/transformers/__init__.py +14 -0
- ommlds/backends/transformers/filecache.py +109 -0
- ommlds/backends/transformers/streamers.py +73 -0
- ommlds/cli/__init__.py +7 -0
- ommlds/cli/_dataclasses.py +3835 -0
- ommlds/cli/asyncs.py +30 -0
- ommlds/cli/backends/catalog.py +88 -0
- ommlds/cli/backends/configs.py +9 -0
- ommlds/cli/backends/inject.py +100 -42
- ommlds/cli/{sessions/chat/backends → backends}/injection.py +1 -1
- ommlds/cli/backends/meta.py +82 -0
- ommlds/cli/{sessions/chat/backends → backends}/types.py +11 -1
- ommlds/cli/{sessions/chat/content → content}/messages.py +2 -2
- ommlds/cli/{sessions/chat/content → content}/strings.py +1 -1
- ommlds/cli/inject.py +17 -8
- ommlds/cli/inputs/asyncs.py +32 -0
- ommlds/cli/inputs/sync.py +75 -0
- ommlds/cli/main.py +346 -114
- ommlds/cli/rendering/configs.py +9 -0
- ommlds/cli/{sessions/chat/rendering → rendering}/inject.py +4 -5
- ommlds/cli/{sessions/chat/rendering → rendering}/markdown.py +1 -1
- ommlds/cli/{sessions/chat/rendering → rendering}/raw.py +1 -1
- ommlds/cli/{sessions/chat/rendering → rendering}/types.py +7 -1
- ommlds/cli/secrets.py +22 -0
- ommlds/cli/sessions/base.py +1 -10
- ommlds/cli/sessions/chat/configs.py +13 -30
- ommlds/cli/sessions/chat/drivers/ai/configs.py +13 -0
- ommlds/cli/sessions/chat/drivers/ai/events.py +57 -0
- ommlds/cli/sessions/chat/{chat → drivers}/ai/inject.py +15 -12
- ommlds/cli/sessions/chat/{chat → drivers}/ai/rendering.py +8 -8
- ommlds/cli/sessions/chat/{chat → drivers}/ai/services.py +5 -5
- ommlds/cli/sessions/chat/{chat → drivers}/ai/tools.py +4 -8
- ommlds/cli/sessions/chat/{chat → drivers}/ai/types.py +10 -1
- ommlds/cli/sessions/chat/drivers/configs.py +25 -0
- ommlds/cli/sessions/chat/drivers/events/inject.py +27 -0
- ommlds/cli/sessions/chat/drivers/events/injection.py +14 -0
- ommlds/cli/sessions/chat/drivers/events/manager.py +16 -0
- ommlds/cli/sessions/chat/drivers/events/types.py +44 -0
- ommlds/cli/sessions/chat/drivers/impl.py +50 -0
- ommlds/cli/sessions/chat/drivers/inject.py +70 -0
- ommlds/cli/sessions/chat/drivers/state/configs.py +13 -0
- ommlds/cli/sessions/chat/drivers/state/ids.py +25 -0
- ommlds/cli/sessions/chat/drivers/state/inject.py +83 -0
- ommlds/cli/sessions/chat/{chat → drivers}/state/inmemory.py +1 -6
- ommlds/cli/sessions/chat/{chat → drivers}/state/storage.py +18 -12
- ommlds/cli/sessions/chat/{chat → drivers}/state/types.py +11 -6
- ommlds/cli/sessions/chat/drivers/tools/configs.py +22 -0
- ommlds/cli/sessions/chat/drivers/tools/confirmation.py +44 -0
- ommlds/cli/sessions/chat/drivers/tools/errorhandling.py +39 -0
- ommlds/cli/sessions/chat/{tools → drivers/tools}/execution.py +3 -4
- ommlds/cli/sessions/chat/drivers/tools/fs/__init__.py +0 -0
- ommlds/cli/sessions/chat/drivers/tools/fs/configs.py +12 -0
- ommlds/cli/sessions/chat/drivers/tools/fs/inject.py +35 -0
- ommlds/cli/sessions/chat/drivers/tools/inject.py +83 -0
- ommlds/cli/sessions/chat/{tools → drivers/tools}/injection.py +20 -5
- ommlds/cli/sessions/chat/{tools → drivers/tools}/rendering.py +3 -3
- ommlds/cli/sessions/chat/drivers/tools/todo/__init__.py +0 -0
- ommlds/cli/sessions/chat/drivers/tools/todo/configs.py +12 -0
- ommlds/cli/sessions/chat/drivers/tools/todo/inject.py +31 -0
- ommlds/cli/sessions/chat/drivers/tools/weather/__init__.py +0 -0
- ommlds/cli/sessions/chat/drivers/tools/weather/configs.py +12 -0
- ommlds/cli/sessions/chat/drivers/tools/weather/inject.py +22 -0
- ommlds/cli/sessions/chat/{tools/weather.py → drivers/tools/weather/tools.py} +1 -1
- ommlds/cli/sessions/chat/drivers/types.py +31 -0
- ommlds/cli/sessions/chat/drivers/user/__init__.py +0 -0
- ommlds/cli/sessions/chat/drivers/user/configs.py +14 -0
- ommlds/cli/sessions/chat/drivers/user/inject.py +41 -0
- ommlds/cli/sessions/chat/facades/__init__.py +0 -0
- ommlds/cli/sessions/chat/facades/commands/__init__.py +0 -0
- ommlds/cli/sessions/chat/facades/commands/base.py +83 -0
- ommlds/cli/sessions/chat/facades/commands/configs.py +9 -0
- ommlds/cli/sessions/chat/facades/commands/inject.py +41 -0
- ommlds/cli/sessions/chat/facades/commands/injection.py +15 -0
- ommlds/cli/sessions/chat/facades/commands/manager.py +59 -0
- ommlds/cli/sessions/chat/facades/commands/simple.py +34 -0
- ommlds/cli/sessions/chat/facades/commands/types.py +13 -0
- ommlds/cli/sessions/chat/facades/configs.py +11 -0
- ommlds/cli/sessions/chat/facades/facade.py +26 -0
- ommlds/cli/sessions/chat/facades/inject.py +35 -0
- ommlds/cli/sessions/chat/facades/ui.py +34 -0
- ommlds/cli/sessions/chat/inject.py +10 -49
- ommlds/cli/sessions/chat/interfaces/__init__.py +0 -0
- ommlds/cli/sessions/chat/interfaces/bare/__init__.py +0 -0
- ommlds/cli/sessions/chat/interfaces/bare/configs.py +15 -0
- ommlds/cli/sessions/chat/interfaces/bare/inject.py +69 -0
- ommlds/cli/sessions/chat/interfaces/bare/interactive.py +49 -0
- ommlds/cli/sessions/chat/interfaces/bare/oneshot.py +21 -0
- ommlds/cli/sessions/chat/{tools/confirmation.py → interfaces/bare/tools.py} +3 -22
- ommlds/cli/sessions/chat/interfaces/base.py +13 -0
- ommlds/cli/sessions/chat/interfaces/configs.py +11 -0
- ommlds/cli/sessions/chat/interfaces/inject.py +29 -0
- ommlds/cli/sessions/chat/interfaces/textual/__init__.py +0 -0
- ommlds/cli/sessions/chat/interfaces/textual/app.py +429 -0
- ommlds/cli/sessions/chat/interfaces/textual/configs.py +11 -0
- ommlds/cli/sessions/chat/interfaces/textual/facades.py +19 -0
- ommlds/cli/sessions/chat/interfaces/textual/inject.py +111 -0
- ommlds/cli/sessions/chat/interfaces/textual/inputhistory.py +174 -0
- ommlds/cli/sessions/chat/interfaces/textual/interface.py +24 -0
- ommlds/cli/sessions/chat/interfaces/textual/styles/__init__.py +29 -0
- ommlds/cli/sessions/chat/interfaces/textual/styles/input.tcss +53 -0
- ommlds/cli/sessions/chat/interfaces/textual/styles/markdown.tcss +7 -0
- ommlds/cli/sessions/chat/interfaces/textual/styles/messages.tcss +167 -0
- ommlds/cli/sessions/chat/interfaces/textual/tools.py +38 -0
- ommlds/cli/sessions/chat/interfaces/textual/widgets/__init__.py +0 -0
- ommlds/cli/sessions/chat/interfaces/textual/widgets/input.py +70 -0
- ommlds/cli/sessions/chat/interfaces/textual/widgets/messages.py +207 -0
- ommlds/cli/sessions/chat/session.py +8 -13
- ommlds/cli/sessions/completion/configs.py +5 -6
- ommlds/cli/sessions/completion/inject.py +15 -2
- ommlds/cli/sessions/completion/session.py +10 -18
- ommlds/cli/sessions/configs.py +10 -0
- ommlds/cli/sessions/embedding/configs.py +5 -6
- ommlds/cli/sessions/embedding/inject.py +15 -2
- ommlds/cli/sessions/embedding/session.py +10 -18
- ommlds/cli/sessions/inject.py +15 -15
- ommlds/cli/state/storage.py +8 -2
- ommlds/minichain/__init__.py +217 -60
- ommlds/minichain/_dataclasses.py +20640 -0
- ommlds/minichain/_typedvalues.py +15 -8
- ommlds/minichain/backends/catalogs/base.py +20 -1
- ommlds/minichain/backends/catalogs/simple.py +2 -2
- ommlds/minichain/backends/catalogs/strings.py +13 -10
- ommlds/minichain/backends/impls/anthropic/chat.py +28 -5
- ommlds/minichain/backends/impls/anthropic/names.py +3 -3
- ommlds/minichain/backends/impls/anthropic/protocol.py +2 -2
- ommlds/minichain/backends/impls/anthropic/stream.py +23 -18
- ommlds/minichain/backends/impls/cerebras/__init__.py +0 -0
- ommlds/minichain/backends/impls/cerebras/chat.py +82 -0
- ommlds/minichain/backends/impls/cerebras/names.py +45 -0
- ommlds/minichain/backends/impls/cerebras/protocol.py +143 -0
- ommlds/minichain/backends/impls/cerebras/stream.py +114 -0
- ommlds/minichain/backends/impls/duckduckgo/search.py +5 -1
- ommlds/minichain/backends/impls/dummy/__init__.py +0 -0
- ommlds/minichain/backends/impls/dummy/chat.py +69 -0
- ommlds/minichain/backends/impls/google/chat.py +20 -84
- ommlds/minichain/backends/impls/google/names.py +6 -0
- ommlds/minichain/backends/impls/google/protocol.py +105 -0
- ommlds/minichain/backends/impls/google/search.py +10 -5
- ommlds/minichain/backends/impls/google/stream.py +64 -142
- ommlds/minichain/backends/impls/google/tools.py +2 -2
- ommlds/minichain/backends/impls/groq/__init__.py +0 -0
- ommlds/minichain/backends/impls/groq/chat.py +77 -0
- ommlds/minichain/backends/impls/groq/names.py +48 -0
- ommlds/minichain/backends/impls/groq/protocol.py +143 -0
- ommlds/minichain/backends/impls/groq/stream.py +114 -0
- ommlds/minichain/backends/impls/huggingface/repos.py +1 -5
- ommlds/minichain/backends/impls/llamacpp/chat.py +15 -3
- ommlds/minichain/backends/impls/llamacpp/completion.py +7 -3
- ommlds/minichain/backends/impls/llamacpp/stream.py +38 -19
- ommlds/minichain/backends/impls/mistral.py +9 -2
- ommlds/minichain/backends/impls/mlx/chat.py +100 -23
- ommlds/minichain/backends/impls/ollama/__init__.py +0 -0
- ommlds/minichain/backends/impls/ollama/chat.py +193 -0
- ommlds/minichain/backends/impls/ollama/protocol.py +144 -0
- ommlds/minichain/backends/impls/openai/chat.py +14 -7
- ommlds/minichain/backends/impls/openai/completion.py +9 -2
- ommlds/minichain/backends/impls/openai/embedding.py +9 -2
- ommlds/minichain/backends/impls/openai/format.py +117 -115
- ommlds/minichain/backends/impls/openai/names.py +33 -5
- ommlds/minichain/backends/impls/openai/stream.py +61 -70
- ommlds/minichain/backends/impls/sentencepiece/tokens.py +9 -6
- ommlds/minichain/backends/impls/tavily.py +66 -0
- ommlds/minichain/backends/impls/tinygrad/chat.py +17 -14
- ommlds/minichain/backends/impls/tokenizers/tokens.py +9 -6
- ommlds/minichain/backends/impls/transformers/sentence.py +5 -2
- ommlds/minichain/backends/impls/transformers/tokens.py +9 -6
- ommlds/minichain/backends/impls/transformers/transformers.py +139 -20
- ommlds/minichain/backends/strings/parsing.py +2 -2
- ommlds/minichain/backends/strings/resolving.py +7 -2
- ommlds/minichain/chat/choices/stream/__init__.py +0 -0
- ommlds/minichain/chat/{stream → choices/stream}/adapters.py +7 -7
- ommlds/minichain/chat/choices/stream/joining.py +31 -0
- ommlds/minichain/chat/choices/stream/services.py +45 -0
- ommlds/minichain/chat/choices/stream/types.py +43 -0
- ommlds/minichain/chat/content.py +42 -0
- ommlds/minichain/chat/messages.py +46 -42
- ommlds/minichain/chat/stream/_marshal.py +4 -4
- ommlds/minichain/chat/stream/joining.py +56 -43
- ommlds/minichain/chat/stream/services.py +15 -15
- ommlds/minichain/chat/stream/types.py +17 -24
- ommlds/minichain/chat/templating.py +3 -3
- ommlds/minichain/content/__init__.py +20 -3
- ommlds/minichain/content/_marshal.py +181 -55
- ommlds/minichain/content/code.py +26 -0
- ommlds/minichain/content/composite.py +28 -0
- ommlds/minichain/content/content.py +27 -0
- ommlds/minichain/content/dynamic.py +12 -0
- ommlds/minichain/content/emphasis.py +27 -0
- ommlds/minichain/content/images.py +2 -2
- ommlds/minichain/content/json.py +2 -2
- ommlds/minichain/content/link.py +13 -0
- ommlds/minichain/content/markdown.py +12 -0
- ommlds/minichain/content/metadata.py +10 -0
- ommlds/minichain/content/namespaces.py +8 -0
- ommlds/minichain/content/placeholders.py +10 -9
- ommlds/minichain/content/quote.py +26 -0
- ommlds/minichain/content/raw.py +49 -0
- ommlds/minichain/content/recursive.py +12 -0
- ommlds/minichain/content/resources.py +22 -0
- ommlds/minichain/content/section.py +26 -0
- ommlds/minichain/content/sequence.py +17 -3
- ommlds/minichain/content/standard.py +32 -0
- ommlds/minichain/content/tag.py +28 -0
- ommlds/minichain/content/templates.py +13 -0
- ommlds/minichain/content/text.py +2 -2
- ommlds/minichain/content/transform/__init__.py +0 -0
- ommlds/minichain/content/transform/json.py +55 -0
- ommlds/minichain/content/transform/markdown.py +8 -0
- ommlds/minichain/content/transform/materialize.py +59 -0
- ommlds/minichain/content/transform/metadata.py +16 -0
- ommlds/minichain/content/transform/namespaces.py +20 -0
- ommlds/minichain/content/transform/placeholders.py +60 -0
- ommlds/minichain/content/{prepare.py → transform/prepare.py} +10 -15
- ommlds/minichain/content/transform/recursive.py +54 -0
- ommlds/minichain/content/transform/resources.py +58 -0
- ommlds/minichain/content/transform/standard.py +43 -0
- ommlds/minichain/content/{transforms → transform}/stringify.py +1 -7
- ommlds/minichain/content/transform/strings.py +33 -0
- ommlds/minichain/content/transform/templates.py +25 -0
- ommlds/minichain/content/transform/types.py +18 -0
- ommlds/minichain/content/transform/visitors.py +38 -0
- ommlds/minichain/content/visitors.py +218 -0
- ommlds/minichain/http/__init__.py +0 -0
- ommlds/minichain/http/stream.py +195 -0
- ommlds/minichain/lib/fs/tools/read.py +1 -1
- ommlds/minichain/lib/fs/tools/recursivels/rendering.py +1 -1
- ommlds/minichain/lib/fs/tools/recursivels/running.py +1 -1
- ommlds/minichain/lib/todo/tools/write.py +2 -1
- ommlds/minichain/lib/todo/types.py +1 -1
- ommlds/minichain/llms/types.py +4 -0
- ommlds/minichain/metadata.py +56 -2
- ommlds/minichain/models/configs.py +2 -2
- ommlds/minichain/models/names.py +2 -0
- ommlds/minichain/registries/globals.py +18 -4
- ommlds/minichain/resources.py +49 -3
- ommlds/minichain/search.py +1 -1
- ommlds/minichain/services/README.md +154 -0
- ommlds/minichain/services/__init__.py +6 -2
- ommlds/minichain/services/_marshal.py +46 -10
- ommlds/minichain/services/_origclasses.py +11 -0
- ommlds/minichain/services/_typedvalues.py +8 -3
- ommlds/minichain/services/requests.py +73 -3
- ommlds/minichain/services/responses.py +73 -3
- ommlds/minichain/services/services.py +9 -0
- ommlds/minichain/standard.py +8 -0
- ommlds/minichain/stream/services.py +43 -17
- ommlds/minichain/text/applypatch.py +2 -1
- ommlds/minichain/text/toolparsing/llamacpp/types.py +1 -1
- ommlds/minichain/tokens/specials.py +1 -1
- ommlds/minichain/tools/execution/catalog.py +2 -2
- ommlds/minichain/tools/execution/errorhandling.py +36 -0
- ommlds/minichain/tools/execution/errors.py +2 -2
- ommlds/minichain/tools/execution/executors.py +1 -1
- ommlds/minichain/tools/fns.py +1 -1
- ommlds/minichain/tools/jsonschema.py +2 -2
- ommlds/minichain/tools/reflect.py +11 -7
- ommlds/minichain/tools/types.py +16 -19
- ommlds/minichain/vectors/_marshal.py +1 -1
- ommlds/minichain/vectors/embeddings.py +1 -1
- ommlds/minichain/wrappers/__init__.py +7 -0
- ommlds/minichain/wrappers/firstinwins.py +144 -0
- ommlds/minichain/wrappers/instrument.py +146 -0
- ommlds/minichain/wrappers/retry.py +168 -0
- ommlds/minichain/wrappers/services.py +98 -0
- ommlds/minichain/wrappers/stream.py +57 -0
- ommlds/nanochat/LICENSE +21 -0
- ommlds/nanochat/__init__.py +0 -0
- ommlds/nanochat/rustbpe/LICENSE +21 -0
- ommlds/nanochat/rustbpe/README.md +10 -0
- ommlds/nanochat/tokenizers.py +440 -0
- ommlds/specs/__init__.py +0 -0
- ommlds/specs/mcp/__init__.py +0 -0
- ommlds/specs/mcp/_marshal.py +23 -0
- ommlds/specs/mcp/clients.py +146 -0
- ommlds/specs/mcp/protocol.py +369 -0
- ommlds/tools/git.py +84 -64
- ommlds/tools/ocr.py +1 -1
- ommlds/wiki/analyze.py +2 -2
- ommlds/wiki/models.py +4 -4
- ommlds/wiki/text/mfh.py +9 -9
- ommlds/wiki/utils/xml.py +5 -5
- {ommlds-0.0.0.dev466.dist-info → ommlds-0.0.0.dev512.dist-info}/METADATA +28 -21
- ommlds-0.0.0.dev512.dist-info/RECORD +534 -0
- {ommlds-0.0.0.dev466.dist-info → ommlds-0.0.0.dev512.dist-info}/WHEEL +1 -1
- ommlds/cli/backends/standard.py +0 -20
- ommlds/cli/sessions/chat/backends/catalog.py +0 -56
- ommlds/cli/sessions/chat/backends/inject.py +0 -37
- ommlds/cli/sessions/chat/chat/state/inject.py +0 -40
- ommlds/cli/sessions/chat/chat/user/inject.py +0 -61
- ommlds/cli/sessions/chat/chat/user/interactive.py +0 -29
- ommlds/cli/sessions/chat/chat/user/oneshot.py +0 -25
- ommlds/cli/sessions/chat/chat/user/types.py +0 -15
- ommlds/cli/sessions/chat/driver.py +0 -43
- ommlds/cli/sessions/chat/tools/inject.py +0 -145
- ommlds/minichain/backends/impls/openai/format2.py +0 -210
- ommlds/minichain/content/materialize.py +0 -196
- ommlds/minichain/content/simple.py +0 -47
- ommlds/minichain/content/transforms/base.py +0 -46
- ommlds/minichain/content/transforms/interleave.py +0 -70
- ommlds/minichain/content/transforms/squeeze.py +0 -72
- ommlds/minichain/content/transforms/strings.py +0 -24
- ommlds/minichain/content/types.py +0 -43
- ommlds/minichain/stream/wrap.py +0 -62
- ommlds-0.0.0.dev466.dist-info/RECORD +0 -376
- /ommlds/{cli/sessions/chat/backends → backends/huggingface}/__init__.py +0 -0
- /ommlds/cli/{sessions/chat/chat → content}/__init__.py +0 -0
- /ommlds/cli/{sessions/chat/chat/ai → inputs}/__init__.py +0 -0
- /ommlds/cli/{sessions/chat/chat/state → rendering}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{chat/user → drivers}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{content → drivers/ai}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{chat → drivers}/ai/injection.py +0 -0
- /ommlds/cli/sessions/chat/{phases → drivers/events}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{rendering → drivers/phases}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{phases → drivers/phases}/inject.py +0 -0
- /ommlds/cli/sessions/chat/{phases → drivers/phases}/injection.py +0 -0
- /ommlds/cli/sessions/chat/{phases → drivers/phases}/manager.py +0 -0
- /ommlds/cli/sessions/chat/{phases → drivers/phases}/types.py +0 -0
- /ommlds/cli/sessions/chat/{tools → drivers/state}/__init__.py +0 -0
- /ommlds/{minichain/content/transforms → cli/sessions/chat/drivers/tools}/__init__.py +0 -0
- {ommlds-0.0.0.dev466.dist-info → ommlds-0.0.0.dev512.dist-info}/entry_points.txt +0 -0
- {ommlds-0.0.0.dev466.dist-info → ommlds-0.0.0.dev512.dist-info}/licenses/LICENSE +0 -0
- {ommlds-0.0.0.dev466.dist-info → ommlds-0.0.0.dev512.dist-info}/top_level.txt +0 -0
|
@@ -8,30 +8,24 @@ from omlish import marshal as msh
|
|
|
8
8
|
from omlish import typedvalues as tv
|
|
9
9
|
from omlish.formats import json
|
|
10
10
|
from omlish.http import all as http
|
|
11
|
-
from omlish.
|
|
11
|
+
from omlish.http import sse
|
|
12
12
|
|
|
13
13
|
from .....backends.google.protocol import types as pt
|
|
14
|
-
from ....chat.choices.
|
|
15
|
-
from ....chat.
|
|
16
|
-
from ....chat.
|
|
17
|
-
from ....chat.
|
|
18
|
-
from ....chat.
|
|
19
|
-
from ....chat.
|
|
20
|
-
from ....chat.
|
|
21
|
-
from ....chat.stream.services import ChatChoicesStreamRequest
|
|
22
|
-
from ....chat.stream.services import ChatChoicesStreamResponse
|
|
23
|
-
from ....chat.stream.services import static_check_is_chat_choices_stream_service
|
|
24
|
-
from ....chat.stream.types import AiChoiceDeltas
|
|
25
|
-
from ....chat.stream.types import AiChoicesDeltas
|
|
26
|
-
from ....chat.stream.types import ContentAiChoiceDelta
|
|
27
|
-
from ....chat.stream.types import ToolUseAiChoiceDelta
|
|
14
|
+
from ....chat.choices.stream.services import ChatChoicesStreamRequest
|
|
15
|
+
from ....chat.choices.stream.services import ChatChoicesStreamResponse
|
|
16
|
+
from ....chat.choices.stream.services import static_check_is_chat_choices_stream_service
|
|
17
|
+
from ....chat.choices.stream.types import AiChoiceDeltas
|
|
18
|
+
from ....chat.choices.stream.types import AiChoicesDeltas
|
|
19
|
+
from ....chat.stream.types import ContentAiDelta
|
|
20
|
+
from ....chat.stream.types import ToolUseAiDelta
|
|
28
21
|
from ....chat.tools.types import Tool
|
|
22
|
+
from ....http.stream import BytesHttpStreamResponseBuilder
|
|
23
|
+
from ....http.stream import SimpleSseLinesHttpStreamResponseHandler
|
|
29
24
|
from ....models.configs import ModelName
|
|
30
|
-
from ....resources import UseResources
|
|
31
25
|
from ....standard import ApiKey
|
|
32
|
-
from ....stream.services import StreamResponseSink
|
|
33
|
-
from ....stream.services import new_stream_response
|
|
34
26
|
from .names import MODEL_NAMES
|
|
27
|
+
from .protocol import make_msg_content
|
|
28
|
+
from .protocol import pop_system_instructions
|
|
35
29
|
from .tools import build_tool_spec_schema
|
|
36
30
|
|
|
37
31
|
|
|
@@ -46,80 +40,53 @@ from .tools import build_tool_spec_schema
|
|
|
46
40
|
class GoogleChatChoicesStreamService:
|
|
47
41
|
DEFAULT_MODEL_NAME: ta.ClassVar[ModelName] = ModelName(check.not_none(MODEL_NAMES.default))
|
|
48
42
|
|
|
49
|
-
def __init__(
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
*configs: ApiKey | ModelName,
|
|
46
|
+
http_client: http.AsyncHttpClient | None = None,
|
|
47
|
+
) -> None:
|
|
50
48
|
super().__init__()
|
|
51
49
|
|
|
50
|
+
self._http_client = http_client
|
|
51
|
+
|
|
52
52
|
with tv.consume(*configs) as cc:
|
|
53
53
|
self._model_name = cc.pop(self.DEFAULT_MODEL_NAME)
|
|
54
54
|
self._api_key = ApiKey.pop_secret(cc, env='GEMINI_API_KEY')
|
|
55
55
|
|
|
56
|
-
def _make_str_content(
|
|
57
|
-
self,
|
|
58
|
-
s: str | None,
|
|
59
|
-
*,
|
|
60
|
-
role: pt.ContentRole | None = None,
|
|
61
|
-
) -> pt.Content | None:
|
|
62
|
-
if s is None:
|
|
63
|
-
return None
|
|
64
|
-
|
|
65
|
-
return pt.Content(
|
|
66
|
-
parts=[pt.Part(
|
|
67
|
-
text=check.not_none(s),
|
|
68
|
-
)],
|
|
69
|
-
role=role,
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
def _make_msg_content(self, m: Message) -> pt.Content:
|
|
73
|
-
if isinstance(m, (AiMessage, SystemMessage, UserMessage)):
|
|
74
|
-
return check.not_none(self._make_str_content(
|
|
75
|
-
check.isinstance(m.c, str),
|
|
76
|
-
role=self.ROLES_MAP[type(m)],
|
|
77
|
-
))
|
|
78
|
-
|
|
79
|
-
elif isinstance(m, ToolUseResultMessage):
|
|
80
|
-
tr_resp_val: pt.Value
|
|
81
|
-
if m.tur.c is None:
|
|
82
|
-
tr_resp_val = pt.NullValue() # type: ignore[unreachable]
|
|
83
|
-
elif isinstance(m.tur.c, str):
|
|
84
|
-
tr_resp_val = pt.StringValue(m.tur.c)
|
|
85
|
-
else:
|
|
86
|
-
raise TypeError(m.tur.c)
|
|
87
|
-
return pt.Content(
|
|
88
|
-
parts=[pt.Part(
|
|
89
|
-
function_response=pt.FunctionResponse(
|
|
90
|
-
id=m.tur.id,
|
|
91
|
-
name=m.tur.name,
|
|
92
|
-
response={
|
|
93
|
-
'value': tr_resp_val,
|
|
94
|
-
},
|
|
95
|
-
),
|
|
96
|
-
)],
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
elif isinstance(m, ToolUseMessage):
|
|
100
|
-
return pt.Content(
|
|
101
|
-
parts=[pt.Part(
|
|
102
|
-
function_call=pt.FunctionCall(
|
|
103
|
-
id=m.tu.id,
|
|
104
|
-
name=m.tu.name,
|
|
105
|
-
args=m.tu.args,
|
|
106
|
-
),
|
|
107
|
-
)],
|
|
108
|
-
role='model',
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
else:
|
|
112
|
-
raise TypeError(m)
|
|
113
|
-
|
|
114
56
|
BASE_URL: ta.ClassVar[str] = 'https://generativelanguage.googleapis.com/v1beta/models'
|
|
115
57
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
58
|
+
def _process_sse(self, so: sse.SseDecoderOutput) -> ta.Iterable[AiChoicesDeltas | None]:
|
|
59
|
+
if not (isinstance(so, sse.SseEvent) and so.type == b'message'):
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
gcr = msh.unmarshal(json.loads(so.data.decode('utf-8')), pt.GenerateContentResponse) # noqa
|
|
63
|
+
cnd = check.single(check.not_none(gcr.candidates))
|
|
64
|
+
|
|
65
|
+
for p in check.not_none(cnd.content).parts or []:
|
|
66
|
+
if (txt := p.text) is not None:
|
|
67
|
+
check.none(p.function_call)
|
|
68
|
+
yield AiChoicesDeltas([
|
|
69
|
+
AiChoiceDeltas([
|
|
70
|
+
ContentAiDelta(check.not_none(txt)),
|
|
71
|
+
]),
|
|
72
|
+
])
|
|
73
|
+
|
|
74
|
+
elif (fc := p.function_call) is not None:
|
|
75
|
+
check.none(p.text)
|
|
76
|
+
yield AiChoicesDeltas([
|
|
77
|
+
AiChoiceDeltas([
|
|
78
|
+
ToolUseAiDelta(
|
|
79
|
+
id=fc.id,
|
|
80
|
+
name=fc.name,
|
|
81
|
+
args=fc.args,
|
|
82
|
+
),
|
|
83
|
+
]),
|
|
84
|
+
])
|
|
85
|
+
|
|
86
|
+
else:
|
|
87
|
+
raise ValueError(p)
|
|
121
88
|
|
|
122
|
-
READ_CHUNK_SIZE =
|
|
89
|
+
READ_CHUNK_SIZE: ta.ClassVar[int] = -1
|
|
123
90
|
|
|
124
91
|
async def invoke(
|
|
125
92
|
self,
|
|
@@ -127,13 +94,6 @@ class GoogleChatChoicesStreamService:
|
|
|
127
94
|
) -> ChatChoicesStreamResponse:
|
|
128
95
|
key = check.not_none(self._api_key).reveal()
|
|
129
96
|
|
|
130
|
-
msgs = list(request.v)
|
|
131
|
-
|
|
132
|
-
system_inst: pt.Content | None = None
|
|
133
|
-
if msgs and isinstance(m0 := msgs[0], SystemMessage):
|
|
134
|
-
system_inst = self._make_msg_content(m0)
|
|
135
|
-
msgs.pop(0)
|
|
136
|
-
|
|
137
97
|
g_tools: list[pt.Tool] = []
|
|
138
98
|
with tv.TypedValues(*request.options).consume() as oc:
|
|
139
99
|
t: Tool
|
|
@@ -142,11 +102,15 @@ class GoogleChatChoicesStreamService:
|
|
|
142
102
|
function_declarations=[build_tool_spec_schema(t.spec)],
|
|
143
103
|
))
|
|
144
104
|
|
|
105
|
+
msgs = list(request.v)
|
|
106
|
+
|
|
107
|
+
system_inst = pop_system_instructions(msgs)
|
|
108
|
+
|
|
145
109
|
g_req = pt.GenerateContentRequest(
|
|
146
110
|
contents=[
|
|
147
|
-
|
|
111
|
+
make_msg_content(m)
|
|
148
112
|
for m in msgs
|
|
149
|
-
],
|
|
113
|
+
] or None,
|
|
150
114
|
tools=g_tools or None,
|
|
151
115
|
system_instruction=system_inst,
|
|
152
116
|
)
|
|
@@ -162,53 +126,11 @@ class GoogleChatChoicesStreamService:
|
|
|
162
126
|
method='POST',
|
|
163
127
|
)
|
|
164
128
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
http_response
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
b = http_response.stream.read1(self.READ_CHUNK_SIZE) # type: ignore[attr-defined]
|
|
174
|
-
for bl in db.feed(b):
|
|
175
|
-
if isinstance(bl, DelimitingBuffer.Incomplete):
|
|
176
|
-
# FIXME: handle
|
|
177
|
-
return []
|
|
178
|
-
|
|
179
|
-
l = bl.decode('utf-8')
|
|
180
|
-
if not l:
|
|
181
|
-
continue
|
|
182
|
-
|
|
183
|
-
if l.startswith('data: '):
|
|
184
|
-
gcr = msh.unmarshal(json.loads(l[6:]), pt.GenerateContentResponse) # noqa
|
|
185
|
-
cnd = check.single(check.not_none(gcr.candidates))
|
|
186
|
-
|
|
187
|
-
for p in check.not_none(cnd.content).parts or []:
|
|
188
|
-
if (txt := p.text) is not None:
|
|
189
|
-
check.none(p.function_call)
|
|
190
|
-
await sink.emit(AiChoicesDeltas([
|
|
191
|
-
AiChoiceDeltas([
|
|
192
|
-
ContentAiChoiceDelta(check.not_none(txt)),
|
|
193
|
-
]),
|
|
194
|
-
]))
|
|
195
|
-
|
|
196
|
-
elif (fc := p.function_call) is not None:
|
|
197
|
-
check.none(p.text)
|
|
198
|
-
await sink.emit(AiChoicesDeltas([
|
|
199
|
-
AiChoiceDeltas([
|
|
200
|
-
ToolUseAiChoiceDelta(
|
|
201
|
-
id=fc.id,
|
|
202
|
-
name=fc.name,
|
|
203
|
-
args=fc.args,
|
|
204
|
-
),
|
|
205
|
-
]),
|
|
206
|
-
]))
|
|
207
|
-
|
|
208
|
-
else:
|
|
209
|
-
raise ValueError(p)
|
|
210
|
-
|
|
211
|
-
if not b:
|
|
212
|
-
return []
|
|
213
|
-
|
|
214
|
-
return await new_stream_response(rs, inner)
|
|
129
|
+
return await BytesHttpStreamResponseBuilder(
|
|
130
|
+
self._http_client,
|
|
131
|
+
lambda http_response: SimpleSseLinesHttpStreamResponseHandler(self._process_sse).as_lines().as_bytes(),
|
|
132
|
+
read_chunk_size=self.READ_CHUNK_SIZE,
|
|
133
|
+
).new_stream_response(
|
|
134
|
+
http_request,
|
|
135
|
+
request.options,
|
|
136
|
+
)
|
|
@@ -7,8 +7,8 @@ from omlish import check
|
|
|
7
7
|
from omlish import dataclasses as dc
|
|
8
8
|
|
|
9
9
|
from .....backends.google.protocol import types as pt
|
|
10
|
-
from ....content.prepare import ContentStrPreparer
|
|
11
|
-
from ....content.prepare import default_content_str_preparer
|
|
10
|
+
from ....content.transform.prepare import ContentStrPreparer
|
|
11
|
+
from ....content.transform.prepare import default_content_str_preparer
|
|
12
12
|
from ....tools.types import EnumToolDtype
|
|
13
13
|
from ....tools.types import MappingToolDtype
|
|
14
14
|
from ....tools.types import NullableToolDtype
|
|
File without changes
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from omlish import check
|
|
4
|
+
from omlish import marshal as msh
|
|
5
|
+
from omlish import typedvalues as tv
|
|
6
|
+
from omlish.formats import json
|
|
7
|
+
from omlish.http import all as http
|
|
8
|
+
|
|
9
|
+
from .....backends.groq import protocol as pt
|
|
10
|
+
from .....backends.groq.clients import REQUIRED_HTTP_HEADERS
|
|
11
|
+
from ....chat.choices.services import ChatChoicesRequest
|
|
12
|
+
from ....chat.choices.services import ChatChoicesResponse
|
|
13
|
+
from ....chat.choices.services import static_check_is_chat_choices_service
|
|
14
|
+
from ....chat.tools.types import Tool
|
|
15
|
+
from ....models.configs import ModelName
|
|
16
|
+
from ....standard import ApiKey
|
|
17
|
+
from ....standard import DefaultOptions
|
|
18
|
+
from .names import MODEL_NAMES
|
|
19
|
+
from .protocol import build_gq_request_messages
|
|
20
|
+
from .protocol import build_gq_request_tool
|
|
21
|
+
from .protocol import build_mc_choices_response
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# @omlish-manifest $.minichain.registries.manifests.RegistryManifest(
|
|
28
|
+
# name='groq',
|
|
29
|
+
# type='ChatChoicesService',
|
|
30
|
+
# )
|
|
31
|
+
@static_check_is_chat_choices_service
|
|
32
|
+
class GroqChatChoicesService:
|
|
33
|
+
DEFAULT_MODEL_NAME: ta.ClassVar[ModelName] = ModelName(check.not_none(MODEL_NAMES.default))
|
|
34
|
+
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
*configs: ApiKey | ModelName | DefaultOptions,
|
|
38
|
+
http_client: http.AsyncHttpClient | None = None,
|
|
39
|
+
) -> None:
|
|
40
|
+
super().__init__()
|
|
41
|
+
|
|
42
|
+
self._http_client = http_client
|
|
43
|
+
|
|
44
|
+
with tv.consume(*configs) as cc:
|
|
45
|
+
self._model_name = cc.pop(self.DEFAULT_MODEL_NAME)
|
|
46
|
+
self._api_key = ApiKey.pop_secret(cc, env='GROQ_API_KEY')
|
|
47
|
+
self._default_options: tv.TypedValues = DefaultOptions.pop(cc)
|
|
48
|
+
|
|
49
|
+
async def invoke(self, request: ChatChoicesRequest) -> ChatChoicesResponse:
|
|
50
|
+
tools: list[pt.ChatCompletionRequest.Tool] = []
|
|
51
|
+
with tv.TypedValues(*request.options).consume() as oc:
|
|
52
|
+
t: Tool
|
|
53
|
+
for t in oc.pop(Tool, []):
|
|
54
|
+
tools.append(build_gq_request_tool(t))
|
|
55
|
+
|
|
56
|
+
gq_request = pt.ChatCompletionRequest(
|
|
57
|
+
messages=build_gq_request_messages(request.v),
|
|
58
|
+
model=MODEL_NAMES.resolve(self._model_name.v),
|
|
59
|
+
tools=tools or None,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
raw_request = msh.marshal(gq_request)
|
|
63
|
+
|
|
64
|
+
http_response = await http.async_request(
|
|
65
|
+
'https://api.groq.com/openai/v1/chat/completions',
|
|
66
|
+
headers={
|
|
67
|
+
http.consts.HEADER_CONTENT_TYPE: http.consts.CONTENT_TYPE_JSON,
|
|
68
|
+
http.consts.HEADER_AUTH: http.consts.format_bearer_auth_header(check.not_none(self._api_key).reveal()),
|
|
69
|
+
**REQUIRED_HTTP_HEADERS,
|
|
70
|
+
},
|
|
71
|
+
data=json.dumps(raw_request).encode('utf-8'),
|
|
72
|
+
client=self._http_client,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
raw_response = json.loads(check.not_none(http_response.data).decode('utf-8'))
|
|
76
|
+
|
|
77
|
+
return build_mc_choices_response(msh.unmarshal(raw_response, pt.ChatCompletionResponse))
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""
|
|
2
|
+
https://console.groq.com/docs/models
|
|
3
|
+
|
|
4
|
+
curl -X GET "https://api.groq.com/openai/v1/models" \
|
|
5
|
+
-H "Authorization: Bearer $GROQ_API_KEY" \
|
|
6
|
+
-H "Content-Type: application/json"
|
|
7
|
+
|
|
8
|
+
"compound-beta",
|
|
9
|
+
"compound-beta-mini",
|
|
10
|
+
"gemma2-9b-it",
|
|
11
|
+
"llama-3.1-8b-instant",
|
|
12
|
+
"llama-3.3-70b-versatile",
|
|
13
|
+
"meta-llama/llama-4-maverick-17b-128e-instruct",
|
|
14
|
+
"meta-llama/llama-4-scout-17b-16e-instruct",
|
|
15
|
+
"meta-llama/llama-guard-4-12b",
|
|
16
|
+
"moonshotai/kimi-k2-instruct",
|
|
17
|
+
"openai/gpt-oss-120b",
|
|
18
|
+
"openai/gpt-oss-20b",
|
|
19
|
+
"qwen/qwen3-32b",
|
|
20
|
+
"""
|
|
21
|
+
from ....models.names import ModelNameCollection
|
|
22
|
+
from ...strings.manifests import BackendStringsManifest
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
##
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
MODEL_NAMES = ModelNameCollection(
|
|
29
|
+
default='gpt-oss-120b',
|
|
30
|
+
aliases={
|
|
31
|
+
'gpt-oss-120b': 'openai/gpt-oss-120b',
|
|
32
|
+
'openai/gpt-oss-120b': None,
|
|
33
|
+
|
|
34
|
+
'gpt-oss-20b': 'openai/gpt-oss-20b',
|
|
35
|
+
'openai/gpt-oss-20b': None,
|
|
36
|
+
},
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# @omlish-manifest
|
|
41
|
+
_BACKEND_STRINGS_MANIFEST = BackendStringsManifest(
|
|
42
|
+
[
|
|
43
|
+
'ChatChoicesService',
|
|
44
|
+
'ChatChoicesStreamService',
|
|
45
|
+
],
|
|
46
|
+
'groq',
|
|
47
|
+
model_names=MODEL_NAMES,
|
|
48
|
+
)
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import itertools
|
|
2
|
+
|
|
3
|
+
from omlish import check
|
|
4
|
+
from omlish.formats import json
|
|
5
|
+
|
|
6
|
+
from .....backends.groq import protocol as pt
|
|
7
|
+
from ....chat.choices.services import ChatChoicesResponse
|
|
8
|
+
from ....chat.choices.stream.types import AiChoiceDeltas
|
|
9
|
+
from ....chat.choices.types import AiChoice
|
|
10
|
+
from ....chat.messages import AiMessage
|
|
11
|
+
from ....chat.messages import AnyAiMessage
|
|
12
|
+
from ....chat.messages import Chat
|
|
13
|
+
from ....chat.messages import SystemMessage
|
|
14
|
+
from ....chat.messages import ToolUseMessage
|
|
15
|
+
from ....chat.messages import ToolUseResultMessage
|
|
16
|
+
from ....chat.messages import UserMessage
|
|
17
|
+
from ....chat.stream.types import AiDelta
|
|
18
|
+
from ....chat.stream.types import ContentAiDelta
|
|
19
|
+
from ....chat.stream.types import ToolUseAiDelta
|
|
20
|
+
from ....chat.tools.types import Tool
|
|
21
|
+
from ....content.transform.prepare import prepare_content_str
|
|
22
|
+
from ....tools.jsonschema import build_tool_spec_params_json_schema
|
|
23
|
+
from ....tools.types import ToolUse
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
##
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def build_gq_request_messages(chat: Chat) -> list[pt.ChatCompletionRequest.Message]:
|
|
30
|
+
gq_msgs: list[pt.ChatCompletionRequest.Message] = []
|
|
31
|
+
|
|
32
|
+
for _, g in itertools.groupby(chat, lambda mc_m: isinstance(mc_m, AnyAiMessage)):
|
|
33
|
+
mc_msgs = list(g)
|
|
34
|
+
|
|
35
|
+
if isinstance(mc_msgs[0], AnyAiMessage):
|
|
36
|
+
tups: list[tuple[AiMessage | None, list[ToolUseMessage]]] = []
|
|
37
|
+
for mc_msg in mc_msgs:
|
|
38
|
+
if isinstance(mc_msg, AiMessage):
|
|
39
|
+
tups.append((mc_msg, []))
|
|
40
|
+
|
|
41
|
+
elif isinstance(mc_msg, ToolUseMessage):
|
|
42
|
+
if not tups:
|
|
43
|
+
tups.append((None, []))
|
|
44
|
+
tups[-1][1].append(mc_msg)
|
|
45
|
+
|
|
46
|
+
else:
|
|
47
|
+
raise TypeError(mc_msg)
|
|
48
|
+
|
|
49
|
+
for mc_ai_msg, mc_tu_msgs in tups:
|
|
50
|
+
gq_msgs.append(pt.ChatCompletionRequest.AssistantMessage(
|
|
51
|
+
content=check.isinstance(mc_ai_msg.c, str) if mc_ai_msg is not None else None,
|
|
52
|
+
tool_calls=[
|
|
53
|
+
pt.ChatCompletionRequest.AssistantMessage.ToolCall(
|
|
54
|
+
function=pt.ChatCompletionRequest.AssistantMessage.ToolCall.Function(
|
|
55
|
+
name=mc_tu_msg.tu.name,
|
|
56
|
+
arguments=check.not_none(mc_tu_msg.tu.raw_args),
|
|
57
|
+
),
|
|
58
|
+
id=check.not_none(mc_tu_msg.tu.id),
|
|
59
|
+
)
|
|
60
|
+
for mc_tu_msg in mc_tu_msgs
|
|
61
|
+
] if mc_tu_msgs else None,
|
|
62
|
+
))
|
|
63
|
+
|
|
64
|
+
else:
|
|
65
|
+
for mc_msg in mc_msgs:
|
|
66
|
+
if isinstance(mc_msg, SystemMessage):
|
|
67
|
+
gq_msgs.append(pt.ChatCompletionRequest.SystemMessage(
|
|
68
|
+
content=check.isinstance(mc_msg.c, str),
|
|
69
|
+
))
|
|
70
|
+
|
|
71
|
+
elif isinstance(mc_msg, UserMessage):
|
|
72
|
+
gq_msgs.append(pt.ChatCompletionRequest.UserMessage(
|
|
73
|
+
content=check.isinstance(mc_msg.c, str),
|
|
74
|
+
))
|
|
75
|
+
|
|
76
|
+
elif isinstance(mc_msg, ToolUseResultMessage):
|
|
77
|
+
gq_msgs.append(pt.ChatCompletionRequest.ToolMessage(
|
|
78
|
+
tool_call_id=check.not_none(mc_msg.tur.id),
|
|
79
|
+
content=check.isinstance(mc_msg.tur.c, str),
|
|
80
|
+
))
|
|
81
|
+
|
|
82
|
+
else:
|
|
83
|
+
raise TypeError(mc_msg)
|
|
84
|
+
|
|
85
|
+
return gq_msgs
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def build_gq_request_tool(t: Tool) -> pt.ChatCompletionRequest.Tool:
|
|
89
|
+
return pt.ChatCompletionRequest.Tool(
|
|
90
|
+
function=pt.ChatCompletionRequest.Tool.Function(
|
|
91
|
+
name=check.not_none(t.spec.name),
|
|
92
|
+
description=prepare_content_str(t.spec.desc) if t.spec.desc is not None else None,
|
|
93
|
+
parameters=build_tool_spec_params_json_schema(t.spec),
|
|
94
|
+
),
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def build_mc_choices_response(gq_resp: pt.ChatCompletionResponse) -> ChatChoicesResponse:
|
|
99
|
+
def build_choice(gq_choice: pt.ChatCompletionResponse.Choice) -> AiChoice:
|
|
100
|
+
gq_msg = gq_choice.message
|
|
101
|
+
|
|
102
|
+
lst: list[AnyAiMessage] = []
|
|
103
|
+
|
|
104
|
+
if gq_msg.content is not None:
|
|
105
|
+
lst.append(AiMessage(
|
|
106
|
+
check.isinstance(gq_msg.content, str),
|
|
107
|
+
))
|
|
108
|
+
|
|
109
|
+
for gq_tc in gq_msg.tool_calls or []:
|
|
110
|
+
lst.append(ToolUseMessage(ToolUse(
|
|
111
|
+
id=gq_tc.id,
|
|
112
|
+
name=gq_tc.function.name,
|
|
113
|
+
args=json.loads(gq_tc.function.arguments or '{}'),
|
|
114
|
+
raw_args=gq_tc.function.arguments,
|
|
115
|
+
)))
|
|
116
|
+
|
|
117
|
+
return AiChoice(lst)
|
|
118
|
+
|
|
119
|
+
return ChatChoicesResponse(list(map(build_choice, gq_resp.choices)))
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def build_mc_ai_choice_deltas(delta: pt.ChatCompletionChunk.Choice.Delta) -> AiChoiceDeltas:
|
|
123
|
+
if delta.role in (None, 'assistant'):
|
|
124
|
+
lst: list[AiDelta] = []
|
|
125
|
+
|
|
126
|
+
if delta.content is not None:
|
|
127
|
+
lst.append(ContentAiDelta(delta.content))
|
|
128
|
+
|
|
129
|
+
for tc in delta.tool_calls or []:
|
|
130
|
+
tc_fn = check.not_none(tc.function)
|
|
131
|
+
lst.append(ToolUseAiDelta(
|
|
132
|
+
id=tc.id,
|
|
133
|
+
name=check.not_none(tc_fn.name),
|
|
134
|
+
args=json.loads(tc_fn.arguments or '{}'),
|
|
135
|
+
))
|
|
136
|
+
|
|
137
|
+
return AiChoiceDeltas(lst)
|
|
138
|
+
|
|
139
|
+
elif delta.channel in ('analysis', 'commentary'):
|
|
140
|
+
return AiChoiceDeltas([])
|
|
141
|
+
|
|
142
|
+
else:
|
|
143
|
+
raise ValueError(delta)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from omlish import check
|
|
4
|
+
from omlish import marshal as msh
|
|
5
|
+
from omlish import typedvalues as tv
|
|
6
|
+
from omlish.formats import json
|
|
7
|
+
from omlish.http import all as http
|
|
8
|
+
from omlish.http import sse
|
|
9
|
+
|
|
10
|
+
from .....backends.groq import protocol as pt
|
|
11
|
+
from .....backends.groq.clients import REQUIRED_HTTP_HEADERS
|
|
12
|
+
from ....chat.choices.stream.services import ChatChoicesStreamRequest
|
|
13
|
+
from ....chat.choices.stream.services import ChatChoicesStreamResponse
|
|
14
|
+
from ....chat.choices.stream.services import static_check_is_chat_choices_stream_service
|
|
15
|
+
from ....chat.choices.stream.types import AiChoicesDeltas
|
|
16
|
+
from ....chat.tools.types import Tool
|
|
17
|
+
from ....configs import Config
|
|
18
|
+
from ....http.stream import BytesHttpStreamResponseBuilder
|
|
19
|
+
from ....http.stream import SimpleSseLinesHttpStreamResponseHandler
|
|
20
|
+
from ....standard import ApiKey
|
|
21
|
+
from .chat import GroqChatChoicesService
|
|
22
|
+
from .names import MODEL_NAMES
|
|
23
|
+
from .protocol import build_gq_request_messages
|
|
24
|
+
from .protocol import build_gq_request_tool
|
|
25
|
+
from .protocol import build_mc_ai_choice_deltas
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# @omlish-manifest $.minichain.registries.manifests.RegistryManifest(
|
|
32
|
+
# name='groq',
|
|
33
|
+
# type='ChatChoicesStreamService',
|
|
34
|
+
# )
|
|
35
|
+
@static_check_is_chat_choices_stream_service
|
|
36
|
+
class GroqChatChoicesStreamService:
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
*configs: Config,
|
|
40
|
+
http_client: http.AsyncHttpClient | None = None,
|
|
41
|
+
) -> None:
|
|
42
|
+
super().__init__()
|
|
43
|
+
|
|
44
|
+
self._http_client = http_client
|
|
45
|
+
|
|
46
|
+
with tv.consume(*configs) as cc:
|
|
47
|
+
self._model_name = cc.pop(GroqChatChoicesService.DEFAULT_MODEL_NAME)
|
|
48
|
+
self._api_key = ApiKey.pop_secret(cc, env='GROQ_API_KEY')
|
|
49
|
+
|
|
50
|
+
URL: ta.ClassVar[str] = 'https://api.groq.com/openai/v1/chat/completions'
|
|
51
|
+
|
|
52
|
+
def _process_sse(self, so: sse.SseDecoderOutput) -> ta.Sequence[AiChoicesDeltas | None]:
|
|
53
|
+
if not (isinstance(so, sse.SseEvent) and so.type == b'message'):
|
|
54
|
+
return []
|
|
55
|
+
|
|
56
|
+
ss = so.data.decode('utf-8')
|
|
57
|
+
if ss == '[DONE]':
|
|
58
|
+
return [None]
|
|
59
|
+
|
|
60
|
+
sj = json.loads(ss) # ChatCompletionChunk
|
|
61
|
+
|
|
62
|
+
check.state(sj['object'] == 'chat.completion.chunk')
|
|
63
|
+
|
|
64
|
+
ccc = msh.unmarshal(sj, pt.ChatCompletionChunk)
|
|
65
|
+
|
|
66
|
+
# FIXME: stop reason
|
|
67
|
+
if not ccc.choices:
|
|
68
|
+
return []
|
|
69
|
+
|
|
70
|
+
if any(choice.finish_reason for choice in ccc.choices):
|
|
71
|
+
check.state(all(choice.finish_reason for choice in ccc.choices))
|
|
72
|
+
return [None]
|
|
73
|
+
|
|
74
|
+
return [AiChoicesDeltas([
|
|
75
|
+
build_mc_ai_choice_deltas(choice.delta)
|
|
76
|
+
for choice in ccc.choices
|
|
77
|
+
])]
|
|
78
|
+
|
|
79
|
+
READ_CHUNK_SIZE: ta.ClassVar[int] = -1
|
|
80
|
+
|
|
81
|
+
async def invoke(self, request: ChatChoicesStreamRequest) -> ChatChoicesStreamResponse:
|
|
82
|
+
tools: list[pt.ChatCompletionRequest.Tool] = []
|
|
83
|
+
with tv.TypedValues(*request.options).consume() as oc:
|
|
84
|
+
t: Tool
|
|
85
|
+
for t in oc.pop(Tool, []):
|
|
86
|
+
tools.append(build_gq_request_tool(t))
|
|
87
|
+
|
|
88
|
+
gq_request = pt.ChatCompletionRequest(
|
|
89
|
+
messages=build_gq_request_messages(request.v),
|
|
90
|
+
model=MODEL_NAMES.resolve(self._model_name.v),
|
|
91
|
+
tools=tools or None,
|
|
92
|
+
stream=True,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
raw_request = msh.marshal(gq_request)
|
|
96
|
+
|
|
97
|
+
http_request = http.HttpRequest(
|
|
98
|
+
self.URL,
|
|
99
|
+
headers={
|
|
100
|
+
http.consts.HEADER_CONTENT_TYPE: http.consts.CONTENT_TYPE_JSON,
|
|
101
|
+
http.consts.HEADER_AUTH: http.consts.format_bearer_auth_header(check.not_none(self._api_key).reveal()),
|
|
102
|
+
**REQUIRED_HTTP_HEADERS,
|
|
103
|
+
},
|
|
104
|
+
data=json.dumps(raw_request).encode('utf-8'),
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
return await BytesHttpStreamResponseBuilder(
|
|
108
|
+
self._http_client,
|
|
109
|
+
lambda http_response: SimpleSseLinesHttpStreamResponseHandler(self._process_sse).as_lines().as_bytes(),
|
|
110
|
+
read_chunk_size=self.READ_CHUNK_SIZE,
|
|
111
|
+
).new_stream_response(
|
|
112
|
+
http_request,
|
|
113
|
+
request.options,
|
|
114
|
+
)
|
|
@@ -3,8 +3,6 @@ TODO:
|
|
|
3
3
|
- local-only check first
|
|
4
4
|
- cat ~/.cache/.../models/.../refs/main -> c5bfd839cd4cda0e5a39a97e00218d9c56e468af
|
|
5
5
|
"""
|
|
6
|
-
import typing as ta
|
|
7
|
-
|
|
8
6
|
from omlish import lang
|
|
9
7
|
|
|
10
8
|
from ....models.configs import ModelRepo
|
|
@@ -12,10 +10,8 @@ from ....models.repos.resolving import ModelRepoResolver
|
|
|
12
10
|
from ....models.repos.resolving import ResolvedModelRepo
|
|
13
11
|
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
with lang.auto_proxy_import(globals()):
|
|
16
14
|
import huggingface_hub as hf
|
|
17
|
-
else:
|
|
18
|
-
hf = lang.proxy_import('huggingface_hub')
|
|
19
15
|
|
|
20
16
|
|
|
21
17
|
##
|