pygpt-net 2.4.37__py3-none-any.whl → 2.4.42__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.
- CHANGELOG.md +37 -0
- README.md +176 -182
- pygpt_net/CHANGELOG.txt +37 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/app.py +3 -1
- pygpt_net/controller/__init__.py +7 -3
- pygpt_net/controller/access/control.py +1 -1
- pygpt_net/controller/access/voice.py +11 -5
- pygpt_net/controller/agent/experts.py +11 -6
- pygpt_net/controller/agent/legacy.py +8 -6
- pygpt_net/controller/agent/llama.py +4 -2
- pygpt_net/controller/assistant/__init__.py +9 -4
- pygpt_net/controller/assistant/batch.py +38 -21
- pygpt_net/controller/assistant/editor.py +7 -6
- pygpt_net/controller/assistant/files.py +23 -7
- pygpt_net/controller/assistant/store.py +20 -7
- pygpt_net/controller/assistant/threads.py +34 -8
- pygpt_net/controller/attachment.py +29 -10
- pygpt_net/controller/audio/__init__.py +26 -5
- pygpt_net/controller/calendar/__init__.py +23 -4
- pygpt_net/controller/calendar/note.py +57 -11
- pygpt_net/controller/camera.py +4 -12
- pygpt_net/controller/chat/__init__.py +5 -3
- pygpt_net/controller/chat/attachment.py +34 -7
- pygpt_net/controller/chat/audio.py +2 -2
- pygpt_net/controller/chat/command.py +4 -2
- pygpt_net/controller/chat/common.py +11 -4
- pygpt_net/controller/chat/files.py +10 -3
- pygpt_net/controller/chat/image.py +17 -5
- pygpt_net/controller/chat/input.py +10 -7
- pygpt_net/controller/chat/output.py +21 -6
- pygpt_net/controller/chat/render.py +100 -21
- pygpt_net/controller/chat/response.py +34 -7
- pygpt_net/controller/chat/stream.py +4 -2
- pygpt_net/controller/chat/text.py +6 -4
- pygpt_net/controller/command.py +11 -3
- pygpt_net/controller/config/__init__.py +34 -6
- pygpt_net/controller/config/field/checkbox.py +7 -4
- pygpt_net/controller/config/field/cmd.py +7 -5
- pygpt_net/controller/config/field/combo.py +14 -6
- pygpt_net/controller/config/field/dictionary.py +14 -11
- pygpt_net/controller/config/field/input.py +9 -6
- pygpt_net/controller/config/field/slider.py +11 -8
- pygpt_net/controller/config/field/textarea.py +8 -5
- pygpt_net/controller/config/placeholder.py +66 -21
- pygpt_net/controller/ctx/__init__.py +138 -49
- pygpt_net/controller/ctx/common.py +15 -4
- pygpt_net/controller/ctx/extra.py +11 -3
- pygpt_net/controller/ctx/summarizer.py +24 -5
- pygpt_net/controller/debug/__init__.py +27 -6
- pygpt_net/controller/dialogs/confirm.py +34 -7
- pygpt_net/controller/dialogs/debug.py +4 -2
- pygpt_net/controller/dialogs/info.py +7 -2
- pygpt_net/controller/files.py +48 -10
- pygpt_net/controller/finder.py +11 -5
- pygpt_net/controller/idx/__init__.py +10 -3
- pygpt_net/controller/idx/common.py +4 -2
- pygpt_net/controller/idx/indexer.py +25 -17
- pygpt_net/controller/idx/settings.py +9 -3
- pygpt_net/controller/kernel/__init__.py +34 -8
- pygpt_net/controller/kernel/reply.py +12 -3
- pygpt_net/controller/kernel/stack.py +5 -3
- pygpt_net/controller/lang/custom.py +2 -7
- pygpt_net/controller/lang/mapping.py +5 -3
- pygpt_net/controller/layout.py +2 -2
- pygpt_net/controller/mode.py +16 -4
- pygpt_net/controller/model/__init__.py +14 -3
- pygpt_net/controller/model/editor.py +8 -3
- pygpt_net/controller/notepad.py +26 -12
- pygpt_net/controller/painter/capture.py +23 -4
- pygpt_net/controller/painter/common.py +9 -7
- pygpt_net/controller/plugins/__init__.py +19 -5
- pygpt_net/controller/plugins/presets.py +15 -6
- pygpt_net/controller/plugins/settings.py +9 -3
- pygpt_net/controller/presets/__init__.py +55 -16
- pygpt_net/controller/presets/editor.py +26 -10
- pygpt_net/controller/settings/__init__.py +3 -2
- pygpt_net/controller/settings/editor.py +29 -7
- pygpt_net/controller/settings/profile.py +22 -5
- pygpt_net/controller/theme/__init__.py +54 -12
- pygpt_net/controller/theme/common.py +24 -2
- pygpt_net/controller/theme/markdown.py +32 -16
- pygpt_net/controller/theme/menu.py +26 -5
- pygpt_net/controller/theme/nodes.py +2 -5
- pygpt_net/controller/tools/__init__.py +40 -2
- pygpt_net/controller/ui/__init__.py +4 -6
- pygpt_net/controller/ui/mode.py +16 -21
- pygpt_net/controller/ui/tabs.py +363 -65
- pygpt_net/core/access/actions.py +6 -4
- pygpt_net/core/access/shortcuts.py +4 -3
- pygpt_net/core/access/voice.py +6 -5
- pygpt_net/core/agents/legacy.py +4 -2
- pygpt_net/core/agents/memory.py +7 -2
- pygpt_net/core/agents/observer/evaluation.py +15 -7
- pygpt_net/core/agents/provider.py +9 -4
- pygpt_net/core/agents/runner.py +61 -15
- pygpt_net/core/agents/tools.py +23 -5
- pygpt_net/core/assistants/__init__.py +6 -4
- pygpt_net/core/assistants/files.py +35 -12
- pygpt_net/core/assistants/store.py +20 -10
- pygpt_net/core/attachments/__init__.py +54 -15
- pygpt_net/core/attachments/context.py +92 -29
- pygpt_net/core/audio/__init__.py +74 -3
- pygpt_net/core/audio/context.py +7 -2
- pygpt_net/core/audio/whisper.py +37 -0
- pygpt_net/core/bridge/__init__.py +22 -6
- pygpt_net/core/bridge/context.py +5 -3
- pygpt_net/core/bridge/worker.py +2 -2
- pygpt_net/core/calendar/__init__.py +57 -11
- pygpt_net/core/chain/__init__.py +8 -2
- pygpt_net/core/chain/chat.py +10 -8
- pygpt_net/core/chain/completion.py +10 -7
- pygpt_net/core/command.py +62 -17
- pygpt_net/core/ctx/__init__.py +260 -58
- pygpt_net/core/ctx/bag.py +25 -4
- pygpt_net/core/ctx/container.py +28 -17
- pygpt_net/core/ctx/idx.py +45 -8
- pygpt_net/core/ctx/output.py +95 -74
- pygpt_net/core/ctx/reply.py +5 -2
- pygpt_net/core/db/__init__.py +8 -7
- pygpt_net/core/db/viewer.py +17 -11
- pygpt_net/core/debug/__init__.py +10 -9
- pygpt_net/core/debug/events.py +22 -10
- pygpt_net/core/debug/tabs.py +9 -3
- pygpt_net/core/docker/__init__.py +11 -5
- pygpt_net/core/docker/builder.py +11 -3
- pygpt_net/core/events/app.py +5 -3
- pygpt_net/core/events/base.py +11 -5
- pygpt_net/core/events/control.py +5 -3
- pygpt_net/core/events/event.py +17 -7
- pygpt_net/core/events/kernel.py +5 -3
- pygpt_net/core/events/render.py +5 -3
- pygpt_net/core/experts/__init__.py +5 -4
- pygpt_net/core/filesystem/__init__.py +52 -34
- pygpt_net/core/filesystem/actions.py +8 -5
- pygpt_net/core/filesystem/editor.py +13 -3
- pygpt_net/core/filesystem/types.py +12 -7
- pygpt_net/core/filesystem/url.py +7 -3
- pygpt_net/core/history.py +3 -2
- pygpt_net/core/idx/__init__.py +48 -27
- pygpt_net/core/idx/chat.py +51 -17
- pygpt_net/core/idx/context.py +6 -2
- pygpt_net/core/idx/indexing.py +107 -42
- pygpt_net/core/idx/llm.py +11 -3
- pygpt_net/core/idx/metadata.py +13 -3
- pygpt_net/core/idx/types/ctx.py +32 -6
- pygpt_net/core/idx/types/external.py +41 -7
- pygpt_net/core/idx/types/files.py +31 -6
- pygpt_net/core/image.py +15 -4
- pygpt_net/core/installer.py +2 -4
- pygpt_net/core/llm/__init__.py +13 -3
- pygpt_net/core/locale.py +34 -8
- pygpt_net/core/models.py +63 -17
- pygpt_net/core/modes.py +11 -13
- pygpt_net/core/notepad.py +10 -5
- pygpt_net/core/plugins.py +31 -19
- pygpt_net/core/presets.py +37 -17
- pygpt_net/core/profile.py +21 -7
- pygpt_net/core/prompt/__init__.py +10 -3
- pygpt_net/core/prompt/custom.py +7 -6
- pygpt_net/core/prompt/template.py +9 -3
- pygpt_net/core/render/base.py +117 -22
- pygpt_net/core/render/markdown/body.py +27 -7
- pygpt_net/core/render/markdown/renderer.py +119 -22
- pygpt_net/core/render/plain/body.py +22 -5
- pygpt_net/core/render/plain/renderer.py +97 -21
- pygpt_net/core/render/web/body.py +75 -25
- pygpt_net/core/render/web/parser.py +3 -1
- pygpt_net/core/render/web/renderer.py +313 -63
- pygpt_net/core/settings.py +10 -5
- pygpt_net/core/tabs/__init__.py +290 -103
- pygpt_net/core/tabs/tab.py +26 -5
- pygpt_net/core/tokens.py +47 -12
- pygpt_net/core/updater/__init__.py +20 -7
- pygpt_net/core/vision/analyzer.py +29 -6
- pygpt_net/core/{web.py → web/__init__.py} +29 -7
- pygpt_net/core/web/helpers.py +237 -0
- pygpt_net/data/config/config.json +15 -4
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/config/modes.json +3 -3
- pygpt_net/data/config/settings.json +55 -10
- pygpt_net/data/config/settings_section.json +3 -0
- pygpt_net/data/css/style.light.css +1 -0
- pygpt_net/data/css/{web.css → web-blocks.css} +162 -133
- pygpt_net/data/css/{web.light.css → web-blocks.light.css} +7 -0
- pygpt_net/data/css/web-chatgpt.css +350 -0
- pygpt_net/data/css/web-chatgpt.dark.css +64 -0
- pygpt_net/data/css/web-chatgpt.light.css +75 -0
- pygpt_net/data/css/web-chatgpt_wide.css +350 -0
- pygpt_net/data/css/web-chatgpt_wide.dark.css +64 -0
- pygpt_net/data/css/web-chatgpt_wide.light.css +75 -0
- pygpt_net/data/icons/split_screen.svg +1 -0
- pygpt_net/data/locale/locale.de.ini +12 -0
- pygpt_net/data/locale/locale.en.ini +18 -2
- pygpt_net/data/locale/locale.es.ini +12 -0
- pygpt_net/data/locale/locale.fr.ini +12 -0
- pygpt_net/data/locale/locale.it.ini +12 -0
- pygpt_net/data/locale/locale.pl.ini +12 -0
- pygpt_net/data/locale/locale.uk.ini +12 -0
- pygpt_net/data/locale/locale.zh.ini +12 -0
- pygpt_net/data/locale/plugin.cmd_web.de.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.en.ini +22 -10
- pygpt_net/data/locale/plugin.cmd_web.es.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.fr.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.it.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.pl.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.uk.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.zh.ini +2 -0
- pygpt_net/data/locale/plugin.mailer.en.ini +21 -0
- pygpt_net/icons.qrc +1 -0
- pygpt_net/icons_rc.py +165 -136
- pygpt_net/item/ctx.py +58 -25
- pygpt_net/plugin/agent/__init__.py +7 -2
- pygpt_net/plugin/audio_input/simple.py +21 -5
- pygpt_net/plugin/audio_output/__init__.py +9 -1
- pygpt_net/plugin/base/config.py +4 -2
- pygpt_net/plugin/base/plugin.py +75 -23
- pygpt_net/plugin/base/worker.py +42 -11
- pygpt_net/plugin/cmd_code_interpreter/__init__.py +39 -37
- pygpt_net/plugin/cmd_code_interpreter/runner.py +25 -12
- pygpt_net/plugin/cmd_history/config.py +2 -2
- pygpt_net/plugin/cmd_web/__init__.py +48 -9
- pygpt_net/plugin/cmd_web/config.py +135 -41
- pygpt_net/plugin/cmd_web/websearch.py +74 -33
- pygpt_net/plugin/cmd_web/worker.py +142 -13
- pygpt_net/plugin/idx_llama_index/config.py +3 -3
- pygpt_net/plugin/mailer/__init__.py +123 -0
- pygpt_net/plugin/mailer/config.py +149 -0
- pygpt_net/plugin/mailer/runner.py +285 -0
- pygpt_net/plugin/mailer/worker.py +123 -0
- pygpt_net/provider/agents/base.py +5 -2
- pygpt_net/provider/agents/openai.py +4 -2
- pygpt_net/provider/agents/openai_assistant.py +4 -2
- pygpt_net/provider/agents/planner.py +4 -2
- pygpt_net/provider/agents/react.py +4 -2
- pygpt_net/provider/audio_output/openai_tts.py +5 -11
- pygpt_net/provider/core/assistant/base.py +5 -3
- pygpt_net/provider/core/assistant/json_file.py +8 -5
- pygpt_net/provider/core/assistant_file/base.py +4 -3
- pygpt_net/provider/core/assistant_file/db_sqlite/__init__.py +4 -3
- pygpt_net/provider/core/assistant_file/db_sqlite/storage.py +3 -2
- pygpt_net/provider/core/assistant_store/base.py +6 -4
- pygpt_net/provider/core/assistant_store/db_sqlite/__init__.py +5 -4
- pygpt_net/provider/core/assistant_store/db_sqlite/storage.py +5 -3
- pygpt_net/provider/core/attachment/base.py +5 -3
- pygpt_net/provider/core/attachment/json_file.py +4 -3
- pygpt_net/provider/core/calendar/base.py +5 -3
- pygpt_net/provider/core/calendar/db_sqlite/__init__.py +6 -5
- pygpt_net/provider/core/calendar/db_sqlite/storage.py +5 -4
- pygpt_net/provider/core/config/base.py +8 -6
- pygpt_net/provider/core/config/json_file.py +9 -7
- pygpt_net/provider/core/config/patch.py +43 -1
- pygpt_net/provider/core/ctx/base.py +30 -25
- pygpt_net/provider/core/ctx/db_sqlite/__init__.py +59 -34
- pygpt_net/provider/core/ctx/db_sqlite/storage.py +62 -30
- pygpt_net/provider/core/ctx/db_sqlite/utils.py +11 -9
- pygpt_net/provider/core/index/base.py +129 -23
- pygpt_net/provider/core/index/db_sqlite/__init__.py +130 -23
- pygpt_net/provider/core/index/db_sqlite/storage.py +130 -23
- pygpt_net/provider/core/index/db_sqlite/utils.py +4 -2
- pygpt_net/provider/core/mode/base.py +5 -3
- pygpt_net/provider/core/mode/json_file.py +7 -6
- pygpt_net/provider/core/model/base.py +6 -4
- pygpt_net/provider/core/model/json_file.py +9 -7
- pygpt_net/provider/core/notepad/base.py +5 -3
- pygpt_net/provider/core/notepad/db_sqlite/__init__.py +5 -4
- pygpt_net/provider/core/notepad/db_sqlite/storage.py +4 -3
- pygpt_net/provider/core/plugin_preset/base.py +4 -2
- pygpt_net/provider/core/plugin_preset/json_file.py +5 -3
- pygpt_net/provider/core/preset/base.py +6 -4
- pygpt_net/provider/core/preset/json_file.py +9 -9
- pygpt_net/provider/core/prompt/base.py +6 -3
- pygpt_net/provider/core/prompt/json_file.py +11 -6
- pygpt_net/provider/gpt/assistants.py +21 -11
- pygpt_net/provider/gpt/audio.py +6 -5
- pygpt_net/provider/gpt/chat.py +10 -7
- pygpt_net/provider/gpt/completion.py +11 -5
- pygpt_net/provider/gpt/image.py +9 -2
- pygpt_net/provider/gpt/store.py +53 -18
- pygpt_net/provider/gpt/vision.py +17 -11
- pygpt_net/provider/llms/anthropic.py +7 -2
- pygpt_net/provider/llms/azure_openai.py +26 -5
- pygpt_net/provider/llms/base.py +47 -9
- pygpt_net/provider/llms/google.py +7 -2
- pygpt_net/provider/llms/hugging_face.py +13 -3
- pygpt_net/provider/llms/hugging_face_api.py +18 -4
- pygpt_net/provider/llms/local.py +7 -2
- pygpt_net/provider/llms/ollama.py +30 -6
- pygpt_net/provider/llms/openai.py +32 -6
- pygpt_net/provider/vector_stores/__init__.py +45 -14
- pygpt_net/provider/vector_stores/base.py +35 -8
- pygpt_net/provider/vector_stores/chroma.py +13 -3
- pygpt_net/provider/vector_stores/ctx_attachment.py +31 -12
- pygpt_net/provider/vector_stores/elasticsearch.py +12 -3
- pygpt_net/provider/vector_stores/pinecode.py +12 -3
- pygpt_net/provider/vector_stores/redis.py +12 -3
- pygpt_net/provider/vector_stores/simple.py +12 -3
- pygpt_net/provider/vector_stores/temp.py +16 -4
- pygpt_net/provider/web/base.py +10 -3
- pygpt_net/provider/web/google_custom_search.py +9 -3
- pygpt_net/provider/web/microsoft_bing.py +9 -3
- pygpt_net/tools/__init__.py +20 -4
- pygpt_net/tools/audio_transcriber/__init__.py +4 -3
- pygpt_net/tools/base.py +28 -7
- pygpt_net/tools/code_interpreter/__init__.py +177 -77
- pygpt_net/tools/code_interpreter/ui/dialogs.py +21 -103
- pygpt_net/tools/code_interpreter/ui/widgets.py +284 -9
- pygpt_net/tools/html_canvas/__init__.py +81 -25
- pygpt_net/tools/html_canvas/ui/dialogs.py +46 -62
- pygpt_net/tools/html_canvas/ui/widgets.py +96 -3
- pygpt_net/tools/image_viewer/__init__.py +10 -4
- pygpt_net/tools/indexer/__init__.py +8 -7
- pygpt_net/tools/media_player/__init__.py +4 -3
- pygpt_net/tools/text_editor/__init__.py +36 -10
- pygpt_net/ui/base/context_menu.py +2 -2
- pygpt_net/ui/layout/chat/input.py +10 -18
- pygpt_net/ui/layout/chat/output.py +27 -45
- pygpt_net/ui/layout/ctx/ctx_list.py +13 -4
- pygpt_net/ui/layout/toolbox/footer.py +18 -2
- pygpt_net/ui/main.py +2 -2
- pygpt_net/ui/menu/audio.py +12 -1
- pygpt_net/ui/menu/config.py +7 -11
- pygpt_net/ui/menu/debug.py +11 -1
- pygpt_net/ui/menu/theme.py +9 -2
- pygpt_net/ui/widget/filesystem/explorer.py +2 -2
- pygpt_net/ui/widget/lists/context.py +27 -5
- pygpt_net/ui/widget/tabs/Input.py +2 -2
- pygpt_net/ui/widget/tabs/body.py +2 -1
- pygpt_net/ui/widget/tabs/layout.py +195 -0
- pygpt_net/ui/widget/tabs/output.py +218 -55
- pygpt_net/ui/widget/textarea/html.py +11 -1
- pygpt_net/ui/widget/textarea/output.py +10 -1
- pygpt_net/ui/widget/textarea/search_input.py +4 -1
- pygpt_net/ui/widget/textarea/web.py +49 -9
- {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.42.dist-info}/METADATA +177 -183
- {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.42.dist-info}/RECORD +340 -325
- /pygpt_net/data/css/{web.dark.css → web-blocks.dark.css} +0 -0
- {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.42.dist-info}/LICENSE +0 -0
- {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.42.dist-info}/WHEEL +0 -0
- {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.42.dist-info}/entry_points.txt +0 -0
@@ -6,9 +6,11 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.14 08:00:00 #
|
10
10
|
# ================================================== #
|
11
|
+
|
11
12
|
import datetime
|
13
|
+
from typing import Optional, List, Dict, Any
|
12
14
|
|
13
15
|
from packaging.version import Version
|
14
16
|
|
@@ -50,7 +52,7 @@ class Store:
|
|
50
52
|
if id in self.items:
|
51
53
|
return self.items[id]
|
52
54
|
|
53
|
-
def get_ids(self) ->
|
55
|
+
def get_ids(self) -> List[str]:
|
54
56
|
"""
|
55
57
|
Return all loaded store IDs
|
56
58
|
|
@@ -59,7 +61,7 @@ class Store:
|
|
59
61
|
return list(self.items.keys())
|
60
62
|
|
61
63
|
|
62
|
-
def get_all(self) ->
|
64
|
+
def get_all(self) -> Dict[str, AssistantStoreItem]:
|
63
65
|
"""
|
64
66
|
Return all stores
|
65
67
|
|
@@ -97,7 +99,7 @@ class Store:
|
|
97
99
|
"""
|
98
100
|
return id in self.items
|
99
101
|
|
100
|
-
def create(self) -> AssistantStoreItem
|
102
|
+
def create(self) -> Optional[AssistantStoreItem]:
|
101
103
|
"""
|
102
104
|
Create new store
|
103
105
|
|
@@ -115,7 +117,7 @@ class Store:
|
|
115
117
|
self.items[store.id] = store
|
116
118
|
return store
|
117
119
|
|
118
|
-
def update(self, store: AssistantStoreItem) -> AssistantStoreItem
|
120
|
+
def update(self, store: AssistantStoreItem) -> Optional[AssistantStoreItem]:
|
119
121
|
"""
|
120
122
|
Update store
|
121
123
|
|
@@ -142,7 +144,7 @@ class Store:
|
|
142
144
|
status = self.parse_status(data)
|
143
145
|
return status, data
|
144
146
|
|
145
|
-
def parse_status(self, store) ->
|
147
|
+
def parse_status(self, store) -> Dict[str, Any]:
|
146
148
|
"""
|
147
149
|
Parse store status
|
148
150
|
|
@@ -185,7 +187,11 @@ class Store:
|
|
185
187
|
self.append_status(store, status) # append to store
|
186
188
|
self.update(store) # save to db
|
187
189
|
|
188
|
-
def append_status(
|
190
|
+
def append_status(
|
191
|
+
self,
|
192
|
+
store: AssistantStoreItem,
|
193
|
+
status: Dict[str, Any]
|
194
|
+
):
|
189
195
|
"""
|
190
196
|
Append status to store
|
191
197
|
|
@@ -208,7 +214,7 @@ class Store:
|
|
208
214
|
if "expires_after" in status:
|
209
215
|
store.expire_days = int(status["expires_after"]["days"] or 0)
|
210
216
|
|
211
|
-
def get_names(self) ->
|
217
|
+
def get_names(self) -> Dict[str, str]:
|
212
218
|
"""
|
213
219
|
Get store name mapping id <> name
|
214
220
|
|
@@ -235,7 +241,7 @@ class Store:
|
|
235
241
|
return True
|
236
242
|
return False
|
237
243
|
|
238
|
-
def import_items(self, items:
|
244
|
+
def import_items(self, items: Dict[str, AssistantStoreItem]):
|
239
245
|
"""
|
240
246
|
Insert items
|
241
247
|
|
@@ -286,5 +292,9 @@ class Store:
|
|
286
292
|
self.provider.save_all(self.items)
|
287
293
|
|
288
294
|
def get_version(self) -> str:
|
289
|
-
"""
|
295
|
+
"""
|
296
|
+
Get config version
|
297
|
+
|
298
|
+
:return: version
|
299
|
+
"""
|
290
300
|
return self.provider.get_version()
|
@@ -6,10 +6,11 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.14 08:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import copy
|
13
|
+
from typing import Optional, List, Dict
|
13
14
|
|
14
15
|
from packaging.version import Version
|
15
16
|
|
@@ -83,7 +84,7 @@ class Attachments:
|
|
83
84
|
|
84
85
|
return list(self.items[mode].keys())
|
85
86
|
|
86
|
-
def get_id_by_idx(self, mode: str, idx: int) -> str
|
87
|
+
def get_id_by_idx(self, mode: str, idx: int) -> Optional[str]:
|
87
88
|
"""
|
88
89
|
Get ID by index in mode
|
89
90
|
|
@@ -97,7 +98,7 @@ class Attachments:
|
|
97
98
|
return id
|
98
99
|
i += 1
|
99
100
|
|
100
|
-
def get_by_id(self, mode: str, id: str) -> AttachmentItem
|
101
|
+
def get_by_id(self, mode: str, id: str) -> Optional[AttachmentItem]:
|
101
102
|
"""
|
102
103
|
Return attachment by ID in mode
|
103
104
|
|
@@ -111,7 +112,7 @@ class Attachments:
|
|
111
112
|
if id in self.items[mode]:
|
112
113
|
return self.items[mode][id]
|
113
114
|
|
114
|
-
def get_by_idx(self, mode: str, idx: int) -> AttachmentItem
|
115
|
+
def get_by_idx(self, mode: str, idx: int) -> Optional[AttachmentItem]:
|
115
116
|
"""
|
116
117
|
Return item by index in mode
|
117
118
|
|
@@ -123,7 +124,11 @@ class Attachments:
|
|
123
124
|
if id is not None:
|
124
125
|
return self.items[mode][id]
|
125
126
|
|
126
|
-
def get_all(
|
127
|
+
def get_all(
|
128
|
+
self,
|
129
|
+
mode: str,
|
130
|
+
only_files: bool = True
|
131
|
+
) -> dict:
|
127
132
|
"""
|
128
133
|
Return all items in mode
|
129
134
|
|
@@ -141,7 +146,11 @@ class Attachments:
|
|
141
146
|
current[attachment.id] = attachment
|
142
147
|
return current
|
143
148
|
|
144
|
-
def get_from_meta_ctx(
|
149
|
+
def get_from_meta_ctx(
|
150
|
+
self,
|
151
|
+
mode: str,
|
152
|
+
meta: CtxMeta
|
153
|
+
) -> List[AttachmentItem]:
|
145
154
|
"""
|
146
155
|
Get attachments from meta context
|
147
156
|
|
@@ -174,8 +183,8 @@ class Attachments:
|
|
174
183
|
def new(
|
175
184
|
self,
|
176
185
|
mode: str,
|
177
|
-
name: str = None,
|
178
|
-
path: str = None,
|
186
|
+
name: Optional[str] = None,
|
187
|
+
path: Optional[str] = None,
|
179
188
|
auto_save: bool = True,
|
180
189
|
type: str = AttachmentItem.TYPE_FILE,
|
181
190
|
) -> AttachmentItem:
|
@@ -233,7 +242,11 @@ class Attachments:
|
|
233
242
|
attachment.id = id
|
234
243
|
return attachment
|
235
244
|
|
236
|
-
def add(
|
245
|
+
def add(
|
246
|
+
self,
|
247
|
+
mode: str,
|
248
|
+
item: AttachmentItem
|
249
|
+
):
|
237
250
|
"""
|
238
251
|
Add item to attachments
|
239
252
|
|
@@ -261,7 +274,12 @@ class Attachments:
|
|
261
274
|
|
262
275
|
return len(self.items[mode]) > 0
|
263
276
|
|
264
|
-
def delete(
|
277
|
+
def delete(
|
278
|
+
self,
|
279
|
+
mode: str,
|
280
|
+
id: str,
|
281
|
+
remove_local: bool = False
|
282
|
+
):
|
265
283
|
"""
|
266
284
|
Delete attachment by file_id
|
267
285
|
|
@@ -280,7 +298,13 @@ class Attachments:
|
|
280
298
|
del self.items[mode][id]
|
281
299
|
self.save()
|
282
300
|
|
283
|
-
def delete_all(
|
301
|
+
def delete_all(
|
302
|
+
self,
|
303
|
+
mode: str,
|
304
|
+
remove_local: bool = False,
|
305
|
+
auto: bool = False,
|
306
|
+
force: bool = False
|
307
|
+
):
|
284
308
|
"""
|
285
309
|
Delete all attachments
|
286
310
|
|
@@ -302,7 +326,11 @@ class Attachments:
|
|
302
326
|
del self.items[mode][id]
|
303
327
|
self.save()
|
304
328
|
|
305
|
-
def clear(
|
329
|
+
def clear(
|
330
|
+
self,
|
331
|
+
mode: str,
|
332
|
+
remove_local: bool = False
|
333
|
+
):
|
306
334
|
"""
|
307
335
|
Clear all attachments in mode
|
308
336
|
|
@@ -355,7 +383,10 @@ class Attachments:
|
|
355
383
|
data.name = name
|
356
384
|
self.save()
|
357
385
|
|
358
|
-
def make_json_list(
|
386
|
+
def make_json_list(
|
387
|
+
self,
|
388
|
+
attachments: Dict[str, AttachmentItem]
|
389
|
+
) -> Dict[str, dict]:
|
359
390
|
"""
|
360
391
|
Make json list
|
361
392
|
|
@@ -371,7 +402,11 @@ class Attachments:
|
|
371
402
|
}
|
372
403
|
return result
|
373
404
|
|
374
|
-
def from_files(
|
405
|
+
def from_files(
|
406
|
+
self,
|
407
|
+
mode: str,
|
408
|
+
files: Dict[str, dict]
|
409
|
+
):
|
375
410
|
"""
|
376
411
|
Load current from assistant files
|
377
412
|
|
@@ -396,7 +431,11 @@ class Attachments:
|
|
396
431
|
item.send = True
|
397
432
|
self.add(mode, item)
|
398
433
|
|
399
|
-
def from_attachments(
|
434
|
+
def from_attachments(
|
435
|
+
self,
|
436
|
+
mode: str,
|
437
|
+
attachments: Dict[str, AttachmentItem]
|
438
|
+
):
|
400
439
|
"""
|
401
440
|
Load current from attachments
|
402
441
|
|
@@ -6,7 +6,7 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.14 08:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import copy
|
@@ -15,6 +15,7 @@ import shutil
|
|
15
15
|
import uuid
|
16
16
|
|
17
17
|
from shutil import copyfile
|
18
|
+
from typing import Optional, List, Dict, Any
|
18
19
|
|
19
20
|
from pygpt_net.core.bridge import BridgeContext
|
20
21
|
from pygpt_net.core.events import KernelEvent
|
@@ -85,7 +86,12 @@ class Context:
|
|
85
86
|
`{query}`
|
86
87
|
"""
|
87
88
|
|
88
|
-
def get_context(
|
89
|
+
def get_context(
|
90
|
+
self,
|
91
|
+
mode: str,
|
92
|
+
ctx: CtxItem,
|
93
|
+
history: List[CtxItem]
|
94
|
+
) -> str:
|
89
95
|
"""
|
90
96
|
Get context for mode
|
91
97
|
|
@@ -103,7 +109,11 @@ class Context:
|
|
103
109
|
content = self.summary_context(ctx, history)
|
104
110
|
return content
|
105
111
|
|
106
|
-
def get_context_text(
|
112
|
+
def get_context_text(
|
113
|
+
self,
|
114
|
+
ctx: CtxItem,
|
115
|
+
filename: bool = False
|
116
|
+
) -> str:
|
107
117
|
"""
|
108
118
|
Get raw text context for meta
|
109
119
|
|
@@ -119,6 +129,8 @@ class Context:
|
|
119
129
|
if ("type" not in file
|
120
130
|
or file["type"] not in ["local_file", "url"]):
|
121
131
|
continue
|
132
|
+
if not "uuid" in file:
|
133
|
+
continue
|
122
134
|
file_id = file["uuid"]
|
123
135
|
file_idx_path = os.path.join(meta_path, file_id)
|
124
136
|
text_path = os.path.join(file_idx_path, file_id + ".txt")
|
@@ -150,7 +162,11 @@ class Context:
|
|
150
162
|
self.last_used_context = context
|
151
163
|
return context
|
152
164
|
|
153
|
-
def query_context(
|
165
|
+
def query_context(
|
166
|
+
self,
|
167
|
+
ctx: CtxItem,
|
168
|
+
history: List[CtxItem]
|
169
|
+
) -> str:
|
154
170
|
"""
|
155
171
|
Query the index for context
|
156
172
|
|
@@ -210,7 +226,11 @@ class Context:
|
|
210
226
|
|
211
227
|
return result
|
212
228
|
|
213
|
-
def summary_context(
|
229
|
+
def summary_context(
|
230
|
+
self,
|
231
|
+
ctx: CtxItem,
|
232
|
+
history: List[CtxItem]
|
233
|
+
) -> str:
|
214
234
|
"""
|
215
235
|
Get summary of the context
|
216
236
|
|
@@ -254,7 +274,10 @@ class Context:
|
|
254
274
|
print("Attachments: summary received: {}".format(response))
|
255
275
|
return response
|
256
276
|
|
257
|
-
def prepare_context_history(
|
277
|
+
def prepare_context_history(
|
278
|
+
self,
|
279
|
+
history: List[CtxItem]
|
280
|
+
) -> List[CtxItem]:
|
258
281
|
"""
|
259
282
|
Prepare context history
|
260
283
|
|
@@ -289,7 +312,7 @@ class Context:
|
|
289
312
|
attachment: AttachmentItem,
|
290
313
|
prompt: str,
|
291
314
|
auto_index: bool = False,
|
292
|
-
real_path: str = None
|
315
|
+
real_path: Optional[str] = None
|
293
316
|
) -> dict:
|
294
317
|
"""
|
295
318
|
Upload attachment for context
|
@@ -374,7 +397,12 @@ class Context:
|
|
374
397
|
|
375
398
|
return result
|
376
399
|
|
377
|
-
def read_content(
|
400
|
+
def read_content(
|
401
|
+
self,
|
402
|
+
attachment: AttachmentItem,
|
403
|
+
path: str,
|
404
|
+
prompt: str
|
405
|
+
) -> str:
|
378
406
|
"""
|
379
407
|
Read content from attachment
|
380
408
|
|
@@ -399,7 +427,11 @@ class Context:
|
|
399
427
|
|
400
428
|
return content
|
401
429
|
|
402
|
-
def store_content(
|
430
|
+
def store_content(
|
431
|
+
self,
|
432
|
+
attachment: AttachmentItem,
|
433
|
+
dir: str
|
434
|
+
) -> str:
|
403
435
|
"""
|
404
436
|
Prepare content for attachment
|
405
437
|
|
@@ -431,7 +463,13 @@ class Context:
|
|
431
463
|
f.write(content)
|
432
464
|
return path
|
433
465
|
|
434
|
-
def index_attachment(
|
466
|
+
def index_attachment(
|
467
|
+
self,
|
468
|
+
type: str,
|
469
|
+
source: str,
|
470
|
+
idx_path: str,
|
471
|
+
documents: Optional[list] = None
|
472
|
+
) -> list:
|
435
473
|
"""
|
436
474
|
Index attachment
|
437
475
|
|
@@ -486,7 +524,11 @@ class Context:
|
|
486
524
|
model_item = self.window.core.models.get(model)
|
487
525
|
return model, model_item
|
488
526
|
|
489
|
-
def duplicate(
|
527
|
+
def duplicate(
|
528
|
+
self,
|
529
|
+
from_meta_id: int,
|
530
|
+
to_meta_id: int
|
531
|
+
) -> bool:
|
490
532
|
"""
|
491
533
|
Duplicate attachments from one meta to another
|
492
534
|
|
@@ -522,12 +564,17 @@ class Context:
|
|
522
564
|
"""
|
523
565
|
return len(meta.additional_ctx)
|
524
566
|
|
525
|
-
def delete(
|
567
|
+
def delete(
|
568
|
+
self,
|
569
|
+
meta: CtxMeta,
|
570
|
+
item: Dict[str, Any],
|
571
|
+
delete_files: bool = False
|
572
|
+
):
|
526
573
|
"""
|
527
574
|
Delete attachment
|
528
575
|
|
529
576
|
:param meta: CtxMeta instance
|
530
|
-
:param item:
|
577
|
+
:param item: Attachment item dict
|
531
578
|
:param delete_files: delete files
|
532
579
|
"""
|
533
580
|
meta.additional_ctx.remove(item)
|
@@ -555,18 +602,11 @@ class Context:
|
|
555
602
|
if meta is not None:
|
556
603
|
self.delete_index(meta)
|
557
604
|
|
558
|
-
def
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
:param delete_files: delete files
|
564
|
-
"""
|
565
|
-
meta = self.window.core.ctx.get_meta_by_id(meta_id)
|
566
|
-
if meta is not None:
|
567
|
-
self.reset_by_meta(meta, delete_files)
|
568
|
-
|
569
|
-
def reset_by_meta(self, meta: CtxMeta, delete_files: bool = False):
|
605
|
+
def reset_by_meta(
|
606
|
+
self,
|
607
|
+
meta: CtxMeta,
|
608
|
+
delete_files: bool = False
|
609
|
+
):
|
570
610
|
"""
|
571
611
|
Delete all attachments for meta
|
572
612
|
|
@@ -578,7 +618,26 @@ class Context:
|
|
578
618
|
if delete_files:
|
579
619
|
self.delete_index(meta)
|
580
620
|
|
581
|
-
def
|
621
|
+
def reset_by_meta_id(
|
622
|
+
self,
|
623
|
+
meta_id: int,
|
624
|
+
delete_files: bool = False
|
625
|
+
):
|
626
|
+
"""
|
627
|
+
Delete all attachments for meta by id
|
628
|
+
|
629
|
+
:param meta_id: Meta id
|
630
|
+
:param delete_files: delete files
|
631
|
+
"""
|
632
|
+
meta = self.window.core.ctx.get_meta_by_id(meta_id)
|
633
|
+
if meta is not None:
|
634
|
+
self.reset_by_meta(meta, delete_files)
|
635
|
+
|
636
|
+
def clear(
|
637
|
+
self,
|
638
|
+
meta: CtxMeta,
|
639
|
+
delete_files: bool = False
|
640
|
+
):
|
582
641
|
"""
|
583
642
|
Clear all attachments by ctx meta
|
584
643
|
|
@@ -602,7 +661,11 @@ class Context:
|
|
602
661
|
if self.is_verbose():
|
603
662
|
print("Attachment deleted dir: {}".format(meta_path))
|
604
663
|
|
605
|
-
def delete_local(
|
664
|
+
def delete_local(
|
665
|
+
self,
|
666
|
+
meta: CtxMeta,
|
667
|
+
item: Dict[str, Any]
|
668
|
+
):
|
606
669
|
"""
|
607
670
|
Delete local attachment
|
608
671
|
|
@@ -646,7 +709,7 @@ class Context:
|
|
646
709
|
self.last_files = []
|
647
710
|
self.last_urls = []
|
648
711
|
|
649
|
-
def get_used_files(self) ->
|
712
|
+
def get_used_files(self) -> List[str]:
|
650
713
|
"""
|
651
714
|
Get last used files
|
652
715
|
|
@@ -654,7 +717,7 @@ class Context:
|
|
654
717
|
"""
|
655
718
|
return self.last_files
|
656
719
|
|
657
|
-
def get_used_urls(self) ->
|
720
|
+
def get_used_urls(self) -> List[str]:
|
658
721
|
"""
|
659
722
|
Get last used URLs
|
660
723
|
|
pygpt_net/core/audio/__init__.py
CHANGED
@@ -6,14 +6,19 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.14 18:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import re
|
13
|
+
from typing import Union, Optional, Tuple, List
|
14
|
+
|
15
|
+
from bs4 import UnicodeDammit
|
13
16
|
|
14
17
|
from pygpt_net.provider.audio_input.base import BaseProvider as InputBaseProvider
|
15
18
|
from pygpt_net.provider.audio_output.base import BaseProvider as OutputBaseProvider
|
16
19
|
|
20
|
+
from .whisper import Whisper
|
21
|
+
|
17
22
|
|
18
23
|
class Audio:
|
19
24
|
def __init__(self, window=None):
|
@@ -23,10 +28,60 @@ class Audio:
|
|
23
28
|
:param window: Window instance
|
24
29
|
"""
|
25
30
|
self.window = window
|
31
|
+
self.whisper = Whisper(window)
|
26
32
|
self.providers = {
|
27
33
|
"input": {},
|
28
34
|
"output": {},
|
29
35
|
}
|
36
|
+
self.last_error = None
|
37
|
+
|
38
|
+
def get_input_devices(self) -> List[Tuple[int, str]]:
|
39
|
+
"""
|
40
|
+
Get input devices
|
41
|
+
|
42
|
+
:return devices list: [(id, name)]
|
43
|
+
"""
|
44
|
+
import pyaudio
|
45
|
+
devices = []
|
46
|
+
try:
|
47
|
+
p = pyaudio.PyAudio()
|
48
|
+
num_devices = p.get_device_count()
|
49
|
+
for i in range(num_devices):
|
50
|
+
info = p.get_device_info_by_index(i)
|
51
|
+
if info["maxInputChannels"] > 0:
|
52
|
+
dammit = UnicodeDammit(info["name"])
|
53
|
+
devices.append((i, dammit.unicode_markup))
|
54
|
+
# print(f"Device ID {i}: {info['name']}")
|
55
|
+
p.terminate()
|
56
|
+
except Exception as e:
|
57
|
+
print(f"Audio input devices receive error: {e}")
|
58
|
+
return devices
|
59
|
+
|
60
|
+
def is_device_compatible(self, device_index: int) -> bool:
|
61
|
+
"""
|
62
|
+
Check if device is compatible
|
63
|
+
|
64
|
+
:param device_index: device index
|
65
|
+
:return: True if compatible
|
66
|
+
"""
|
67
|
+
import pyaudio
|
68
|
+
rate = int(self.window.core.config.get('audio.input.rate', 44100))
|
69
|
+
channels = int(self.window.core.config.get('audio.input.channels', 1))
|
70
|
+
p = pyaudio.PyAudio()
|
71
|
+
info = p.get_device_info_by_index(device_index)
|
72
|
+
supported = False
|
73
|
+
try:
|
74
|
+
p.is_format_supported(
|
75
|
+
rate=rate,
|
76
|
+
input_device=info['index'],
|
77
|
+
input_channels=channels,
|
78
|
+
input_format=pyaudio.paInt16)
|
79
|
+
supported = True
|
80
|
+
except ValueError as e:
|
81
|
+
self.last_error = str(e)
|
82
|
+
supported = False
|
83
|
+
p.terminate()
|
84
|
+
return supported
|
30
85
|
|
31
86
|
def is_registered(self, id: str, type: str = "output") -> bool:
|
32
87
|
"""
|
@@ -62,7 +117,11 @@ class Audio:
|
|
62
117
|
return list(self.providers[type].keys())
|
63
118
|
return []
|
64
119
|
|
65
|
-
def get(
|
120
|
+
def get(
|
121
|
+
self,
|
122
|
+
id: str,
|
123
|
+
type: str = "output"
|
124
|
+
) -> Optional[Union[InputBaseProvider, OutputBaseProvider]]:
|
66
125
|
"""
|
67
126
|
Get provider instance
|
68
127
|
|
@@ -74,7 +133,11 @@ class Audio:
|
|
74
133
|
return self.providers[type][id]
|
75
134
|
return None
|
76
135
|
|
77
|
-
def register(
|
136
|
+
def register(
|
137
|
+
self,
|
138
|
+
provider: Union[InputBaseProvider, OutputBaseProvider],
|
139
|
+
type: str = "output"
|
140
|
+
):
|
78
141
|
"""
|
79
142
|
Register provider
|
80
143
|
|
@@ -92,3 +155,11 @@ class Audio:
|
|
92
155
|
:return: cleaned text
|
93
156
|
"""
|
94
157
|
return re.sub(r'~###~.*?~###~', '', str(text))
|
158
|
+
|
159
|
+
def get_last_error(self) -> str:
|
160
|
+
"""
|
161
|
+
Return last error
|
162
|
+
|
163
|
+
:return: Error
|
164
|
+
"""
|
165
|
+
return self.last_error
|
pygpt_net/core/audio/context.py
CHANGED
@@ -6,9 +6,14 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.14 08:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
|
+
from typing import Dict, Any
|
13
|
+
|
14
|
+
from pygpt_net.item.ctx import CtxItem
|
15
|
+
|
16
|
+
|
12
17
|
class AudioContext:
|
13
18
|
def __init__(self, **kwargs):
|
14
19
|
"""
|
@@ -19,7 +24,7 @@ class AudioContext:
|
|
19
24
|
self.data = kwargs.get("ctx", None)
|
20
25
|
self.prev_id = kwargs.get("prev_id", None)
|
21
26
|
|
22
|
-
def to_dict(self) ->
|
27
|
+
def to_dict(self) -> Dict:
|
23
28
|
"""
|
24
29
|
Return as dictionary
|
25
30
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# ================================================== #
|
4
|
+
# This file is a part of PYGPT package #
|
5
|
+
# Website: https://pygpt.net #
|
6
|
+
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
|
+
# MIT License #
|
8
|
+
# Created By : Marcin Szczygliński #
|
9
|
+
# Updated Date: 2024.12.14 18:00:00 #
|
10
|
+
# ================================================== #
|
11
|
+
|
12
|
+
from typing import List
|
13
|
+
|
14
|
+
class Whisper:
|
15
|
+
def __init__(self, window=None):
|
16
|
+
"""
|
17
|
+
Whisper core
|
18
|
+
|
19
|
+
:param window: Window instance
|
20
|
+
"""
|
21
|
+
self.window = window
|
22
|
+
self.voices = [
|
23
|
+
"alloy",
|
24
|
+
"echo",
|
25
|
+
"fable",
|
26
|
+
"onyx",
|
27
|
+
"nova",
|
28
|
+
"shimmer",
|
29
|
+
]
|
30
|
+
|
31
|
+
def get_voices(self) -> List[str]:
|
32
|
+
"""
|
33
|
+
Get whisper voices
|
34
|
+
|
35
|
+
:return: whisper voice name
|
36
|
+
"""
|
37
|
+
return self.voices
|