rasa-pro 3.12.21__py3-none-any.whl → 3.13.0__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 -4
- rasa/api.py +1 -1
- rasa/cli/dialogue_understanding_test.py +1 -1
- rasa/cli/e2e_test.py +1 -8
- rasa/cli/evaluate.py +2 -2
- rasa/cli/export.py +5 -3
- rasa/cli/inspect.py +7 -0
- rasa/cli/llm_fine_tuning.py +1 -1
- 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/project_templates/defaults.py +133 -0
- rasa/cli/project_templates/tutorial/config.yml +1 -1
- rasa/cli/project_templates/tutorial/endpoints.yml +1 -1
- rasa/cli/run.py +1 -1
- rasa/cli/scaffold.py +2 -3
- rasa/cli/shell.py +6 -1
- rasa/cli/studio/download.py +0 -22
- rasa/cli/studio/link.py +36 -0
- rasa/cli/studio/pull.py +79 -0
- rasa/cli/studio/push.py +78 -0
- rasa/cli/studio/studio.py +12 -0
- rasa/cli/studio/train.py +1 -5
- rasa/cli/studio/upload.py +6 -4
- rasa/cli/train.py +5 -1
- rasa/cli/utils.py +1 -1
- rasa/cli/x.py +1 -1
- rasa/constants.py +2 -0
- rasa/core/__init__.py +0 -16
- rasa/core/actions/action.py +43 -29
- rasa/core/actions/action_repeat_bot_messages.py +18 -22
- rasa/core/actions/action_run_slot_rejections.py +1 -2
- rasa/core/agent.py +24 -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/__init__.py +3 -0
- rasa/core/channels/botframework.py +2 -2
- rasa/core/channels/channel.py +2 -2
- rasa/core/channels/development_inspector.py +1 -1
- rasa/core/channels/facebook.py +1 -4
- 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 +11 -5
- rasa/core/channels/inspector/dist/assets/{arc-9f75cc3b.js → arc-371401b1.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-7f34db23.js → blockDiagram-38ab4fdb-3f126156.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-948bab2c.js → c4Diagram-3d4e48cf-12f22eb7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/channel-f1efda17.js +1 -0
- rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-53b0dd0e.js → classDiagram-70f12bd4-03b1d386.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-fdf789e7.js → classDiagram-v2-f2320105-84f69d63.js} +1 -1
- rasa/core/channels/inspector/dist/assets/clone-fdf164e2.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-87c4ece5.js → createText-2e5e7dd3-ca47fd38.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-5a8b0749.js → edges-e0da2a9e-f837ca8a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-66da90e2.js → erDiagram-9861fffd-8717ac54.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-10044f05.js → flowDb-956e92f1-94f38b83.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-f338f66a.js → flowDiagram-66a62f08-b616f9fb.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-7d7a1629.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-b13140aa.js → flowchart-elk-definition-4a651766-f5d24bb8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-f2b4a55a.js → ganttDiagram-c361ad54-b43ba8d9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-dedc298d.js → gitGraphDiagram-72cf32ee-c3aafaa5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-4ede11ff.js → graph-0d0a2c10.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3862675e-65549d37.js → index-3862675e-58ea0305.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3a23e736.js → index-cce6f8a1.js} +123 -123
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-65439671.js → infoDiagram-f8f76790-b8f60461.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-56d03d98.js → journeyDiagram-49397b02-95be5545.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-dd48f7f4.js → layout-da885b9b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-1569ad2c.js → line-f1c817d3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-48bf4935.js → linear-d42801e6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-688504c1.js → mindmap-definition-fc14e90a-a38923a6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-78b6d7e6.js → pieDiagram-8a3498a8-ca6e71e9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-048b84b3.js → quadrantDiagram-120e2f19-b290dae9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-dd67f107.js → requirementDiagram-deff3bca-03f02ceb.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-8128436e.js → sankeyDiagram-04a897e0-c49eee40.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-1a0d1461.js → sequenceDiagram-704730f1-b2cd6a3d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-46d388ed.js → stateDiagram-587899a1-e53a2028.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-ea42951a.js → stateDiagram-v2-d93cdb3a-e1982a03.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-7427ed0c.js → styles-6aaf32cf-d0226ca5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-ff5e5a16.js → styles-9a916d00-0e21dc00.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-7b3680cf.js → styles-c10674c1-9588494e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-f860f2ad.js → svgDrawCommon-08f97a94-be478d4f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-2eebf0c8.js → timeline-definition-85554ec2-74631749.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-5d7f4e96.js → xychartDiagram-e933f94c-a043552f.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/socketio.py +56 -41
- rasa/core/channels/studio_chat.py +329 -68
- rasa/core/channels/vier_cvg.py +1 -2
- rasa/core/channels/voice_ready/audiocodes.py +4 -11
- rasa/core/channels/voice_ready/jambonz.py +5 -6
- rasa/core/channels/voice_ready/twilio_voice.py +13 -12
- rasa/core/channels/voice_ready/utils.py +22 -0
- rasa/core/channels/voice_stream/audiocodes.py +13 -16
- rasa/core/channels/voice_stream/browser_audio.py +1 -1
- rasa/core/channels/voice_stream/genesys.py +37 -18
- rasa/core/channels/voice_stream/jambonz.py +232 -0
- rasa/core/channels/voice_stream/tts/__init__.py +8 -0
- rasa/core/channels/voice_stream/twilio_media_streams.py +15 -12
- rasa/core/channels/voice_stream/voice_channel.py +71 -27
- rasa/core/concurrent_lock_store.py +24 -10
- rasa/core/evaluation/marker_tracker_loader.py +1 -1
- rasa/core/exporter.py +37 -1
- rasa/core/http_interpreter.py +3 -7
- rasa/core/information_retrieval/faiss.py +18 -11
- rasa/core/information_retrieval/ingestion/faq_parser.py +158 -0
- rasa/core/jobs.py +2 -1
- rasa/core/lock_store.py +151 -60
- rasa/core/nlg/contextual_response_rephraser.py +17 -7
- rasa/core/nlg/generator.py +5 -22
- rasa/core/nlg/interpolator.py +2 -3
- rasa/core/nlg/response.py +6 -43
- rasa/core/nlg/summarize.py +1 -1
- rasa/core/nlg/translate.py +0 -8
- rasa/core/policies/enterprise_search_policy.py +305 -189
- rasa/core/policies/enterprise_search_policy_config.py +241 -0
- rasa/core/policies/enterprise_search_prompt_with_relevancy_check_and_citation_template.jinja2 +67 -0
- rasa/core/policies/flow_policy.py +1 -1
- rasa/core/policies/flows/flow_executor.py +102 -17
- rasa/core/policies/intentless_policy.py +56 -17
- rasa/core/processor.py +70 -49
- rasa/core/run.py +33 -11
- rasa/core/tracker_stores/__init__.py +0 -0
- rasa/core/{auth_retry_tracker_store.py → tracker_stores/auth_retry_tracker_store.py} +66 -1
- rasa/core/tracker_stores/dynamo_tracker_store.py +256 -0
- rasa/core/tracker_stores/mongo_tracker_store.py +223 -0
- rasa/core/tracker_stores/redis_tracker_store.py +252 -0
- rasa/core/tracker_stores/sql_tracker_store.py +582 -0
- rasa/core/tracker_stores/tracker_store.py +839 -0
- rasa/core/training/interactive.py +1 -1
- rasa/core/utils.py +24 -95
- rasa/dialogue_understanding/coexistence/intent_based_router.py +2 -1
- rasa/dialogue_understanding/coexistence/llm_based_router.py +13 -11
- rasa/dialogue_understanding/commands/can_not_handle_command.py +2 -0
- rasa/dialogue_understanding/commands/cancel_flow_command.py +3 -1
- 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/correct_slots_command.py +5 -6
- rasa/dialogue_understanding/commands/error_command.py +1 -1
- rasa/dialogue_understanding/commands/human_handoff_command.py +3 -3
- 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 +8 -4
- rasa/dialogue_understanding/commands/skip_question_command.py +3 -3
- rasa/dialogue_understanding/commands/start_flow_command.py +7 -3
- 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/llm_based_command_generator.py +1 -2
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +3 -2
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +2 -2
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_template.jinja2 +0 -2
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +1 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +1 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +79 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +79 -0
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +26 -461
- 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 +461 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +20 -64
- rasa/dialogue_understanding/patterns/cancel.py +1 -2
- rasa/dialogue_understanding/patterns/clarify.py +1 -1
- rasa/dialogue_understanding/patterns/correction.py +2 -2
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +42 -27
- rasa/dialogue_understanding/patterns/domain_for_patterns.py +190 -0
- rasa/dialogue_understanding/processor/command_processor.py +6 -7
- rasa/dialogue_understanding_test/command_metric_calculation.py +7 -40
- rasa/dialogue_understanding_test/command_metrics.py +38 -0
- rasa/dialogue_understanding_test/du_test_case.py +58 -25
- rasa/dialogue_understanding_test/du_test_result.py +228 -132
- rasa/dialogue_understanding_test/du_test_runner.py +11 -2
- rasa/dialogue_understanding_test/du_test_schema.yml +3 -3
- rasa/dialogue_understanding_test/io.py +35 -8
- rasa/e2e_test/constants.py +1 -1
- rasa/e2e_test/e2e_test_runner.py +1 -1
- rasa/e2e_test/e2e_test_schema.yml +3 -3
- rasa/engine/constants.py +1 -1
- rasa/engine/graph.py +2 -2
- rasa/engine/recipes/default_recipe.py +1 -1
- rasa/engine/validation.py +3 -2
- rasa/hooks.py +2 -30
- rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +2 -6
- rasa/model_manager/model_api.py +89 -1
- rasa/model_manager/runner_service.py +20 -4
- rasa/model_manager/socket_bridge.py +0 -7
- rasa/model_manager/trainer_service.py +10 -4
- rasa/plugin.py +2 -15
- 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 +393 -0
- rasa/privacy/privacy_manager.py +594 -0
- rasa/server.py +23 -2
- rasa/shared/constants.py +17 -0
- rasa/shared/core/command_payload_reader.py +1 -5
- rasa/shared/core/constants.py +4 -3
- rasa/shared/core/domain.py +172 -11
- rasa/shared/core/events.py +100 -6
- rasa/shared/core/flows/flow.py +30 -5
- 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/flows_yaml_schema.json +3 -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 +71 -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/validation.py +25 -5
- rasa/shared/core/flows/yaml_flows_io.py +106 -5
- rasa/shared/core/slots.py +29 -1
- rasa/shared/core/trackers.py +21 -10
- rasa/shared/core/training_data/story_reader/yaml_story_reader.py +1 -4
- rasa/shared/importers/importer.py +8 -0
- rasa/shared/providers/_configs/azure_openai_client_config.py +2 -2
- rasa/shared/providers/_configs/default_litellm_client_config.py +1 -1
- rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +1 -1
- rasa/shared/providers/_configs/openai_client_config.py +1 -1
- rasa/shared/providers/_configs/rasa_llm_client_config.py +1 -1
- rasa/shared/providers/_configs/self_hosted_llm_client_config.py +1 -1
- rasa/shared/providers/_configs/utils.py +0 -99
- rasa/shared/providers/llm/default_litellm_llm_client.py +2 -2
- rasa/shared/utils/common.py +43 -1
- rasa/shared/utils/configs.py +110 -0
- rasa/shared/utils/constants.py +0 -3
- rasa/shared/utils/llm.py +245 -8
- rasa/shared/utils/pykwalify_extensions.py +0 -9
- rasa/shared/utils/yaml.py +32 -0
- rasa/studio/constants.py +1 -0
- rasa/studio/data_handler.py +33 -12
- rasa/studio/download.py +117 -435
- rasa/studio/link.py +211 -0
- rasa/studio/prompts.py +221 -0
- rasa/studio/pull/__init__.py +0 -0
- rasa/studio/pull/data.py +222 -0
- rasa/studio/pull/domains.py +60 -0
- rasa/studio/pull/pull.py +239 -0
- rasa/studio/push.py +138 -0
- rasa/studio/results_logger.py +6 -1
- rasa/studio/train.py +1 -1
- rasa/studio/upload.py +243 -72
- rasa/studio/utils.py +33 -0
- rasa/telemetry.py +83 -26
- rasa/tracing/config.py +4 -5
- rasa/tracing/constants.py +19 -1
- rasa/tracing/instrumentation/attribute_extractors.py +68 -16
- 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 +43 -22
- rasa/utils/endpoints.py +22 -1
- rasa/utils/licensing.py +2 -3
- rasa/utils/log_utils.py +1 -45
- rasa/validator.py +2 -8
- rasa/version.py +1 -1
- {rasa_pro-3.12.21.dist-info → rasa_pro-3.13.0.dist-info}/METADATA +13 -14
- {rasa_pro-3.12.21.dist-info → rasa_pro-3.13.0.dist-info}/RECORD +333 -309
- 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/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-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/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/information_retrieval/ingestion}/__init__.py +0 -0
- {rasa_pro-3.12.21.dist-info → rasa_pro-3.13.0.dist-info}/NOTICE +0 -0
- {rasa_pro-3.12.21.dist-info → rasa_pro-3.13.0.dist-info}/WHEEL +0 -0
- {rasa_pro-3.12.21.dist-info → rasa_pro-3.13.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import itertools
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Any, Dict, Iterable, Iterator, List, Optional, Text
|
|
6
|
+
|
|
7
|
+
import structlog
|
|
8
|
+
from pymongo.synchronous.collection import Collection
|
|
9
|
+
|
|
10
|
+
from rasa.core.brokers.broker import EventBroker
|
|
11
|
+
from rasa.core.tracker_stores.tracker_store import SerializedTrackerAsText, TrackerStore
|
|
12
|
+
from rasa.shared.core.domain import Domain
|
|
13
|
+
from rasa.shared.core.events import SessionStarted
|
|
14
|
+
from rasa.shared.core.trackers import DialogueStateTracker, EventVerbosity
|
|
15
|
+
|
|
16
|
+
structlogger = structlog.get_logger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class MongoTrackerStore(TrackerStore, SerializedTrackerAsText):
|
|
20
|
+
"""Stores conversation history in Mongo.
|
|
21
|
+
|
|
22
|
+
Property methods:
|
|
23
|
+
conversations: returns the current conversation
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
domain: Domain,
|
|
29
|
+
host: Optional[Text] = "mongodb://localhost:27017",
|
|
30
|
+
db: Optional[Text] = "rasa",
|
|
31
|
+
username: Optional[Text] = None,
|
|
32
|
+
password: Optional[Text] = None,
|
|
33
|
+
auth_source: Optional[Text] = "admin",
|
|
34
|
+
collection: Text = "conversations",
|
|
35
|
+
event_broker: Optional[EventBroker] = None,
|
|
36
|
+
**kwargs: Dict[Text, Any],
|
|
37
|
+
) -> None:
|
|
38
|
+
from pymongo import MongoClient
|
|
39
|
+
from pymongo.database import Database
|
|
40
|
+
|
|
41
|
+
self.client: MongoClient = MongoClient(
|
|
42
|
+
host,
|
|
43
|
+
username=username,
|
|
44
|
+
password=password,
|
|
45
|
+
authSource=auth_source,
|
|
46
|
+
# delay connect until process forking is done
|
|
47
|
+
connect=False,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
self.db = Database(self.client, db)
|
|
51
|
+
self.collection = collection
|
|
52
|
+
super().__init__(domain, event_broker, **kwargs)
|
|
53
|
+
|
|
54
|
+
self._ensure_indices()
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def conversations(self) -> Collection:
|
|
58
|
+
"""Returns the current conversation."""
|
|
59
|
+
return self.db[self.collection]
|
|
60
|
+
|
|
61
|
+
def _ensure_indices(self) -> None:
|
|
62
|
+
"""Create an index on the sender_id."""
|
|
63
|
+
self.conversations.create_index("sender_id")
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def _current_tracker_state_without_events(tracker: DialogueStateTracker) -> Dict:
|
|
67
|
+
# get current tracker state and remove `events` key from state
|
|
68
|
+
# since events are pushed separately in the `update_one()` operation
|
|
69
|
+
state = tracker.current_state(EventVerbosity.ALL)
|
|
70
|
+
state.pop("events", None)
|
|
71
|
+
|
|
72
|
+
return state
|
|
73
|
+
|
|
74
|
+
async def delete(self, sender_id: Text) -> None:
|
|
75
|
+
"""Delete tracker for the given sender_id.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
sender_id: Sender id of the tracker to be deleted.
|
|
79
|
+
"""
|
|
80
|
+
if not await self.exists(sender_id):
|
|
81
|
+
structlogger.info(
|
|
82
|
+
"mongo_tracker_store.delete.no_tracker_for_sender_id",
|
|
83
|
+
event_info=f"Could not find tracker for conversation ID '{sender_id}'.",
|
|
84
|
+
)
|
|
85
|
+
return None
|
|
86
|
+
self.conversations.delete_one({"sender_id": sender_id})
|
|
87
|
+
|
|
88
|
+
structlogger.info(
|
|
89
|
+
"mongo_tracker_store.delete.deleted_tracker",
|
|
90
|
+
sender_id=sender_id,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
async def save(self, tracker: DialogueStateTracker) -> None:
|
|
94
|
+
"""Saves the current conversation state."""
|
|
95
|
+
await self.stream_events(tracker)
|
|
96
|
+
|
|
97
|
+
additional_events = self._additional_events(tracker)
|
|
98
|
+
|
|
99
|
+
self.conversations.update_one(
|
|
100
|
+
{"sender_id": tracker.sender_id},
|
|
101
|
+
{
|
|
102
|
+
"$set": self._current_tracker_state_without_events(tracker),
|
|
103
|
+
"$push": {
|
|
104
|
+
"events": {"$each": [e.as_dict() for e in additional_events]}
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
upsert=True,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
def _additional_events(self, tracker: DialogueStateTracker) -> Iterator:
|
|
111
|
+
"""Return events from the tracker which aren't currently stored.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
tracker: Tracker to inspect.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
List of serialised events that aren't currently stored.
|
|
118
|
+
|
|
119
|
+
"""
|
|
120
|
+
stored = self.conversations.find_one({"sender_id": tracker.sender_id}) or {}
|
|
121
|
+
all_events = self._events_from_serialized_tracker(stored)
|
|
122
|
+
|
|
123
|
+
number_events_since_last_session = len(
|
|
124
|
+
self._events_since_last_session_start(all_events)
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
return itertools.islice(
|
|
128
|
+
tracker.events, number_events_since_last_session, len(tracker.events)
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
@staticmethod
|
|
132
|
+
def _events_from_serialized_tracker(serialised: Dict) -> List[Dict]:
|
|
133
|
+
return serialised.get("events", [])
|
|
134
|
+
|
|
135
|
+
@staticmethod
|
|
136
|
+
def _events_since_last_session_start(events: List[Dict]) -> List[Dict]:
|
|
137
|
+
"""Retrieve events since and including the latest `SessionStart` event.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
events: All events for a conversation ID.
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
List of serialised events since and including the latest `SessionStarted`
|
|
144
|
+
event. Returns all events if no such event is found.
|
|
145
|
+
|
|
146
|
+
"""
|
|
147
|
+
events_after_session_start = []
|
|
148
|
+
for event in reversed(events):
|
|
149
|
+
events_after_session_start.append(event)
|
|
150
|
+
if event["event"] == SessionStarted.type_name:
|
|
151
|
+
break
|
|
152
|
+
|
|
153
|
+
return list(reversed(events_after_session_start))
|
|
154
|
+
|
|
155
|
+
async def _retrieve(
|
|
156
|
+
self, sender_id: Text, fetch_events_from_all_sessions: bool
|
|
157
|
+
) -> Optional[List[Dict[Text, Any]]]:
|
|
158
|
+
stored = self.conversations.find_one({"sender_id": sender_id})
|
|
159
|
+
|
|
160
|
+
# look for conversations which have used an `int` sender_id in the past
|
|
161
|
+
# and update them.
|
|
162
|
+
if not stored and sender_id.isdigit():
|
|
163
|
+
from pymongo import ReturnDocument
|
|
164
|
+
|
|
165
|
+
stored = self.conversations.find_one_and_update(
|
|
166
|
+
{"sender_id": int(sender_id)},
|
|
167
|
+
{"$set": {"sender_id": str(sender_id)}},
|
|
168
|
+
return_document=ReturnDocument.AFTER,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
if not stored:
|
|
172
|
+
return None
|
|
173
|
+
|
|
174
|
+
events = self._events_from_serialized_tracker(stored)
|
|
175
|
+
|
|
176
|
+
if not fetch_events_from_all_sessions:
|
|
177
|
+
events = self._events_since_last_session_start(events)
|
|
178
|
+
|
|
179
|
+
return events
|
|
180
|
+
|
|
181
|
+
async def retrieve(self, sender_id: Text) -> Optional[DialogueStateTracker]:
|
|
182
|
+
"""Retrieves tracker for the latest conversation session."""
|
|
183
|
+
events = await self._retrieve(sender_id, fetch_events_from_all_sessions=False)
|
|
184
|
+
|
|
185
|
+
if not events:
|
|
186
|
+
return None
|
|
187
|
+
|
|
188
|
+
return DialogueStateTracker.from_dict(sender_id, events, self.domain.slots)
|
|
189
|
+
|
|
190
|
+
async def retrieve_full_tracker(
|
|
191
|
+
self, conversation_id: Text
|
|
192
|
+
) -> Optional[DialogueStateTracker]:
|
|
193
|
+
"""Fetching all tracker events across conversation sessions."""
|
|
194
|
+
events = await self._retrieve(
|
|
195
|
+
conversation_id, fetch_events_from_all_sessions=True
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
if not events:
|
|
199
|
+
return None
|
|
200
|
+
|
|
201
|
+
return DialogueStateTracker.from_dict(
|
|
202
|
+
conversation_id, events, self.domain.slots
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
async def keys(self) -> Iterable[Text]:
|
|
206
|
+
"""Returns sender_ids of the Mongo Tracker Store."""
|
|
207
|
+
return [c["sender_id"] for c in self.conversations.find()]
|
|
208
|
+
|
|
209
|
+
async def update(self, tracker: DialogueStateTracker) -> None:
|
|
210
|
+
"""Overwrites the tracker for the given sender_id."""
|
|
211
|
+
self.conversations.replace_one(
|
|
212
|
+
{"sender_id": tracker.sender_id},
|
|
213
|
+
tracker.current_state(EventVerbosity.ALL),
|
|
214
|
+
upsert=True,
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
first_event_timestamp = str(datetime.fromtimestamp(tracker.events[0].timestamp))
|
|
218
|
+
|
|
219
|
+
structlogger.info(
|
|
220
|
+
"redis_tracker_store.update.updated_tracker",
|
|
221
|
+
sender_id=tracker.sender_id,
|
|
222
|
+
first_event_timestamp=first_event_timestamp,
|
|
223
|
+
)
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from typing import Any, Dict, Iterable, Optional, Text
|
|
5
|
+
|
|
6
|
+
import structlog
|
|
7
|
+
|
|
8
|
+
import rasa.shared
|
|
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.trackers import DialogueStateTracker
|
|
13
|
+
|
|
14
|
+
structlogger = structlog.get_logger(__name__)
|
|
15
|
+
|
|
16
|
+
# default value for key prefix in RedisTrackerStore
|
|
17
|
+
DEFAULT_REDIS_TRACKER_STORE_KEY_PREFIX = "tracker:"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class RedisTrackerStore(TrackerStore, SerializedTrackerAsText):
|
|
21
|
+
"""Stores conversation history in Redis."""
|
|
22
|
+
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
domain: Domain,
|
|
26
|
+
host: Text = "localhost",
|
|
27
|
+
port: int = 6379,
|
|
28
|
+
db: int = 0,
|
|
29
|
+
username: Optional[Text] = None,
|
|
30
|
+
password: Optional[Text] = None,
|
|
31
|
+
event_broker: Optional[EventBroker] = None,
|
|
32
|
+
record_exp: Optional[float] = None,
|
|
33
|
+
key_prefix: Optional[Text] = None,
|
|
34
|
+
use_ssl: bool = False,
|
|
35
|
+
ssl_keyfile: Optional[Text] = None,
|
|
36
|
+
ssl_certfile: Optional[Text] = None,
|
|
37
|
+
ssl_ca_certs: Optional[Text] = None,
|
|
38
|
+
**kwargs: Dict[Text, Any],
|
|
39
|
+
) -> None:
|
|
40
|
+
"""Initializes the tracker store."""
|
|
41
|
+
import redis
|
|
42
|
+
|
|
43
|
+
self.red = redis.StrictRedis(
|
|
44
|
+
host=host,
|
|
45
|
+
port=port,
|
|
46
|
+
db=db,
|
|
47
|
+
username=username,
|
|
48
|
+
password=password,
|
|
49
|
+
ssl=use_ssl,
|
|
50
|
+
ssl_keyfile=ssl_keyfile,
|
|
51
|
+
ssl_certfile=ssl_certfile,
|
|
52
|
+
ssl_ca_certs=ssl_ca_certs,
|
|
53
|
+
decode_responses=True,
|
|
54
|
+
)
|
|
55
|
+
self.record_exp = record_exp
|
|
56
|
+
|
|
57
|
+
self.key_prefix = DEFAULT_REDIS_TRACKER_STORE_KEY_PREFIX
|
|
58
|
+
if key_prefix:
|
|
59
|
+
structlogger.debug(
|
|
60
|
+
"redis_tracker_store.init.custom_key_prefix",
|
|
61
|
+
event_info=f"Setting non-default redis key prefix: '{key_prefix}'.",
|
|
62
|
+
)
|
|
63
|
+
self._set_key_prefix(key_prefix)
|
|
64
|
+
|
|
65
|
+
super().__init__(domain, event_broker, **kwargs)
|
|
66
|
+
|
|
67
|
+
def _set_key_prefix(self, key_prefix: Text) -> None:
|
|
68
|
+
if isinstance(key_prefix, str) and key_prefix.isalnum():
|
|
69
|
+
self.key_prefix = key_prefix + ":" + DEFAULT_REDIS_TRACKER_STORE_KEY_PREFIX
|
|
70
|
+
else:
|
|
71
|
+
structlogger.warning(
|
|
72
|
+
"redis_tracker_store.init.invalid_key_prefix",
|
|
73
|
+
event_info=(
|
|
74
|
+
f"Omitting provided non-alphanumeric "
|
|
75
|
+
f"redis key prefix: '{key_prefix}'. "
|
|
76
|
+
f"Using default '{self.key_prefix}' instead."
|
|
77
|
+
),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
def _get_key_prefix(self) -> Text:
|
|
81
|
+
return self.key_prefix
|
|
82
|
+
|
|
83
|
+
async def save(
|
|
84
|
+
self, tracker: DialogueStateTracker, timeout: Optional[float] = None
|
|
85
|
+
) -> None:
|
|
86
|
+
"""Saves the current conversation state."""
|
|
87
|
+
await self.stream_events(tracker)
|
|
88
|
+
|
|
89
|
+
if not timeout and self.record_exp:
|
|
90
|
+
timeout = self.record_exp
|
|
91
|
+
|
|
92
|
+
# if the sender_id starts with the key prefix, we remove it
|
|
93
|
+
# this is used to avoid storing the prefix twice
|
|
94
|
+
sender_id = tracker.sender_id
|
|
95
|
+
if sender_id.startswith(self.key_prefix):
|
|
96
|
+
sender_id = sender_id[len(self.key_prefix) :]
|
|
97
|
+
|
|
98
|
+
stored = self.red.get(self.key_prefix + sender_id)
|
|
99
|
+
|
|
100
|
+
if stored is not None:
|
|
101
|
+
prior_tracker = self.deserialise_tracker(sender_id, stored)
|
|
102
|
+
|
|
103
|
+
tracker = self._merge_trackers(prior_tracker, tracker)
|
|
104
|
+
|
|
105
|
+
serialised_tracker = self.serialise_tracker(tracker)
|
|
106
|
+
self.red.set(self.key_prefix + sender_id, serialised_tracker, ex=timeout)
|
|
107
|
+
|
|
108
|
+
async def delete(self, sender_id: Text) -> None:
|
|
109
|
+
"""Delete tracker for the given sender_id.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
sender_id: Sender id of the tracker to be deleted.
|
|
113
|
+
"""
|
|
114
|
+
if not await self.exists(sender_id):
|
|
115
|
+
structlogger.info(
|
|
116
|
+
"redis_tracker_store.delete.no_tracker_for_sender_id",
|
|
117
|
+
event_info=f"Could not find tracker for conversation ID '{sender_id}'.",
|
|
118
|
+
)
|
|
119
|
+
return None
|
|
120
|
+
|
|
121
|
+
if sender_id.startswith(self.key_prefix):
|
|
122
|
+
sender_id = sender_id[len(self.key_prefix) :]
|
|
123
|
+
|
|
124
|
+
self.red.delete(self.key_prefix + sender_id)
|
|
125
|
+
structlogger.info(
|
|
126
|
+
"redis_tracker_store.delete.deleted_tracker",
|
|
127
|
+
sender_id=sender_id,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
async def retrieve(self, sender_id: Text) -> Optional[DialogueStateTracker]:
|
|
131
|
+
"""Retrieves tracker for the latest conversation session.
|
|
132
|
+
|
|
133
|
+
The Redis key is formed by appending a prefix to sender_id.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
sender_id: Conversation ID to fetch the tracker for.
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
Tracker containing events from the latest conversation sessions.
|
|
140
|
+
"""
|
|
141
|
+
return await self._retrieve(sender_id, fetch_all_sessions=False)
|
|
142
|
+
|
|
143
|
+
async def retrieve_full_tracker(
|
|
144
|
+
self, sender_id: Text
|
|
145
|
+
) -> Optional[DialogueStateTracker]:
|
|
146
|
+
"""Retrieves tracker for all conversation sessions.
|
|
147
|
+
|
|
148
|
+
The Redis key is formed by appending a prefix to sender_id.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
sender_id: Conversation ID to fetch the tracker for.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
Tracker containing events from all conversation sessions.
|
|
155
|
+
"""
|
|
156
|
+
return await self._retrieve(sender_id, fetch_all_sessions=True)
|
|
157
|
+
|
|
158
|
+
async def _retrieve(
|
|
159
|
+
self, sender_id: Text, fetch_all_sessions: bool
|
|
160
|
+
) -> Optional[DialogueStateTracker]:
|
|
161
|
+
"""Returns tracker matching sender_id.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
sender_id: Conversation ID to fetch the tracker for.
|
|
165
|
+
fetch_all_sessions: Whether to fetch all sessions or only the last one.
|
|
166
|
+
"""
|
|
167
|
+
if sender_id.startswith(self.key_prefix):
|
|
168
|
+
sender_id = sender_id[len(self.key_prefix) :]
|
|
169
|
+
|
|
170
|
+
stored = self.red.get(self.key_prefix + sender_id)
|
|
171
|
+
if stored is None:
|
|
172
|
+
structlogger.debug(
|
|
173
|
+
"redis_tracker_store.retrieve.no_tracker_for_sender_id",
|
|
174
|
+
event_info=f"Could not find tracker for conversation ID '{sender_id}'.",
|
|
175
|
+
)
|
|
176
|
+
return None
|
|
177
|
+
|
|
178
|
+
tracker = self.deserialise_tracker(sender_id, stored)
|
|
179
|
+
if fetch_all_sessions:
|
|
180
|
+
return tracker
|
|
181
|
+
|
|
182
|
+
# only return the last session
|
|
183
|
+
multiple_tracker_sessions = (
|
|
184
|
+
rasa.shared.core.trackers.get_trackers_for_conversation_sessions(tracker)
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
if len(multiple_tracker_sessions) <= 1:
|
|
188
|
+
return tracker
|
|
189
|
+
|
|
190
|
+
return multiple_tracker_sessions[-1]
|
|
191
|
+
|
|
192
|
+
async def keys(self) -> Iterable[Text]:
|
|
193
|
+
"""Returns keys of the Redis Tracker Store."""
|
|
194
|
+
return self.red.keys(self.key_prefix + "*")
|
|
195
|
+
|
|
196
|
+
@staticmethod
|
|
197
|
+
def _merge_trackers(
|
|
198
|
+
prior_tracker: DialogueStateTracker, tracker: DialogueStateTracker
|
|
199
|
+
) -> DialogueStateTracker:
|
|
200
|
+
"""Merges two trackers.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
prior_tracker: Tracker containing events from the previous conversation
|
|
204
|
+
sessions.
|
|
205
|
+
tracker: Tracker containing events from the current conversation session.
|
|
206
|
+
"""
|
|
207
|
+
if not prior_tracker.events:
|
|
208
|
+
return tracker
|
|
209
|
+
|
|
210
|
+
last_event_timestamp = prior_tracker.events[-1].timestamp
|
|
211
|
+
past_tracker = tracker.travel_back_in_time(target_time=last_event_timestamp)
|
|
212
|
+
|
|
213
|
+
if past_tracker.events == prior_tracker.events:
|
|
214
|
+
return tracker
|
|
215
|
+
|
|
216
|
+
merged = tracker.init_copy()
|
|
217
|
+
merged.update_with_events(list(prior_tracker.events), override_timestamp=False)
|
|
218
|
+
|
|
219
|
+
for new_event in tracker.events:
|
|
220
|
+
# Event subclasses implement `__eq__` method that make it difficult
|
|
221
|
+
# to compare events. We use `as_dict` to compare events.
|
|
222
|
+
if all(
|
|
223
|
+
[
|
|
224
|
+
new_event.as_dict() != existing_event.as_dict()
|
|
225
|
+
for existing_event in merged.events
|
|
226
|
+
]
|
|
227
|
+
):
|
|
228
|
+
merged.update(new_event)
|
|
229
|
+
|
|
230
|
+
return merged
|
|
231
|
+
|
|
232
|
+
async def update(self, tracker: DialogueStateTracker) -> None:
|
|
233
|
+
"""Overwrites the tracker for the given sender_id."""
|
|
234
|
+
serialised_tracker = self.serialise_tracker(tracker)
|
|
235
|
+
|
|
236
|
+
# if the sender_id starts with the key prefix, we remove it
|
|
237
|
+
# this is used to avoid storing the prefix twice
|
|
238
|
+
sender_id = tracker.sender_id
|
|
239
|
+
if sender_id.startswith(self.key_prefix):
|
|
240
|
+
sender_id = sender_id[len(self.key_prefix) :]
|
|
241
|
+
|
|
242
|
+
self.red.set(
|
|
243
|
+
self.key_prefix + sender_id, serialised_tracker, ex=self.record_exp
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
first_event_timestamp = str(datetime.fromtimestamp(tracker.events[0].timestamp))
|
|
247
|
+
|
|
248
|
+
structlogger.info(
|
|
249
|
+
"redis_tracker_store.update.updated_tracker",
|
|
250
|
+
sender_id=tracker.sender_id,
|
|
251
|
+
first_event_timestamp=first_event_timestamp,
|
|
252
|
+
)
|