rasa-pro 3.10.16__py3-none-any.whl → 3.11.0a1__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.
- README.md +396 -17
- rasa/api.py +9 -3
- rasa/cli/arguments/default_arguments.py +23 -2
- rasa/cli/arguments/run.py +15 -0
- rasa/cli/arguments/train.py +3 -9
- rasa/cli/e2e_test.py +1 -1
- rasa/cli/evaluate.py +1 -1
- rasa/cli/inspect.py +8 -4
- rasa/cli/llm_fine_tuning.py +12 -15
- rasa/cli/run.py +8 -1
- rasa/cli/studio/studio.py +8 -18
- rasa/cli/train.py +11 -53
- rasa/cli/utils.py +8 -10
- rasa/cli/x.py +1 -1
- rasa/constants.py +1 -1
- rasa/core/actions/action.py +2 -0
- rasa/core/actions/action_hangup.py +29 -0
- rasa/core/agent.py +2 -2
- rasa/core/brokers/kafka.py +3 -1
- rasa/core/brokers/pika.py +3 -1
- rasa/core/channels/__init__.py +8 -6
- rasa/core/channels/channel.py +21 -4
- rasa/core/channels/development_inspector.py +143 -46
- rasa/core/channels/inspector/README.md +1 -1
- rasa/core/channels/inspector/dist/assets/{arc-b6e548fe.js → arc-86942a71.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-fa03ac9e.js → c4Diagram-d0fbc5ce-b0290676.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-ee67392a.js → classDiagram-936ed81e-f6405f6e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-9b283fae.js → classDiagram-v2-c3cb15f1-ef61ac77.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{createText-62fc7601-8b6fcc2a.js → createText-62fc7601-f0411e58.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-22e77f4f.js → edges-f2ad444c-7dcc4f3b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-60ffc87f.js → erDiagram-9d236eb7-e0c092d7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-9dd802e4.js → flowDb-1972c806-fba2e3ce.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-5fa1912f.js → flowDiagram-7ea5b25a-7a70b71a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-24a5f41a.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-622a1fd2.js → flowchart-elk-definition-abe16c3d-00a59b68.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-e285a63a.js → ganttDiagram-9b5ea136-293c91fa.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-f237bdca.js → gitGraphDiagram-99d0ae7c-07b2d68c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-4b03d70e.js → index-2c4b9a3b-bc959fbd.js} +1 -1
- rasa/core/channels/inspector/dist/assets/index-3a8a5a28.js +1317 -0
- rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-72a0fa5f.js → infoDiagram-736b4530-4a350f72.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-82218c41.js → journeyDiagram-df861f2b-af464fb7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-78cff630.js → layout-0071f036.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-5038b469.js → line-2f73cc83.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-c4fc4098.js → linear-f014b4cc.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-c33c8ea6.js → mindmap-definition-beec6740-d2426fb6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-a8d03059.js → pieDiagram-dbbf0591-776f01a2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-6a0e56b2.js → quadrantDiagram-4d7f4fd6-82e00b57.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-2dc7c7bd.js → requirementDiagram-6fc4c22a-ea13c6bb.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-2360fe39.js → sankeyDiagram-8f13d901-1feca7e9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-41b9f9ad.js → sequenceDiagram-b655622a-070c61d2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-0aad326f.js → stateDiagram-59f0c015-24f46263.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-9847d984.js → stateDiagram-v2-2b26beab-c9056051.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-080da4f6-564d890e.js → styles-080da4f6-08abc34a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-38957613.js → styles-3dcbcfbf-bc74c25a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9c745c82-f0fc6921.js → styles-9c745c82-4e5d66de.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-ef3c5a77.js → svgDrawCommon-4835440b-849c4517.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-bf3e91c1.js → timeline-definition-5b62e21b-d0fb1598.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-4d4026c0.js → xychartDiagram-2b33534f-04d115e2.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +18 -17
- rasa/core/channels/inspector/index.html +17 -16
- rasa/core/channels/inspector/package.json +5 -1
- rasa/core/channels/inspector/src/App.tsx +117 -67
- rasa/core/channels/inspector/src/components/Chat.tsx +95 -0
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +11 -10
- rasa/core/channels/inspector/src/components/DialogueStack.tsx +10 -25
- rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +1 -1
- rasa/core/channels/inspector/src/helpers/formatters.test.ts +10 -0
- rasa/core/channels/inspector/src/helpers/formatters.ts +107 -41
- rasa/core/channels/inspector/src/helpers/utils.ts +92 -7
- rasa/core/channels/inspector/src/types.ts +21 -1
- rasa/core/channels/inspector/yarn.lock +94 -1
- rasa/core/channels/rest.py +51 -46
- rasa/core/channels/socketio.py +22 -0
- rasa/core/channels/{audiocodes.py → voice_ready/audiocodes.py} +110 -68
- rasa/core/channels/{voice_aware → voice_ready}/jambonz.py +11 -4
- rasa/core/channels/{voice_aware → voice_ready}/jambonz_protocol.py +57 -5
- rasa/core/channels/{twilio_voice.py → voice_ready/twilio_voice.py} +58 -7
- rasa/core/channels/{voice_aware → voice_ready}/utils.py +16 -0
- rasa/core/channels/voice_stream/asr/__init__.py +0 -0
- rasa/core/channels/voice_stream/asr/asr_engine.py +71 -0
- rasa/core/channels/voice_stream/asr/asr_event.py +13 -0
- rasa/core/channels/voice_stream/asr/deepgram.py +77 -0
- rasa/core/channels/voice_stream/audio_bytes.py +7 -0
- rasa/core/channels/voice_stream/tts/__init__.py +0 -0
- rasa/core/channels/voice_stream/tts/azure.py +100 -0
- rasa/core/channels/voice_stream/tts/cartesia.py +114 -0
- rasa/core/channels/voice_stream/tts/tts_cache.py +27 -0
- rasa/core/channels/voice_stream/tts/tts_engine.py +48 -0
- rasa/core/channels/voice_stream/twilio_media_streams.py +164 -0
- rasa/core/channels/voice_stream/util.py +57 -0
- rasa/core/channels/voice_stream/voice_channel.py +247 -0
- rasa/core/featurizers/single_state_featurizer.py +1 -22
- rasa/core/featurizers/tracker_featurizers.py +18 -115
- rasa/core/nlg/contextual_response_rephraser.py +11 -2
- rasa/{nlu → core}/persistor.py +16 -38
- rasa/core/policies/enterprise_search_policy.py +12 -15
- rasa/core/policies/flows/flow_executor.py +8 -18
- rasa/core/policies/intentless_policy.py +10 -15
- rasa/core/policies/ted_policy.py +33 -58
- rasa/core/policies/unexpected_intent_policy.py +7 -15
- rasa/core/processor.py +13 -64
- rasa/core/run.py +11 -1
- rasa/core/secrets_manager/constants.py +4 -0
- rasa/core/secrets_manager/factory.py +8 -0
- rasa/core/secrets_manager/vault.py +11 -1
- rasa/core/training/interactive.py +1 -1
- rasa/core/utils.py +1 -11
- rasa/dialogue_understanding/coexistence/llm_based_router.py +10 -10
- rasa/dialogue_understanding/commands/__init__.py +2 -0
- rasa/dialogue_understanding/commands/change_flow_command.py +0 -6
- rasa/dialogue_understanding/commands/session_end_command.py +61 -0
- rasa/dialogue_understanding/generator/flow_retrieval.py +0 -7
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +12 -3
- rasa/dialogue_understanding/generator/llm_command_generator.py +1 -1
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +3 -28
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +1 -19
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +4 -37
- rasa/e2e_test/aggregate_test_stats_calculator.py +1 -11
- rasa/e2e_test/assertions.py +6 -48
- rasa/e2e_test/e2e_test_runner.py +6 -9
- rasa/e2e_test/utils/e2e_yaml_utils.py +1 -1
- rasa/e2e_test/utils/io.py +1 -3
- rasa/engine/graph.py +3 -10
- rasa/engine/recipes/config_files/default_config.yml +0 -3
- rasa/engine/recipes/default_recipe.py +0 -1
- rasa/engine/recipes/graph_recipe.py +0 -1
- rasa/engine/runner/dask.py +2 -2
- rasa/engine/storage/local_model_storage.py +12 -42
- rasa/engine/storage/storage.py +1 -5
- rasa/engine/validation.py +1 -78
- rasa/keys +1 -0
- rasa/model_training.py +13 -16
- rasa/nlu/classifiers/diet_classifier.py +25 -38
- rasa/nlu/classifiers/logistic_regression_classifier.py +9 -22
- rasa/nlu/classifiers/sklearn_intent_classifier.py +16 -37
- rasa/nlu/extractors/crf_entity_extractor.py +50 -93
- rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +16 -45
- rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +17 -52
- rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +3 -5
- rasa/server.py +1 -1
- rasa/shared/constants.py +3 -12
- rasa/shared/core/constants.py +4 -0
- rasa/shared/core/domain.py +101 -47
- rasa/shared/core/events.py +29 -0
- rasa/shared/core/flows/flows_list.py +20 -11
- rasa/shared/core/flows/validation.py +25 -0
- rasa/shared/core/flows/yaml_flows_io.py +3 -24
- rasa/shared/importers/importer.py +40 -39
- rasa/shared/importers/multi_project.py +23 -11
- rasa/shared/importers/rasa.py +7 -2
- rasa/shared/importers/remote_importer.py +196 -0
- rasa/shared/importers/utils.py +3 -1
- rasa/shared/nlu/training_data/features.py +2 -120
- rasa/shared/nlu/training_data/training_data.py +18 -19
- rasa/shared/providers/_configs/azure_openai_client_config.py +3 -5
- rasa/shared/providers/embedding/_base_litellm_embedding_client.py +1 -6
- rasa/shared/providers/llm/_base_litellm_client.py +11 -31
- rasa/shared/providers/llm/self_hosted_llm_client.py +3 -15
- rasa/shared/utils/common.py +3 -22
- rasa/shared/utils/io.py +0 -1
- rasa/shared/utils/llm.py +30 -27
- rasa/shared/utils/schemas/events.py +2 -0
- rasa/shared/utils/schemas/model_config.yml +0 -10
- rasa/shared/utils/yaml.py +44 -0
- rasa/studio/auth.py +5 -3
- rasa/studio/config.py +4 -13
- rasa/studio/constants.py +0 -1
- rasa/studio/data_handler.py +3 -10
- rasa/studio/upload.py +8 -17
- rasa/tracing/instrumentation/attribute_extractors.py +1 -1
- rasa/utils/io.py +66 -0
- rasa/utils/tensorflow/model_data.py +193 -2
- rasa/validator.py +0 -12
- rasa/version.py +1 -1
- rasa_pro-3.11.0a1.dist-info/METADATA +576 -0
- {rasa_pro-3.10.16.dist-info → rasa_pro-3.11.0a1.dist-info}/RECORD +181 -164
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-1844e5a5.js +0 -1
- rasa/core/channels/inspector/dist/assets/index-a5d3e69d.js +0 -1040
- rasa/utils/tensorflow/feature_array.py +0 -366
- rasa_pro-3.10.16.dist-info/METADATA +0 -196
- /rasa/core/channels/{voice_aware → voice_ready}/__init__.py +0 -0
- /rasa/core/channels/{voice_native → voice_stream}/__init__.py +0 -0
- {rasa_pro-3.10.16.dist-info → rasa_pro-3.11.0a1.dist-info}/NOTICE +0 -0
- {rasa_pro-3.10.16.dist-info → rasa_pro-3.11.0a1.dist-info}/WHEEL +0 -0
- {rasa_pro-3.10.16.dist-info → rasa_pro-3.11.0a1.dist-info}/entry_points.txt +0 -0
rasa/cli/llm_fine_tuning.py
CHANGED
|
@@ -22,7 +22,6 @@ from rasa.cli.e2e_test import (
|
|
|
22
22
|
)
|
|
23
23
|
from rasa.core.exceptions import AgentNotReady
|
|
24
24
|
from rasa.core.utils import AvailableEndpoints
|
|
25
|
-
from rasa.dialogue_understanding.generator import SingleStepLLMCommandGenerator
|
|
26
25
|
from rasa.e2e_test.e2e_test_runner import E2ETestRunner
|
|
27
26
|
from rasa.llm_fine_tuning.annotation_module import annotate_e2e_tests
|
|
28
27
|
from rasa.llm_fine_tuning.llm_data_preparation_module import convert_to_fine_tuning_data
|
|
@@ -45,9 +44,6 @@ from rasa.shared.constants import (
|
|
|
45
44
|
DEFAULT_MODELS_PATH,
|
|
46
45
|
LLM_CONFIG_KEY,
|
|
47
46
|
)
|
|
48
|
-
from rasa.shared.utils.llm import (
|
|
49
|
-
combine_custom_and_default_config,
|
|
50
|
-
)
|
|
51
47
|
from rasa.shared.utils.yaml import read_config_file
|
|
52
48
|
from rasa.utils.beta import ensure_beta_feature_is_enabled
|
|
53
49
|
|
|
@@ -279,19 +275,20 @@ def _get_llm_command_generator_config(e2e_test_runner: E2ETestRunner) -> Dict[st
|
|
|
279
275
|
|
|
280
276
|
train_schema = e2e_test_runner.agent.processor.model_metadata.train_schema # type: ignore
|
|
281
277
|
|
|
282
|
-
for
|
|
283
|
-
if
|
|
284
|
-
return
|
|
285
|
-
|
|
286
|
-
|
|
278
|
+
for node in train_schema.nodes:
|
|
279
|
+
if "SingleStepLLMCommandGenerator" in node:
|
|
280
|
+
return {
|
|
281
|
+
**DEFAULT_LLM_CONFIG,
|
|
282
|
+
**train_schema.nodes[node].config.get(LLM_CONFIG_KEY),
|
|
283
|
+
}
|
|
287
284
|
|
|
288
285
|
rasa.shared.utils.cli.print_error(
|
|
289
|
-
"The provided model
|
|
290
|
-
"
|
|
291
|
-
"
|
|
292
|
-
"
|
|
286
|
+
"The provided model was not trained with the 'SingleStepLLMCommandGenerator'."
|
|
287
|
+
"Without the 'SingleStepLLMCommandGenerator' no data for fine-tuning can be "
|
|
288
|
+
"created. Please add the 'SingleStepLLMCommandGenerator' to your config and"
|
|
289
|
+
"train your model."
|
|
293
290
|
)
|
|
294
|
-
sys.exit(
|
|
291
|
+
sys.exit(0)
|
|
295
292
|
|
|
296
293
|
|
|
297
294
|
def log_start_of_module(module_name: str) -> None:
|
|
@@ -355,7 +352,7 @@ def get_valid_endpoints(endpoints_file: str) -> AvailableEndpoints:
|
|
|
355
352
|
validated_endpoints_file = rasa.cli.utils.get_validated_path(
|
|
356
353
|
endpoints_file, "endpoints", DEFAULT_ENDPOINTS_PATH, True
|
|
357
354
|
)
|
|
358
|
-
endpoints = AvailableEndpoints.
|
|
355
|
+
endpoints = AvailableEndpoints.read_endpoints(validated_endpoints_file)
|
|
359
356
|
|
|
360
357
|
# Ignore all endpoints apart from action server, model, nlu and nlg
|
|
361
358
|
# to ensure InMemoryTrackerStore is being used instead of production
|
rasa/cli/run.py
CHANGED
|
@@ -6,6 +6,7 @@ from typing import List, Text
|
|
|
6
6
|
from rasa.api import run as rasa_run
|
|
7
7
|
from rasa.cli import SubParsersAction
|
|
8
8
|
from rasa.cli.arguments import run as arguments
|
|
9
|
+
from rasa.cli.arguments.default_arguments import SkipYamlValidation
|
|
9
10
|
from rasa.cli.utils import get_validated_path
|
|
10
11
|
from rasa.exceptions import ModelNotFound
|
|
11
12
|
from rasa.shared.constants import (
|
|
@@ -15,6 +16,7 @@ from rasa.shared.constants import (
|
|
|
15
16
|
DEFAULT_MODELS_PATH,
|
|
16
17
|
DOCS_BASE_URL,
|
|
17
18
|
)
|
|
19
|
+
from rasa.shared.core.domain import Domain
|
|
18
20
|
from rasa.shared.utils.cli import print_error
|
|
19
21
|
|
|
20
22
|
logger = logging.getLogger(__name__)
|
|
@@ -87,6 +89,11 @@ def run(args: argparse.Namespace) -> None:
|
|
|
87
89
|
args.credentials, "credentials", DEFAULT_CREDENTIALS_PATH, True
|
|
88
90
|
)
|
|
89
91
|
|
|
92
|
+
if SkipYamlValidation.DOMAIN.value in args.skip_yaml_validation:
|
|
93
|
+
Domain.validate_yaml = False
|
|
94
|
+
else:
|
|
95
|
+
Domain.validate_yaml = True
|
|
96
|
+
|
|
90
97
|
if args.enable_api:
|
|
91
98
|
if not args.remote_storage:
|
|
92
99
|
args.model = _validate_model_path(args.model, "model", DEFAULT_MODELS_PATH)
|
|
@@ -106,7 +113,7 @@ def run(args: argparse.Namespace) -> None:
|
|
|
106
113
|
return
|
|
107
114
|
|
|
108
115
|
# start server if model server is configured
|
|
109
|
-
endpoints = AvailableEndpoints.
|
|
116
|
+
endpoints = AvailableEndpoints.read_endpoints(args.endpoints)
|
|
110
117
|
model_server = endpoints.model if endpoints and endpoints.model else None
|
|
111
118
|
if model_server is not None:
|
|
112
119
|
rasa_run(**vars(args))
|
rasa/cli/studio/studio.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import argparse
|
|
2
|
-
from typing import List, Optional
|
|
2
|
+
from typing import List, Optional
|
|
3
3
|
from urllib.parse import ParseResult, urlparse
|
|
4
4
|
|
|
5
5
|
import questionary
|
|
@@ -149,7 +149,7 @@ def _configure_studio_url() -> Optional[str]:
|
|
|
149
149
|
return studio_url
|
|
150
150
|
|
|
151
151
|
|
|
152
|
-
def _get_advanced_config(studio_url: str) ->
|
|
152
|
+
def _get_advanced_config(studio_url: str) -> tuple:
|
|
153
153
|
"""Get the advanced configuration values for Rasa Studio."""
|
|
154
154
|
keycloak_url = questionary.text(
|
|
155
155
|
"Please provide your Rasa Studio Keycloak URL",
|
|
@@ -167,7 +167,7 @@ def _get_advanced_config(studio_url: str) -> Tuple:
|
|
|
167
167
|
return keycloak_url, realm_name, client_id
|
|
168
168
|
|
|
169
169
|
|
|
170
|
-
def _get_default_config(studio_url: str) ->
|
|
170
|
+
def _get_default_config(studio_url: str) -> tuple:
|
|
171
171
|
"""Get the default configuration values for Rasa Studio."""
|
|
172
172
|
keycloak_url = studio_url + "auth/"
|
|
173
173
|
realm_name = DEFAULT_REALM_NAME
|
|
@@ -178,7 +178,6 @@ def _get_default_config(studio_url: str) -> Tuple:
|
|
|
178
178
|
f"Keycloak URL: {keycloak_url}, "
|
|
179
179
|
f"Realm Name: '{realm_name}', "
|
|
180
180
|
f"Client ID: '{client_id}'. "
|
|
181
|
-
f"SSL verification is enabled."
|
|
182
181
|
f"You can use '--advanced' to configure these settings."
|
|
183
182
|
)
|
|
184
183
|
|
|
@@ -186,11 +185,7 @@ def _get_default_config(studio_url: str) -> Tuple:
|
|
|
186
185
|
|
|
187
186
|
|
|
188
187
|
def _create_studio_config(
|
|
189
|
-
studio_url: str,
|
|
190
|
-
keycloak_url: str,
|
|
191
|
-
realm_name: str,
|
|
192
|
-
client_id: str,
|
|
193
|
-
disable_verify: bool = False,
|
|
188
|
+
studio_url: str, keycloak_url: str, realm_name: str, client_id: str
|
|
194
189
|
) -> StudioConfig:
|
|
195
190
|
"""Create a StudioConfig object with the provided parameters."""
|
|
196
191
|
return StudioConfig(
|
|
@@ -198,7 +193,6 @@ def _create_studio_config(
|
|
|
198
193
|
studio_url=studio_url + "api/graphql/",
|
|
199
194
|
client_id=client_id,
|
|
200
195
|
realm_name=realm_name,
|
|
201
|
-
disable_verify=disable_verify,
|
|
202
196
|
)
|
|
203
197
|
|
|
204
198
|
|
|
@@ -233,23 +227,19 @@ def _configure_studio_config(args: argparse.Namespace) -> StudioConfig:
|
|
|
233
227
|
|
|
234
228
|
# create a configuration and auth object to try to reach the studio
|
|
235
229
|
studio_config = _create_studio_config(
|
|
236
|
-
studio_url,
|
|
237
|
-
keycloak_url,
|
|
238
|
-
realm_name,
|
|
239
|
-
client_id,
|
|
240
|
-
disable_verify=args.disable_verify,
|
|
230
|
+
studio_url, keycloak_url, realm_name, client_id
|
|
241
231
|
)
|
|
242
232
|
|
|
243
|
-
if
|
|
233
|
+
if args.disable_verify:
|
|
244
234
|
rasa.shared.utils.cli.print_info(
|
|
245
235
|
"Disabling SSL verification for the Rasa Studio authentication server."
|
|
246
236
|
)
|
|
237
|
+
studio_auth = StudioAuth(studio_config, verify=False)
|
|
247
238
|
else:
|
|
248
239
|
rasa.shared.utils.cli.print_info(
|
|
249
240
|
"Enabling SSL verification for the Rasa Studio authentication server."
|
|
250
241
|
)
|
|
251
|
-
|
|
252
|
-
studio_auth = StudioAuth(studio_config)
|
|
242
|
+
studio_auth = StudioAuth(studio_config, verify=True)
|
|
253
243
|
|
|
254
244
|
if _check_studio_auth(studio_auth):
|
|
255
245
|
return studio_config
|
rasa/cli/train.py
CHANGED
|
@@ -1,33 +1,25 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
import asyncio
|
|
3
|
-
import os
|
|
4
3
|
import sys
|
|
5
4
|
from pathlib import Path
|
|
6
5
|
from typing import Dict, List, Optional, Text, Union
|
|
7
6
|
|
|
8
7
|
import structlog
|
|
9
|
-
from tarsafe import TarSafe
|
|
10
8
|
|
|
11
9
|
import rasa.cli.arguments.train as train_arguments
|
|
12
10
|
import rasa.cli.utils
|
|
13
11
|
import rasa.core.utils
|
|
14
12
|
import rasa.utils.common
|
|
15
|
-
from rasa.api import train as train_all
|
|
16
13
|
from rasa.cli import SubParsersAction
|
|
17
|
-
from rasa.core import ContextualResponseRephraser
|
|
18
14
|
from rasa.core.nlg.generator import NaturalLanguageGenerator
|
|
19
15
|
from rasa.core.train import do_compare_training
|
|
20
|
-
from rasa.engine.validation import validate_api_type_config_key_usage
|
|
21
|
-
from rasa.nlu.persistor import get_persistor
|
|
22
16
|
from rasa.shared.constants import (
|
|
23
17
|
CONFIG_MANDATORY_KEYS,
|
|
24
18
|
CONFIG_MANDATORY_KEYS_CORE,
|
|
25
19
|
CONFIG_MANDATORY_KEYS_NLU,
|
|
26
20
|
DEFAULT_DATA_PATH,
|
|
27
21
|
DEFAULT_DOMAIN_PATHS,
|
|
28
|
-
LLM_CONFIG_KEY,
|
|
29
22
|
)
|
|
30
|
-
from rasa.shared.exceptions import RasaException
|
|
31
23
|
from rasa.shared.importers.importer import TrainingDataImporter
|
|
32
24
|
|
|
33
25
|
structlogger = structlog.getLogger(__name__)
|
|
@@ -44,7 +36,7 @@ def add_subparser(
|
|
|
44
36
|
"""
|
|
45
37
|
train_parser = subparsers.add_parser(
|
|
46
38
|
"train",
|
|
47
|
-
help="Trains a Rasa model using your
|
|
39
|
+
help="Trains a Rasa model using your NLU data and stories.",
|
|
48
40
|
parents=parents,
|
|
49
41
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
50
42
|
)
|
|
@@ -78,12 +70,6 @@ def add_subparser(
|
|
|
78
70
|
def _check_nlg_endpoint_validity(endpoint: Union[Path, str]) -> None:
|
|
79
71
|
try:
|
|
80
72
|
endpoints = rasa.core.utils.read_endpoints_from_path(endpoint)
|
|
81
|
-
if endpoints.nlg is not None:
|
|
82
|
-
validate_api_type_config_key_usage(
|
|
83
|
-
endpoints.nlg.kwargs,
|
|
84
|
-
LLM_CONFIG_KEY,
|
|
85
|
-
ContextualResponseRephraser.__name__,
|
|
86
|
-
)
|
|
87
73
|
NaturalLanguageGenerator.create(endpoints.nlg)
|
|
88
74
|
except Exception as e:
|
|
89
75
|
structlogger.error(
|
|
@@ -97,37 +83,6 @@ def _check_nlg_endpoint_validity(endpoint: Union[Path, str]) -> None:
|
|
|
97
83
|
sys.exit(1)
|
|
98
84
|
|
|
99
85
|
|
|
100
|
-
def retrieve_and_unpack_bot_config_from_remote_storage(
|
|
101
|
-
args: argparse.Namespace,
|
|
102
|
-
) -> None:
|
|
103
|
-
"""Retrieve and unpack bot config from remote storage.
|
|
104
|
-
|
|
105
|
-
Bot config is retrieved from remote storage and unpacked
|
|
106
|
-
to the current working directory.
|
|
107
|
-
"""
|
|
108
|
-
persistor = get_persistor(args.remote_storage)
|
|
109
|
-
if persistor is None:
|
|
110
|
-
raise RasaException(
|
|
111
|
-
f"Could not find a persistor for "
|
|
112
|
-
f"the storage type '{args.remote_storage}'."
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
current_working_directory = os.getcwd()
|
|
116
|
-
|
|
117
|
-
persistor.retrieve(args.remote_bot_config_path, current_working_directory)
|
|
118
|
-
|
|
119
|
-
remote_bot_config_tar_file_name = os.path.basename(args.remote_bot_config_path)
|
|
120
|
-
|
|
121
|
-
with TarSafe.open(remote_bot_config_tar_file_name, "r:gz") as tar:
|
|
122
|
-
tar.extractall(path=current_working_directory)
|
|
123
|
-
|
|
124
|
-
structlogger.debug(
|
|
125
|
-
"rasa.train.retrieve_and_unpack_bot_config.remove_downloaded_archive",
|
|
126
|
-
training_data_path=args.remote_bot_config_path,
|
|
127
|
-
)
|
|
128
|
-
os.remove(Path(current_working_directory).joinpath(remote_bot_config_tar_file_name))
|
|
129
|
-
|
|
130
|
-
|
|
131
86
|
def run_training(args: argparse.Namespace, can_exit: bool = False) -> Optional[Text]:
|
|
132
87
|
"""Trains a model.
|
|
133
88
|
|
|
@@ -139,9 +94,7 @@ def run_training(args: argparse.Namespace, can_exit: bool = False) -> Optional[T
|
|
|
139
94
|
Returns:
|
|
140
95
|
Path to a trained model or `None` if training was not successful.
|
|
141
96
|
"""
|
|
142
|
-
|
|
143
|
-
if hasattr(args, "remote_bot_config_path") and args.remote_bot_config_path:
|
|
144
|
-
retrieve_and_unpack_bot_config_from_remote_storage(args)
|
|
97
|
+
from rasa.api import train as train_all
|
|
145
98
|
|
|
146
99
|
domain = rasa.cli.utils.get_validated_path(
|
|
147
100
|
args.domain, "domain", DEFAULT_DOMAIN_PATHS, none_is_valid=True
|
|
@@ -157,16 +110,20 @@ def run_training(args: argparse.Namespace, can_exit: bool = False) -> Optional[T
|
|
|
157
110
|
for f in args.data
|
|
158
111
|
]
|
|
159
112
|
|
|
113
|
+
training_data_importer = TrainingDataImporter.load_from_config(
|
|
114
|
+
domain_path=domain, training_data_paths=args.data, config_path=config
|
|
115
|
+
)
|
|
116
|
+
|
|
160
117
|
if not args.skip_validation:
|
|
161
118
|
structlogger.info(
|
|
162
119
|
"cli.train.run_training",
|
|
163
120
|
event_info="Started validating domain and training data...",
|
|
164
121
|
)
|
|
165
|
-
|
|
166
|
-
domain_path=domain, training_data_paths=args.data, config_path=config
|
|
167
|
-
)
|
|
122
|
+
|
|
168
123
|
rasa.cli.utils.validate_files(
|
|
169
|
-
args.fail_on_validation_warnings,
|
|
124
|
+
args.fail_on_validation_warnings,
|
|
125
|
+
args.validation_max_history,
|
|
126
|
+
training_data_importer,
|
|
170
127
|
)
|
|
171
128
|
|
|
172
129
|
training_result = train_all(
|
|
@@ -185,6 +142,7 @@ def run_training(args: argparse.Namespace, can_exit: bool = False) -> Optional[T
|
|
|
185
142
|
model_to_finetune=_model_for_finetuning(args),
|
|
186
143
|
finetuning_epoch_fraction=args.epoch_fraction,
|
|
187
144
|
remote_storage=args.remote_storage,
|
|
145
|
+
file_importer=training_data_importer,
|
|
188
146
|
)
|
|
189
147
|
if training_result.code != 0 and can_exit:
|
|
190
148
|
sys.exit(training_result.code)
|
rasa/cli/utils.py
CHANGED
|
@@ -1,32 +1,30 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import argparse
|
|
3
|
+
import structlog
|
|
2
4
|
import importlib
|
|
3
|
-
import json
|
|
4
5
|
import os
|
|
5
6
|
import sys
|
|
6
7
|
import time
|
|
7
8
|
from pathlib import Path
|
|
8
9
|
from types import FrameType
|
|
9
|
-
from typing import
|
|
10
|
-
|
|
10
|
+
from typing import Any, Dict, List, Optional, TYPE_CHECKING, Text, Union, overload
|
|
11
11
|
import randomname
|
|
12
|
-
import structlog
|
|
13
12
|
|
|
14
13
|
import rasa.shared.utils.cli
|
|
15
14
|
import rasa.shared.utils.io
|
|
16
|
-
from rasa import
|
|
15
|
+
from rasa.shared.importers.importer import TrainingDataImporter
|
|
17
16
|
from rasa.shared.constants import (
|
|
18
17
|
ASSISTANT_ID_DEFAULT_VALUE,
|
|
19
18
|
ASSISTANT_ID_KEY,
|
|
20
19
|
DEFAULT_CONFIG_PATH,
|
|
21
20
|
)
|
|
22
|
-
from rasa
|
|
21
|
+
from rasa import telemetry
|
|
23
22
|
from rasa.shared.utils.yaml import read_config_file
|
|
24
23
|
from rasa.utils.io import write_yaml
|
|
25
24
|
|
|
26
25
|
if TYPE_CHECKING:
|
|
27
26
|
from questionary import Question
|
|
28
27
|
from typing_extensions import Literal
|
|
29
|
-
|
|
30
28
|
from rasa.validator import Validator
|
|
31
29
|
|
|
32
30
|
structlogger = structlog.get_logger()
|
|
@@ -472,10 +470,10 @@ def get_e2e_results_file_name(
|
|
|
472
470
|
) -> str:
|
|
473
471
|
"""Returns the name of the e2e results file."""
|
|
474
472
|
if results_output_path.is_dir():
|
|
475
|
-
file_name =
|
|
473
|
+
file_name = results_output_path / f"e2e_results_{result_type}.yml"
|
|
476
474
|
else:
|
|
477
475
|
parent = results_output_path.parent
|
|
478
476
|
stem = results_output_path.stem
|
|
479
|
-
file_name =
|
|
477
|
+
file_name = parent / f"{stem}_{result_type}.yml"
|
|
480
478
|
|
|
481
|
-
return file_name
|
|
479
|
+
return str(file_name)
|
rasa/cli/x.py
CHANGED
|
@@ -179,7 +179,7 @@ def run_in_enterprise_connection_mode(args: argparse.Namespace) -> None:
|
|
|
179
179
|
print_success("Starting a Rasa server in Rasa Enterprise connection mode... 🚀")
|
|
180
180
|
|
|
181
181
|
credentials_path, endpoints_path = _get_credentials_and_endpoints_paths(args)
|
|
182
|
-
endpoints = AvailableEndpoints.
|
|
182
|
+
endpoints = AvailableEndpoints.read_endpoints(endpoints_path)
|
|
183
183
|
|
|
184
184
|
_rasa_service(args, endpoints, None, credentials_path)
|
|
185
185
|
|
rasa/constants.py
CHANGED
|
@@ -18,7 +18,7 @@ CONFIG_TELEMETRY_ID = "rasa_user_id"
|
|
|
18
18
|
CONFIG_TELEMETRY_ENABLED = "enabled"
|
|
19
19
|
CONFIG_TELEMETRY_DATE = "date"
|
|
20
20
|
|
|
21
|
-
MINIMUM_COMPATIBLE_VERSION = "3.10.
|
|
21
|
+
MINIMUM_COMPATIBLE_VERSION = "3.10.0rc1"
|
|
22
22
|
|
|
23
23
|
GLOBAL_USER_CONFIG_PATH = os.path.expanduser("~/.config/rasa/global.yml")
|
|
24
24
|
|
rasa/core/actions/action.py
CHANGED
|
@@ -112,6 +112,7 @@ def default_actions(action_endpoint: Optional[EndpointConfig] = None) -> List["A
|
|
|
112
112
|
from rasa.core.actions.action_trigger_chitchat import ActionTriggerChitchat
|
|
113
113
|
from rasa.core.actions.action_trigger_search import ActionTriggerSearch
|
|
114
114
|
from rasa.core.actions.two_stage_fallback import TwoStageFallbackAction
|
|
115
|
+
from rasa.core.actions.action_hangup import ActionHangup
|
|
115
116
|
from rasa.dialogue_understanding.patterns.cancel import ActionCancelFlow
|
|
116
117
|
from rasa.dialogue_understanding.patterns.clarify import ActionClarifyFlows
|
|
117
118
|
from rasa.dialogue_understanding.patterns.correction import ActionCorrectFlowSlot
|
|
@@ -138,6 +139,7 @@ def default_actions(action_endpoint: Optional[EndpointConfig] = None) -> List["A
|
|
|
138
139
|
ActionTriggerSearch(),
|
|
139
140
|
ActionTriggerChitchat(),
|
|
140
141
|
ActionResetRouting(),
|
|
142
|
+
ActionHangup(),
|
|
141
143
|
]
|
|
142
144
|
|
|
143
145
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from typing import Optional, Dict, Any, List
|
|
2
|
+
|
|
3
|
+
from rasa.core.actions.action import Action
|
|
4
|
+
from rasa.core.channels import OutputChannel
|
|
5
|
+
from rasa.core.nlg import NaturalLanguageGenerator
|
|
6
|
+
from rasa.shared.core.constants import ACTION_HANGUP
|
|
7
|
+
from rasa.shared.core.domain import Domain
|
|
8
|
+
from rasa.shared.core.events import Event, SessionEnded
|
|
9
|
+
from rasa.shared.core.trackers import DialogueStateTracker
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ActionHangup(Action):
|
|
13
|
+
"""Action which hangs up the call."""
|
|
14
|
+
|
|
15
|
+
def name(self) -> str:
|
|
16
|
+
"""Return the name of the action."""
|
|
17
|
+
return ACTION_HANGUP
|
|
18
|
+
|
|
19
|
+
async def run(
|
|
20
|
+
self,
|
|
21
|
+
output_channel: OutputChannel,
|
|
22
|
+
nlg: NaturalLanguageGenerator,
|
|
23
|
+
tracker: DialogueStateTracker,
|
|
24
|
+
domain: Domain,
|
|
25
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
26
|
+
) -> List[Event]:
|
|
27
|
+
"""Ask the output channel to hang up the call."""
|
|
28
|
+
await output_channel.hangup(tracker.sender_id)
|
|
29
|
+
return [SessionEnded(metadata={"_reason": "hangup"})]
|
rasa/core/agent.py
CHANGED
|
@@ -19,6 +19,7 @@ from rasa.core.exceptions import AgentNotReady
|
|
|
19
19
|
from rasa.core.http_interpreter import RasaNLUHttpInterpreter
|
|
20
20
|
from rasa.core.lock_store import InMemoryLockStore, LockStore
|
|
21
21
|
from rasa.core.nlg import NaturalLanguageGenerator, TemplatedNaturalLanguageGenerator
|
|
22
|
+
from rasa.core.persistor import StorageType
|
|
22
23
|
from rasa.core.policies.policy import PolicyPrediction
|
|
23
24
|
from rasa.core.processor import MessageProcessor
|
|
24
25
|
from rasa.core.tracker_store import (
|
|
@@ -28,7 +29,6 @@ from rasa.core.tracker_store import (
|
|
|
28
29
|
)
|
|
29
30
|
from rasa.core.utils import AvailableEndpoints
|
|
30
31
|
from rasa.exceptions import ModelNotFound
|
|
31
|
-
from rasa.nlu.persistor import StorageType
|
|
32
32
|
from rasa.nlu.utils import is_url
|
|
33
33
|
from rasa.shared.constants import DEFAULT_SENDER_ID
|
|
34
34
|
from rasa.shared.core.domain import Domain
|
|
@@ -544,7 +544,7 @@ class Agent:
|
|
|
544
544
|
|
|
545
545
|
def load_model_from_remote_storage(self, model_name: Text) -> None:
|
|
546
546
|
"""Loads an Agent from remote storage."""
|
|
547
|
-
from rasa.
|
|
547
|
+
from rasa.core.persistor import get_persistor
|
|
548
548
|
|
|
549
549
|
persistor = get_persistor(self.remote_storage)
|
|
550
550
|
|
rasa/core/brokers/kafka.py
CHANGED
|
@@ -2,6 +2,8 @@ import asyncio
|
|
|
2
2
|
import os
|
|
3
3
|
import json
|
|
4
4
|
import logging
|
|
5
|
+
from functools import cached_property
|
|
6
|
+
|
|
5
7
|
import structlog
|
|
6
8
|
import threading
|
|
7
9
|
from asyncio import AbstractEventLoop
|
|
@@ -270,7 +272,7 @@ class KafkaEventBroker(EventBroker):
|
|
|
270
272
|
if self.producer:
|
|
271
273
|
self.producer.flush()
|
|
272
274
|
|
|
273
|
-
@
|
|
275
|
+
@cached_property
|
|
274
276
|
def rasa_environment(self) -> Optional[Text]:
|
|
275
277
|
"""Get value of the `RASA_ENVIRONMENT` environment variable."""
|
|
276
278
|
return os.environ.get("RASA_ENVIRONMENT", "RASA_ENVIRONMENT_NOT_SET")
|
rasa/core/brokers/pika.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import json
|
|
3
3
|
import logging
|
|
4
|
+
from functools import cached_property
|
|
5
|
+
|
|
4
6
|
import structlog
|
|
5
7
|
import os
|
|
6
8
|
import ssl
|
|
@@ -333,7 +335,7 @@ class PikaEventBroker(EventBroker):
|
|
|
333
335
|
delivery_mode=aio_pika.DeliveryMode.PERSISTENT,
|
|
334
336
|
)
|
|
335
337
|
|
|
336
|
-
@
|
|
338
|
+
@cached_property
|
|
337
339
|
def rasa_environment(self) -> Optional[Text]:
|
|
338
340
|
"""Get value of the `RASA_ENVIRONMENT` environment variable."""
|
|
339
341
|
return os.environ.get("RASA_ENVIRONMENT")
|
rasa/core/channels/__init__.py
CHANGED
|
@@ -21,13 +21,15 @@ from rasa.core.channels.rocketchat import RocketChatInput
|
|
|
21
21
|
from rasa.core.channels.slack import SlackInput
|
|
22
22
|
from rasa.core.channels.telegram import TelegramInput
|
|
23
23
|
from rasa.core.channels.twilio import TwilioInput
|
|
24
|
-
from rasa.core.channels.twilio_voice import TwilioVoiceInput
|
|
25
|
-
from rasa.core.channels.
|
|
24
|
+
from rasa.core.channels.voice_ready.twilio_voice import TwilioVoiceInput
|
|
25
|
+
from rasa.core.channels.voice_ready.jambonz import JambonzVoiceReadyInput
|
|
26
|
+
from rasa.core.channels.voice_ready.audiocodes import AudiocodesInput
|
|
26
27
|
from rasa.core.channels.webexteams import WebexTeamsInput
|
|
27
28
|
from rasa.core.channels.hangouts import HangoutsInput
|
|
28
|
-
from rasa.core.channels.audiocodes import AudiocodesInput
|
|
29
|
-
from rasa.core.channels.development_inspector import DevelopmentInspectInput
|
|
30
29
|
from rasa.core.channels.vier_cvg import CVGInput
|
|
30
|
+
from rasa.core.channels.voice_stream.twilio_media_streams import (
|
|
31
|
+
TwilioMediaStreamsInputChannel,
|
|
32
|
+
)
|
|
31
33
|
|
|
32
34
|
input_channel_classes: List[Type[InputChannel]] = [
|
|
33
35
|
CmdlineInput,
|
|
@@ -46,9 +48,9 @@ input_channel_classes: List[Type[InputChannel]] = [
|
|
|
46
48
|
WebexTeamsInput,
|
|
47
49
|
HangoutsInput,
|
|
48
50
|
AudiocodesInput,
|
|
49
|
-
DevelopmentInspectInput,
|
|
50
51
|
CVGInput,
|
|
51
|
-
|
|
52
|
+
JambonzVoiceReadyInput,
|
|
53
|
+
TwilioMediaStreamsInputChannel,
|
|
52
54
|
]
|
|
53
55
|
|
|
54
56
|
# Mapping from an input channel name to its class to allow name based lookup.
|
rasa/core/channels/channel.py
CHANGED
|
@@ -25,6 +25,7 @@ from rasa.shared.core.trackers import (
|
|
|
25
25
|
EventVerbosity,
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
+
|
|
28
29
|
try:
|
|
29
30
|
from urlparse import urljoin
|
|
30
31
|
except ImportError:
|
|
@@ -61,7 +62,7 @@ class UserMessage:
|
|
|
61
62
|
input_channel: the name of the channel which received this message.
|
|
62
63
|
message_id: ID of the message.
|
|
63
64
|
metadata: additional metadata for this message.
|
|
64
|
-
|
|
65
|
+
**kwargs: additional arguments which will be included in the message.
|
|
65
66
|
"""
|
|
66
67
|
self.text = text.strip() if text else text
|
|
67
68
|
|
|
@@ -235,7 +236,11 @@ class OutputChannel:
|
|
|
235
236
|
"""Attaches the current tracker state to the output channel."""
|
|
236
237
|
self.tracker_state = tracker.current_state(EventVerbosity.AFTER_RESTART)
|
|
237
238
|
|
|
238
|
-
async def send_response(
|
|
239
|
+
async def send_response(
|
|
240
|
+
self,
|
|
241
|
+
recipient_id: Text,
|
|
242
|
+
message: Dict[Text, Any],
|
|
243
|
+
) -> None:
|
|
239
244
|
"""Send a message to the client."""
|
|
240
245
|
if message.get("quick_replies"):
|
|
241
246
|
await self.send_quick_replies(
|
|
@@ -267,7 +272,10 @@ class OutputChannel:
|
|
|
267
272
|
await self.send_elements(recipient_id, message.pop("elements"), **message)
|
|
268
273
|
|
|
269
274
|
async def send_text_message(
|
|
270
|
-
self,
|
|
275
|
+
self,
|
|
276
|
+
recipient_id: Text,
|
|
277
|
+
text: Text,
|
|
278
|
+
**kwargs: Any,
|
|
271
279
|
) -> None:
|
|
272
280
|
"""Send a message through this channel."""
|
|
273
281
|
raise NotImplementedError(
|
|
@@ -319,6 +327,7 @@ class OutputChannel:
|
|
|
319
327
|
self, recipient_id: Text, elements: Iterable[Dict[Text, Any]], **kwargs: Any
|
|
320
328
|
) -> None:
|
|
321
329
|
"""Sends elements to the output.
|
|
330
|
+
|
|
322
331
|
Default implementation will just post the elements as a string.
|
|
323
332
|
"""
|
|
324
333
|
for element in elements:
|
|
@@ -333,10 +342,15 @@ class OutputChannel:
|
|
|
333
342
|
self, recipient_id: Text, json_message: Dict[Text, Any], **kwargs: Any
|
|
334
343
|
) -> None:
|
|
335
344
|
"""Sends json dict to the output channel.
|
|
345
|
+
|
|
336
346
|
Default implementation will just post the json contents as a string.
|
|
337
347
|
"""
|
|
338
348
|
await self.send_text_message(recipient_id, json.dumps(json_message))
|
|
339
349
|
|
|
350
|
+
async def hangup(self, recipient_id: Text, **kwargs: Any) -> None:
|
|
351
|
+
"""Indicate that the conversation should be ended."""
|
|
352
|
+
pass
|
|
353
|
+
|
|
340
354
|
|
|
341
355
|
class CollectingOutputChannel(OutputChannel):
|
|
342
356
|
"""Output channel that collects send messages in a list.
|
|
@@ -385,7 +399,10 @@ class CollectingOutputChannel(OutputChannel):
|
|
|
385
399
|
self.messages.append(message)
|
|
386
400
|
|
|
387
401
|
async def send_text_message(
|
|
388
|
-
self,
|
|
402
|
+
self,
|
|
403
|
+
recipient_id: Text,
|
|
404
|
+
text: Text,
|
|
405
|
+
**kwargs: Any,
|
|
389
406
|
) -> None:
|
|
390
407
|
for message_part in text.strip().split("\n\n"):
|
|
391
408
|
await self._persist_message(self._message(recipient_id, text=message_part))
|