rasa-pro 3.8.18__py3-none-any.whl → 3.9.14__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 +6 -42
- rasa/__main__.py +14 -9
- rasa/anonymization/anonymization_pipeline.py +0 -1
- rasa/anonymization/anonymization_rule_executor.py +3 -3
- rasa/anonymization/utils.py +4 -3
- rasa/api.py +2 -2
- rasa/cli/arguments/default_arguments.py +1 -1
- rasa/cli/arguments/run.py +2 -2
- rasa/cli/arguments/test.py +1 -1
- rasa/cli/arguments/train.py +10 -10
- rasa/cli/e2e_test.py +27 -7
- rasa/cli/export.py +0 -1
- rasa/cli/license.py +3 -3
- rasa/cli/project_templates/calm/actions/action_template.py +1 -1
- rasa/cli/project_templates/calm/config.yml +1 -1
- rasa/cli/project_templates/calm/credentials.yml +1 -1
- rasa/cli/project_templates/calm/data/flows/add_contact.yml +1 -1
- rasa/cli/project_templates/calm/data/flows/remove_contact.yml +1 -1
- rasa/cli/project_templates/calm/domain/add_contact.yml +8 -2
- rasa/cli/project_templates/calm/domain/list_contacts.yml +3 -0
- rasa/cli/project_templates/calm/domain/remove_contact.yml +9 -2
- rasa/cli/project_templates/calm/domain/shared.yml +5 -0
- rasa/cli/project_templates/calm/endpoints.yml +4 -4
- rasa/cli/project_templates/default/actions/actions.py +1 -1
- rasa/cli/project_templates/default/config.yml +5 -5
- rasa/cli/project_templates/default/credentials.yml +1 -1
- rasa/cli/project_templates/default/endpoints.yml +4 -4
- rasa/cli/project_templates/default/tests/test_stories.yml +1 -1
- rasa/cli/project_templates/tutorial/config.yml +1 -1
- rasa/cli/project_templates/tutorial/credentials.yml +1 -1
- rasa/cli/project_templates/tutorial/data/patterns.yml +6 -0
- rasa/cli/project_templates/tutorial/domain.yml +4 -0
- rasa/cli/project_templates/tutorial/endpoints.yml +6 -6
- rasa/cli/run.py +0 -1
- rasa/cli/scaffold.py +3 -2
- rasa/cli/studio/download.py +11 -0
- rasa/cli/studio/studio.py +180 -24
- rasa/cli/studio/upload.py +0 -8
- rasa/cli/telemetry.py +18 -6
- rasa/cli/utils.py +21 -10
- rasa/cli/x.py +3 -2
- rasa/constants.py +1 -1
- rasa/core/actions/action.py +90 -315
- rasa/core/actions/action_exceptions.py +24 -0
- rasa/core/actions/constants.py +3 -0
- rasa/core/actions/custom_action_executor.py +188 -0
- rasa/core/actions/forms.py +11 -7
- rasa/core/actions/grpc_custom_action_executor.py +251 -0
- rasa/core/actions/http_custom_action_executor.py +140 -0
- rasa/core/actions/loops.py +3 -0
- rasa/core/actions/two_stage_fallback.py +1 -1
- rasa/core/agent.py +2 -4
- rasa/core/brokers/pika.py +1 -2
- rasa/core/channels/audiocodes.py +1 -1
- rasa/core/channels/botframework.py +0 -1
- rasa/core/channels/callback.py +0 -1
- rasa/core/channels/console.py +6 -8
- rasa/core/channels/development_inspector.py +1 -1
- rasa/core/channels/facebook.py +0 -3
- rasa/core/channels/hangouts.py +0 -6
- rasa/core/channels/inspector/dist/assets/{arc-5623b6dc.js → arc-b6e548fe.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-685c106a.js → c4Diagram-d0fbc5ce-fa03ac9e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-8cbed007.js → classDiagram-936ed81e-ee67392a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-5889cf12.js → classDiagram-v2-c3cb15f1-9b283fae.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{createText-62fc7601-24c249d7.js → createText-62fc7601-8b6fcc2a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-7dd06a75.js → edges-f2ad444c-22e77f4f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-62c1e54c.js → erDiagram-9d236eb7-60ffc87f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-ce49b86f.js → flowDb-1972c806-9dd802e4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-4067e48f.js → flowDiagram-7ea5b25a-5fa1912f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-1844e5a5.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-59fe4051.js → flowchart-elk-definition-abe16c3d-622a1fd2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-47e3a43b.js → ganttDiagram-9b5ea136-e285a63a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-5a2ac0d9.js → gitGraphDiagram-99d0ae7c-f237bdca.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-dfb8efc4.js → index-2c4b9a3b-4b03d70e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-268a75c0.js → index-a5d3e69d.js} +4 -4
- rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-b0c470f2.js → infoDiagram-736b4530-72a0fa5f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-2edb829a.js → journeyDiagram-df861f2b-82218c41.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-b6873d69.js → layout-78cff630.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-1efc5781.js → line-5038b469.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-661e9b94.js → linear-c4fc4098.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-2d2e727f.js → mindmap-definition-beec6740-c33c8ea6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-9d3ea93d.js → pieDiagram-dbbf0591-a8d03059.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-06a178a2.js → quadrantDiagram-4d7f4fd6-6a0e56b2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-0bfedffc.js → requirementDiagram-6fc4c22a-2dc7c7bd.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-d76d0a04.js → sankeyDiagram-8f13d901-2360fe39.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-37bb4341.js → sequenceDiagram-b655622a-41b9f9ad.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-f52f7f57.js → stateDiagram-59f0c015-0aad326f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-4a986a20.js → stateDiagram-v2-2b26beab-9847d984.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-080da4f6-7dd9ae12.js → styles-080da4f6-564d890e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-46e1ca14.js → styles-3dcbcfbf-38957613.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9c745c82-4a97439a.js → styles-9c745c82-f0fc6921.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-823917a3.js → svgDrawCommon-4835440b-ef3c5a77.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-9ea72896.js → timeline-definition-5b62e21b-bf3e91c1.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-b631a8b6.js → xychartDiagram-2b33534f-4d4026c0.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +1 -1
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +10 -0
- rasa/core/channels/inspector/src/helpers/formatters.test.ts +4 -7
- rasa/core/channels/inspector/src/helpers/formatters.ts +3 -2
- rasa/core/channels/rest.py +36 -21
- rasa/core/channels/rocketchat.py +0 -1
- rasa/core/channels/socketio.py +1 -1
- rasa/core/channels/telegram.py +3 -3
- rasa/core/channels/webexteams.py +0 -1
- rasa/core/concurrent_lock_store.py +1 -1
- rasa/core/evaluation/marker_base.py +1 -3
- rasa/core/evaluation/marker_stats.py +1 -2
- rasa/core/featurizers/single_state_featurizer.py +3 -26
- rasa/core/featurizers/tracker_featurizers.py +18 -122
- rasa/core/information_retrieval/__init__.py +7 -0
- rasa/core/information_retrieval/faiss.py +9 -4
- rasa/core/information_retrieval/information_retrieval.py +64 -7
- rasa/core/information_retrieval/milvus.py +7 -14
- rasa/core/information_retrieval/qdrant.py +8 -15
- rasa/core/lock_store.py +0 -1
- rasa/core/migrate.py +1 -2
- rasa/core/nlg/callback.py +3 -4
- rasa/core/policies/enterprise_search_policy.py +86 -22
- rasa/core/policies/enterprise_search_prompt_template.jinja2 +4 -41
- rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +60 -0
- rasa/core/policies/flows/flow_executor.py +104 -2
- rasa/core/policies/intentless_policy.py +7 -9
- rasa/core/policies/memoization.py +3 -3
- rasa/core/policies/policy.py +18 -9
- rasa/core/policies/rule_policy.py +8 -11
- rasa/core/policies/ted_policy.py +61 -88
- rasa/core/policies/unexpected_intent_policy.py +8 -17
- rasa/core/processor.py +136 -47
- rasa/core/run.py +41 -25
- rasa/core/secrets_manager/endpoints.py +2 -2
- rasa/core/secrets_manager/vault.py +6 -8
- rasa/core/test.py +3 -5
- rasa/core/tracker_store.py +49 -14
- rasa/core/train.py +1 -3
- rasa/core/training/interactive.py +9 -6
- rasa/core/utils.py +5 -10
- rasa/dialogue_understanding/coexistence/intent_based_router.py +11 -4
- rasa/dialogue_understanding/coexistence/llm_based_router.py +2 -3
- rasa/dialogue_understanding/commands/__init__.py +4 -0
- rasa/dialogue_understanding/commands/can_not_handle_command.py +9 -0
- rasa/dialogue_understanding/commands/cancel_flow_command.py +9 -0
- rasa/dialogue_understanding/commands/change_flow_command.py +38 -0
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +9 -0
- rasa/dialogue_understanding/commands/clarify_command.py +9 -0
- rasa/dialogue_understanding/commands/correct_slots_command.py +9 -0
- rasa/dialogue_understanding/commands/error_command.py +12 -0
- rasa/dialogue_understanding/commands/handle_code_change_command.py +9 -0
- rasa/dialogue_understanding/commands/human_handoff_command.py +9 -0
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +9 -0
- rasa/dialogue_understanding/commands/noop_command.py +9 -0
- rasa/dialogue_understanding/commands/set_slot_command.py +34 -3
- rasa/dialogue_understanding/commands/skip_question_command.py +9 -0
- rasa/dialogue_understanding/commands/start_flow_command.py +9 -0
- rasa/dialogue_understanding/generator/__init__.py +16 -1
- rasa/dialogue_understanding/generator/command_generator.py +92 -6
- rasa/dialogue_understanding/generator/constants.py +18 -0
- rasa/dialogue_understanding/generator/flow_retrieval.py +7 -5
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +467 -0
- rasa/dialogue_understanding/generator/llm_command_generator.py +39 -609
- rasa/dialogue_understanding/generator/multi_step/__init__.py +0 -0
- rasa/dialogue_understanding/generator/multi_step/fill_slots_prompt.jinja2 +62 -0
- rasa/dialogue_understanding/generator/multi_step/handle_flows_prompt.jinja2 +38 -0
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +827 -0
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +69 -8
- rasa/dialogue_understanding/generator/single_step/__init__.py +0 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +345 -0
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +44 -39
- rasa/dialogue_understanding/processor/command_processor.py +111 -3
- rasa/e2e_test/constants.py +1 -0
- rasa/e2e_test/e2e_test_case.py +44 -0
- rasa/e2e_test/e2e_test_runner.py +114 -11
- rasa/e2e_test/e2e_test_schema.yml +18 -0
- rasa/engine/caching.py +0 -1
- rasa/engine/graph.py +18 -6
- rasa/engine/recipes/config_files/default_config.yml +3 -3
- rasa/engine/recipes/default_components.py +1 -1
- rasa/engine/recipes/default_recipe.py +4 -5
- rasa/engine/recipes/recipe.py +1 -1
- rasa/engine/runner/dask.py +3 -9
- rasa/engine/storage/local_model_storage.py +0 -2
- rasa/engine/validation.py +179 -145
- rasa/exceptions.py +2 -2
- rasa/graph_components/validators/default_recipe_validator.py +3 -5
- rasa/hooks.py +0 -1
- rasa/model.py +1 -1
- rasa/model_training.py +1 -0
- rasa/nlu/classifiers/diet_classifier.py +33 -52
- 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 +54 -97
- rasa/nlu/extractors/duckling_entity_extractor.py +1 -1
- rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +1 -5
- rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +0 -4
- rasa/nlu/featurizers/featurizer.py +1 -1
- rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +18 -49
- rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +26 -64
- rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +3 -5
- rasa/nlu/persistor.py +68 -26
- rasa/nlu/selectors/response_selector.py +7 -10
- rasa/nlu/test.py +0 -3
- rasa/nlu/utils/hugging_face/registry.py +1 -1
- rasa/nlu/utils/spacy_utils.py +1 -3
- rasa/server.py +22 -7
- rasa/shared/constants.py +12 -1
- rasa/shared/core/command_payload_reader.py +109 -0
- rasa/shared/core/constants.py +4 -5
- rasa/shared/core/domain.py +57 -56
- rasa/shared/core/events.py +4 -7
- rasa/shared/core/flows/flow.py +9 -0
- rasa/shared/core/flows/flows_list.py +12 -0
- rasa/shared/core/flows/steps/action.py +7 -2
- rasa/shared/core/generator.py +12 -11
- rasa/shared/core/slot_mappings.py +315 -24
- rasa/shared/core/slots.py +4 -2
- rasa/shared/core/trackers.py +32 -14
- rasa/shared/core/training_data/loading.py +0 -1
- rasa/shared/core/training_data/story_reader/story_reader.py +3 -3
- rasa/shared/core/training_data/story_reader/yaml_story_reader.py +11 -11
- rasa/shared/core/training_data/story_writer/yaml_story_writer.py +5 -3
- rasa/shared/core/training_data/structures.py +1 -1
- rasa/shared/core/training_data/visualization.py +1 -1
- rasa/shared/data.py +58 -1
- rasa/shared/exceptions.py +36 -2
- rasa/shared/importers/importer.py +1 -2
- rasa/shared/importers/rasa.py +0 -1
- rasa/shared/nlu/constants.py +2 -0
- rasa/shared/nlu/training_data/entities_parser.py +1 -2
- rasa/shared/nlu/training_data/features.py +2 -120
- rasa/shared/nlu/training_data/formats/dialogflow.py +3 -2
- rasa/shared/nlu/training_data/formats/rasa_yaml.py +3 -5
- rasa/shared/nlu/training_data/formats/readerwriter.py +0 -1
- rasa/shared/nlu/training_data/message.py +13 -0
- rasa/shared/nlu/training_data/training_data.py +0 -2
- rasa/shared/providers/openai/session_handler.py +2 -2
- rasa/shared/utils/constants.py +3 -0
- rasa/shared/utils/io.py +11 -1
- rasa/shared/utils/llm.py +1 -2
- rasa/shared/utils/pykwalify_extensions.py +1 -0
- rasa/shared/utils/schemas/domain.yml +3 -0
- rasa/shared/utils/yaml.py +44 -35
- rasa/studio/auth.py +26 -10
- rasa/studio/constants.py +2 -0
- rasa/studio/data_handler.py +114 -107
- rasa/studio/download.py +160 -27
- rasa/studio/results_logger.py +137 -0
- rasa/studio/train.py +6 -7
- rasa/studio/upload.py +159 -134
- rasa/telemetry.py +188 -34
- rasa/tracing/config.py +18 -3
- rasa/tracing/constants.py +26 -2
- rasa/tracing/instrumentation/attribute_extractors.py +50 -41
- rasa/tracing/instrumentation/instrumentation.py +290 -44
- rasa/tracing/instrumentation/intentless_policy_instrumentation.py +7 -5
- rasa/tracing/instrumentation/metrics.py +109 -21
- rasa/tracing/metric_instrument_provider.py +83 -3
- rasa/utils/cli.py +2 -1
- rasa/utils/common.py +1 -1
- rasa/utils/endpoints.py +1 -2
- rasa/utils/io.py +72 -6
- rasa/utils/licensing.py +246 -31
- rasa/utils/ml_utils.py +1 -1
- rasa/utils/tensorflow/data_generator.py +1 -1
- rasa/utils/tensorflow/environment.py +1 -1
- rasa/utils/tensorflow/model_data.py +201 -12
- rasa/utils/tensorflow/model_data_utils.py +499 -500
- rasa/utils/tensorflow/models.py +5 -6
- rasa/utils/tensorflow/rasa_layers.py +15 -15
- rasa/utils/train_utils.py +1 -1
- rasa/utils/url_tools.py +53 -0
- rasa/validator.py +305 -3
- rasa/version.py +1 -1
- {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.14.dist-info}/METADATA +25 -61
- {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.14.dist-info}/RECORD +276 -259
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-85583a23.js +0 -1
- rasa/utils/tensorflow/feature_array.py +0 -370
- /rasa/dialogue_understanding/generator/{command_prompt_template.jinja2 → single_step/command_prompt_template.jinja2} +0 -0
- {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.14.dist-info}/NOTICE +0 -0
- {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.14.dist-info}/WHEEL +0 -0
- {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.14.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from functools import wraps
|
|
3
|
+
from typing import Callable, Any, Dict
|
|
4
|
+
|
|
5
|
+
import structlog
|
|
6
|
+
from keycloak.exceptions import KeycloakError
|
|
7
|
+
from requests.exceptions import RequestException, Timeout, ConnectionError
|
|
8
|
+
|
|
9
|
+
from rasa.shared.exceptions import RasaException
|
|
10
|
+
from rasa.shared.utils.cli import print_success, print_error
|
|
11
|
+
from rasa.studio.config import StudioConfig
|
|
12
|
+
|
|
13
|
+
structlogger = structlog.get_logger()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class StudioResult:
|
|
18
|
+
message: str
|
|
19
|
+
was_successful: bool
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def success(message: str) -> "StudioResult":
|
|
23
|
+
return StudioResult(message, was_successful=True)
|
|
24
|
+
|
|
25
|
+
@staticmethod
|
|
26
|
+
def error(response: Dict[str, Any]) -> "StudioResult":
|
|
27
|
+
"""Create a StudioResult from a GraphQL error response.
|
|
28
|
+
|
|
29
|
+
Factory will evaluate the response and return a StudioResult with the
|
|
30
|
+
appropriate message and success status.
|
|
31
|
+
"""
|
|
32
|
+
if isinstance(response.get("errors"), list):
|
|
33
|
+
error_details = "; ".join(
|
|
34
|
+
[error.get("message", "Unknown error") for error in response["errors"]]
|
|
35
|
+
)
|
|
36
|
+
else:
|
|
37
|
+
error_details = "No detailed error information available."
|
|
38
|
+
|
|
39
|
+
structlogger.warn(
|
|
40
|
+
"studio.graphql_error", event_info=error_details, response=response
|
|
41
|
+
)
|
|
42
|
+
return StudioResult(error_details, was_successful=False)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def with_studio_error_handler(
|
|
46
|
+
func: Callable[..., StudioResult],
|
|
47
|
+
) -> Callable[..., StudioResult]:
|
|
48
|
+
@wraps(func)
|
|
49
|
+
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
50
|
+
try:
|
|
51
|
+
result = func(*args, **kwargs)
|
|
52
|
+
if result.was_successful:
|
|
53
|
+
print_success(result.message)
|
|
54
|
+
else:
|
|
55
|
+
print_error(result.message)
|
|
56
|
+
return result
|
|
57
|
+
except RasaException as e:
|
|
58
|
+
return _handle_rasa_exception(e)
|
|
59
|
+
except KeycloakError as e:
|
|
60
|
+
return _handle_keycloak_error(e)
|
|
61
|
+
except ConnectionError as e:
|
|
62
|
+
return _handle_connection_error(e)
|
|
63
|
+
except Timeout as e:
|
|
64
|
+
return _handle_timeout_error(e)
|
|
65
|
+
except RequestException as e:
|
|
66
|
+
return _handle_request_exception(e)
|
|
67
|
+
except Exception as e:
|
|
68
|
+
return _handle_unexpected_error(e)
|
|
69
|
+
|
|
70
|
+
return wrapper
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def response_has_errors(response: Dict) -> bool:
|
|
74
|
+
return (
|
|
75
|
+
"errors" in response
|
|
76
|
+
and isinstance(response["errors"], list)
|
|
77
|
+
and len(response["errors"]) > 0
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _handle_rasa_exception(e: RasaException) -> StudioResult:
|
|
82
|
+
error_msg = "Rasa internal exception was raised while interacting with Studio."
|
|
83
|
+
structlogger.error("studio.rasa_error", event_info=error_msg, exception=str(e))
|
|
84
|
+
return StudioResult(message=str(e), was_successful=False)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _handle_keycloak_error(e: KeycloakError) -> StudioResult:
|
|
88
|
+
error_msg = (
|
|
89
|
+
f"Unable to authenticate with Keycloak at "
|
|
90
|
+
f"{StudioConfig.read_config().authentication_server_url} "
|
|
91
|
+
)
|
|
92
|
+
if e.response_code == 401:
|
|
93
|
+
error_msg += "Please check if the credentials are correct."
|
|
94
|
+
elif e.error_message.startswith("Can't connect to server"):
|
|
95
|
+
error_msg += (
|
|
96
|
+
"Please check if the server is running "
|
|
97
|
+
"and the configured URL is correct. \n"
|
|
98
|
+
"You may need to reconfigure Rasa Studio "
|
|
99
|
+
"using 'rasa studio config'."
|
|
100
|
+
)
|
|
101
|
+
else:
|
|
102
|
+
error_msg += f"Error message: {e.error_message}"
|
|
103
|
+
structlogger.error("studio.keycloak_error", event_info=error_msg, exception=str(e))
|
|
104
|
+
return StudioResult(error_msg, was_successful=False)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _handle_connection_error(e: ConnectionError) -> StudioResult:
|
|
108
|
+
studio_url = StudioConfig.read_config().studio_url
|
|
109
|
+
error_msg = (
|
|
110
|
+
f"Unable to reach Rasa Studio API at {studio_url} \n"
|
|
111
|
+
"Please check if Studio is running and the configured URL is correct. \n"
|
|
112
|
+
"You may need to reconfigure Rasa Studio using 'rasa studio config'."
|
|
113
|
+
)
|
|
114
|
+
structlogger.error("studio.graphql_error", event_info=error_msg, exception=str(e))
|
|
115
|
+
return StudioResult(error_msg, was_successful=False)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _handle_timeout_error(e: Timeout) -> StudioResult:
|
|
119
|
+
error_msg = "The request timed out. Please try again later."
|
|
120
|
+
structlogger.error("studio.graphql_timeout", event_info=error_msg, exception=str(e))
|
|
121
|
+
return StudioResult(error_msg, was_successful=False)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _handle_request_exception(e: RequestException) -> StudioResult:
|
|
125
|
+
error_msg = f"An error occurred while communicating with the server: {e!s}"
|
|
126
|
+
structlogger.error(
|
|
127
|
+
"studio.graphql.request_exception", event_info=error_msg, exception=str(e)
|
|
128
|
+
)
|
|
129
|
+
return StudioResult(error_msg, was_successful=False)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _handle_unexpected_error(e: Exception) -> StudioResult:
|
|
133
|
+
error_msg = f"An unexpected error occurred: {e!s}"
|
|
134
|
+
structlogger.exception(
|
|
135
|
+
"studio.unexpected_error", event_info=error_msg, exception=str(e)
|
|
136
|
+
)
|
|
137
|
+
return StudioResult(error_msg, was_successful=False)
|
rasa/studio/train.py
CHANGED
|
@@ -19,11 +19,11 @@ from rasa.shared.constants import (
|
|
|
19
19
|
from rasa.shared.core.flows.yaml_flows_io import YamlFlowsWriter
|
|
20
20
|
from rasa.shared.importers.importer import TrainingDataImporter
|
|
21
21
|
from rasa.shared.utils.yaml import read_yaml, write_yaml
|
|
22
|
+
from rasa.studio import data_handler
|
|
22
23
|
from rasa.utils.common import get_temp_dir_name
|
|
23
24
|
|
|
24
25
|
from rasa.studio.config import StudioConfig
|
|
25
26
|
from rasa.studio.data_handler import (
|
|
26
|
-
DataDiffGenerator,
|
|
27
27
|
StudioDataHandler,
|
|
28
28
|
import_data_from_studio,
|
|
29
29
|
)
|
|
@@ -50,9 +50,9 @@ def handle_train(args: argparse.Namespace) -> Optional[str]:
|
|
|
50
50
|
handler, domain, args.data
|
|
51
51
|
)
|
|
52
52
|
|
|
53
|
-
domain = data_original.get_domain().merge(data_form_studio.get_domain()) # type: ignore[assignment]
|
|
53
|
+
domain = data_original.get_domain().merge(data_form_studio.get_domain()) # type: ignore[assignment]
|
|
54
54
|
|
|
55
|
-
domain_file = _create_temp_file(read_yaml(domain.as_yaml()), "domain.yml") # type: ignore[union-attr]
|
|
55
|
+
domain_file = _create_temp_file(read_yaml(domain.as_yaml()), "domain.yml") # type: ignore[union-attr]
|
|
56
56
|
|
|
57
57
|
studio_training_files = make_training_files(
|
|
58
58
|
handler, data_form_studio, data_original
|
|
@@ -116,11 +116,10 @@ def make_training_files(
|
|
|
116
116
|
training_files.append(training_file)
|
|
117
117
|
|
|
118
118
|
if handler.has_flows():
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
119
|
+
diff_flows = data_handler.create_new_flows_from_diff(
|
|
120
|
+
data_form_studio.get_flows().underlying_flows,
|
|
121
|
+
data_original.get_flows().underlying_flows,
|
|
122
122
|
)
|
|
123
|
-
diff_flows = diff.create_new_flows_from_diff()
|
|
124
123
|
tmp_dir = get_temp_dir_name()
|
|
125
124
|
training_file = Path(tmp_dir, "flows.yml")
|
|
126
125
|
YamlFlowsWriter.dump(diff_flows, training_file)
|
rasa/studio/upload.py
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
import base64
|
|
3
|
-
import
|
|
4
|
-
from typing import Dict, Iterable, List, Set, Text, Tuple, Union
|
|
3
|
+
import sys
|
|
4
|
+
from typing import Dict, Iterable, List, Set, Text, Tuple, Union, Any
|
|
5
5
|
|
|
6
|
+
import questionary
|
|
6
7
|
import requests
|
|
8
|
+
import structlog
|
|
7
9
|
|
|
8
10
|
import rasa.cli.telemetry
|
|
9
11
|
import rasa.cli.utils
|
|
@@ -11,16 +13,19 @@ import rasa.shared.utils.cli
|
|
|
11
13
|
import rasa.shared.utils.io
|
|
12
14
|
from rasa.shared.constants import (
|
|
13
15
|
DEFAULT_DOMAIN_PATHS,
|
|
16
|
+
DEFAULT_CONFIG_PATH,
|
|
14
17
|
)
|
|
15
18
|
from rasa.shared.core.flows.yaml_flows_io import YamlFlowsWriter
|
|
16
19
|
from rasa.shared.exceptions import RasaException
|
|
17
20
|
from rasa.shared.importers.importer import TrainingDataImporter, FlowSyncImporter
|
|
18
21
|
from rasa.shared.nlu.training_data.formats.rasa_yaml import RasaYAMLWriter
|
|
19
|
-
from rasa.shared.utils.yaml import dump_obj_as_yaml_to_string
|
|
22
|
+
from rasa.shared.utils.yaml import dump_obj_as_yaml_to_string, read_yaml_file
|
|
23
|
+
from rasa.studio import results_logger
|
|
20
24
|
from rasa.studio.auth import KeycloakTokenReader
|
|
21
25
|
from rasa.studio.config import StudioConfig
|
|
26
|
+
from rasa.studio.results_logger import StudioResult, with_studio_error_handler
|
|
22
27
|
|
|
23
|
-
|
|
28
|
+
structlogger = structlog.get_logger()
|
|
24
29
|
|
|
25
30
|
|
|
26
31
|
def _get_selected_entities_and_intents(
|
|
@@ -32,37 +37,59 @@ def _get_selected_entities_and_intents(
|
|
|
32
37
|
|
|
33
38
|
if entities is None or len(entities) == 0:
|
|
34
39
|
entities = entities_from_files
|
|
35
|
-
|
|
40
|
+
structlogger.info(
|
|
41
|
+
"rasa.studio.upload.entities_empty",
|
|
42
|
+
event_info="No entities specified. Using all entities from files.",
|
|
43
|
+
)
|
|
36
44
|
|
|
37
45
|
intents = args.intents
|
|
38
46
|
|
|
39
47
|
if intents is None or len(intents) == 0:
|
|
40
48
|
intents = intents_from_files
|
|
41
|
-
|
|
49
|
+
structlogger.info(
|
|
50
|
+
"rasa.studio.upload.intents_empty",
|
|
51
|
+
event_info="No intents specified. Using all intents from files.",
|
|
52
|
+
)
|
|
42
53
|
|
|
43
54
|
return list(entities), list(intents)
|
|
44
55
|
|
|
45
56
|
|
|
46
57
|
def handle_upload(args: argparse.Namespace) -> None:
|
|
47
58
|
"""Uploads primitives to rasa studio."""
|
|
48
|
-
assistant_name = args.assistant_name[0]
|
|
49
59
|
endpoint = StudioConfig.read_config().studio_url
|
|
50
60
|
if not endpoint:
|
|
51
61
|
rasa.shared.utils.cli.print_error_and_exit(
|
|
52
62
|
"No GraphQL endpoint found in config. Please run `rasa studio config`."
|
|
53
63
|
)
|
|
54
64
|
else:
|
|
55
|
-
|
|
65
|
+
structlogger.info(
|
|
66
|
+
"rasa.studio.upload.loading_data", event_info="Loading data..."
|
|
67
|
+
)
|
|
56
68
|
|
|
57
69
|
args.domain = rasa.cli.utils.get_validated_path(
|
|
58
70
|
args.domain, "domain", DEFAULT_DOMAIN_PATHS
|
|
59
71
|
)
|
|
60
72
|
|
|
73
|
+
args.config = rasa.cli.utils.get_validated_path(
|
|
74
|
+
args.config, "config", DEFAULT_CONFIG_PATH
|
|
75
|
+
)
|
|
76
|
+
|
|
61
77
|
# check safely if args.calm is set and not fail if not
|
|
62
78
|
if hasattr(args, "calm") and args.calm:
|
|
63
|
-
upload_calm_assistant(args,
|
|
79
|
+
upload_calm_assistant(args, endpoint)
|
|
64
80
|
else:
|
|
65
|
-
upload_nlu_assistant(args,
|
|
81
|
+
upload_nlu_assistant(args, endpoint)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
config_keys = [
|
|
85
|
+
"recipe",
|
|
86
|
+
"language",
|
|
87
|
+
"pipeline",
|
|
88
|
+
"llm",
|
|
89
|
+
"policies",
|
|
90
|
+
"model_name",
|
|
91
|
+
"assistant_id",
|
|
92
|
+
]
|
|
66
93
|
|
|
67
94
|
|
|
68
95
|
def extract_values(data: Dict, keys: List[Text]) -> Dict:
|
|
@@ -70,9 +97,36 @@ def extract_values(data: Dict, keys: List[Text]) -> Dict:
|
|
|
70
97
|
return {key: data.get(key) for key in keys if data.get(key)}
|
|
71
98
|
|
|
72
99
|
|
|
73
|
-
def
|
|
74
|
-
|
|
75
|
-
|
|
100
|
+
def _get_assistant_name(config: Dict[Text, Any]) -> str:
|
|
101
|
+
config_assistant_id = config.get("assistant_id", "")
|
|
102
|
+
assistant_name = questionary.text(
|
|
103
|
+
"Please provide the assistant name", default=config_assistant_id
|
|
104
|
+
).ask()
|
|
105
|
+
if not assistant_name:
|
|
106
|
+
structlogger.error(
|
|
107
|
+
"rasa.studio.upload.assistant_name_empty",
|
|
108
|
+
event_info="Assistant name cannot be empty.",
|
|
109
|
+
)
|
|
110
|
+
sys.exit(1)
|
|
111
|
+
|
|
112
|
+
# if assistant_name exists and different from config assistant_id,
|
|
113
|
+
# notify user and upload with new assistant_name
|
|
114
|
+
same = assistant_name == config_assistant_id
|
|
115
|
+
if not same and config_assistant_id != "":
|
|
116
|
+
structlogger.info(
|
|
117
|
+
"rasa.studio.upload.assistant_name_mismatch",
|
|
118
|
+
event_info=(
|
|
119
|
+
f"Assistant name '{assistant_name}' is different"
|
|
120
|
+
f" from the one in the config file: '{config_assistant_id}'."
|
|
121
|
+
),
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
structlogger.info(f"Uploading assistant with the name '{assistant_name}'.")
|
|
125
|
+
return assistant_name
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@with_studio_error_handler
|
|
129
|
+
def upload_calm_assistant(args: argparse.Namespace, endpoint: str) -> StudioResult:
|
|
76
130
|
"""Uploads the CALM assistant data to Rasa Studio.
|
|
77
131
|
|
|
78
132
|
Args:
|
|
@@ -82,101 +136,92 @@ def upload_calm_assistant(
|
|
|
82
136
|
- flows: The path to the flows
|
|
83
137
|
- endpoints: The path to the endpoints
|
|
84
138
|
- config: The path to the config
|
|
85
|
-
assistant_name: The name of the assistant
|
|
86
139
|
endpoint: The studio endpoint
|
|
87
140
|
Returns:
|
|
88
141
|
None
|
|
89
142
|
"""
|
|
90
|
-
|
|
143
|
+
structlogger.info(
|
|
144
|
+
"rasa.studio.upload.loading_data", event_info="Parsing CALM assistant data..."
|
|
145
|
+
)
|
|
91
146
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
)
|
|
147
|
+
importer = TrainingDataImporter.load_from_dict(
|
|
148
|
+
domain_path=args.domain,
|
|
149
|
+
config_path=args.config,
|
|
150
|
+
)
|
|
97
151
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
training_data_paths.append(args.flows)
|
|
129
|
-
elif isinstance(training_data_paths, str):
|
|
152
|
+
# Prepare config and domain
|
|
153
|
+
config = importer.get_config()
|
|
154
|
+
domain_from_files = importer.get_domain().as_dict()
|
|
155
|
+
endpoints_from_files = read_yaml_file(args.endpoints)
|
|
156
|
+
config_from_files = read_yaml_file(args.config)
|
|
157
|
+
|
|
158
|
+
# Extract domain and config values
|
|
159
|
+
domain_keys = [
|
|
160
|
+
"version",
|
|
161
|
+
"actions",
|
|
162
|
+
"responses",
|
|
163
|
+
"slots",
|
|
164
|
+
"intents",
|
|
165
|
+
"entities",
|
|
166
|
+
"forms",
|
|
167
|
+
"session_config",
|
|
168
|
+
]
|
|
169
|
+
|
|
170
|
+
domain = extract_values(domain_from_files, domain_keys)
|
|
171
|
+
|
|
172
|
+
assistant_name = _get_assistant_name(config)
|
|
173
|
+
|
|
174
|
+
training_data_paths = args.data
|
|
175
|
+
|
|
176
|
+
if isinstance(training_data_paths, list):
|
|
177
|
+
training_data_paths.append(args.flows)
|
|
178
|
+
elif isinstance(training_data_paths, str):
|
|
179
|
+
if isinstance(args.flows, list):
|
|
180
|
+
training_data_paths = [training_data_paths] + args.flows
|
|
181
|
+
elif isinstance(args.flows, str):
|
|
130
182
|
training_data_paths = [training_data_paths, args.flows]
|
|
183
|
+
else:
|
|
184
|
+
raise RasaException("Invalid flows path")
|
|
131
185
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
user_flows = flow_importer.get_flows().user_flows
|
|
138
|
-
flows = list(user_flows)
|
|
139
|
-
|
|
140
|
-
# We instantiate the TrainingDataImporter again on purpose to avoid
|
|
141
|
-
# adding patterns to domain's actions. More info https://t.ly/W8uuc
|
|
142
|
-
nlu_importer = TrainingDataImporter.load_from_dict(
|
|
143
|
-
domain_path=args.domain, training_data_paths=args.data
|
|
144
|
-
)
|
|
145
|
-
nlu_data = nlu_importer.get_nlu_data()
|
|
186
|
+
# Prepare flows
|
|
187
|
+
flow_importer = FlowSyncImporter.load_from_dict(
|
|
188
|
+
training_data_paths=training_data_paths
|
|
189
|
+
)
|
|
146
190
|
|
|
147
|
-
|
|
191
|
+
user_flows = flow_importer.get_flows().user_flows
|
|
192
|
+
flows = list(user_flows)
|
|
148
193
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
194
|
+
# We instantiate the TrainingDataImporter again on purpose to avoid
|
|
195
|
+
# adding patterns to domain's actions. More info https://t.ly/W8uuc
|
|
196
|
+
nlu_importer = TrainingDataImporter.load_from_dict(
|
|
197
|
+
domain_path=args.domain, training_data_paths=args.data
|
|
198
|
+
)
|
|
199
|
+
nlu_data = nlu_importer.get_nlu_data()
|
|
152
200
|
|
|
153
|
-
|
|
201
|
+
intents_from_files = nlu_data.intents
|
|
154
202
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
flows_yaml=YamlFlowsWriter().dumps(flows),
|
|
159
|
-
domain_yaml=dump_obj_as_yaml_to_string(domain),
|
|
160
|
-
config_yaml=dump_obj_as_yaml_to_string(config),
|
|
161
|
-
nlu_yaml=nlu_examples_yaml,
|
|
162
|
-
)
|
|
203
|
+
nlu_examples = nlu_data.filter_training_examples(
|
|
204
|
+
lambda ex: ex.get("intent") in intents_from_files
|
|
205
|
+
)
|
|
163
206
|
|
|
164
|
-
|
|
165
|
-
response, status = make_request(endpoint, graphql_req)
|
|
207
|
+
nlu_examples_yaml = RasaYAMLWriter().dumps(nlu_examples)
|
|
166
208
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
209
|
+
# Build GraphQL request
|
|
210
|
+
graphql_req = build_import_request(
|
|
211
|
+
assistant_name,
|
|
212
|
+
flows_yaml=YamlFlowsWriter().dumps(flows),
|
|
213
|
+
domain_yaml=dump_obj_as_yaml_to_string(domain),
|
|
214
|
+
config_yaml=dump_obj_as_yaml_to_string(config_from_files),
|
|
215
|
+
endpoints=dump_obj_as_yaml_to_string(endpoints_from_files),
|
|
216
|
+
nlu_yaml=nlu_examples_yaml,
|
|
217
|
+
)
|
|
172
218
|
|
|
173
|
-
|
|
174
|
-
|
|
219
|
+
structlogger.info("Uploading to Rasa Studio...")
|
|
220
|
+
return make_request(endpoint, graphql_req)
|
|
175
221
|
|
|
176
222
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
) -> None:
|
|
223
|
+
@with_studio_error_handler
|
|
224
|
+
def upload_nlu_assistant(args: argparse.Namespace, endpoint: str) -> StudioResult:
|
|
180
225
|
"""Uploads the classic (dm1) assistant data to Rasa Studio.
|
|
181
226
|
|
|
182
227
|
Args:
|
|
@@ -185,14 +230,13 @@ def upload_nlu_assistant(
|
|
|
185
230
|
- domain: The path to the domain
|
|
186
231
|
- intents: The intents to upload
|
|
187
232
|
- entities: The entities to upload
|
|
188
|
-
assistant_name: The name of the assistant
|
|
189
233
|
endpoint: The studio endpoint
|
|
190
234
|
Returns:
|
|
191
235
|
None
|
|
192
236
|
"""
|
|
193
|
-
|
|
237
|
+
structlogger.info("Found DM1 assistant data, parsing...")
|
|
194
238
|
importer = TrainingDataImporter.load_from_dict(
|
|
195
|
-
domain_path=args.domain, training_data_paths=args.data
|
|
239
|
+
domain_path=args.domain, training_data_paths=args.data, config_path=args.config
|
|
196
240
|
)
|
|
197
241
|
|
|
198
242
|
intents_from_files = importer.get_nlu_data().intents
|
|
@@ -202,7 +246,12 @@ def upload_nlu_assistant(
|
|
|
202
246
|
args, intents_from_files, entities_from_files
|
|
203
247
|
)
|
|
204
248
|
|
|
205
|
-
|
|
249
|
+
config_from_files = importer.get_config()
|
|
250
|
+
config = extract_values(config_from_files, config_keys)
|
|
251
|
+
|
|
252
|
+
assistant_name = _get_assistant_name(config)
|
|
253
|
+
|
|
254
|
+
structlogger.info("Validating data...")
|
|
206
255
|
_check_for_missing_primitives(
|
|
207
256
|
intents, entities, intents_from_files, entities_from_files
|
|
208
257
|
)
|
|
@@ -219,15 +268,11 @@ def upload_nlu_assistant(
|
|
|
219
268
|
|
|
220
269
|
graphql_req = build_request(assistant_name, nlu_examples_yaml, domain_yaml)
|
|
221
270
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
if status:
|
|
225
|
-
rasa.shared.utils.cli.print_success(response)
|
|
226
|
-
else:
|
|
227
|
-
rasa.shared.utils.cli.print_error(response)
|
|
271
|
+
structlogger.info("Uploading to Rasa Studio...")
|
|
272
|
+
return make_request(endpoint, graphql_req)
|
|
228
273
|
|
|
229
274
|
|
|
230
|
-
def make_request(endpoint: str, graphql_req: Dict) ->
|
|
275
|
+
def make_request(endpoint: str, graphql_req: Dict) -> StudioResult:
|
|
231
276
|
"""Makes a request to the studio endpoint to upload data.
|
|
232
277
|
|
|
233
278
|
Args:
|
|
@@ -235,7 +280,6 @@ def make_request(endpoint: str, graphql_req: Dict) -> Tuple[str, bool]:
|
|
|
235
280
|
graphql_req: The graphql request
|
|
236
281
|
"""
|
|
237
282
|
token = KeycloakTokenReader().get_token()
|
|
238
|
-
|
|
239
283
|
res = requests.post(
|
|
240
284
|
endpoint,
|
|
241
285
|
json=graphql_req,
|
|
@@ -245,30 +289,9 @@ def make_request(endpoint: str, graphql_req: Dict) -> Tuple[str, bool]:
|
|
|
245
289
|
},
|
|
246
290
|
)
|
|
247
291
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
print_errors_from_response(response)
|
|
252
|
-
|
|
253
|
-
if res.status_code != 200:
|
|
254
|
-
return f"Upload failed with status code {res.status_code}", False
|
|
255
|
-
elif _response_has_errors(response):
|
|
256
|
-
return "Error while uploading data!", False
|
|
257
|
-
|
|
258
|
-
return "Upload successful!", True
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
def _response_has_errors(response: Dict) -> bool:
|
|
262
|
-
return (
|
|
263
|
-
"errors" in response
|
|
264
|
-
and isinstance(response["errors"], list)
|
|
265
|
-
and len(response["errors"]) > 0
|
|
266
|
-
)
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
def print_errors_from_response(response: Dict) -> None:
|
|
270
|
-
for error in response["errors"]:
|
|
271
|
-
logger.error(error["message"])
|
|
292
|
+
if results_logger.response_has_errors(res.json()):
|
|
293
|
+
return StudioResult.error(res.json())
|
|
294
|
+
return StudioResult.success("Upload successful")
|
|
272
295
|
|
|
273
296
|
|
|
274
297
|
def _add_missing_entities(
|
|
@@ -278,7 +301,7 @@ def _add_missing_entities(
|
|
|
278
301
|
all_entities.extend(entities)
|
|
279
302
|
for entity in entities_from_intents:
|
|
280
303
|
if entity not in entities:
|
|
281
|
-
|
|
304
|
+
structlogger.warning(
|
|
282
305
|
f"Adding entity '{entity}' to upload since it is used in an intent."
|
|
283
306
|
)
|
|
284
307
|
all_entities.append(entity)
|
|
@@ -290,6 +313,7 @@ def build_import_request(
|
|
|
290
313
|
flows_yaml: str,
|
|
291
314
|
domain_yaml: str,
|
|
292
315
|
config_yaml: str,
|
|
316
|
+
endpoints: str,
|
|
293
317
|
nlu_yaml: str = "",
|
|
294
318
|
) -> Dict:
|
|
295
319
|
# b64encode expects bytes and returns bytes so we need to decode to string
|
|
@@ -297,6 +321,7 @@ def build_import_request(
|
|
|
297
321
|
base64_flows = base64.b64encode(flows_yaml.encode("utf-8")).decode("utf-8")
|
|
298
322
|
base64_config = base64.b64encode(config_yaml.encode("utf-8")).decode("utf-8")
|
|
299
323
|
base64_nlu = base64.b64encode(nlu_yaml.encode("utf-8")).decode("utf-8")
|
|
324
|
+
base64_endpoints = base64.b64encode(endpoints.encode("utf-8")).decode("utf-8")
|
|
300
325
|
|
|
301
326
|
graphql_req = {
|
|
302
327
|
"query": (
|
|
@@ -310,6 +335,7 @@ def build_import_request(
|
|
|
310
335
|
"flows": base64_flows,
|
|
311
336
|
"nlu": base64_nlu,
|
|
312
337
|
"config": base64_config,
|
|
338
|
+
"endpoints": base64_endpoints,
|
|
313
339
|
}
|
|
314
340
|
},
|
|
315
341
|
}
|
|
@@ -347,16 +373,15 @@ def _filter_domain(
|
|
|
347
373
|
entities: List[Union[str, Dict]], intents: List[str], domain_from_files: Dict
|
|
348
374
|
) -> Dict:
|
|
349
375
|
"""Filters the domain to only include the selected entities and intents."""
|
|
350
|
-
|
|
376
|
+
selected_entities = _remove_not_selected_entities(
|
|
377
|
+
entities, domain_from_files.get("entities", [])
|
|
378
|
+
)
|
|
379
|
+
return {
|
|
351
380
|
"version": domain_from_files["version"],
|
|
352
381
|
"intents": intents,
|
|
353
|
-
"entities":
|
|
354
|
-
entities, domain_from_files["entities"]
|
|
355
|
-
),
|
|
382
|
+
"entities": selected_entities,
|
|
356
383
|
}
|
|
357
384
|
|
|
358
|
-
return domain
|
|
359
|
-
|
|
360
385
|
|
|
361
386
|
def _check_for_missing_primitives(
|
|
362
387
|
intents: Iterable[str],
|