rasa-pro 3.13.0.dev3__py3-none-any.whl → 3.13.0.dev7__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/api.py +4 -0
- rasa/cli/arguments/default_arguments.py +13 -1
- rasa/cli/arguments/train.py +2 -0
- rasa/cli/evaluate.py +1 -1
- rasa/cli/export.py +2 -2
- 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/cli/train.py +1 -0
- rasa/constants.py +2 -0
- rasa/core/agent.py +2 -2
- rasa/core/brokers/kafka.py +4 -0
- rasa/core/brokers/pika.py +4 -0
- rasa/core/brokers/sql.py +1 -1
- rasa/core/channels/channel.py +68 -5
- rasa/core/channels/inspector/.eslintrc.cjs +12 -6
- rasa/core/channels/inspector/.prettierrc +5 -0
- rasa/core/channels/inspector/README.md +10 -4
- rasa/core/channels/inspector/dist/assets/{arc-c7691751.js → arc-c4b064fc.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-ab99dff7.js → blockDiagram-38ab4fdb-215b5026.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-08c35a6b.js → c4Diagram-3d4e48cf-2b54a0a3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/channel-3730f5fd.js +1 -0
- rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-9e9c71c9.js → classDiagram-70f12bd4-daacea5f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-15e7e2bf.js → classDiagram-v2-f2320105-930d4dc2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/clone-e847561e.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-9c105cb1.js → createText-2e5e7dd3-83c206ba.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-77e89e48.js → edges-e0da2a9e-b0eb01d0.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-7a011646.js → erDiagram-9861fffd-17586500.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-b6f105ac.js → flowDb-956e92f1-be2a1776.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-ce4f18c2.js → flowDiagram-66a62f08-c2120ebd.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-efbbfe00.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-cb5f6da4.js → flowchart-elk-definition-4a651766-a6ab5c48.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-e4d19e28.js → ganttDiagram-c361ad54-ef613457.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-727b1c33.js → gitGraphDiagram-72cf32ee-d59185b3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-6e2ab9a7.js → graph-0f155405.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3862675e-84ec700f.js → index-3862675e-d5f1d1b7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-098a1a24.js → index-47737d3a.js} +162 -149
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-78dda442.js → infoDiagram-f8f76790-b07d141f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-f1cc6dd1.js → journeyDiagram-49397b02-1936d429.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-d98dcd0c.js → layout-dde8d0f3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-838e3d82.js → line-0c2c7ee0.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-eae72406.js → linear-35dd89a4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-c96fd84b.js → mindmap-definition-fc14e90a-56192851.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-c936d4e2.js → pieDiagram-8a3498a8-fc21ed78.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-b338eb8f.js → quadrantDiagram-120e2f19-25e98518.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-c6b6c0d5.js → requirementDiagram-deff3bca-546ff1f5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-b9372e19.js → sankeyDiagram-04a897e0-02d8b82d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-479e0a3f.js → sequenceDiagram-704730f1-3ca5a92e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-fd26eebc.js → stateDiagram-587899a1-128ea07c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-3233e0ae.js → stateDiagram-v2-d93cdb3a-95f290af.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-1fdd392b.js → styles-6aaf32cf-4984898a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-6d7bfa1b.js → styles-9a916d00-1bf266ba.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-f86aab11.js → styles-c10674c1-60521c63.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-e3e49d7a.js → svgDrawCommon-08f97a94-a25b6e12.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-6fe08b4d.js → timeline-definition-85554ec2-0fc086bf.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-c2e06fd6.js → xychartDiagram-e933f94c-44ee592e.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +1 -1
- rasa/core/channels/inspector/package.json +3 -1
- rasa/core/channels/inspector/src/App.tsx +92 -90
- rasa/core/channels/inspector/src/components/Chat.tsx +61 -36
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +40 -43
- rasa/core/channels/inspector/src/components/DialogueInformation.tsx +57 -57
- rasa/core/channels/inspector/src/components/DialogueStack.tsx +36 -27
- rasa/core/channels/inspector/src/components/ExpandIcon.tsx +4 -4
- rasa/core/channels/inspector/src/components/FullscreenButton.tsx +7 -7
- rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +28 -12
- rasa/core/channels/inspector/src/components/NoActiveFlow.tsx +9 -9
- rasa/core/channels/inspector/src/components/RasaLogo.tsx +5 -5
- rasa/core/channels/inspector/src/components/RecruitmentPanel.tsx +55 -60
- rasa/core/channels/inspector/src/components/SaraDiagrams.tsx +5 -5
- rasa/core/channels/inspector/src/components/Slots.tsx +22 -22
- rasa/core/channels/inspector/src/components/Welcome.tsx +28 -31
- rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +245 -0
- rasa/core/channels/inspector/src/helpers/audio/microphone-processor.js +12 -0
- rasa/core/channels/inspector/src/helpers/audio/playback-processor.js +36 -0
- rasa/core/channels/inspector/src/helpers/conversation.ts +16 -0
- rasa/core/channels/inspector/src/helpers/formatters.test.ts +181 -181
- rasa/core/channels/inspector/src/helpers/formatters.ts +111 -111
- rasa/core/channels/inspector/src/helpers/utils.ts +78 -61
- rasa/core/channels/inspector/src/main.tsx +8 -8
- rasa/core/channels/inspector/src/theme/Button/Button.ts +8 -8
- rasa/core/channels/inspector/src/theme/Heading/Heading.ts +7 -7
- rasa/core/channels/inspector/src/theme/Input/Input.ts +9 -9
- rasa/core/channels/inspector/src/theme/Link/Link.ts +6 -6
- rasa/core/channels/inspector/src/theme/Modal/Modal.ts +13 -13
- rasa/core/channels/inspector/src/theme/Table/Table.tsx +10 -10
- rasa/core/channels/inspector/src/theme/Tooltip/Tooltip.ts +5 -5
- rasa/core/channels/inspector/src/theme/base/breakpoints.ts +7 -7
- rasa/core/channels/inspector/src/theme/base/colors.ts +64 -64
- rasa/core/channels/inspector/src/theme/base/fonts/fontFaces.css +21 -18
- rasa/core/channels/inspector/src/theme/base/radii.ts +8 -8
- rasa/core/channels/inspector/src/theme/base/shadows.ts +5 -5
- rasa/core/channels/inspector/src/theme/base/sizes.ts +5 -5
- rasa/core/channels/inspector/src/theme/base/space.ts +12 -12
- rasa/core/channels/inspector/src/theme/base/styles.ts +5 -5
- rasa/core/channels/inspector/src/theme/base/typography.ts +12 -12
- rasa/core/channels/inspector/src/theme/base/zIndices.ts +3 -3
- rasa/core/channels/inspector/src/theme/index.ts +38 -38
- rasa/core/channels/inspector/src/types.ts +56 -50
- rasa/core/channels/inspector/yarn.lock +5 -0
- rasa/core/channels/voice_ready/audiocodes.py +75 -32
- 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/evaluation/marker_tracker_loader.py +1 -1
- rasa/core/exporter.py +1 -1
- rasa/core/lock_store.py +151 -60
- rasa/core/nlg/contextual_response_rephraser.py +4 -2
- rasa/core/nlg/summarize.py +1 -1
- rasa/core/persistor.py +55 -20
- rasa/core/policies/enterprise_search_policy.py +7 -4
- rasa/core/policies/intentless_policy.py +15 -9
- rasa/core/processor.py +2 -2
- rasa/core/run.py +7 -2
- rasa/core/{auth_retry_tracker_store.py → tracker_stores/auth_retry_tracker_store.py} +5 -1
- rasa/core/tracker_stores/dynamo_tracker_store.py +218 -0
- rasa/core/tracker_stores/mongo_tracker_store.py +206 -0
- rasa/core/tracker_stores/redis_tracker_store.py +219 -0
- rasa/core/tracker_stores/sql_tracker_store.py +555 -0
- rasa/core/tracker_stores/tracker_store.py +805 -0
- rasa/core/utils.py +6 -0
- rasa/dialogue_understanding/coexistence/llm_based_router.py +8 -3
- rasa/dialogue_understanding/commands/clarify_command.py +2 -2
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +2 -2
- rasa/dialogue_understanding/generator/constants.py +2 -2
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +1 -1
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +33 -12
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +2 -2
- rasa/dialogue_understanding_test/du_test_case.py +16 -8
- rasa/hooks.py +2 -2
- rasa/keys +1 -0
- rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +4 -2
- rasa/model_manager/config.py +3 -1
- rasa/model_manager/model_api.py +1 -2
- rasa/model_manager/runner_service.py +8 -4
- rasa/model_manager/trainer_service.py +1 -0
- rasa/model_training.py +12 -3
- rasa/nlu/extractors/crf_entity_extractor.py +66 -16
- rasa/plugin.py +1 -4
- rasa/server.py +6 -2
- rasa/shared/constants.py +4 -0
- rasa/shared/core/domain.py +165 -11
- rasa/shared/core/events.py +68 -2
- 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/_configs/azure_openai_client_config.py +4 -0
- rasa/shared/providers/_configs/openai_client_config.py +4 -0
- rasa/shared/providers/_utils.py +83 -0
- rasa/shared/providers/embedding/_base_litellm_embedding_client.py +3 -0
- rasa/shared/providers/llm/_base_litellm_client.py +11 -5
- 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/__init__.py +0 -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/telemetry.py +2 -2
- rasa/tracing/config.py +1 -1
- rasa/tracing/instrumentation/attribute_extractors.py +1 -1
- rasa/tracing/instrumentation/instrumentation.py +1 -1
- rasa/utils/common.py +36 -0
- rasa/utils/endpoints.py +22 -1
- rasa/utils/licensing.py +2 -3
- rasa/validator.py +1 -2
- rasa/version.py +1 -1
- {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev7.dist-info}/METADATA +10 -10
- {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev7.dist-info}/RECORD +213 -210
- 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/core/channels/inspector/src/helpers/audiostream.ts +0 -191
- rasa/core/tracker_store.py +0 -1792
- 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 → core/tracker_stores}/__init__.py +0 -0
- {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev7.dist-info}/NOTICE +0 -0
- {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev7.dist-info}/WHEEL +0 -0
- {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev7.dist-info}/entry_points.txt +0 -0
rasa/shared/core/flows/flow.py
CHANGED
|
@@ -38,6 +38,7 @@ from rasa.shared.core.flows.flow_step_sequence import FlowStepSequence
|
|
|
38
38
|
from rasa.shared.core.flows.nlu_trigger import NLUTriggers
|
|
39
39
|
from rasa.shared.core.flows.steps import (
|
|
40
40
|
ActionFlowStep,
|
|
41
|
+
CallFlowStep,
|
|
41
42
|
CollectInformationFlowStep,
|
|
42
43
|
EndFlowStep,
|
|
43
44
|
StartFlowStep,
|
|
@@ -52,6 +53,8 @@ from rasa.shared.core.slots import Slot
|
|
|
52
53
|
|
|
53
54
|
structlogger = structlog.get_logger()
|
|
54
55
|
|
|
56
|
+
DEFAULT_RUN_PATTERN_COMPLETED = True
|
|
57
|
+
|
|
55
58
|
|
|
56
59
|
class FlowLanguageTranslation(BaseModel):
|
|
57
60
|
"""Represents the translation of the flow properties in a specific language."""
|
|
@@ -60,8 +63,15 @@ class FlowLanguageTranslation(BaseModel):
|
|
|
60
63
|
"""The human-readable name of the flow."""
|
|
61
64
|
|
|
62
65
|
class Config:
|
|
66
|
+
"""Config for the FlowLanguageTranslation class."""
|
|
67
|
+
|
|
63
68
|
extra = "ignore"
|
|
64
69
|
|
|
70
|
+
def __eq__(self, other: object) -> bool:
|
|
71
|
+
if isinstance(other, FlowLanguageTranslation):
|
|
72
|
+
return self.name == other.name
|
|
73
|
+
return False
|
|
74
|
+
|
|
65
75
|
|
|
66
76
|
@dataclass
|
|
67
77
|
class Flow:
|
|
@@ -89,8 +99,25 @@ class Flow:
|
|
|
89
99
|
"""The path to the file where the flow is stored."""
|
|
90
100
|
persisted_slots: List[str] = field(default_factory=list)
|
|
91
101
|
"""The list of slots that should be persisted after the flow ends."""
|
|
92
|
-
run_pattern_completed: bool =
|
|
102
|
+
run_pattern_completed: bool = DEFAULT_RUN_PATTERN_COMPLETED
|
|
93
103
|
"""Whether the pattern_completed flow should be run after the flow ends."""
|
|
104
|
+
metadata: Dict[Text, Any] = field(default_factory=dict)
|
|
105
|
+
|
|
106
|
+
def __eq__(self, other: object) -> bool:
|
|
107
|
+
if isinstance(other, Flow):
|
|
108
|
+
return (
|
|
109
|
+
self.id == other.id
|
|
110
|
+
and self.custom_name == other.custom_name
|
|
111
|
+
and self.description == other.description
|
|
112
|
+
and self.translation == other.translation
|
|
113
|
+
and self.guard_condition == other.guard_condition
|
|
114
|
+
and self.step_sequence == other.step_sequence
|
|
115
|
+
and self.nlu_triggers == other.nlu_triggers
|
|
116
|
+
and self.always_include_in_prompt == other.always_include_in_prompt
|
|
117
|
+
and self.persisted_slots == other.persisted_slots
|
|
118
|
+
and self.run_pattern_completed == other.run_pattern_completed
|
|
119
|
+
)
|
|
120
|
+
return False
|
|
94
121
|
|
|
95
122
|
@staticmethod
|
|
96
123
|
def from_json(
|
|
@@ -129,7 +156,9 @@ class Flow:
|
|
|
129
156
|
# data. When the model is trained, take the provided file_path.
|
|
130
157
|
file_path=data.get(KEY_FILE_PATH) if KEY_FILE_PATH in data else file_path,
|
|
131
158
|
persisted_slots=data.get(KEY_PERSISTED_SLOTS, []),
|
|
132
|
-
run_pattern_completed=data.get(
|
|
159
|
+
run_pattern_completed=data.get(
|
|
160
|
+
KEY_RUN_PATTERN_COMPLETED, DEFAULT_RUN_PATTERN_COMPLETED
|
|
161
|
+
),
|
|
133
162
|
translation=extract_translations(
|
|
134
163
|
translation_data=data.get(KEY_TRANSLATION, {})
|
|
135
164
|
),
|
|
@@ -208,7 +237,7 @@ class Flow:
|
|
|
208
237
|
if self.persisted_slots:
|
|
209
238
|
data[KEY_PERSISTED_SLOTS] = self.persisted_slots
|
|
210
239
|
if self.run_pattern_completed is not None:
|
|
211
|
-
data[
|
|
240
|
+
data[KEY_RUN_PATTERN_COMPLETED] = self.run_pattern_completed
|
|
212
241
|
if self.translation:
|
|
213
242
|
data[KEY_TRANSLATION] = {
|
|
214
243
|
language_code: translation.dict()
|
|
@@ -231,9 +260,9 @@ class Flow:
|
|
|
231
260
|
return translation.name if translation else None
|
|
232
261
|
|
|
233
262
|
def readable_name(self, language: Optional[Language] = None) -> str:
|
|
234
|
-
"""
|
|
235
|
-
|
|
236
|
-
falls back to the flow's name, and finally the flow's ID.
|
|
263
|
+
"""Returns the flow's name in the specified language if available.
|
|
264
|
+
|
|
265
|
+
Otherwise falls back to the flow's name, and finally the flow's ID.
|
|
237
266
|
|
|
238
267
|
Args:
|
|
239
268
|
language: Preferred language code.
|
|
@@ -466,161 +495,156 @@ class Flow:
|
|
|
466
495
|
and a set of visited step IDs to prevent revisiting steps.
|
|
467
496
|
It calls `go_over_steps` to recursively explore and fill the paths list.
|
|
468
497
|
"""
|
|
469
|
-
|
|
470
|
-
|
|
498
|
+
all_paths = FlowPathsList(self.id, paths=[])
|
|
499
|
+
start_step: FlowStep = self.first_step_in_flow()
|
|
471
500
|
current_path: FlowPath = FlowPath(flow=self.id, nodes=[])
|
|
472
|
-
|
|
501
|
+
visited_step_ids: Set[str] = set()
|
|
473
502
|
|
|
474
|
-
self._go_over_steps(
|
|
475
|
-
|
|
476
|
-
if not flow_paths_list.is_path_part_of_list(current_path):
|
|
477
|
-
flow_paths_list.paths.append(copy.deepcopy(current_path))
|
|
503
|
+
self._go_over_steps(start_step, current_path, all_paths, visited_step_ids)
|
|
478
504
|
|
|
479
505
|
structlogger.debug(
|
|
480
506
|
"shared.core.flows.flow.extract_all_paths",
|
|
481
507
|
comment="Extraction complete",
|
|
482
|
-
number_of_paths=len(
|
|
508
|
+
number_of_paths=len(all_paths.paths),
|
|
483
509
|
flow_name=self.name,
|
|
484
510
|
)
|
|
485
|
-
return
|
|
511
|
+
return all_paths
|
|
486
512
|
|
|
487
513
|
def _go_over_steps(
|
|
488
514
|
self,
|
|
489
|
-
|
|
515
|
+
current_step: FlowStep,
|
|
490
516
|
current_path: FlowPath,
|
|
491
|
-
|
|
492
|
-
|
|
517
|
+
all_paths: FlowPathsList,
|
|
518
|
+
visited_step_ids: Set[str],
|
|
493
519
|
) -> None:
|
|
494
520
|
"""Processes the flow steps recursively.
|
|
495
521
|
|
|
496
|
-
Either following direct step IDs or handling conditions, and adds complete
|
|
497
|
-
paths to the collected_paths.
|
|
498
|
-
|
|
499
522
|
Args:
|
|
500
|
-
|
|
523
|
+
current_step: The current step being processed.
|
|
501
524
|
current_path: The current path being constructed.
|
|
502
|
-
|
|
503
|
-
|
|
525
|
+
all_paths: The list where completed paths are added.
|
|
526
|
+
visited_step_ids: A set of steps that have been visited to avoid cycles.
|
|
504
527
|
|
|
505
528
|
Returns:
|
|
506
|
-
None: This function modifies
|
|
529
|
+
None: This function modifies all_paths in place by appending new paths
|
|
507
530
|
as they are found.
|
|
508
531
|
"""
|
|
509
|
-
#
|
|
510
|
-
#
|
|
511
|
-
#
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
# We only create new path nodes for ActionFlowStep and
|
|
526
|
-
# CollectInformationFlowStep because these are externally visible
|
|
527
|
-
# changes in the assistant's behaviour (trackable in the e2e tests).
|
|
528
|
-
# For other flow steps, we only follow their links.
|
|
529
|
-
# We decided to ignore calls to other flows in our coverage analysis.
|
|
530
|
-
if not isinstance(step, (CollectInformationFlowStep, ActionFlowStep)):
|
|
531
|
-
self._handle_links(
|
|
532
|
-
step.next.links,
|
|
533
|
-
current_path,
|
|
534
|
-
completed_paths,
|
|
535
|
-
step_ids_visited,
|
|
536
|
-
)
|
|
537
|
-
continue
|
|
538
|
-
|
|
539
|
-
# 2. Check if already visited this custom step id
|
|
540
|
-
# in order to keep track of loops
|
|
541
|
-
if step.custom_id is not None and step.custom_id in step_ids_visited:
|
|
542
|
-
if not completed_paths.is_path_part_of_list(current_path):
|
|
543
|
-
completed_paths.paths.append(copy.deepcopy(current_path))
|
|
544
|
-
return # Stop traversing this path if we've revisited a step
|
|
545
|
-
elif step.custom_id is not None:
|
|
546
|
-
step_ids_visited.add(step.custom_id)
|
|
547
|
-
|
|
548
|
-
# 3. Append step info to the path
|
|
549
|
-
current_path.nodes.append(
|
|
550
|
-
PathNode(
|
|
551
|
-
flow=current_path.flow,
|
|
552
|
-
step_id=step.id,
|
|
553
|
-
lines=step.metadata["line_numbers"],
|
|
554
|
-
)
|
|
532
|
+
# Check if the step is relevant for testable_paths extraction.
|
|
533
|
+
# We only create new path nodes for ActionFlowStep, CallFlowStep and
|
|
534
|
+
# CollectInformationFlowStep because these are externally visible
|
|
535
|
+
# changes in the assistant's behaviour (trackable in the e2e tests).
|
|
536
|
+
# For other flow steps, we only follow their links.
|
|
537
|
+
# We decided to ignore calls to other flows in our coverage analysis.
|
|
538
|
+
should_add_node = isinstance(
|
|
539
|
+
current_step, (CollectInformationFlowStep, ActionFlowStep, CallFlowStep)
|
|
540
|
+
)
|
|
541
|
+
if should_add_node:
|
|
542
|
+
# Add current step to the current path that is being constructed.
|
|
543
|
+
current_path.nodes.append(
|
|
544
|
+
PathNode(
|
|
545
|
+
flow=current_path.flow,
|
|
546
|
+
step_id=current_step.id,
|
|
547
|
+
lines=current_step.metadata["line_numbers"],
|
|
555
548
|
)
|
|
549
|
+
)
|
|
556
550
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
)
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
551
|
+
if current_step.id in visited_step_ids or self.is_end_of_path(current_step):
|
|
552
|
+
# Found a cycle, or reached an end step, do not proceed further.
|
|
553
|
+
all_paths.paths.append(copy.deepcopy(current_path))
|
|
554
|
+
# Remove the last node from the path if it was added.
|
|
555
|
+
if should_add_node:
|
|
556
|
+
current_path.nodes.pop()
|
|
557
|
+
return
|
|
558
|
+
|
|
559
|
+
# Mark current step as visited in this path.
|
|
560
|
+
visited_step_ids.add(current_step.id)
|
|
561
|
+
|
|
562
|
+
# Iterate over all links of the current step.
|
|
563
|
+
for link in current_step.next.links:
|
|
564
|
+
self._handle_link(
|
|
565
|
+
current_path,
|
|
566
|
+
all_paths,
|
|
567
|
+
visited_step_ids,
|
|
568
|
+
link,
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
# Backtrack the current step and remove it from the path.
|
|
572
|
+
visited_step_ids.remove(current_step.id)
|
|
573
573
|
|
|
574
|
-
|
|
574
|
+
# Remove the last node from the path if it was added.
|
|
575
|
+
if should_add_node:
|
|
576
|
+
current_path.nodes.pop()
|
|
577
|
+
|
|
578
|
+
def _handle_link(
|
|
575
579
|
self,
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
+
current_path: FlowPath,
|
|
581
|
+
all_paths: FlowPathsList,
|
|
582
|
+
visited_step_ids: Set[str],
|
|
583
|
+
link: FlowStepLink,
|
|
580
584
|
) -> None:
|
|
581
|
-
"""
|
|
582
|
-
|
|
583
|
-
Potentially recursively calling itself to handle conditional paths and
|
|
584
|
-
branching.
|
|
585
|
+
"""Handles the next step in a flow.
|
|
585
586
|
|
|
586
587
|
Args:
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
to avoid loops.
|
|
588
|
+
current_path: The current path being constructed.
|
|
589
|
+
all_paths: The list where completed paths are added.
|
|
590
|
+
visited_step_ids: A set of steps that have been visited to avoid cycles.
|
|
591
|
+
link: The link to be followed.
|
|
592
592
|
|
|
593
593
|
Returns:
|
|
594
|
-
None:
|
|
595
|
-
as they are
|
|
594
|
+
None: This function modifies all_paths in place by appending new paths
|
|
595
|
+
as they are found.
|
|
596
596
|
"""
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
if isinstance(link, StaticFlowStepLink):
|
|
602
|
-
# Find this id in the flow steps and restart from there
|
|
603
|
-
for i, step in enumerate(steps):
|
|
604
|
-
if step.id == link.target_step_id:
|
|
605
|
-
self._go_over_steps(
|
|
606
|
-
steps[i:],
|
|
607
|
-
copy.deepcopy(path),
|
|
608
|
-
collected_paths,
|
|
609
|
-
copy.deepcopy(step_ids_visited),
|
|
610
|
-
)
|
|
611
|
-
|
|
612
|
-
# If conditions
|
|
613
|
-
elif isinstance(link, (IfFlowStepLink, ElseFlowStepLink)):
|
|
614
|
-
# Handling conditional paths
|
|
615
|
-
target_steps: Union[str, List[FlowStep]]
|
|
616
|
-
if isinstance(link.target_reference, FlowStepSequence):
|
|
617
|
-
target_steps = link.target_reference.child_steps
|
|
618
|
-
else:
|
|
619
|
-
target_steps = link.target_reference
|
|
620
|
-
|
|
597
|
+
# StaticFlowStepLink is a direct link to the next step.
|
|
598
|
+
if isinstance(link, StaticFlowStepLink):
|
|
599
|
+
# Find the step by its id and continue the path.
|
|
600
|
+
if step := self._get_step_by_step_id(link.target_step_id):
|
|
621
601
|
self._go_over_steps(
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
602
|
+
step,
|
|
603
|
+
current_path,
|
|
604
|
+
all_paths,
|
|
605
|
+
visited_step_ids,
|
|
626
606
|
)
|
|
607
|
+
return
|
|
608
|
+
# IfFlowStepLink and ElseFlowStepLink are conditional links.
|
|
609
|
+
elif isinstance(link, (IfFlowStepLink, ElseFlowStepLink)):
|
|
610
|
+
if isinstance(link.target_reference, FlowStepSequence):
|
|
611
|
+
# If the target is a FlowStepSequence, we need to go over all
|
|
612
|
+
# child steps of the sequence.
|
|
613
|
+
for child_step in link.target_reference.child_steps:
|
|
614
|
+
self._go_over_steps(
|
|
615
|
+
child_step,
|
|
616
|
+
current_path,
|
|
617
|
+
all_paths,
|
|
618
|
+
visited_step_ids,
|
|
619
|
+
)
|
|
620
|
+
return
|
|
621
|
+
else:
|
|
622
|
+
# Find the step by its id and continue the path.
|
|
623
|
+
if step := self._get_step_by_step_id(link.target_reference):
|
|
624
|
+
self._go_over_steps(
|
|
625
|
+
step,
|
|
626
|
+
current_path,
|
|
627
|
+
all_paths,
|
|
628
|
+
visited_step_ids,
|
|
629
|
+
)
|
|
630
|
+
return
|
|
631
|
+
|
|
632
|
+
def is_end_of_path(self, step: FlowStep) -> bool:
|
|
633
|
+
"""Check if there is no path available from the current step."""
|
|
634
|
+
if (
|
|
635
|
+
len(step.next.links) == 1
|
|
636
|
+
and isinstance(step.next.links[0], StaticFlowStepLink)
|
|
637
|
+
and step.next.links[0].target == END_STEP
|
|
638
|
+
):
|
|
639
|
+
return True
|
|
640
|
+
return False
|
|
641
|
+
|
|
642
|
+
def _get_step_by_step_id(
|
|
643
|
+
self,
|
|
644
|
+
step_id: Optional[str],
|
|
645
|
+
) -> Optional[FlowStep]:
|
|
646
|
+
"""Get a step by its id from a list of steps."""
|
|
647
|
+
for step in self.steps:
|
|
648
|
+
if step.id == step_id:
|
|
649
|
+
return step
|
|
650
|
+
return None
|
|
@@ -100,7 +100,9 @@ class FlowStep:
|
|
|
100
100
|
"""Most steps allow linking to the next step. But some don't."""
|
|
101
101
|
return True
|
|
102
102
|
|
|
103
|
-
def as_json(
|
|
103
|
+
def as_json(
|
|
104
|
+
self, step_properties: Optional[Dict[Text, Any]] = None
|
|
105
|
+
) -> Dict[Text, Any]:
|
|
104
106
|
"""Serialize the FlowStep object.
|
|
105
107
|
|
|
106
108
|
Returns:
|
|
@@ -108,10 +110,13 @@ class FlowStep:
|
|
|
108
110
|
"""
|
|
109
111
|
data: Dict[Text, Any] = {"id": self.id}
|
|
110
112
|
|
|
111
|
-
if
|
|
112
|
-
data
|
|
113
|
+
if step_properties:
|
|
114
|
+
data.update(step_properties)
|
|
115
|
+
|
|
113
116
|
if self.description:
|
|
114
117
|
data["description"] = self.description
|
|
118
|
+
if dumped_next := self.next.as_json():
|
|
119
|
+
data["next"] = dumped_next
|
|
115
120
|
if self.metadata:
|
|
116
121
|
data["metadata"] = self.metadata
|
|
117
122
|
return data
|
|
@@ -143,6 +148,17 @@ class FlowStep:
|
|
|
143
148
|
"""Return all the utterances used in this step."""
|
|
144
149
|
return set()
|
|
145
150
|
|
|
151
|
+
def __eq__(self, other: object) -> bool:
|
|
152
|
+
if not isinstance(other, FlowStep):
|
|
153
|
+
return False
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
self.idx == other.idx
|
|
157
|
+
and self.description == other.description
|
|
158
|
+
and self.next == other.next
|
|
159
|
+
and self.flow_id == other.flow_id
|
|
160
|
+
)
|
|
161
|
+
|
|
146
162
|
|
|
147
163
|
@dataclass
|
|
148
164
|
class FlowStepWithFlowReference:
|
|
@@ -74,6 +74,11 @@ class FlowStepLinks:
|
|
|
74
74
|
depth = max(depth, link.depth_in_tree())
|
|
75
75
|
return depth
|
|
76
76
|
|
|
77
|
+
def __eq__(self, other: object) -> bool:
|
|
78
|
+
if isinstance(other, FlowStepLinks):
|
|
79
|
+
return self.links == other.links
|
|
80
|
+
return False
|
|
81
|
+
|
|
77
82
|
|
|
78
83
|
class FlowStepLink:
|
|
79
84
|
"""A flow step link that links two steps in a single flow."""
|
|
@@ -193,6 +198,11 @@ class BranchingFlowStepLink(FlowStepLink):
|
|
|
193
198
|
return depth + 1
|
|
194
199
|
return 1
|
|
195
200
|
|
|
201
|
+
def __eq__(self, other: object) -> bool:
|
|
202
|
+
if isinstance(other, BranchingFlowStepLink):
|
|
203
|
+
return self.target_reference == other.target_reference
|
|
204
|
+
return False
|
|
205
|
+
|
|
196
206
|
|
|
197
207
|
@dataclass
|
|
198
208
|
class IfFlowStepLink(BranchingFlowStepLink):
|
|
@@ -324,3 +334,8 @@ class StaticFlowStepLink(FlowStepLink):
|
|
|
324
334
|
def depth_in_tree(self) -> int:
|
|
325
335
|
"""Returns the depth in the tree."""
|
|
326
336
|
return 0
|
|
337
|
+
|
|
338
|
+
def __eq__(self, other: object) -> bool:
|
|
339
|
+
if isinstance(other, StaticFlowStepLink):
|
|
340
|
+
return self.target_step_id == other.target_step_id
|
|
341
|
+
return False
|
|
@@ -70,3 +70,9 @@ class FlowStepSequence:
|
|
|
70
70
|
def empty(cls) -> FlowStepSequence:
|
|
71
71
|
"""Create an empty FlowStepSequence object."""
|
|
72
72
|
return cls(child_steps=[])
|
|
73
|
+
|
|
74
|
+
def __eq__(self, other: object) -> bool:
|
|
75
|
+
return (
|
|
76
|
+
isinstance(other, FlowStepSequence)
|
|
77
|
+
and self.child_steps == other.child_steps
|
|
78
|
+
)
|
|
@@ -28,6 +28,14 @@ class NLUTrigger:
|
|
|
28
28
|
"""
|
|
29
29
|
return self.intent == intent and confidence >= self.confidence_threshold
|
|
30
30
|
|
|
31
|
+
def __eq__(self, other: object) -> bool:
|
|
32
|
+
if isinstance(other, NLUTrigger):
|
|
33
|
+
return (
|
|
34
|
+
self.intent == other.intent
|
|
35
|
+
and self.confidence_threshold == other.confidence_threshold
|
|
36
|
+
)
|
|
37
|
+
return False
|
|
38
|
+
|
|
31
39
|
|
|
32
40
|
@dataclass
|
|
33
41
|
class NLUTriggers:
|
|
@@ -115,3 +123,8 @@ class NLUTriggers:
|
|
|
115
123
|
trigger_condition.is_triggered(intent, confidence)
|
|
116
124
|
for trigger_condition in self.trigger_conditions
|
|
117
125
|
)
|
|
126
|
+
|
|
127
|
+
def __eq__(self, other: object) -> bool:
|
|
128
|
+
if isinstance(other, NLUTriggers):
|
|
129
|
+
return self.trigger_conditions == other.trigger_conditions
|
|
130
|
+
return False
|
|
@@ -31,15 +31,13 @@ class ActionFlowStep(FlowStep):
|
|
|
31
31
|
**base.__dict__,
|
|
32
32
|
)
|
|
33
33
|
|
|
34
|
-
def as_json(self) -> Dict[Text, Any]:
|
|
34
|
+
def as_json(self) -> Dict[Text, Any]: # type: ignore[override]
|
|
35
35
|
"""Serialize the ActionFlowStep
|
|
36
36
|
|
|
37
37
|
Returns:
|
|
38
38
|
The ActionFlowStep object as serialized data.
|
|
39
39
|
"""
|
|
40
|
-
|
|
41
|
-
data["action"] = self.action
|
|
42
|
-
return data
|
|
40
|
+
return super().as_json(step_properties={"action": self.action})
|
|
43
41
|
|
|
44
42
|
@property
|
|
45
43
|
def default_id_postfix(self) -> str:
|
|
@@ -55,3 +53,8 @@ class ActionFlowStep(FlowStep):
|
|
|
55
53
|
def custom_action(self) -> Optional[str]:
|
|
56
54
|
"""Return all the custom actions used in this step."""
|
|
57
55
|
return self.action if not self.action.startswith(UTTER_PREFIX) else None
|
|
56
|
+
|
|
57
|
+
def __eq__(self, other: object) -> bool:
|
|
58
|
+
if isinstance(other, type(self)):
|
|
59
|
+
return self.action == other.action and super().__eq__(other)
|
|
60
|
+
return False
|
|
@@ -34,15 +34,13 @@ class CallFlowStep(FlowStep):
|
|
|
34
34
|
**base.__dict__,
|
|
35
35
|
)
|
|
36
36
|
|
|
37
|
-
def as_json(self) -> Dict[Text, Any]:
|
|
37
|
+
def as_json(self) -> Dict[Text, Any]: # type: ignore[override]
|
|
38
38
|
"""Returns the flow step as a dictionary.
|
|
39
39
|
|
|
40
40
|
Returns:
|
|
41
41
|
The flow step as a dictionary.
|
|
42
42
|
"""
|
|
43
|
-
|
|
44
|
-
dump["call"] = self.call
|
|
45
|
-
return dump
|
|
43
|
+
return super().as_json(step_properties={"call": self.call})
|
|
46
44
|
|
|
47
45
|
def steps_in_tree(
|
|
48
46
|
self, should_resolve_calls: bool = True
|
|
@@ -62,3 +60,12 @@ class CallFlowStep(FlowStep):
|
|
|
62
60
|
def default_id_postfix(self) -> str:
|
|
63
61
|
"""Returns the default id postfix of the flow step."""
|
|
64
62
|
return f"call_{self.call}"
|
|
63
|
+
|
|
64
|
+
def __eq__(self, other: object) -> bool:
|
|
65
|
+
if isinstance(other, type(self)):
|
|
66
|
+
return (
|
|
67
|
+
self.call == other.call
|
|
68
|
+
and self.called_flow_reference == other.called_flow_reference
|
|
69
|
+
and super().__eq__(other)
|
|
70
|
+
)
|
|
71
|
+
return False
|
|
@@ -7,6 +7,10 @@ from rasa.shared.constants import ACTION_ASK_PREFIX, UTTER_ASK_PREFIX
|
|
|
7
7
|
from rasa.shared.core.flows.flow_step import FlowStep
|
|
8
8
|
from rasa.shared.core.slots import SlotRejection
|
|
9
9
|
|
|
10
|
+
DEFAULT_ASK_BEFORE_FILLING = False
|
|
11
|
+
DEFAULT_RESET_AFTER_FLOW_ENDS = True
|
|
12
|
+
DEFAULT_FORCE_SLOT_FILLING = False
|
|
13
|
+
|
|
10
14
|
|
|
11
15
|
@dataclass
|
|
12
16
|
class CollectInformationFlowStep(FlowStep):
|
|
@@ -20,9 +24,9 @@ class CollectInformationFlowStep(FlowStep):
|
|
|
20
24
|
"""The action that the assistant uses to ask for the slot."""
|
|
21
25
|
rejections: List[SlotRejection]
|
|
22
26
|
"""how the slot value is validated using predicate evaluation."""
|
|
23
|
-
ask_before_filling: bool =
|
|
27
|
+
ask_before_filling: bool = DEFAULT_ASK_BEFORE_FILLING
|
|
24
28
|
"""Whether to always ask the question even if the slot is already filled."""
|
|
25
|
-
reset_after_flow_ends: bool =
|
|
29
|
+
reset_after_flow_ends: bool = DEFAULT_RESET_AFTER_FLOW_ENDS
|
|
26
30
|
"""Whether to reset the slot value at the end of the flow."""
|
|
27
31
|
force_slot_filling: bool = False
|
|
28
32
|
"""Whether to keep only the SetSlot command for the collected slot."""
|
|
@@ -43,7 +47,7 @@ class CollectInformationFlowStep(FlowStep):
|
|
|
43
47
|
base = super().from_json(flow_id, data)
|
|
44
48
|
return CollectInformationFlowStep(
|
|
45
49
|
collect=data["collect"],
|
|
46
|
-
utter=data.get("utter",
|
|
50
|
+
utter=data.get("utter", cls._default_utter(data["collect"])),
|
|
47
51
|
# as of now it is not possible to define a different name for the
|
|
48
52
|
# action, always use the default name 'action_ask_<slot_name>'
|
|
49
53
|
collect_action=f"{ACTION_ASK_PREFIX}{data['collect']}",
|
|
@@ -57,7 +61,11 @@ class CollectInformationFlowStep(FlowStep):
|
|
|
57
61
|
**base.__dict__,
|
|
58
62
|
)
|
|
59
63
|
|
|
60
|
-
|
|
64
|
+
@staticmethod
|
|
65
|
+
def _default_utter(collect: str) -> str:
|
|
66
|
+
return f"{UTTER_ASK_PREFIX}{collect}"
|
|
67
|
+
|
|
68
|
+
def as_json(self) -> Dict[str, Any]: # type: ignore[override]
|
|
61
69
|
"""Serialize the CollectInformationFlowStep object.
|
|
62
70
|
|
|
63
71
|
Returns:
|
|
@@ -70,8 +78,7 @@ class CollectInformationFlowStep(FlowStep):
|
|
|
70
78
|
data["reset_after_flow_ends"] = self.reset_after_flow_ends
|
|
71
79
|
data["rejections"] = [rejection.as_dict() for rejection in self.rejections]
|
|
72
80
|
data["force_slot_filling"] = self.force_slot_filling
|
|
73
|
-
|
|
74
|
-
return data
|
|
81
|
+
return super().as_json(step_properties=data)
|
|
75
82
|
|
|
76
83
|
@property
|
|
77
84
|
def default_id_postfix(self) -> str:
|
|
@@ -82,3 +89,17 @@ class CollectInformationFlowStep(FlowStep):
|
|
|
82
89
|
def utterances(self) -> Set[str]:
|
|
83
90
|
"""Return all the utterances used in this step."""
|
|
84
91
|
return {self.utter} | {r.utter for r in self.rejections}
|
|
92
|
+
|
|
93
|
+
def __eq__(self, other: object) -> bool:
|
|
94
|
+
if isinstance(other, type(self)):
|
|
95
|
+
return (
|
|
96
|
+
self.collect == other.collect
|
|
97
|
+
and self.utter == other.utter
|
|
98
|
+
and self.collect_action == other.collect_action
|
|
99
|
+
and self.rejections == other.rejections
|
|
100
|
+
and self.ask_before_filling == other.ask_before_filling
|
|
101
|
+
and self.reset_after_flow_ends == other.reset_after_flow_ends
|
|
102
|
+
and self.force_slot_filling == other.force_slot_filling
|
|
103
|
+
and super().__eq__(other)
|
|
104
|
+
)
|
|
105
|
+
return False
|
|
@@ -28,7 +28,7 @@ class InternalFlowStep(FlowStep):
|
|
|
28
28
|
"or de-serialized."
|
|
29
29
|
)
|
|
30
30
|
|
|
31
|
-
def as_json(self) -> Dict[Text, Any]:
|
|
31
|
+
def as_json(self) -> Dict[Text, Any]: # type: ignore[override]
|
|
32
32
|
"""Serialize the InternalFlowStep object
|
|
33
33
|
|
|
34
34
|
Returns:
|
|
@@ -43,3 +43,8 @@ class InternalFlowStep(FlowStep):
|
|
|
43
43
|
def default_id_postfix(self) -> str:
|
|
44
44
|
"""Returns the default id postfix of the flow step."""
|
|
45
45
|
raise ValueError("Internal flow steps do not need a default id")
|
|
46
|
+
|
|
47
|
+
def __eq__(self, other: object) -> bool:
|
|
48
|
+
if isinstance(other, type(self)):
|
|
49
|
+
return super().__eq__(other)
|
|
50
|
+
return False
|
|
@@ -37,17 +37,20 @@ class LinkFlowStep(FlowStep):
|
|
|
37
37
|
**base.__dict__,
|
|
38
38
|
)
|
|
39
39
|
|
|
40
|
-
def as_json(self) -> Dict[Text, Any]:
|
|
40
|
+
def as_json(self) -> Dict[Text, Any]: # type: ignore[override]
|
|
41
41
|
"""Serialize the LinkFlowStep object
|
|
42
42
|
|
|
43
43
|
Returns:
|
|
44
44
|
the LinkFlowStep object as serialized data.
|
|
45
45
|
"""
|
|
46
|
-
|
|
47
|
-
data["link"] = self.link
|
|
48
|
-
return data
|
|
46
|
+
return super().as_json(step_properties={"link": self.link})
|
|
49
47
|
|
|
50
48
|
@property
|
|
51
49
|
def default_id_postfix(self) -> str:
|
|
52
50
|
"""Returns the default id postfix of the flow step."""
|
|
53
51
|
return f"link_{self.link}"
|
|
52
|
+
|
|
53
|
+
def __eq__(self, other: object) -> bool:
|
|
54
|
+
if isinstance(other, type(self)):
|
|
55
|
+
return self.link == other.link and super().__eq__(other)
|
|
56
|
+
return False
|