rasa-pro 3.13.0.dev3__py3-none-any.whl → 3.13.0.dev5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rasa-pro might be problematic. Click here for more details.
- rasa/__main__.py +3 -1
- rasa/cli/inspect.py +8 -4
- rasa/cli/project_templates/default/config.yml +5 -32
- rasa/cli/project_templates/{calm → default}/e2e_tests/cancelations/user_cancels_during_a_correction.yml +1 -1
- rasa/cli/project_templates/{calm → default}/e2e_tests/cancelations/user_changes_mind_on_a_whim.yml +1 -1
- rasa/cli/project_templates/{calm → default}/e2e_tests/corrections/user_corrects_contact_handle.yml +1 -1
- rasa/cli/project_templates/{calm → default}/e2e_tests/corrections/user_corrects_contact_name.yml +1 -1
- rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_adds_contact_to_their_list.yml +1 -1
- rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_lists_contacts.yml +1 -1
- rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_removes_contact.yml +1 -1
- rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_removes_contact_from_list.yml +1 -1
- rasa/cli/project_templates/default/endpoints.yml +18 -2
- rasa/cli/scaffold.py +3 -4
- rasa/cli/studio/download.py +1 -1
- rasa/cli/studio/upload.py +0 -6
- rasa/core/channels/channel.py +68 -5
- rasa/core/channels/inspector/dist/assets/{arc-c7691751.js → arc-9f75cc3b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-ab99dff7.js → blockDiagram-38ab4fdb-7f34db23.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-08c35a6b.js → c4Diagram-3d4e48cf-948bab2c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/channel-dfa68278.js +1 -0
- rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-9e9c71c9.js → classDiagram-70f12bd4-53b0dd0e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-15e7e2bf.js → classDiagram-v2-f2320105-fdf789e7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/clone-edb7f119.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-9c105cb1.js → createText-2e5e7dd3-87c4ece5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-77e89e48.js → edges-e0da2a9e-5a8b0749.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-7a011646.js → erDiagram-9861fffd-66da90e2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-b6f105ac.js → flowDb-956e92f1-10044f05.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-ce4f18c2.js → flowDiagram-66a62f08-f338f66a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-65e7c670.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-cb5f6da4.js → flowchart-elk-definition-4a651766-b13140aa.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-e4d19e28.js → ganttDiagram-c361ad54-f2b4a55a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-727b1c33.js → gitGraphDiagram-72cf32ee-dedc298d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-6e2ab9a7.js → graph-4ede11ff.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3862675e-84ec700f.js → index-3862675e-65549d37.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-098a1a24.js → index-3a23e736.js} +142 -129
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-78dda442.js → infoDiagram-f8f76790-65439671.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-f1cc6dd1.js → journeyDiagram-49397b02-56d03d98.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-d98dcd0c.js → layout-dd48f7f4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-838e3d82.js → line-1569ad2c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-eae72406.js → linear-48bf4935.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-c96fd84b.js → mindmap-definition-fc14e90a-688504c1.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-c936d4e2.js → pieDiagram-8a3498a8-78b6d7e6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-b338eb8f.js → quadrantDiagram-120e2f19-048b84b3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-c6b6c0d5.js → requirementDiagram-deff3bca-dd67f107.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-b9372e19.js → sankeyDiagram-04a897e0-8128436e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-479e0a3f.js → sequenceDiagram-704730f1-1a0d1461.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-fd26eebc.js → stateDiagram-587899a1-46d388ed.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-3233e0ae.js → stateDiagram-v2-d93cdb3a-ea42951a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-1fdd392b.js → styles-6aaf32cf-7427ed0c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-6d7bfa1b.js → styles-9a916d00-ff5e5a16.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-f86aab11.js → styles-c10674c1-7b3680cf.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-e3e49d7a.js → svgDrawCommon-08f97a94-f860f2ad.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-6fe08b4d.js → timeline-definition-85554ec2-2eebf0c8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-c2e06fd6.js → xychartDiagram-e933f94c-5d7f4e96.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +1 -1
- rasa/core/channels/inspector/src/App.tsx +3 -2
- rasa/core/channels/inspector/src/components/Chat.tsx +23 -2
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +2 -5
- rasa/core/channels/inspector/src/helpers/conversation.ts +16 -0
- rasa/core/channels/inspector/src/types.ts +1 -1
- rasa/core/channels/voice_ready/audiocodes.py +41 -15
- rasa/core/channels/voice_ready/twilio_voice.py +48 -1
- rasa/core/channels/voice_stream/tts/azure.py +11 -2
- rasa/core/channels/voice_stream/twilio_media_streams.py +101 -26
- rasa/core/channels/voice_stream/voice_channel.py +28 -2
- rasa/core/concurrent_lock_store.py +24 -10
- rasa/core/lock_store.py +151 -60
- rasa/dialogue_understanding_test/du_test_case.py +16 -8
- rasa/plugin.py +0 -3
- rasa/shared/constants.py +1 -0
- rasa/shared/core/domain.py +165 -11
- rasa/shared/core/flows/flow.py +155 -131
- rasa/shared/core/flows/flow_step.py +19 -3
- rasa/shared/core/flows/flow_step_links.py +15 -0
- rasa/shared/core/flows/flow_step_sequence.py +6 -0
- rasa/shared/core/flows/nlu_trigger.py +13 -0
- rasa/shared/core/flows/steps/action.py +7 -4
- rasa/shared/core/flows/steps/call.py +11 -4
- rasa/shared/core/flows/steps/collect.py +27 -6
- rasa/shared/core/flows/steps/internal.py +6 -1
- rasa/shared/core/flows/steps/link.py +7 -4
- rasa/shared/core/flows/steps/no_operation.py +7 -4
- rasa/shared/core/flows/steps/set_slots.py +8 -4
- rasa/shared/core/flows/yaml_flows_io.py +106 -5
- rasa/shared/importers/importer.py +8 -0
- rasa/shared/providers/_utils.py +83 -0
- rasa/shared/providers/llm/_base_litellm_client.py +6 -3
- rasa/shared/providers/llm/azure_openai_llm_client.py +6 -68
- rasa/shared/providers/router/_base_litellm_router_client.py +53 -1
- rasa/shared/utils/common.py +42 -0
- rasa/studio/download/domains.py +49 -0
- rasa/studio/download/download.py +439 -0
- rasa/studio/download/flows.py +359 -0
- rasa/studio/results_logger.py +6 -1
- rasa/studio/upload.py +69 -5
- rasa/utils/common.py +36 -0
- rasa/utils/endpoints.py +22 -1
- rasa/utils/licensing.py +1 -1
- rasa/validator.py +1 -2
- rasa/version.py +1 -1
- {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev5.dist-info}/METADATA +8 -8
- {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev5.dist-info}/RECORD +119 -125
- rasa/cli/project_templates/calm/config.yml +0 -10
- rasa/cli/project_templates/calm/credentials.yml +0 -33
- rasa/cli/project_templates/calm/endpoints.yml +0 -58
- rasa/cli/project_templates/default/actions/actions.py +0 -27
- rasa/cli/project_templates/default/data/nlu.yml +0 -91
- rasa/cli/project_templates/default/data/rules.yml +0 -13
- rasa/cli/project_templates/default/data/stories.yml +0 -30
- rasa/cli/project_templates/default/domain.yml +0 -34
- rasa/cli/project_templates/default/tests/test_stories.yml +0 -91
- rasa/core/channels/inspector/dist/assets/channel-11268142.js +0 -1
- rasa/core/channels/inspector/dist/assets/clone-ff7f2ce7.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-cba7ae20.js +0 -1
- rasa/studio/download.py +0 -489
- /rasa/cli/project_templates/{calm → default}/actions/action_template.py +0 -0
- /rasa/cli/project_templates/{calm → default}/actions/add_contact.py +0 -0
- /rasa/cli/project_templates/{calm → default}/actions/db.py +0 -0
- /rasa/cli/project_templates/{calm → default}/actions/list_contacts.py +0 -0
- /rasa/cli/project_templates/{calm → default}/actions/remove_contact.py +0 -0
- /rasa/cli/project_templates/{calm → default}/data/flows/add_contact.yml +0 -0
- /rasa/cli/project_templates/{calm → default}/data/flows/list_contacts.yml +0 -0
- /rasa/cli/project_templates/{calm → default}/data/flows/remove_contact.yml +0 -0
- /rasa/cli/project_templates/{calm → default}/db/contacts.json +0 -0
- /rasa/cli/project_templates/{calm → default}/domain/add_contact.yml +0 -0
- /rasa/cli/project_templates/{calm → default}/domain/list_contacts.yml +0 -0
- /rasa/cli/project_templates/{calm → default}/domain/remove_contact.yml +0 -0
- /rasa/cli/project_templates/{calm → default}/domain/shared.yml +0 -0
- /rasa/{cli/project_templates/calm/actions → studio/download}/__init__.py +0 -0
- {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev5.dist-info}/NOTICE +0 -0
- {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev5.dist-info}/WHEEL +0 -0
- {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev5.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any, Dict, List, Set, Text
|
|
4
|
+
|
|
5
|
+
from rasa.shared.core.flows import Flow
|
|
6
|
+
from rasa.shared.core.flows.flow_step_links import StaticFlowStepLink
|
|
7
|
+
from rasa.shared.core.flows.flows_list import FlowsList
|
|
8
|
+
from rasa.shared.core.flows.yaml_flows_io import YAMLFlowsReader, YamlFlowsWriter
|
|
9
|
+
from rasa.shared.importers.importer import TrainingDataImporter
|
|
10
|
+
from rasa.shared.utils.yaml import read_yaml
|
|
11
|
+
from rasa.studio.constants import STUDIO_NLU_FILENAME
|
|
12
|
+
from rasa.studio.data_handler import StudioDataHandler
|
|
13
|
+
from rasa.utils.mapper import RasaPrimitiveStorageMapper
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
STUDIO_FLOWS_DIR_NAME = "studio_flows"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def merge_flows_with_overwrite(
|
|
21
|
+
data_paths: List[Path],
|
|
22
|
+
handler: Any,
|
|
23
|
+
data_from_studio: TrainingDataImporter,
|
|
24
|
+
data_local: TrainingDataImporter,
|
|
25
|
+
mapper: RasaPrimitiveStorageMapper,
|
|
26
|
+
) -> None:
|
|
27
|
+
"""
|
|
28
|
+
Merges flows data from a file or directory when overwrite is enabled.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
data_paths: List of paths to the training data.
|
|
32
|
+
handler: The StudioDataHandler instance.
|
|
33
|
+
data_from_studio: The TrainingDataImporter instance for Studio data.
|
|
34
|
+
data_local: The TrainingDataImporter instance for local data.
|
|
35
|
+
mapper: The RasaPrimitiveStorageMapper instance for mapping.
|
|
36
|
+
"""
|
|
37
|
+
if len(data_paths) != 1:
|
|
38
|
+
# TODO: Handle multiple data paths.
|
|
39
|
+
raise NotImplementedError("Multiple data paths are not supported yet.")
|
|
40
|
+
|
|
41
|
+
data_path = data_paths[0]
|
|
42
|
+
if data_path.is_file():
|
|
43
|
+
merge_training_data_file(handler, data_from_studio, data_local, data_path)
|
|
44
|
+
elif data_path.is_dir():
|
|
45
|
+
merge_training_data_dir(
|
|
46
|
+
handler, data_from_studio, data_local, data_path, mapper
|
|
47
|
+
)
|
|
48
|
+
else:
|
|
49
|
+
raise ValueError("Provided data path is neither a file nor a directory.")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def merge_training_data_file(
|
|
53
|
+
handler: StudioDataHandler,
|
|
54
|
+
data_from_studio: TrainingDataImporter,
|
|
55
|
+
data_local: TrainingDataImporter,
|
|
56
|
+
file_path: Path,
|
|
57
|
+
) -> None:
|
|
58
|
+
"""
|
|
59
|
+
Merges NLU and flows data when training data is stored in a single file.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
handler: The StudioDataHandler instance.
|
|
63
|
+
data_from_studio: The TrainingDataImporter instance for Studio data.
|
|
64
|
+
data_local: The TrainingDataImporter instance for local data.
|
|
65
|
+
file_path: The path to the training data file.
|
|
66
|
+
"""
|
|
67
|
+
if handler.has_nlu():
|
|
68
|
+
nlu_data_merged = data_from_studio.get_nlu_data().merge(
|
|
69
|
+
data_local.get_nlu_data()
|
|
70
|
+
)
|
|
71
|
+
nlu_data_merged.persist_nlu(file_path)
|
|
72
|
+
|
|
73
|
+
if handler.has_flows():
|
|
74
|
+
flows_data_merged = data_from_studio.get_user_flows().merge(
|
|
75
|
+
data_local.get_user_flows()
|
|
76
|
+
)
|
|
77
|
+
YamlFlowsWriter.dump(
|
|
78
|
+
flows=flows_data_merged.underlying_flows,
|
|
79
|
+
filename=file_path,
|
|
80
|
+
should_clean_json=True,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def merge_training_data_dir(
|
|
85
|
+
handler: StudioDataHandler,
|
|
86
|
+
data_from_studio: TrainingDataImporter,
|
|
87
|
+
data_local: TrainingDataImporter,
|
|
88
|
+
data_path: Path,
|
|
89
|
+
mapper: RasaPrimitiveStorageMapper,
|
|
90
|
+
) -> None:
|
|
91
|
+
"""
|
|
92
|
+
Merges NLU and flows data when training data is stored in a directory.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
handler: The StudioDataHandler instance.
|
|
96
|
+
data_from_studio: The TrainingDataImporter instance for Studio data.
|
|
97
|
+
data_local: The TrainingDataImporter instance for local data.
|
|
98
|
+
data_path: The path to the training data directory.
|
|
99
|
+
mapper: The RasaPrimitiveStorageMapper instance for mapping.
|
|
100
|
+
"""
|
|
101
|
+
if handler.has_nlu():
|
|
102
|
+
merge_nlu_in_directory(data_from_studio, data_local, data_path, mapper)
|
|
103
|
+
|
|
104
|
+
if handler.has_flows():
|
|
105
|
+
merge_flows_in_directory(data_from_studio, data_path, mapper)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def merge_nlu_in_directory(
|
|
109
|
+
data_from_studio: TrainingDataImporter,
|
|
110
|
+
data_local: TrainingDataImporter,
|
|
111
|
+
data_path: Path,
|
|
112
|
+
mapper: RasaPrimitiveStorageMapper,
|
|
113
|
+
) -> None:
|
|
114
|
+
"""
|
|
115
|
+
Merges NLU data by checking for an existing NLU file in the directory.
|
|
116
|
+
If it exists, the new Studio data is merged with the local data.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
data_from_studio: The TrainingDataImporter instance for Studio data.
|
|
120
|
+
data_local: The TrainingDataImporter instance for local data.
|
|
121
|
+
data_path: The path to the training data directory.
|
|
122
|
+
mapper: The RasaPrimitiveStorageMapper instance for mapping.
|
|
123
|
+
"""
|
|
124
|
+
from rasa.studio.download.download import pretty_write_nlu_yaml
|
|
125
|
+
|
|
126
|
+
nlu_data = data_from_studio.get_nlu_data()
|
|
127
|
+
nlu_file_path = get_nlu_path(data_path, data_local, mapper)
|
|
128
|
+
|
|
129
|
+
if nlu_file_path.exists():
|
|
130
|
+
local_nlu = TrainingDataImporter.load_from_dict(
|
|
131
|
+
training_data_paths=[str(nlu_file_path)]
|
|
132
|
+
)
|
|
133
|
+
nlu_data = nlu_data.merge(local_nlu.get_nlu_data())
|
|
134
|
+
|
|
135
|
+
pretty_write_nlu_yaml(read_yaml(nlu_data.nlu_as_yaml()), nlu_file_path)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def get_nlu_path(
|
|
139
|
+
base_path: Path,
|
|
140
|
+
data_local: TrainingDataImporter,
|
|
141
|
+
mapper: RasaPrimitiveStorageMapper,
|
|
142
|
+
) -> Path:
|
|
143
|
+
"""Determines where NLU data should be stored.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
base_path: The base path for the training data.
|
|
147
|
+
data_local: The TrainingDataImporter instance for local data.
|
|
148
|
+
mapper: The RasaPrimitiveStorageMapper instance for mapping.
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
The path where NLU data should be stored.
|
|
152
|
+
"""
|
|
153
|
+
nlu_paths = set()
|
|
154
|
+
for intent in data_local.get_nlu_data().intents:
|
|
155
|
+
for p in mapper.get_file(intent, "intents").get("training", []):
|
|
156
|
+
nlu_paths.add(p)
|
|
157
|
+
|
|
158
|
+
return _select_path(nlu_paths, "nlu", base_path, STUDIO_NLU_FILENAME)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def get_flows_path(
|
|
162
|
+
base_path: Path,
|
|
163
|
+
data_local: TrainingDataImporter,
|
|
164
|
+
mapper: RasaPrimitiveStorageMapper,
|
|
165
|
+
) -> Path:
|
|
166
|
+
"""Determines where flows data should be stored.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
base_path: The base path for the training data.
|
|
170
|
+
data_local: The TrainingDataImporter instance for local data.
|
|
171
|
+
mapper: The RasaPrimitiveStorageMapper instance for mapping.
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
The path where flows data should be stored.
|
|
175
|
+
"""
|
|
176
|
+
flow_paths = set()
|
|
177
|
+
for flow in data_local.get_user_flows().underlying_flows:
|
|
178
|
+
for p in mapper.get_file(flow.id, "flows").get("training", []):
|
|
179
|
+
flow_paths.add(p)
|
|
180
|
+
|
|
181
|
+
return _select_path(flow_paths, "flows", base_path, "flows.yml")
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def merge_flows_in_directory(
|
|
185
|
+
data_from_studio: TrainingDataImporter,
|
|
186
|
+
data_path: Path,
|
|
187
|
+
mapper: RasaPrimitiveStorageMapper,
|
|
188
|
+
) -> None:
|
|
189
|
+
"""
|
|
190
|
+
Merges flows data by updating local flow files in a directory with any changes
|
|
191
|
+
from Studio, and then dumping any new flows that do not exist in any local file.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
data_from_studio: Training data importer containing the flows from Studio.
|
|
195
|
+
data_path: The path to the directory where local flows reside.
|
|
196
|
+
mapper: Utility for mapping flow IDs to their respective file paths.
|
|
197
|
+
"""
|
|
198
|
+
# Extract flows from Studio data and map flow IDs to their instances.
|
|
199
|
+
studio_flows = data_from_studio.get_user_flows()
|
|
200
|
+
studio_flow_map: Dict[Text, Flow] = {
|
|
201
|
+
flow.id: flow for flow in studio_flows.underlying_flows
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
# Load existing local flows from the specified directory.
|
|
205
|
+
local_flows_file = TrainingDataImporter.load_from_dict(
|
|
206
|
+
training_data_paths=[str(data_path)]
|
|
207
|
+
)
|
|
208
|
+
local_flows = local_flows_file.get_user_flows().underlying_flows
|
|
209
|
+
|
|
210
|
+
# Gather the unique file paths where each local flow is stored.
|
|
211
|
+
local_flow_paths: Set[Path] = _get_local_flow_paths(local_flows, mapper)
|
|
212
|
+
|
|
213
|
+
# Track updated flows and update local files with Studio flow data.
|
|
214
|
+
all_updated_flows: List[Flow] = []
|
|
215
|
+
for flow_file_path in local_flow_paths:
|
|
216
|
+
updated_file_flows = _update_flow_file(flow_file_path, studio_flow_map)
|
|
217
|
+
all_updated_flows.extend(updated_file_flows)
|
|
218
|
+
|
|
219
|
+
# Identify new Studio flows and save them as separate files in the directory.
|
|
220
|
+
new_flows = [
|
|
221
|
+
flow for flow in studio_flow_map.values() if flow not in all_updated_flows
|
|
222
|
+
]
|
|
223
|
+
_dump_flows_as_separate_files(new_flows, data_path)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def _get_local_flow_paths(
|
|
227
|
+
local_flows: List[Any],
|
|
228
|
+
mapper: RasaPrimitiveStorageMapper,
|
|
229
|
+
) -> Set[Path]:
|
|
230
|
+
"""
|
|
231
|
+
Args:
|
|
232
|
+
local_flows: List of local flows.
|
|
233
|
+
mapper: The RasaPrimitiveStorageMapper instance for mapping.
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
A set of paths for the local flow files.
|
|
237
|
+
"""
|
|
238
|
+
paths: Set[Path] = set()
|
|
239
|
+
for flow in local_flows:
|
|
240
|
+
paths.update(mapper.get_file(flow.id, "flows").get("training", []))
|
|
241
|
+
return paths
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _update_flow_file(
|
|
245
|
+
flow_file_path: Path, studio_flows_map: Dict[Text, Any]
|
|
246
|
+
) -> List[Flow]:
|
|
247
|
+
"""
|
|
248
|
+
Reads a flow file, updates outdated flows, and replaces them with studio versions.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
flow_file_path: The path to the flow file.
|
|
252
|
+
studio_flows_map: A dictionary mapping flow IDs to their updated versions.
|
|
253
|
+
|
|
254
|
+
Returns:
|
|
255
|
+
A list of flows from the updated flow file.
|
|
256
|
+
"""
|
|
257
|
+
file_flows = YAMLFlowsReader.read_from_file(flow_file_path, False)
|
|
258
|
+
updated_list: List[Any] = []
|
|
259
|
+
has_changes = False
|
|
260
|
+
|
|
261
|
+
for flow in file_flows.underlying_flows:
|
|
262
|
+
studio_flow = studio_flows_map.get(flow.id)
|
|
263
|
+
if studio_flow is not None and studio_flow != flow:
|
|
264
|
+
updated_list.append(studio_flow)
|
|
265
|
+
has_changes = True
|
|
266
|
+
else:
|
|
267
|
+
updated_list.append(flow)
|
|
268
|
+
|
|
269
|
+
if has_changes:
|
|
270
|
+
new_flows_list = FlowsList(underlying_flows=updated_list)
|
|
271
|
+
new_flows_list = strip_default_next_references(new_flows_list)
|
|
272
|
+
YamlFlowsWriter.dump(
|
|
273
|
+
flows=new_flows_list.underlying_flows,
|
|
274
|
+
filename=flow_file_path,
|
|
275
|
+
should_clean_json=True,
|
|
276
|
+
)
|
|
277
|
+
return new_flows_list.underlying_flows
|
|
278
|
+
|
|
279
|
+
return file_flows.underlying_flows
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def _dump_flows_as_separate_files(flows: List[Any], data_path: Path) -> None:
|
|
283
|
+
"""Dump flow into separate files within a directory.
|
|
284
|
+
|
|
285
|
+
Creates a new directory under the given data_path and writes each flow
|
|
286
|
+
into a separate YAML file. Each file is named after the flow's id.
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
flows: List of new flows to be dumped.
|
|
290
|
+
data_path: The path to the directory where the files will be created.
|
|
291
|
+
"""
|
|
292
|
+
# If there are no flows, don't create a directory.
|
|
293
|
+
if not flows:
|
|
294
|
+
return
|
|
295
|
+
|
|
296
|
+
new_flows_dir = data_path / STUDIO_FLOWS_DIR_NAME
|
|
297
|
+
new_flows_dir.mkdir(parents=True, exist_ok=True)
|
|
298
|
+
for flow in flows:
|
|
299
|
+
file_name = f"{flow.id}.yml"
|
|
300
|
+
file_path = new_flows_dir / file_name
|
|
301
|
+
single_flow_list = FlowsList(underlying_flows=[flow])
|
|
302
|
+
YamlFlowsWriter.dump(
|
|
303
|
+
flows=single_flow_list.underlying_flows,
|
|
304
|
+
filename=file_path,
|
|
305
|
+
should_clean_json=True,
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def strip_default_next_references(flows: FlowsList) -> FlowsList:
|
|
310
|
+
"""Strips default next references from flows.
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
flows: The FlowsList instance containing the flows.
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
An updated FlowsList instance with default next references removed.
|
|
317
|
+
"""
|
|
318
|
+
default_step_ids = [step.default_id for flow in flows for step in flow.steps]
|
|
319
|
+
for flow in flows:
|
|
320
|
+
for step in flow.steps:
|
|
321
|
+
if (
|
|
322
|
+
step.next.links
|
|
323
|
+
and isinstance(step.next.links[0], StaticFlowStepLink)
|
|
324
|
+
and step.next.links[0].target in default_step_ids
|
|
325
|
+
):
|
|
326
|
+
step.next.links = []
|
|
327
|
+
return flows
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def _select_path(
|
|
331
|
+
paths: Set[Path], primitive_type: str, default_path: Path, default: str
|
|
332
|
+
) -> Path:
|
|
333
|
+
"""Selects a path from a set of paths.
|
|
334
|
+
|
|
335
|
+
If exactly one path exists, returns it.
|
|
336
|
+
If multiple exist, returns one with a warning.
|
|
337
|
+
If none exist, returns a default path.
|
|
338
|
+
|
|
339
|
+
Args:
|
|
340
|
+
paths: A set of paths.
|
|
341
|
+
primitive_type: The type of the primitive (e.g., "domain", "nlu").
|
|
342
|
+
default_path: The default path to use if no paths exist.
|
|
343
|
+
default: The default file name.
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
The selected path.
|
|
347
|
+
"""
|
|
348
|
+
if len(paths) == 1:
|
|
349
|
+
path = paths.pop()
|
|
350
|
+
elif len(paths) > 1:
|
|
351
|
+
path = paths.pop()
|
|
352
|
+
logger.warning(
|
|
353
|
+
f"Saving {primitive_type} to {path}. "
|
|
354
|
+
f"Please keep Studio-related {primitive_type} in a single file."
|
|
355
|
+
)
|
|
356
|
+
else:
|
|
357
|
+
path = default_path / Path(default)
|
|
358
|
+
logger.info(f"Saving {primitive_type} to {path}.")
|
|
359
|
+
return path
|
rasa/studio/results_logger.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from functools import wraps
|
|
3
|
-
from typing import Any, Callable, Dict
|
|
3
|
+
from typing import Any, Callable, Dict, Text
|
|
4
4
|
|
|
5
5
|
import structlog
|
|
6
6
|
from keycloak.exceptions import KeycloakError
|
|
@@ -78,6 +78,11 @@ def response_has_errors(response: Dict) -> bool:
|
|
|
78
78
|
)
|
|
79
79
|
|
|
80
80
|
|
|
81
|
+
def response_has_id(response: Dict[Text, Any]) -> bool:
|
|
82
|
+
response_id = response.get("id")
|
|
83
|
+
return isinstance(response_id, str) and bool(response_id)
|
|
84
|
+
|
|
85
|
+
|
|
81
86
|
def _handle_rasa_exception(e: RasaException) -> StudioResult:
|
|
82
87
|
error_msg = "Rasa internal exception was raised while interacting with Studio."
|
|
83
88
|
structlogger.error("studio.rasa_error", event_info=error_msg, exception=str(e))
|
rasa/studio/upload.py
CHANGED
|
@@ -158,11 +158,7 @@ def handle_upload(args: argparse.Namespace) -> None:
|
|
|
158
158
|
RasaYAMLReader.expand_env_vars = False
|
|
159
159
|
YAMLFlowsReader.expand_env_vars = False
|
|
160
160
|
|
|
161
|
-
|
|
162
|
-
if hasattr(args, "calm") and args.calm:
|
|
163
|
-
upload_calm_assistant(args, endpoint, verify=verify)
|
|
164
|
-
else:
|
|
165
|
-
upload_nlu_assistant(args, endpoint, verify=verify)
|
|
161
|
+
upload_calm_assistant(args, endpoint, verify=verify)
|
|
166
162
|
|
|
167
163
|
|
|
168
164
|
config_keys = [
|
|
@@ -226,6 +222,7 @@ def upload_calm_assistant(
|
|
|
226
222
|
- endpoints: The path to the endpoints
|
|
227
223
|
- config: The path to the config
|
|
228
224
|
endpoint: The studio endpoint
|
|
225
|
+
verify: Whether to verify SSL
|
|
229
226
|
Returns:
|
|
230
227
|
None
|
|
231
228
|
"""
|
|
@@ -244,6 +241,7 @@ def upload_calm_assistant(
|
|
|
244
241
|
# Prepare config and domain
|
|
245
242
|
config = importer.get_config()
|
|
246
243
|
assistant_name = _get_assistant_name(config)
|
|
244
|
+
|
|
247
245
|
config_from_files = read_yaml_file(args.config, expand_env_vars=False)
|
|
248
246
|
domain_from_files = importer.get_user_domain().as_dict()
|
|
249
247
|
|
|
@@ -563,3 +561,69 @@ def remove_quotes(node: Any) -> Any:
|
|
|
563
561
|
return {k: remove_quotes(v) for k, v in node.items()}
|
|
564
562
|
else:
|
|
565
563
|
return node
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
def check_if_assistant_already_exists(
|
|
567
|
+
assistant_name: str, endpoint: str, verify: bool = True
|
|
568
|
+
) -> bool:
|
|
569
|
+
"""Checks if the assistant already exists in Studio.
|
|
570
|
+
|
|
571
|
+
Args:
|
|
572
|
+
assistant_name: The name of the assistant
|
|
573
|
+
endpoint: The studio endpoint
|
|
574
|
+
verify: Whether to verify SSL
|
|
575
|
+
|
|
576
|
+
Returns:
|
|
577
|
+
bool: The upload confirmation
|
|
578
|
+
"""
|
|
579
|
+
graphql_req = build_get_assistant_by_name_request(assistant_name)
|
|
580
|
+
|
|
581
|
+
structlogger.info(
|
|
582
|
+
"rasa.studio.upload.assistant_already_exists",
|
|
583
|
+
event_info="Checking if assistant already exists...",
|
|
584
|
+
assistant_name=assistant_name,
|
|
585
|
+
)
|
|
586
|
+
|
|
587
|
+
token = KeycloakTokenReader().get_token()
|
|
588
|
+
res = requests.post(
|
|
589
|
+
endpoint,
|
|
590
|
+
json=graphql_req,
|
|
591
|
+
headers={
|
|
592
|
+
"Authorization": f"{token.token_type} {token.access_token}",
|
|
593
|
+
"Content-Type": "application/json",
|
|
594
|
+
},
|
|
595
|
+
verify=verify,
|
|
596
|
+
)
|
|
597
|
+
response = res.json()["data"]["assistantByName"] or {}
|
|
598
|
+
if results_logger.response_has_id(response):
|
|
599
|
+
structlogger.info(
|
|
600
|
+
"rasa.studio.upload.assistant_already_exists",
|
|
601
|
+
event_info="Assistant already exists.",
|
|
602
|
+
)
|
|
603
|
+
return True
|
|
604
|
+
|
|
605
|
+
structlogger.info(
|
|
606
|
+
"rasa.studio.upload.assistant_already_exists", event_info="Assistant not found."
|
|
607
|
+
)
|
|
608
|
+
return False
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
def build_get_assistant_by_name_request(
|
|
612
|
+
assistant_name: str,
|
|
613
|
+
) -> Dict:
|
|
614
|
+
graphql_req = {
|
|
615
|
+
"query": (
|
|
616
|
+
"query AssistantByName($input: AssistantByNameInput!) {"
|
|
617
|
+
" assistantByName(input: $input) {"
|
|
618
|
+
" ... on Assistant { id name mode }"
|
|
619
|
+
" ... on AssistantByName_AssistantNotFound { _ }"
|
|
620
|
+
" }"
|
|
621
|
+
"}"
|
|
622
|
+
),
|
|
623
|
+
"variables": {
|
|
624
|
+
"input": {
|
|
625
|
+
"assistantName": assistant_name,
|
|
626
|
+
}
|
|
627
|
+
},
|
|
628
|
+
}
|
|
629
|
+
return graphql_req
|
rasa/utils/common.py
CHANGED
|
@@ -48,6 +48,7 @@ T = TypeVar("T")
|
|
|
48
48
|
|
|
49
49
|
EXPECTED_WARNINGS: List[Tuple[Type[Warning], str]] = [
|
|
50
50
|
# TODO (issue #9932)
|
|
51
|
+
# DM1 warnings
|
|
51
52
|
(
|
|
52
53
|
np.VisibleDeprecationWarning,
|
|
53
54
|
"Creating an ndarray from ragged nested sequences.*",
|
|
@@ -94,6 +95,41 @@ EXPECTED_WARNINGS: List[Tuple[Type[Warning], str]] = [
|
|
|
94
95
|
DeprecationWarning,
|
|
95
96
|
"https://importlib-resources.readthedocs.io/en/latest/using.html#migrating-from-legacy",
|
|
96
97
|
),
|
|
98
|
+
# CALM warnings
|
|
99
|
+
# Ignore deprecation warning for ml_dtypes.float8_e4m3b11
|
|
100
|
+
(
|
|
101
|
+
DeprecationWarning,
|
|
102
|
+
"ml_dtypes.float8_e4m3b11 is deprecated. Use ml_dtypes.float8_e4m3b11fnuz",
|
|
103
|
+
),
|
|
104
|
+
# Ignore deprecation warning for the load_module() method
|
|
105
|
+
(
|
|
106
|
+
DeprecationWarning,
|
|
107
|
+
"the load_module\\(\\) method is deprecated and slated for removal*",
|
|
108
|
+
),
|
|
109
|
+
# Ignore deprecation warning for the rule-based policy
|
|
110
|
+
(
|
|
111
|
+
UserWarning,
|
|
112
|
+
"Found a rule-based policy in your configuration but no rule-based training*",
|
|
113
|
+
),
|
|
114
|
+
# Ignore deprecation warning for the TEDPolicy
|
|
115
|
+
(
|
|
116
|
+
UserWarning,
|
|
117
|
+
"Skipping training of `TEDPolicy` as no data was provided.*",
|
|
118
|
+
),
|
|
119
|
+
# Ignore deprecation warning for the LexicalSyntacticFeaturizer
|
|
120
|
+
(
|
|
121
|
+
UserWarning,
|
|
122
|
+
"No lexical syntactic features could be extracted from the training data.*",
|
|
123
|
+
),
|
|
124
|
+
# Ignore deprecation warning for the LexicalSyntacticFeaturizer2
|
|
125
|
+
(
|
|
126
|
+
UserWarning,
|
|
127
|
+
"The LexicalSyntacticFeaturizer run_LexicalSyntacticFeaturizer2 has not been*",
|
|
128
|
+
),
|
|
129
|
+
(
|
|
130
|
+
FutureWarning,
|
|
131
|
+
"'request_timeout' is deprecated and will be removed in 4.0.0. Use 'timeout'*",
|
|
132
|
+
),
|
|
97
133
|
]
|
|
98
134
|
|
|
99
135
|
PYTHON_LOGGING_SCHEMA_DOCS = (
|
rasa/utils/endpoints.py
CHANGED
|
@@ -190,7 +190,13 @@ class EndpointConfig:
|
|
|
190
190
|
sslcontext = None
|
|
191
191
|
if self.cafile:
|
|
192
192
|
try:
|
|
193
|
-
|
|
193
|
+
# create a SSL context with the provided CA file
|
|
194
|
+
# and set the minimum TLS version to 1.2
|
|
195
|
+
# Purpose is set to SERVER_AUTH to verify the server's certificate
|
|
196
|
+
sslcontext = ssl.create_default_context(
|
|
197
|
+
purpose=ssl.Purpose.SERVER_AUTH, cafile=self.cafile
|
|
198
|
+
)
|
|
199
|
+
sslcontext.minimum_version = ssl.TLSVersion.TLSv1_2
|
|
194
200
|
except FileNotFoundError as e:
|
|
195
201
|
raise FileNotFoundException(
|
|
196
202
|
f"Failed to find certificate file, "
|
|
@@ -233,6 +239,21 @@ class EndpointConfig:
|
|
|
233
239
|
**self.kwargs,
|
|
234
240
|
)
|
|
235
241
|
|
|
242
|
+
def to_dict(self) -> Dict[Text, Any]:
|
|
243
|
+
"""Convert the endpoint config to a dictionary."""
|
|
244
|
+
data = {
|
|
245
|
+
"url": self.url,
|
|
246
|
+
"params": self.params,
|
|
247
|
+
"headers": self.headers,
|
|
248
|
+
"basic_auth": self.basic_auth,
|
|
249
|
+
"token": self.token,
|
|
250
|
+
"token_name": self.token_name,
|
|
251
|
+
"cafile": self.cafile,
|
|
252
|
+
"actions_module": self.actions_module,
|
|
253
|
+
}
|
|
254
|
+
data.update(self.kwargs)
|
|
255
|
+
return data
|
|
256
|
+
|
|
236
257
|
def __eq__(self, other: Any) -> bool:
|
|
237
258
|
if isinstance(self, type(other)):
|
|
238
259
|
return (
|
rasa/utils/licensing.py
CHANGED
|
@@ -15,7 +15,6 @@ from dotenv import dotenv_values
|
|
|
15
15
|
from sanic import Sanic
|
|
16
16
|
|
|
17
17
|
from rasa import telemetry
|
|
18
|
-
from rasa.core import jobs
|
|
19
18
|
from rasa.shared.utils.cli import print_error_and_exit
|
|
20
19
|
|
|
21
20
|
if typing.TYPE_CHECKING:
|
|
@@ -506,6 +505,7 @@ async def _schedule_conversation_counting(
|
|
|
506
505
|
app: Sanic, tracker_store: Optional["TrackerStore"], max_number_conversations: int
|
|
507
506
|
) -> None:
|
|
508
507
|
"""Schedule a job counting the number of conversations in the current month."""
|
|
508
|
+
from rasa.core import jobs
|
|
509
509
|
|
|
510
510
|
async def conversation_counting_job(
|
|
511
511
|
app: Sanic,
|
rasa/validator.py
CHANGED
|
@@ -531,7 +531,7 @@ class Validator:
|
|
|
531
531
|
condition_active_loop
|
|
532
532
|
and condition_active_loop not in self.domain.form_names
|
|
533
533
|
):
|
|
534
|
-
structlogger.
|
|
534
|
+
structlogger.error(
|
|
535
535
|
"validator.verify_slot_mappings.not_in_domain",
|
|
536
536
|
slot=slot.name,
|
|
537
537
|
form=condition_active_loop,
|
|
@@ -566,7 +566,6 @@ class Validator:
|
|
|
566
566
|
f"The slot needs to be added to this key."
|
|
567
567
|
),
|
|
568
568
|
)
|
|
569
|
-
everything_is_alright = False
|
|
570
569
|
|
|
571
570
|
return everything_is_alright
|
|
572
571
|
|
rasa/version.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: rasa-pro
|
|
3
|
-
Version: 3.13.0.
|
|
3
|
+
Version: 3.13.0.dev5
|
|
4
4
|
Summary: State-of-the-art open-core Conversational AI framework for Enterprises that natively leverages generative AI for effortless assistant development.
|
|
5
5
|
Keywords: nlp,machine-learning,machine-learning-library,bot,bots,botkit,rasa conversational-agents,conversational-ai,chatbot,chatbot-framework,bot-framework
|
|
6
6
|
Author: Rasa Technologies GmbH
|
|
@@ -22,11 +22,11 @@ Provides-Extra: spacy
|
|
|
22
22
|
Provides-Extra: transformers
|
|
23
23
|
Requires-Dist: CacheControl (>=0.14.2,<0.15.0)
|
|
24
24
|
Requires-Dist: PyJWT[crypto] (>=2.8.0,<3.0.0)
|
|
25
|
-
Requires-Dist: SQLAlchemy (>=2.0.
|
|
25
|
+
Requires-Dist: SQLAlchemy (>=2.0.40,<2.1.0)
|
|
26
26
|
Requires-Dist: absl-py (>=2.0,<2.1)
|
|
27
27
|
Requires-Dist: aio-pika (>=8.2.3,<9.4.4)
|
|
28
28
|
Requires-Dist: aiogram (>=3.15,<3.16)
|
|
29
|
-
Requires-Dist: aiohttp (>=3.
|
|
29
|
+
Requires-Dist: aiohttp (>=3.10,<3.11)
|
|
30
30
|
Requires-Dist: apscheduler (>=3.10,<3.11)
|
|
31
31
|
Requires-Dist: attrs (>=23.1,<23.2)
|
|
32
32
|
Requires-Dist: azure-identity (>=1.19.0,<1.20.0)
|
|
@@ -37,7 +37,7 @@ Requires-Dist: colorama (>=0.4.6,<0.5.0) ; sys_platform == "win32"
|
|
|
37
37
|
Requires-Dist: colorclass (>=2.2,<2.3)
|
|
38
38
|
Requires-Dist: coloredlogs (>=15,<16)
|
|
39
39
|
Requires-Dist: colorhash (>=2.0,<2.1.0)
|
|
40
|
-
Requires-Dist: confluent-kafka (>=2.
|
|
40
|
+
Requires-Dist: confluent-kafka (>=2.10.0,<3.0.0)
|
|
41
41
|
Requires-Dist: cryptography (>=44.0.1)
|
|
42
42
|
Requires-Dist: cvg-python-sdk (>=0.5.1,<0.6.0)
|
|
43
43
|
Requires-Dist: dask (>=2024.7.0,<2024.8.0)
|
|
@@ -63,7 +63,7 @@ Requires-Dist: keras (==2.14.0)
|
|
|
63
63
|
Requires-Dist: langchain (>=0.2.17,<0.3.0)
|
|
64
64
|
Requires-Dist: langchain-community (>=0.2.19,<0.3.0)
|
|
65
65
|
Requires-Dist: langcodes (>=3.5.0,<4.0.0)
|
|
66
|
-
Requires-Dist: litellm (
|
|
66
|
+
Requires-Dist: litellm (==1.52.6)
|
|
67
67
|
Requires-Dist: matplotlib (>=3.7,<3.8)
|
|
68
68
|
Requires-Dist: mattermostwrapper (>=2.2,<2.3)
|
|
69
69
|
Requires-Dist: networkx (>=3.1,<3.2)
|
|
@@ -83,7 +83,7 @@ Requires-Dist: presidio-anonymizer (>=2.2.354,<3.0.0)
|
|
|
83
83
|
Requires-Dist: prompt-toolkit (>=3.0.28,<3.0.29)
|
|
84
84
|
Requires-Dist: protobuf (>=4.23.3,<4.25.4)
|
|
85
85
|
Requires-Dist: psutil (>=5.9.5,<6.0.0)
|
|
86
|
-
Requires-Dist: psycopg2-binary (>=2.9.
|
|
86
|
+
Requires-Dist: psycopg2-binary (>=2.9.10,<2.10.0)
|
|
87
87
|
Requires-Dist: pycountry (>=22.3.5,<23.0.0)
|
|
88
88
|
Requires-Dist: pydot (>=1.4,<1.5)
|
|
89
89
|
Requires-Dist: pykwalify (>=1.8,<1.9)
|
|
@@ -92,7 +92,7 @@ Requires-Dist: pymongo (>=4.10.1,<4.11.0)
|
|
|
92
92
|
Requires-Dist: pypred (>=0.4.0,<0.5.0)
|
|
93
93
|
Requires-Dist: python-dateutil (>=2.8.2,<2.9.0)
|
|
94
94
|
Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
|
|
95
|
-
Requires-Dist: python-engineio (>=4.
|
|
95
|
+
Requires-Dist: python-engineio (>=4.12.0,<6,!=5.0.0)
|
|
96
96
|
Requires-Dist: python-keycloak (>=3.12.0,<4.0.0)
|
|
97
97
|
Requires-Dist: python-socketio (>=5.8,<6)
|
|
98
98
|
Requires-Dist: pytz (>=2022.7.1,<2023.0)
|
|
@@ -100,7 +100,7 @@ Requires-Dist: pyyaml (>=6.0)
|
|
|
100
100
|
Requires-Dist: qdrant-client (>=1.9.1,<1.10.0)
|
|
101
101
|
Requires-Dist: questionary (>=1.10.0,<2.1.0)
|
|
102
102
|
Requires-Dist: randomname (>=0.2.1,<0.3.0)
|
|
103
|
-
Requires-Dist: rasa-sdk (==3.
|
|
103
|
+
Requires-Dist: rasa-sdk (==3.13.0.dev1)
|
|
104
104
|
Requires-Dist: redis (>=4.6.0,<6.0)
|
|
105
105
|
Requires-Dist: regex (>=2024.7.24,<2024.8.0)
|
|
106
106
|
Requires-Dist: requests (>=2.32.3,<2.33.0)
|