rasa-pro 3.13.0.dev5__py3-none-any.whl → 3.13.0.dev8__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 +0 -3
- rasa/api.py +5 -1
- rasa/cli/arguments/default_arguments.py +13 -1
- rasa/cli/arguments/train.py +2 -0
- rasa/cli/dialogue_understanding_test.py +1 -1
- rasa/cli/e2e_test.py +1 -1
- rasa/cli/evaluate.py +2 -2
- rasa/cli/export.py +3 -3
- rasa/cli/llm_fine_tuning.py +12 -11
- rasa/cli/project_templates/defaults.py +133 -0
- rasa/cli/run.py +1 -1
- rasa/cli/studio/link.py +53 -0
- rasa/cli/studio/pull.py +78 -0
- rasa/cli/studio/push.py +78 -0
- rasa/cli/studio/studio.py +12 -0
- rasa/cli/studio/upload.py +8 -0
- rasa/cli/train.py +2 -1
- rasa/cli/utils.py +1 -1
- rasa/cli/x.py +1 -1
- rasa/constants.py +4 -0
- rasa/core/__init__.py +0 -16
- rasa/core/actions/action.py +5 -1
- rasa/core/actions/action_repeat_bot_messages.py +18 -22
- rasa/core/actions/action_run_slot_rejections.py +0 -1
- rasa/core/agent.py +18 -3
- rasa/core/available_endpoints.py +146 -0
- rasa/core/brokers/kafka.py +4 -0
- rasa/core/brokers/pika.py +5 -2
- rasa/core/brokers/sql.py +1 -1
- rasa/core/channels/botframework.py +2 -2
- rasa/core/channels/channel.py +2 -2
- rasa/core/channels/hangouts.py +8 -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-9f75cc3b.js → arc-c4b064fc.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-7f34db23.js → blockDiagram-38ab4fdb-215b5026.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-948bab2c.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-53b0dd0e.js → classDiagram-70f12bd4-daacea5f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-fdf789e7.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-87c4ece5.js → createText-2e5e7dd3-83c206ba.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-5a8b0749.js → edges-e0da2a9e-b0eb01d0.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-66da90e2.js → erDiagram-9861fffd-17586500.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-10044f05.js → flowDb-956e92f1-be2a1776.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-f338f66a.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-b13140aa.js → flowchart-elk-definition-4a651766-a6ab5c48.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-f2b4a55a.js → ganttDiagram-c361ad54-ef613457.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-dedc298d.js → gitGraphDiagram-72cf32ee-d59185b3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-4ede11ff.js → graph-0f155405.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3862675e-65549d37.js → index-3862675e-d5f1d1b7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3a23e736.js → index-47737d3a.js} +123 -123
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-65439671.js → infoDiagram-f8f76790-b07d141f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-56d03d98.js → journeyDiagram-49397b02-1936d429.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-dd48f7f4.js → layout-dde8d0f3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-1569ad2c.js → line-0c2c7ee0.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-48bf4935.js → linear-35dd89a4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-688504c1.js → mindmap-definition-fc14e90a-56192851.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-78b6d7e6.js → pieDiagram-8a3498a8-fc21ed78.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-048b84b3.js → quadrantDiagram-120e2f19-25e98518.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-dd67f107.js → requirementDiagram-deff3bca-546ff1f5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-8128436e.js → sankeyDiagram-04a897e0-02d8b82d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-1a0d1461.js → sequenceDiagram-704730f1-3ca5a92e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-46d388ed.js → stateDiagram-587899a1-128ea07c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-ea42951a.js → stateDiagram-v2-d93cdb3a-95f290af.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-7427ed0c.js → styles-6aaf32cf-4984898a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-ff5e5a16.js → styles-9a916d00-1bf266ba.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-7b3680cf.js → styles-c10674c1-60521c63.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-f860f2ad.js → svgDrawCommon-08f97a94-a25b6e12.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-2eebf0c8.js → timeline-definition-85554ec2-0fc086bf.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-5d7f4e96.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 +91 -90
- rasa/core/channels/inspector/src/components/Chat.tsx +45 -41
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +40 -40
- 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 +7 -7
- 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/mattermost.py +1 -1
- rasa/core/channels/rasa_chat.py +2 -4
- rasa/core/channels/rest.py +5 -4
- rasa/core/channels/studio_chat.py +3 -2
- rasa/core/channels/vier_cvg.py +1 -2
- rasa/core/channels/voice_ready/audiocodes.py +35 -25
- rasa/core/channels/voice_stream/audiocodes.py +7 -4
- rasa/core/channels/voice_stream/genesys.py +2 -2
- rasa/core/channels/voice_stream/twilio_media_streams.py +10 -5
- rasa/core/channels/voice_stream/voice_channel.py +33 -22
- rasa/core/evaluation/marker_tracker_loader.py +1 -1
- rasa/core/exporter.py +1 -1
- rasa/core/http_interpreter.py +3 -7
- rasa/core/jobs.py +2 -1
- rasa/core/nlg/contextual_response_rephraser.py +38 -11
- rasa/core/nlg/generator.py +0 -1
- rasa/core/nlg/interpolator.py +2 -3
- rasa/core/nlg/summarize.py +40 -6
- rasa/core/persistor.py +55 -20
- rasa/core/policies/enterprise_search_policy.py +290 -66
- rasa/core/policies/enterprise_search_prompt_with_relevancy_check_and_citation_template.jinja2 +63 -0
- rasa/core/policies/flow_policy.py +1 -1
- rasa/core/policies/flows/flow_executor.py +96 -17
- rasa/core/policies/intentless_policy.py +24 -16
- rasa/core/processor.py +106 -53
- rasa/core/run.py +40 -13
- rasa/core/tracker_stores/__init__.py +0 -0
- 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/training/interactive.py +1 -1
- rasa/core/utils.py +24 -91
- rasa/dialogue_understanding/coexistence/intent_based_router.py +2 -1
- rasa/dialogue_understanding/coexistence/llm_based_router.py +8 -3
- rasa/dialogue_understanding/commands/can_not_handle_command.py +2 -0
- rasa/dialogue_understanding/commands/cancel_flow_command.py +2 -0
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +2 -0
- rasa/dialogue_understanding/commands/clarify_command.py +6 -2
- rasa/dialogue_understanding/commands/command_syntax_manager.py +1 -0
- rasa/dialogue_understanding/commands/human_handoff_command.py +2 -0
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +2 -0
- rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +2 -0
- rasa/dialogue_understanding/commands/set_slot_command.py +11 -1
- rasa/dialogue_understanding/commands/skip_question_command.py +2 -0
- rasa/dialogue_understanding/commands/start_flow_command.py +4 -0
- rasa/dialogue_understanding/commands/utils.py +26 -2
- rasa/dialogue_understanding/generator/__init__.py +7 -1
- rasa/dialogue_understanding/generator/command_generator.py +4 -2
- rasa/dialogue_understanding/generator/command_parser.py +2 -2
- rasa/dialogue_understanding/generator/command_parser_validator.py +63 -0
- 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_v3_gpt_4o_2024_11_20_template.jinja2 +78 -0
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +28 -463
- rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +147 -0
- rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +477 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +8 -58
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +37 -25
- rasa/dialogue_understanding/patterns/domain_for_patterns.py +190 -0
- rasa/dialogue_understanding/processor/command_processor.py +3 -3
- rasa/dialogue_understanding/processor/command_processor_component.py +3 -3
- rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +17 -4
- rasa/dialogue_understanding/utils.py +68 -12
- rasa/dialogue_understanding_test/du_test_case.py +1 -1
- rasa/dialogue_understanding_test/du_test_runner.py +4 -22
- rasa/dialogue_understanding_test/test_case_simulation/test_case_tracker_simulator.py +2 -6
- rasa/e2e_test/e2e_test_runner.py +1 -1
- rasa/engine/constants.py +1 -1
- rasa/engine/recipes/default_recipe.py +26 -2
- rasa/engine/validation.py +3 -2
- rasa/hooks.py +2 -30
- rasa/keys +1 -0
- rasa/llm_fine_tuning/annotation_module.py +39 -9
- rasa/llm_fine_tuning/conversations.py +3 -0
- rasa/llm_fine_tuning/llm_data_preparation_module.py +66 -49
- rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +4 -2
- rasa/llm_fine_tuning/paraphrasing/rephrase_validator.py +52 -44
- rasa/llm_fine_tuning/paraphrasing_module.py +10 -12
- rasa/llm_fine_tuning/storage.py +4 -4
- rasa/llm_fine_tuning/utils.py +63 -1
- rasa/model_manager/config.py +3 -1
- rasa/model_manager/model_api.py +89 -2
- rasa/model_manager/runner_service.py +8 -4
- rasa/model_manager/trainer_service.py +5 -4
- rasa/model_training.py +12 -3
- rasa/nlu/extractors/crf_entity_extractor.py +66 -16
- rasa/plugin.py +2 -12
- rasa/privacy/__init__.py +0 -0
- rasa/privacy/constants.py +83 -0
- rasa/privacy/event_broker_utils.py +77 -0
- rasa/privacy/privacy_config.py +281 -0
- rasa/privacy/privacy_config_schema.json +86 -0
- rasa/privacy/privacy_filter.py +340 -0
- rasa/privacy/privacy_manager.py +576 -0
- rasa/server.py +29 -4
- rasa/shared/constants.py +6 -0
- rasa/shared/core/constants.py +4 -3
- rasa/shared/core/domain.py +7 -0
- rasa/shared/core/events.py +99 -3
- rasa/shared/core/flows/flow.py +1 -2
- rasa/shared/core/flows/flows_yaml_schema.json +3 -0
- rasa/shared/core/flows/steps/collect.py +46 -2
- rasa/shared/core/slots.py +28 -0
- rasa/shared/exceptions.py +4 -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/embedding/_base_litellm_embedding_client.py +3 -0
- rasa/shared/providers/llm/_base_litellm_client.py +5 -2
- rasa/shared/utils/llm.py +161 -6
- rasa/shared/utils/yaml.py +32 -0
- rasa/studio/data_handler.py +3 -3
- rasa/studio/download/download.py +37 -60
- rasa/studio/download/flows.py +23 -31
- rasa/studio/link.py +200 -0
- rasa/studio/pull.py +94 -0
- rasa/studio/push.py +131 -0
- rasa/studio/upload.py +117 -67
- rasa/telemetry.py +84 -27
- rasa/tracing/config.py +4 -5
- rasa/tracing/constants.py +19 -1
- rasa/tracing/instrumentation/attribute_extractors.py +11 -3
- rasa/tracing/instrumentation/instrumentation.py +54 -3
- rasa/tracing/instrumentation/metrics.py +98 -15
- rasa/tracing/metric_instrument_provider.py +75 -3
- rasa/utils/common.py +1 -27
- rasa/utils/licensing.py +1 -2
- rasa/utils/log_utils.py +1 -45
- rasa/validator.py +2 -8
- rasa/version.py +1 -1
- {rasa_pro-3.13.0.dev5.dist-info → rasa_pro-3.13.0.dev8.dist-info}/METADATA +8 -9
- {rasa_pro-3.13.0.dev5.dist-info → rasa_pro-3.13.0.dev8.dist-info}/RECORD +254 -231
- rasa/anonymization/__init__.py +0 -2
- rasa/anonymization/anonymisation_rule_yaml_reader.py +0 -91
- rasa/anonymization/anonymization_pipeline.py +0 -286
- rasa/anonymization/anonymization_rule_executor.py +0 -266
- rasa/anonymization/anonymization_rule_orchestrator.py +0 -119
- rasa/anonymization/schemas/config.yml +0 -47
- rasa/anonymization/utils.py +0 -118
- rasa/core/channels/inspector/dist/assets/channel-dfa68278.js +0 -1
- rasa/core/channels/inspector/dist/assets/clone-edb7f119.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-65e7c670.js +0 -1
- rasa/core/channels/inspector/src/helpers/audiostream.ts +0 -191
- rasa/core/tracker_store.py +0 -1792
- {rasa_pro-3.13.0.dev5.dist-info → rasa_pro-3.13.0.dev8.dist-info}/NOTICE +0 -0
- {rasa_pro-3.13.0.dev5.dist-info → rasa_pro-3.13.0.dev8.dist-info}/WHEEL +0 -0
- {rasa_pro-3.13.0.dev5.dist-info → rasa_pro-3.13.0.dev8.dist-info}/entry_points.txt +0 -0
rasa/core/run.py
CHANGED
|
@@ -30,12 +30,11 @@ from rasa import server, telemetry
|
|
|
30
30
|
from rasa.constants import ENV_SANIC_BACKLOG
|
|
31
31
|
from rasa.core import agent, channels, constants
|
|
32
32
|
from rasa.core.agent import Agent
|
|
33
|
+
from rasa.core.available_endpoints import AvailableEndpoints
|
|
33
34
|
from rasa.core.channels import console
|
|
34
35
|
from rasa.core.channels.channel import InputChannel
|
|
35
36
|
from rasa.core.channels.development_inspector import DevelopmentInspectProxy
|
|
36
37
|
from rasa.core.persistor import StorageType
|
|
37
|
-
from rasa.core.utils import AvailableEndpoints
|
|
38
|
-
from rasa.plugin import plugin_manager
|
|
39
38
|
from rasa.shared.exceptions import RasaException
|
|
40
39
|
from rasa.shared.utils.yaml import read_config_file
|
|
41
40
|
from rasa.utils import licensing
|
|
@@ -45,7 +44,7 @@ logger = logging.getLogger() # get the root logger
|
|
|
45
44
|
|
|
46
45
|
def create_http_input_channels(
|
|
47
46
|
channel: Optional[Text], credentials_file: Optional[Text]
|
|
48
|
-
) -> List[
|
|
47
|
+
) -> List[InputChannel]:
|
|
49
48
|
"""Instantiate the chosen input channel."""
|
|
50
49
|
if credentials_file:
|
|
51
50
|
all_credentials = read_config_file(credentials_file)
|
|
@@ -59,22 +58,45 @@ def create_http_input_channels(
|
|
|
59
58
|
"To connect to all given channels, omit the '--connector' "
|
|
60
59
|
"argument.".format(channel)
|
|
61
60
|
)
|
|
62
|
-
return [
|
|
61
|
+
return [
|
|
62
|
+
_create_single_channel(
|
|
63
|
+
channel,
|
|
64
|
+
all_credentials.get(channel),
|
|
65
|
+
)
|
|
66
|
+
]
|
|
63
67
|
else:
|
|
64
68
|
return [_create_single_channel(c, k) for c, k in all_credentials.items()]
|
|
65
69
|
|
|
66
70
|
|
|
67
|
-
def _create_single_channel(
|
|
71
|
+
def _create_single_channel(
|
|
72
|
+
channel: Text,
|
|
73
|
+
credentials: Optional[Dict[Text, Any]],
|
|
74
|
+
) -> Any:
|
|
75
|
+
"""Create a single input channel based on the channel name and credentials.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
channel: The name of the input channel to create.
|
|
79
|
+
credentials: The credentials for the input channel.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
An instance of the input channel class.
|
|
83
|
+
|
|
84
|
+
Raises:
|
|
85
|
+
RasaException: If the channel class cannot be found or instantiated.
|
|
86
|
+
"""
|
|
68
87
|
from rasa.core.channels import BUILTIN_CHANNELS
|
|
69
88
|
|
|
70
89
|
if channel in BUILTIN_CHANNELS:
|
|
71
|
-
|
|
90
|
+
channel_class = BUILTIN_CHANNELS[channel]
|
|
91
|
+
|
|
92
|
+
return channel_class.from_credentials(credentials)
|
|
72
93
|
else:
|
|
73
94
|
# try to load channel based on class name
|
|
74
95
|
try:
|
|
75
96
|
input_channel_class = rasa.shared.utils.common.class_from_module_path(
|
|
76
97
|
channel
|
|
77
98
|
)
|
|
99
|
+
|
|
78
100
|
return input_channel_class.from_credentials(credentials)
|
|
79
101
|
except (AttributeError, ImportError):
|
|
80
102
|
raise RasaException(
|
|
@@ -86,13 +108,15 @@ def _create_single_channel(channel: Text, credentials: Dict[Text, Any]) -> Any:
|
|
|
86
108
|
)
|
|
87
109
|
|
|
88
110
|
|
|
89
|
-
def _create_app_without_api(
|
|
111
|
+
def _create_app_without_api(
|
|
112
|
+
cors: Optional[Union[Text, List[Text]]] = None, is_inspector_enabled: bool = False
|
|
113
|
+
) -> Sanic:
|
|
90
114
|
app = Sanic("rasa_core_no_api", configure_logging=False)
|
|
91
115
|
|
|
92
116
|
# Reset Sanic warnings filter that allows the triggering of Sanic warnings
|
|
93
117
|
warnings.filterwarnings("ignore", category=DeprecationWarning, module=r"sanic.*")
|
|
94
118
|
|
|
95
|
-
server.add_root_route(app)
|
|
119
|
+
server.add_root_route(app, is_inspector_enabled)
|
|
96
120
|
server.configure_cors(app, cors)
|
|
97
121
|
return app
|
|
98
122
|
|
|
@@ -106,7 +130,7 @@ def _is_apple_silicon_system() -> bool:
|
|
|
106
130
|
|
|
107
131
|
|
|
108
132
|
def configure_app(
|
|
109
|
-
input_channels: Optional[List[
|
|
133
|
+
input_channels: Optional[List[InputChannel]] = None,
|
|
110
134
|
cors: Optional[Union[Text, List[Text], None]] = None,
|
|
111
135
|
auth_token: Optional[Text] = None,
|
|
112
136
|
enable_api: bool = True,
|
|
@@ -127,6 +151,7 @@ def configure_app(
|
|
|
127
151
|
server_listeners: Optional[List[Tuple[Callable, Text]]] = None,
|
|
128
152
|
use_uvloop: Optional[bool] = True,
|
|
129
153
|
keep_alive_timeout: int = constants.DEFAULT_KEEP_ALIVE_TIMEOUT,
|
|
154
|
+
is_inspector_enabled: bool = False,
|
|
130
155
|
) -> Sanic:
|
|
131
156
|
"""Run the agent."""
|
|
132
157
|
rasa.core.utils.configure_file_logging(
|
|
@@ -144,6 +169,7 @@ def configure_app(
|
|
|
144
169
|
jwt_private_key=jwt_private_key,
|
|
145
170
|
jwt_method=jwt_method,
|
|
146
171
|
endpoints=endpoints,
|
|
172
|
+
is_inspector_enabled=is_inspector_enabled,
|
|
147
173
|
)
|
|
148
174
|
)
|
|
149
175
|
else:
|
|
@@ -186,10 +212,6 @@ def configure_app(
|
|
|
186
212
|
logger.info("Killing Sanic server now.")
|
|
187
213
|
running_app.stop() # kill the sanic server
|
|
188
214
|
|
|
189
|
-
@app.after_server_stop
|
|
190
|
-
async def after_server_stop(running_app: Sanic) -> None:
|
|
191
|
-
plugin_manager().hook.after_server_stop()
|
|
192
|
-
|
|
193
215
|
if server_listeners:
|
|
194
216
|
for listener, event in server_listeners:
|
|
195
217
|
app.register_listener(listener, event)
|
|
@@ -259,6 +281,7 @@ def serve_application(
|
|
|
259
281
|
syslog_protocol=syslog_protocol,
|
|
260
282
|
request_timeout=request_timeout,
|
|
261
283
|
server_listeners=server_listeners,
|
|
284
|
+
is_inspector_enabled=inspect,
|
|
262
285
|
)
|
|
263
286
|
|
|
264
287
|
ssl_context = server.create_ssl_context(
|
|
@@ -341,3 +364,7 @@ async def close_resources(app: Sanic, _: AbstractEventLoop) -> None:
|
|
|
341
364
|
event_broker = current_agent.tracker_store.event_broker
|
|
342
365
|
if event_broker:
|
|
343
366
|
await event_broker.close()
|
|
367
|
+
|
|
368
|
+
privacy_manager = current_agent.privacy_manager
|
|
369
|
+
if privacy_manager:
|
|
370
|
+
privacy_manager.stop()
|
|
File without changes
|
|
@@ -3,7 +3,7 @@ from typing import Iterable, Optional, Text
|
|
|
3
3
|
|
|
4
4
|
from rasa.core.brokers.broker import EventBroker
|
|
5
5
|
from rasa.core.secrets_manager.secret_manager import EndpointResolver
|
|
6
|
-
from rasa.core.tracker_store import TrackerStore, create_tracker_store
|
|
6
|
+
from rasa.core.tracker_stores.tracker_store import TrackerStore, create_tracker_store
|
|
7
7
|
from rasa.shared.core.domain import Domain
|
|
8
8
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
9
9
|
from rasa.utils.endpoints import EndpointConfig
|
|
@@ -119,3 +119,7 @@ class AuthRetryTrackerStore(TrackerStore):
|
|
|
119
119
|
"""Recreate tracker store with updated credentials."""
|
|
120
120
|
endpoint_config = EndpointResolver.update_config(self.endpoint_config)
|
|
121
121
|
return create_tracker_store(endpoint_config, domain, event_broker)
|
|
122
|
+
|
|
123
|
+
async def delete(self, sender_id: Text) -> None:
|
|
124
|
+
"""Delete tracker for the given sender_id."""
|
|
125
|
+
await self._tracker_store.delete(sender_id)
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Dict, Iterable, Optional, Text
|
|
5
|
+
|
|
6
|
+
import structlog
|
|
7
|
+
from boto3.dynamodb.conditions import Key
|
|
8
|
+
|
|
9
|
+
import rasa.utils
|
|
10
|
+
from rasa.constants import DEFAULT_SANIC_WORKERS, ENV_SANIC_WORKERS
|
|
11
|
+
from rasa.core.tracker_stores.tracker_store import (
|
|
12
|
+
SerializedTrackerAsDict,
|
|
13
|
+
TrackerStore,
|
|
14
|
+
)
|
|
15
|
+
from rasa.shared.core.domain import Domain
|
|
16
|
+
from rasa.shared.core.trackers import DialogueStateTracker
|
|
17
|
+
from rasa.shared.exceptions import RasaException
|
|
18
|
+
from rasa.utils.endpoints import EndpointConfig
|
|
19
|
+
|
|
20
|
+
structlogger = structlog.get_logger(__name__)
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
import boto3.resources.factory.dynamodb.Table
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class DynamoTrackerStore(TrackerStore, SerializedTrackerAsDict):
|
|
27
|
+
"""Stores conversation history in DynamoDB."""
|
|
28
|
+
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
domain: Domain,
|
|
32
|
+
table_name: Text = "states",
|
|
33
|
+
region: Text = "us-east-1",
|
|
34
|
+
event_broker: Optional[EndpointConfig] = None,
|
|
35
|
+
**kwargs: Dict[Text, Any],
|
|
36
|
+
) -> None:
|
|
37
|
+
"""Initialize `DynamoTrackerStore`.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
domain: Domain associated with this tracker store.
|
|
41
|
+
table_name: The name of the DynamoDB table, does not need to be present a
|
|
42
|
+
priori.
|
|
43
|
+
region: The name of the region associated with the client.
|
|
44
|
+
A client is associated with a single region.
|
|
45
|
+
event_broker: An event broker used to publish events.
|
|
46
|
+
kwargs: Additional kwargs.
|
|
47
|
+
"""
|
|
48
|
+
import boto3
|
|
49
|
+
|
|
50
|
+
self.client = boto3.client("dynamodb", region_name=region)
|
|
51
|
+
self.region = region
|
|
52
|
+
self.table_name = table_name
|
|
53
|
+
self.db = self.get_or_create_table(table_name)
|
|
54
|
+
super().__init__(domain, event_broker, **kwargs)
|
|
55
|
+
|
|
56
|
+
def get_or_create_table(
|
|
57
|
+
self, table_name: Text
|
|
58
|
+
) -> "boto3.resources.factory.dynamodb.Table":
|
|
59
|
+
"""Returns table or creates one if the table name is not in the table list."""
|
|
60
|
+
import boto3
|
|
61
|
+
|
|
62
|
+
dynamo = boto3.resource("dynamodb", region_name=self.region)
|
|
63
|
+
try:
|
|
64
|
+
self.client.describe_table(TableName=table_name)
|
|
65
|
+
except self.client.exceptions.ResourceNotFoundException:
|
|
66
|
+
sanic_workers_count = int(
|
|
67
|
+
os.environ.get(ENV_SANIC_WORKERS, DEFAULT_SANIC_WORKERS)
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
if sanic_workers_count > 1:
|
|
71
|
+
structlogger.error(
|
|
72
|
+
"dynamo_tracker_store.table_creation_not_supported_in_multi_worker_mode",
|
|
73
|
+
event_info=(
|
|
74
|
+
"DynamoDB table creation is not "
|
|
75
|
+
"supported in multi-worker mode. "
|
|
76
|
+
"Table should already exist.",
|
|
77
|
+
),
|
|
78
|
+
)
|
|
79
|
+
raise RasaException(
|
|
80
|
+
"DynamoDB table creation is not supported in "
|
|
81
|
+
"case of multiple sanic workers. To create the table either "
|
|
82
|
+
"run Rasa with a single worker or create the table manually."
|
|
83
|
+
"Here are the defaults which can be used to "
|
|
84
|
+
"create the table manually: "
|
|
85
|
+
f"Table name: {table_name}, Primary key: sender_id, "
|
|
86
|
+
f"key type `HASH`, attribute type `S` (String), "
|
|
87
|
+
"Provisioned throughput: Read capacity units: 5, "
|
|
88
|
+
"Write capacity units: 5"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
table = dynamo.create_table(
|
|
92
|
+
TableName=self.table_name,
|
|
93
|
+
KeySchema=[{"AttributeName": "sender_id", "KeyType": "HASH"}],
|
|
94
|
+
AttributeDefinitions=[
|
|
95
|
+
{"AttributeName": "sender_id", "AttributeType": "S"}
|
|
96
|
+
],
|
|
97
|
+
ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5},
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Wait until the table exists.
|
|
101
|
+
table.meta.client.get_waiter("table_exists").wait(TableName=table_name)
|
|
102
|
+
else:
|
|
103
|
+
table = dynamo.Table(table_name)
|
|
104
|
+
|
|
105
|
+
return table
|
|
106
|
+
|
|
107
|
+
async def save(self, tracker: DialogueStateTracker) -> None:
|
|
108
|
+
"""Saves the current conversation state."""
|
|
109
|
+
await self.stream_events(tracker)
|
|
110
|
+
serialized = self.serialise_tracker(tracker)
|
|
111
|
+
|
|
112
|
+
self.db.put_item(Item=serialized)
|
|
113
|
+
|
|
114
|
+
async def delete(self, sender_id: Text) -> None:
|
|
115
|
+
"""Delete tracker for the given sender_id."""
|
|
116
|
+
if not await self.exists(sender_id):
|
|
117
|
+
structlogger.info(
|
|
118
|
+
"dynamo_tracker_store.delete.no_tracker_for_sender_id",
|
|
119
|
+
event_info=f"Could not find tracker for conversation ID '{sender_id}'.",
|
|
120
|
+
)
|
|
121
|
+
return None
|
|
122
|
+
|
|
123
|
+
self.db.delete_item(
|
|
124
|
+
Key={"sender_id": sender_id},
|
|
125
|
+
ConditionExpression="attribute_exists(sender_id)",
|
|
126
|
+
)
|
|
127
|
+
structlogger.info(
|
|
128
|
+
"dynamo_tracker_store.delete.deleted_tracker",
|
|
129
|
+
sender_id=sender_id,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
@staticmethod
|
|
133
|
+
def serialise_tracker(
|
|
134
|
+
tracker: "DialogueStateTracker",
|
|
135
|
+
) -> Dict:
|
|
136
|
+
"""Serializes the tracker, returns object with decimal types.
|
|
137
|
+
|
|
138
|
+
DynamoDB cannot store `float`s, so we'll convert them to `Decimal`s.
|
|
139
|
+
"""
|
|
140
|
+
return rasa.utils.json_utils.replace_floats_with_decimals(
|
|
141
|
+
SerializedTrackerAsDict.serialise_tracker(tracker)
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
async def retrieve(self, sender_id: Text) -> Optional[DialogueStateTracker]:
|
|
145
|
+
"""Retrieve dialogues for a sender_id in reverse-chronological order.
|
|
146
|
+
|
|
147
|
+
Based on the session_date sort key.
|
|
148
|
+
"""
|
|
149
|
+
return await self._retrieve(sender_id, fetch_all_sessions=False)
|
|
150
|
+
|
|
151
|
+
async def retrieve_full_tracker(
|
|
152
|
+
self, sender_id: Text
|
|
153
|
+
) -> Optional[DialogueStateTracker]:
|
|
154
|
+
"""Retrieves tracker for all conversation sessions.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
sender_id: Conversation ID to fetch the tracker for.
|
|
158
|
+
"""
|
|
159
|
+
return await self._retrieve(sender_id, fetch_all_sessions=True)
|
|
160
|
+
|
|
161
|
+
async def _retrieve(
|
|
162
|
+
self, sender_id: Text, fetch_all_sessions: bool
|
|
163
|
+
) -> Optional[DialogueStateTracker]:
|
|
164
|
+
"""Returns tracker matching sender_id.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
sender_id: Conversation ID to fetch the tracker for.
|
|
168
|
+
fetch_all_sessions: Whether to fetch all sessions or only the last one.
|
|
169
|
+
"""
|
|
170
|
+
dialogues = self.db.query(
|
|
171
|
+
KeyConditionExpression=Key("sender_id").eq(sender_id),
|
|
172
|
+
ScanIndexForward=False,
|
|
173
|
+
)["Items"]
|
|
174
|
+
|
|
175
|
+
if not dialogues:
|
|
176
|
+
return None
|
|
177
|
+
|
|
178
|
+
events_with_floats = []
|
|
179
|
+
for dialogue in dialogues:
|
|
180
|
+
if dialogue.get("events"):
|
|
181
|
+
events = rasa.utils.json_utils.replace_decimals_with_floats(
|
|
182
|
+
dialogue["events"]
|
|
183
|
+
)
|
|
184
|
+
events_with_floats += events
|
|
185
|
+
|
|
186
|
+
if self.domain is None:
|
|
187
|
+
slots = []
|
|
188
|
+
else:
|
|
189
|
+
slots = self.domain.slots
|
|
190
|
+
|
|
191
|
+
tracker = DialogueStateTracker.from_dict(sender_id, events_with_floats, slots)
|
|
192
|
+
|
|
193
|
+
if fetch_all_sessions:
|
|
194
|
+
return tracker
|
|
195
|
+
|
|
196
|
+
# only return the last session
|
|
197
|
+
multiple_tracker_sessions = (
|
|
198
|
+
rasa.shared.core.trackers.get_trackers_for_conversation_sessions(tracker)
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
if len(multiple_tracker_sessions) <= 1:
|
|
202
|
+
return tracker
|
|
203
|
+
|
|
204
|
+
return multiple_tracker_sessions[-1]
|
|
205
|
+
|
|
206
|
+
async def keys(self) -> Iterable[Text]:
|
|
207
|
+
"""Returns sender_ids of the `DynamoTrackerStore`."""
|
|
208
|
+
response = self.db.scan(ProjectionExpression="sender_id")
|
|
209
|
+
sender_ids = [i["sender_id"] for i in response["Items"]]
|
|
210
|
+
|
|
211
|
+
while response.get("LastEvaluatedKey"):
|
|
212
|
+
response = self.db.scan(
|
|
213
|
+
ProjectionExpression="sender_id",
|
|
214
|
+
ExclusiveStartKey=response["LastEvaluatedKey"],
|
|
215
|
+
)
|
|
216
|
+
sender_ids.extend([i["sender_id"] for i in response["Items"]])
|
|
217
|
+
|
|
218
|
+
return sender_ids
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import itertools
|
|
4
|
+
from typing import Any, Dict, Iterable, Iterator, List, Optional, Text
|
|
5
|
+
|
|
6
|
+
import structlog
|
|
7
|
+
from pymongo.synchronous.collection import Collection
|
|
8
|
+
|
|
9
|
+
from rasa.core.brokers.broker import EventBroker
|
|
10
|
+
from rasa.core.tracker_stores.tracker_store import SerializedTrackerAsText, TrackerStore
|
|
11
|
+
from rasa.shared.core.domain import Domain
|
|
12
|
+
from rasa.shared.core.events import SessionStarted
|
|
13
|
+
from rasa.shared.core.trackers import DialogueStateTracker, EventVerbosity
|
|
14
|
+
|
|
15
|
+
structlogger = structlog.get_logger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class MongoTrackerStore(TrackerStore, SerializedTrackerAsText):
|
|
19
|
+
"""Stores conversation history in Mongo.
|
|
20
|
+
|
|
21
|
+
Property methods:
|
|
22
|
+
conversations: returns the current conversation
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
domain: Domain,
|
|
28
|
+
host: Optional[Text] = "mongodb://localhost:27017",
|
|
29
|
+
db: Optional[Text] = "rasa",
|
|
30
|
+
username: Optional[Text] = None,
|
|
31
|
+
password: Optional[Text] = None,
|
|
32
|
+
auth_source: Optional[Text] = "admin",
|
|
33
|
+
collection: Text = "conversations",
|
|
34
|
+
event_broker: Optional[EventBroker] = None,
|
|
35
|
+
**kwargs: Dict[Text, Any],
|
|
36
|
+
) -> None:
|
|
37
|
+
from pymongo import MongoClient
|
|
38
|
+
from pymongo.database import Database
|
|
39
|
+
|
|
40
|
+
self.client: MongoClient = MongoClient(
|
|
41
|
+
host,
|
|
42
|
+
username=username,
|
|
43
|
+
password=password,
|
|
44
|
+
authSource=auth_source,
|
|
45
|
+
# delay connect until process forking is done
|
|
46
|
+
connect=False,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
self.db = Database(self.client, db)
|
|
50
|
+
self.collection = collection
|
|
51
|
+
super().__init__(domain, event_broker, **kwargs)
|
|
52
|
+
|
|
53
|
+
self._ensure_indices()
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def conversations(self) -> Collection:
|
|
57
|
+
"""Returns the current conversation."""
|
|
58
|
+
return self.db[self.collection]
|
|
59
|
+
|
|
60
|
+
def _ensure_indices(self) -> None:
|
|
61
|
+
"""Create an index on the sender_id."""
|
|
62
|
+
self.conversations.create_index("sender_id")
|
|
63
|
+
|
|
64
|
+
@staticmethod
|
|
65
|
+
def _current_tracker_state_without_events(tracker: DialogueStateTracker) -> Dict:
|
|
66
|
+
# get current tracker state and remove `events` key from state
|
|
67
|
+
# since events are pushed separately in the `update_one()` operation
|
|
68
|
+
state = tracker.current_state(EventVerbosity.ALL)
|
|
69
|
+
state.pop("events", None)
|
|
70
|
+
|
|
71
|
+
return state
|
|
72
|
+
|
|
73
|
+
async def delete(self, sender_id: Text) -> None:
|
|
74
|
+
"""Delete tracker for the given sender_id.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
sender_id: Sender id of the tracker to be deleted.
|
|
78
|
+
"""
|
|
79
|
+
if not await self.exists(sender_id):
|
|
80
|
+
structlogger.info(
|
|
81
|
+
"mongo_tracker_store.delete.no_tracker_for_sender_id",
|
|
82
|
+
event_info=f"Could not find tracker for conversation ID '{sender_id}'.",
|
|
83
|
+
)
|
|
84
|
+
return None
|
|
85
|
+
self.conversations.delete_one({"sender_id": sender_id})
|
|
86
|
+
|
|
87
|
+
structlogger.info(
|
|
88
|
+
"mongo_tracker_store.delete.deleted_tracker",
|
|
89
|
+
sender_id=sender_id,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
async def save(self, tracker: DialogueStateTracker) -> None:
|
|
93
|
+
"""Saves the current conversation state."""
|
|
94
|
+
await self.stream_events(tracker)
|
|
95
|
+
|
|
96
|
+
additional_events = self._additional_events(tracker)
|
|
97
|
+
|
|
98
|
+
self.conversations.update_one(
|
|
99
|
+
{"sender_id": tracker.sender_id},
|
|
100
|
+
{
|
|
101
|
+
"$set": self._current_tracker_state_without_events(tracker),
|
|
102
|
+
"$push": {
|
|
103
|
+
"events": {"$each": [e.as_dict() for e in additional_events]}
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
upsert=True,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
def _additional_events(self, tracker: DialogueStateTracker) -> Iterator:
|
|
110
|
+
"""Return events from the tracker which aren't currently stored.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
tracker: Tracker to inspect.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
List of serialised events that aren't currently stored.
|
|
117
|
+
|
|
118
|
+
"""
|
|
119
|
+
stored = self.conversations.find_one({"sender_id": tracker.sender_id}) or {}
|
|
120
|
+
all_events = self._events_from_serialized_tracker(stored)
|
|
121
|
+
|
|
122
|
+
number_events_since_last_session = len(
|
|
123
|
+
self._events_since_last_session_start(all_events)
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
return itertools.islice(
|
|
127
|
+
tracker.events, number_events_since_last_session, len(tracker.events)
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
@staticmethod
|
|
131
|
+
def _events_from_serialized_tracker(serialised: Dict) -> List[Dict]:
|
|
132
|
+
return serialised.get("events", [])
|
|
133
|
+
|
|
134
|
+
@staticmethod
|
|
135
|
+
def _events_since_last_session_start(events: List[Dict]) -> List[Dict]:
|
|
136
|
+
"""Retrieve events since and including the latest `SessionStart` event.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
events: All events for a conversation ID.
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
List of serialised events since and including the latest `SessionStarted`
|
|
143
|
+
event. Returns all events if no such event is found.
|
|
144
|
+
|
|
145
|
+
"""
|
|
146
|
+
events_after_session_start = []
|
|
147
|
+
for event in reversed(events):
|
|
148
|
+
events_after_session_start.append(event)
|
|
149
|
+
if event["event"] == SessionStarted.type_name:
|
|
150
|
+
break
|
|
151
|
+
|
|
152
|
+
return list(reversed(events_after_session_start))
|
|
153
|
+
|
|
154
|
+
async def _retrieve(
|
|
155
|
+
self, sender_id: Text, fetch_events_from_all_sessions: bool
|
|
156
|
+
) -> Optional[List[Dict[Text, Any]]]:
|
|
157
|
+
stored = self.conversations.find_one({"sender_id": sender_id})
|
|
158
|
+
|
|
159
|
+
# look for conversations which have used an `int` sender_id in the past
|
|
160
|
+
# and update them.
|
|
161
|
+
if not stored and sender_id.isdigit():
|
|
162
|
+
from pymongo import ReturnDocument
|
|
163
|
+
|
|
164
|
+
stored = self.conversations.find_one_and_update(
|
|
165
|
+
{"sender_id": int(sender_id)},
|
|
166
|
+
{"$set": {"sender_id": str(sender_id)}},
|
|
167
|
+
return_document=ReturnDocument.AFTER,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
if not stored:
|
|
171
|
+
return None
|
|
172
|
+
|
|
173
|
+
events = self._events_from_serialized_tracker(stored)
|
|
174
|
+
|
|
175
|
+
if not fetch_events_from_all_sessions:
|
|
176
|
+
events = self._events_since_last_session_start(events)
|
|
177
|
+
|
|
178
|
+
return events
|
|
179
|
+
|
|
180
|
+
async def retrieve(self, sender_id: Text) -> Optional[DialogueStateTracker]:
|
|
181
|
+
"""Retrieves tracker for the latest conversation session."""
|
|
182
|
+
events = await self._retrieve(sender_id, fetch_events_from_all_sessions=False)
|
|
183
|
+
|
|
184
|
+
if not events:
|
|
185
|
+
return None
|
|
186
|
+
|
|
187
|
+
return DialogueStateTracker.from_dict(sender_id, events, self.domain.slots)
|
|
188
|
+
|
|
189
|
+
async def retrieve_full_tracker(
|
|
190
|
+
self, conversation_id: Text
|
|
191
|
+
) -> Optional[DialogueStateTracker]:
|
|
192
|
+
"""Fetching all tracker events across conversation sessions."""
|
|
193
|
+
events = await self._retrieve(
|
|
194
|
+
conversation_id, fetch_events_from_all_sessions=True
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
if not events:
|
|
198
|
+
return None
|
|
199
|
+
|
|
200
|
+
return DialogueStateTracker.from_dict(
|
|
201
|
+
conversation_id, events, self.domain.slots
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
async def keys(self) -> Iterable[Text]:
|
|
205
|
+
"""Returns sender_ids of the Mongo Tracker Store."""
|
|
206
|
+
return [c["sender_id"] for c in self.conversations.find()]
|