rasa-pro 3.11.4__py3-none-any.whl → 3.12.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.
- README.md +10 -13
- rasa/__main__.py +7 -7
- rasa/anonymization/anonymisation_rule_yaml_reader.py +1 -1
- rasa/anonymization/anonymization_pipeline.py +3 -3
- rasa/anonymization/anonymization_rule_executor.py +17 -11
- rasa/anonymization/anonymization_rule_orchestrator.py +2 -3
- rasa/cli/arguments/data.py +2 -2
- rasa/cli/arguments/default_arguments.py +1 -1
- rasa/cli/arguments/evaluate.py +2 -1
- rasa/cli/arguments/interactive.py +1 -1
- rasa/cli/arguments/run.py +1 -1
- rasa/cli/arguments/test.py +7 -5
- rasa/cli/arguments/train.py +3 -3
- rasa/cli/arguments/visualize.py +2 -2
- rasa/cli/arguments/x.py +1 -0
- rasa/cli/data.py +20 -3
- rasa/cli/dialogue_understanding_test.py +386 -0
- rasa/cli/evaluate.py +1 -1
- rasa/cli/export.py +6 -6
- rasa/cli/inspect.py +20 -1
- rasa/cli/interactive.py +4 -5
- rasa/cli/llm_fine_tuning.py +51 -16
- rasa/cli/markers.py +1 -2
- rasa/cli/project_templates/calm/actions/add_contact.py +1 -1
- rasa/cli/project_templates/calm/config.yml +2 -2
- rasa/cli/project_templates/calm/domain/list_contacts.yml +1 -2
- rasa/cli/project_templates/calm/domain/remove_contact.yml +1 -2
- rasa/cli/project_templates/calm/domain/shared.yml +1 -4
- rasa/cli/project_templates/calm/endpoints.yml +2 -2
- rasa/cli/project_templates/tutorial/actions/actions.py +3 -2
- rasa/cli/shell.py +5 -6
- rasa/cli/studio/download.py +1 -2
- rasa/cli/studio/studio.py +2 -3
- rasa/cli/studio/train.py +0 -1
- rasa/cli/telemetry.py +2 -2
- rasa/cli/test.py +11 -11
- rasa/cli/train.py +3 -0
- rasa/cli/utils.py +25 -5
- rasa/constants.py +0 -1
- rasa/core/__init__.py +0 -1
- rasa/core/actions/action.py +137 -208
- rasa/core/actions/action_handle_digressions.py +164 -0
- rasa/core/actions/action_hangup.py +1 -1
- rasa/core/actions/action_repeat_bot_messages.py +2 -2
- rasa/core/actions/action_run_slot_rejections.py +18 -6
- rasa/core/actions/action_trigger_chitchat.py +1 -1
- rasa/core/actions/action_trigger_flow.py +5 -5
- rasa/core/actions/action_trigger_search.py +1 -1
- rasa/core/actions/custom_action_executor.py +1 -1
- rasa/core/actions/direct_custom_actions_executor.py +1 -0
- rasa/core/actions/forms.py +22 -15
- rasa/core/actions/http_custom_action_executor.py +8 -1
- rasa/core/actions/loops.py +3 -3
- rasa/core/actions/two_stage_fallback.py +13 -13
- rasa/core/auth_retry_tracker_store.py +1 -2
- rasa/core/brokers/broker.py +2 -1
- rasa/core/brokers/file.py +1 -1
- rasa/core/brokers/kafka.py +8 -8
- rasa/core/brokers/pika.py +8 -9
- rasa/core/brokers/sql.py +4 -3
- rasa/core/channels/__init__.py +7 -0
- rasa/core/channels/botframework.py +2 -2
- rasa/core/channels/callback.py +4 -4
- rasa/core/channels/channel.py +11 -11
- rasa/core/channels/console.py +0 -1
- rasa/core/channels/development_inspector.py +80 -24
- rasa/core/channels/facebook.py +5 -5
- rasa/core/channels/hangouts.py +7 -8
- rasa/core/channels/inspector/dist/assets/Tableau10-1b767f5e.js +1 -0
- rasa/core/channels/inspector/dist/assets/arc-9f1365dc.js +1 -0
- rasa/core/channels/inspector/dist/assets/blockDiagram-38ab4fdb-e0f81b12.js +118 -0
- rasa/core/channels/inspector/dist/assets/c4Diagram-3d4e48cf-9deaee1c.js +10 -0
- rasa/core/channels/inspector/dist/assets/channel-44956714.js +1 -0
- rasa/core/channels/inspector/dist/assets/classDiagram-70f12bd4-20450a96.js +2 -0
- rasa/core/channels/inspector/dist/assets/classDiagram-v2-f2320105-749d2abf.js +2 -0
- rasa/core/channels/inspector/dist/assets/clone-a9475142.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-62fc7601-89c73b31.js → createText-2e5e7dd3-bef0b38c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/edges-e0da2a9e-943801a7.js +4 -0
- rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-907e0440.js → erDiagram-9861fffd-d523a948.js} +4 -4
- rasa/core/channels/inspector/dist/assets/flowDb-956e92f1-54e4cf19.js +10 -0
- rasa/core/channels/inspector/dist/assets/flowDiagram-66a62f08-48bfbbe8.js +4 -0
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-43fa749a.js +1 -0
- rasa/core/channels/inspector/dist/assets/flowchart-elk-definition-4a651766-17c30827.js +139 -0
- rasa/core/channels/inspector/dist/assets/ganttDiagram-c361ad54-43086f2d.js +257 -0
- rasa/core/channels/inspector/dist/assets/gitGraphDiagram-72cf32ee-5c8b693e.js +70 -0
- rasa/core/channels/inspector/dist/assets/graph-41a90d26.js +1 -0
- rasa/core/channels/inspector/dist/assets/index-3862675e-b43eeae9.js +1 -0
- rasa/core/channels/inspector/dist/assets/{index-e793d777.js → index-e8affe45.js} +201 -196
- rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-8ceba4db.js → infoDiagram-f8f76790-0b20676b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-960d3809.js → journeyDiagram-49397b02-39bce7b5.js} +4 -4
- rasa/core/channels/inspector/dist/assets/katex-498eb57e.js +261 -0
- rasa/core/channels/inspector/dist/assets/layout-dc8eeea4.js +1 -0
- rasa/core/channels/inspector/dist/assets/{line-eeccc4e2.js → line-c4d2e756.js} +1 -1
- rasa/core/channels/inspector/dist/assets/linear-86f6f2d9.js +1 -0
- rasa/core/channels/inspector/dist/assets/mindmap-definition-fc14e90a-4216f771.js +312 -0
- rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-dc9b5e1b.js → pieDiagram-8a3498a8-1a0cfa96.js} +7 -7
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-a08cba6d.js → quadrantDiagram-120e2f19-f91e67cf.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-87242b9e.js → requirementDiagram-deff3bca-d4046bed.js} +2 -2
- rasa/core/channels/inspector/dist/assets/sankeyDiagram-04a897e0-2cf6d1d7.js +8 -0
- rasa/core/channels/inspector/dist/assets/sequenceDiagram-704730f1-751ac4f5.js +122 -0
- rasa/core/channels/inspector/dist/assets/stateDiagram-587899a1-f734f4d4.js +1 -0
- rasa/core/channels/inspector/dist/assets/stateDiagram-v2-d93cdb3a-91c65710.js +1 -0
- rasa/core/channels/inspector/dist/assets/{styles-9c745c82-cef936a6.js → styles-6aaf32cf-e0cff7be.js} +1 -1
- rasa/core/channels/inspector/dist/assets/styles-9a916d00-c8029e5d.js +160 -0
- rasa/core/channels/inspector/dist/assets/styles-c10674c1-114f312a.js +116 -0
- rasa/core/channels/inspector/dist/assets/svgDrawCommon-08f97a94-b7b9dc00.js +1 -0
- rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-0d39bdb2.js → timeline-definition-85554ec2-9536d189.js} +3 -3
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-a03fa445.js → xychartDiagram-e933f94c-bf3b0f36.js} +3 -3
- rasa/core/channels/inspector/dist/index.html +1 -1
- rasa/core/channels/inspector/package.json +11 -3
- rasa/core/channels/inspector/src/App.tsx +15 -2
- rasa/core/channels/inspector/src/components/RasaLogo.tsx +31 -0
- rasa/core/channels/inspector/src/components/RecruitmentPanel.tsx +68 -0
- rasa/core/channels/inspector/src/components/Welcome.tsx +19 -13
- rasa/core/channels/inspector/yarn.lock +94 -99
- rasa/core/channels/mattermost.py +4 -4
- rasa/core/channels/rasa_chat.py +4 -4
- rasa/core/channels/rest.py +11 -12
- rasa/core/channels/rocketchat.py +4 -3
- rasa/core/channels/slack.py +6 -5
- rasa/core/channels/socketio.py +8 -28
- rasa/core/channels/studio_chat.py +212 -0
- rasa/core/channels/telegram.py +105 -55
- rasa/core/channels/twilio.py +3 -3
- rasa/core/channels/vier_cvg.py +2 -2
- rasa/core/channels/voice_ready/audiocodes.py +51 -32
- rasa/core/channels/voice_ready/jambonz.py +5 -5
- rasa/core/channels/voice_ready/jambonz_protocol.py +3 -4
- rasa/core/channels/voice_ready/twilio_voice.py +9 -8
- rasa/core/channels/voice_ready/utils.py +2 -2
- rasa/core/channels/voice_stream/asr/asr_engine.py +12 -6
- rasa/core/channels/voice_stream/asr/asr_event.py +5 -0
- rasa/core/channels/voice_stream/asr/azure.py +16 -3
- rasa/core/channels/voice_stream/asr/deepgram.py +76 -19
- rasa/core/channels/voice_stream/audiocodes.py +292 -0
- rasa/core/channels/voice_stream/browser_audio.py +14 -7
- rasa/core/channels/voice_stream/call_state.py +6 -2
- rasa/core/channels/voice_stream/genesys.py +320 -0
- rasa/core/channels/voice_stream/tts/azure.py +13 -5
- rasa/core/channels/voice_stream/tts/cartesia.py +34 -14
- rasa/core/channels/voice_stream/tts/tts_cache.py +3 -2
- rasa/core/channels/voice_stream/tts/tts_engine.py +1 -1
- rasa/core/channels/voice_stream/twilio_media_streams.py +12 -8
- rasa/core/channels/voice_stream/util.py +1 -1
- rasa/core/channels/voice_stream/voice_channel.py +100 -56
- rasa/core/channels/webexteams.py +3 -4
- rasa/core/constants.py +2 -0
- rasa/core/evaluation/marker.py +7 -6
- rasa/core/evaluation/marker_base.py +15 -16
- rasa/core/evaluation/marker_stats.py +3 -4
- rasa/core/evaluation/marker_tracker_loader.py +5 -4
- rasa/core/exporter.py +4 -4
- rasa/core/featurizers/precomputation.py +8 -8
- rasa/core/featurizers/single_state_featurizer.py +7 -7
- rasa/core/featurizers/tracker_featurizers.py +13 -13
- rasa/core/http_interpreter.py +3 -4
- rasa/core/information_retrieval/__init__.py +1 -1
- rasa/core/information_retrieval/faiss.py +4 -4
- rasa/core/information_retrieval/information_retrieval.py +2 -2
- rasa/core/information_retrieval/milvus.py +3 -3
- rasa/core/information_retrieval/qdrant.py +3 -3
- rasa/core/jobs.py +1 -0
- rasa/core/lock.py +2 -3
- rasa/core/lock_store.py +3 -3
- rasa/core/migrate.py +12 -9
- rasa/core/nlg/__init__.py +1 -1
- rasa/core/nlg/callback.py +2 -3
- rasa/core/nlg/contextual_response_rephraser.py +82 -14
- rasa/core/nlg/generator.py +85 -17
- rasa/core/nlg/interpolator.py +4 -3
- rasa/core/nlg/response.py +9 -7
- rasa/core/nlg/summarize.py +1 -0
- rasa/core/nlg/translate.py +55 -0
- rasa/core/persistor.py +3 -3
- rasa/core/policies/ensemble.py +10 -9
- rasa/core/policies/enterprise_search_policy.py +87 -21
- rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +1 -1
- rasa/core/policies/flow_policy.py +13 -14
- rasa/core/policies/flows/flow_executor.py +85 -55
- rasa/core/policies/intentless_policy.py +6 -7
- rasa/core/policies/memoization.py +22 -20
- rasa/core/policies/policy.py +24 -22
- rasa/core/policies/rule_policy.py +37 -36
- rasa/core/policies/ted_policy.py +87 -85
- rasa/core/policies/unexpected_intent_policy.py +77 -75
- rasa/core/processor.py +167 -74
- rasa/core/run.py +5 -4
- rasa/core/secrets_manager/endpoints.py +2 -3
- rasa/core/secrets_manager/factory.py +2 -3
- rasa/core/secrets_manager/secret_manager.py +2 -3
- rasa/core/secrets_manager/vault.py +2 -2
- rasa/core/test.py +30 -30
- rasa/core/tracker_store.py +138 -49
- rasa/core/train.py +1 -1
- rasa/core/training/__init__.py +2 -2
- rasa/core/training/converters/responses_prefix_converter.py +1 -2
- rasa/core/training/interactive.py +13 -13
- rasa/core/training/story_conflict.py +4 -5
- rasa/core/training/training.py +3 -5
- rasa/core/utils.py +5 -5
- rasa/core/visualize.py +1 -1
- rasa/dialogue_understanding/coexistence/intent_based_router.py +2 -2
- rasa/dialogue_understanding/coexistence/llm_based_router.py +5 -5
- rasa/dialogue_understanding/commands/__init__.py +22 -22
- rasa/dialogue_understanding/commands/can_not_handle_command.py +38 -1
- rasa/dialogue_understanding/commands/cancel_flow_command.py +96 -9
- rasa/dialogue_understanding/commands/change_flow_command.py +36 -2
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +36 -4
- rasa/dialogue_understanding/commands/clarify_command.py +46 -4
- rasa/dialogue_understanding/commands/command.py +3 -2
- rasa/dialogue_understanding/commands/command_syntax_manager.py +55 -0
- rasa/dialogue_understanding/commands/correct_slots_command.py +14 -5
- rasa/dialogue_understanding/commands/error_command.py +1 -1
- rasa/dialogue_understanding/commands/free_form_answer_command.py +2 -1
- rasa/dialogue_understanding/commands/handle_code_change_command.py +2 -2
- rasa/dialogue_understanding/commands/handle_digressions_command.py +144 -0
- rasa/dialogue_understanding/commands/human_handoff_command.py +34 -4
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +36 -4
- rasa/dialogue_understanding/commands/noop_command.py +2 -1
- rasa/dialogue_understanding/commands/prompt_command.py +94 -0
- rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +34 -4
- rasa/dialogue_understanding/commands/restart_command.py +2 -5
- rasa/dialogue_understanding/commands/session_end_command.py +3 -5
- rasa/dialogue_understanding/commands/session_start_command.py +3 -5
- rasa/dialogue_understanding/commands/set_slot_command.py +55 -16
- rasa/dialogue_understanding/commands/skip_question_command.py +34 -4
- rasa/dialogue_understanding/commands/start_flow_command.py +78 -2
- rasa/dialogue_understanding/commands/user_silence_command.py +3 -5
- rasa/dialogue_understanding/commands/utils.py +126 -43
- rasa/dialogue_understanding/constants.py +2 -0
- rasa/dialogue_understanding/generator/__init__.py +2 -0
- rasa/dialogue_understanding/generator/command_generator.py +120 -79
- rasa/dialogue_understanding/generator/command_parser.py +245 -0
- rasa/dialogue_understanding/generator/constants.py +12 -4
- rasa/dialogue_understanding/generator/flow_retrieval.py +7 -7
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +187 -59
- rasa/dialogue_understanding/generator/llm_command_generator.py +6 -3
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +106 -110
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +53 -11
- rasa/dialogue_understanding/generator/prompt_templates/__init__.py +0 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +58 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +57 -0
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +574 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +41 -386
- rasa/dialogue_understanding/generator/utils.py +76 -0
- rasa/dialogue_understanding/patterns/cancel.py +2 -1
- rasa/dialogue_understanding/patterns/cannot_handle.py +1 -0
- rasa/dialogue_understanding/patterns/chitchat.py +1 -1
- rasa/dialogue_understanding/patterns/clarify.py +2 -1
- rasa/dialogue_understanding/patterns/code_change.py +2 -0
- rasa/dialogue_understanding/patterns/collect_information.py +7 -4
- rasa/dialogue_understanding/patterns/completed.py +1 -1
- rasa/dialogue_understanding/patterns/continue_interrupted.py +1 -1
- rasa/dialogue_understanding/patterns/correction.py +17 -3
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +78 -2
- rasa/dialogue_understanding/patterns/handle_digressions.py +81 -0
- rasa/dialogue_understanding/patterns/human_handoff.py +1 -1
- rasa/dialogue_understanding/patterns/internal_error.py +1 -0
- rasa/dialogue_understanding/patterns/search.py +1 -1
- rasa/dialogue_understanding/patterns/session_start.py +1 -1
- rasa/dialogue_understanding/patterns/skip_question.py +1 -0
- rasa/dialogue_understanding/patterns/user_silence.py +1 -1
- rasa/dialogue_understanding/patterns/validate_slot.py +65 -0
- rasa/dialogue_understanding/processor/command_processor.py +193 -43
- rasa/dialogue_understanding/processor/command_processor_component.py +1 -1
- rasa/dialogue_understanding/stack/dialogue_stack.py +4 -3
- rasa/dialogue_understanding/stack/frames/__init__.py +2 -2
- rasa/dialogue_understanding/stack/frames/chit_chat_frame.py +4 -1
- rasa/dialogue_understanding/stack/frames/dialogue_stack_frame.py +2 -3
- rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +5 -2
- rasa/dialogue_understanding/stack/frames/search_frame.py +4 -1
- rasa/dialogue_understanding/stack/utils.py +56 -10
- rasa/dialogue_understanding/utils.py +164 -0
- rasa/dialogue_understanding_test/README.md +429 -0
- rasa/dialogue_understanding_test/__init__.py +0 -0
- rasa/dialogue_understanding_test/command_comparison.py +60 -0
- rasa/dialogue_understanding_test/command_metric_calculation.py +122 -0
- rasa/dialogue_understanding_test/constants.py +22 -0
- rasa/dialogue_understanding_test/du_test_case.py +448 -0
- rasa/dialogue_understanding_test/du_test_result.py +390 -0
- rasa/dialogue_understanding_test/du_test_runner.py +322 -0
- rasa/dialogue_understanding_test/du_test_schema.yml +161 -0
- rasa/dialogue_understanding_test/io.py +443 -0
- rasa/dialogue_understanding_test/test_case_simulation/__init__.py +0 -0
- rasa/dialogue_understanding_test/test_case_simulation/exception.py +28 -0
- rasa/dialogue_understanding_test/test_case_simulation/test_case_tracker_simulator.py +336 -0
- rasa/dialogue_understanding_test/utils.py +70 -0
- rasa/dialogue_understanding_test/validation.py +77 -0
- rasa/e2e_test/aggregate_test_stats_calculator.py +1 -1
- rasa/e2e_test/assertions.py +202 -175
- rasa/e2e_test/assertions_schema.yml +6 -0
- rasa/e2e_test/constants.py +16 -1
- rasa/e2e_test/e2e_config.py +102 -41
- rasa/e2e_test/e2e_config_schema.yml +28 -10
- rasa/e2e_test/e2e_test_case.py +5 -5
- rasa/e2e_test/e2e_test_converter.py +2 -3
- rasa/e2e_test/e2e_test_coverage_report.py +6 -6
- rasa/e2e_test/e2e_test_result.py +1 -1
- rasa/e2e_test/e2e_test_runner.py +143 -38
- rasa/e2e_test/llm_judge_prompts/answer_relevance_prompt_template.jinja2 +93 -0
- rasa/e2e_test/llm_judge_prompts/groundedness_prompt_template.jinja2 +169 -0
- rasa/e2e_test/stub_custom_action.py +1 -1
- rasa/e2e_test/utils/generative_assertions.py +243 -0
- rasa/e2e_test/utils/io.py +123 -93
- rasa/e2e_test/utils/validation.py +101 -3
- rasa/engine/caching.py +5 -7
- rasa/engine/constants.py +1 -1
- rasa/engine/graph.py +3 -2
- rasa/engine/language.py +182 -0
- rasa/engine/recipes/config_files/default_config.yml +4 -0
- rasa/engine/recipes/default_components.py +13 -15
- rasa/engine/recipes/default_recipe.py +65 -49
- rasa/engine/recipes/graph_recipe.py +10 -7
- rasa/engine/recipes/recipe.py +2 -2
- rasa/engine/runner/dask.py +2 -2
- rasa/engine/runner/interface.py +1 -0
- rasa/engine/storage/local_model_storage.py +6 -4
- rasa/engine/storage/resource.py +2 -1
- rasa/engine/storage/storage.py +8 -3
- rasa/engine/training/components.py +2 -1
- rasa/engine/training/fingerprinting.py +4 -2
- rasa/engine/training/graph_trainer.py +4 -4
- rasa/engine/training/hooks.py +2 -2
- rasa/engine/validation.py +36 -33
- rasa/exceptions.py +3 -2
- rasa/graph_components/converters/nlu_message_converter.py +3 -3
- rasa/graph_components/providers/domain_for_core_training_provider.py +3 -3
- rasa/graph_components/providers/domain_provider.py +3 -2
- rasa/graph_components/providers/flows_provider.py +2 -3
- rasa/graph_components/providers/forms_provider.py +4 -4
- rasa/graph_components/providers/nlu_training_data_provider.py +5 -3
- rasa/graph_components/providers/responses_provider.py +4 -4
- rasa/graph_components/providers/rule_only_provider.py +3 -2
- rasa/graph_components/providers/story_graph_provider.py +8 -8
- rasa/graph_components/providers/training_tracker_provider.py +3 -2
- rasa/graph_components/validators/default_recipe_validator.py +16 -16
- rasa/graph_components/validators/finetuning_validator.py +10 -8
- rasa/hooks.py +19 -14
- rasa/jupyter.py +2 -2
- rasa/llm_fine_tuning/annotation_module.py +4 -4
- rasa/llm_fine_tuning/conversations.py +5 -33
- rasa/llm_fine_tuning/llm_data_preparation_module.py +6 -4
- rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +4 -4
- rasa/llm_fine_tuning/paraphrasing/rephrase_validator.py +18 -13
- rasa/llm_fine_tuning/paraphrasing_module.py +6 -2
- rasa/llm_fine_tuning/storage.py +3 -3
- rasa/llm_fine_tuning/train_test_split_module.py +27 -27
- rasa/llm_fine_tuning/utils.py +7 -0
- rasa/markers/marker.py +2 -3
- rasa/markers/marker_base.py +1 -2
- rasa/markers/upload.py +2 -2
- rasa/markers/validate.py +2 -3
- rasa/model.py +3 -5
- rasa/model_manager/config.py +1 -1
- rasa/model_manager/model_api.py +5 -4
- rasa/model_manager/runner_service.py +13 -10
- rasa/model_manager/socket_bridge.py +15 -9
- rasa/model_manager/studio_jwt_auth.py +1 -0
- rasa/model_manager/trainer_service.py +9 -7
- rasa/model_manager/utils.py +1 -1
- rasa/model_manager/warm_rasa_process.py +14 -9
- rasa/model_service.py +5 -6
- rasa/model_testing.py +13 -15
- rasa/model_training.py +29 -29
- rasa/nlu/classifiers/diet_classifier.py +72 -73
- rasa/nlu/classifiers/fallback_classifier.py +9 -8
- rasa/nlu/classifiers/keyword_intent_classifier.py +7 -6
- rasa/nlu/classifiers/logistic_regression_classifier.py +3 -3
- rasa/nlu/classifiers/mitie_intent_classifier.py +5 -4
- rasa/nlu/classifiers/regex_message_handler.py +3 -2
- rasa/nlu/classifiers/sklearn_intent_classifier.py +2 -2
- rasa/nlu/convert.py +2 -2
- rasa/nlu/emulators/dialogflow.py +3 -3
- rasa/nlu/emulators/luis.py +5 -5
- rasa/nlu/emulators/no_emulator.py +1 -0
- rasa/nlu/emulators/wit.py +4 -4
- rasa/nlu/extractors/crf_entity_extractor.py +11 -11
- rasa/nlu/extractors/duckling_entity_extractor.py +7 -6
- rasa/nlu/extractors/entity_synonyms.py +10 -9
- rasa/nlu/extractors/extractor.py +16 -16
- rasa/nlu/extractors/mitie_entity_extractor.py +10 -9
- rasa/nlu/extractors/regex_entity_extractor.py +11 -10
- rasa/nlu/extractors/spacy_entity_extractor.py +2 -2
- rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +15 -14
- rasa/nlu/featurizers/dense_featurizer/dense_featurizer.py +2 -1
- rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +10 -9
- rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +9 -7
- rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +13 -12
- rasa/nlu/featurizers/featurizer.py +5 -4
- rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +6 -6
- rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +4 -4
- rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +4 -4
- rasa/nlu/featurizers/sparse_featurizer/sparse_featurizer.py +2 -0
- rasa/nlu/model.py +0 -1
- rasa/nlu/selectors/response_selector.py +67 -68
- rasa/nlu/test.py +38 -38
- rasa/nlu/tokenizers/jieba_tokenizer.py +1 -2
- rasa/nlu/tokenizers/mitie_tokenizer.py +2 -2
- rasa/nlu/tokenizers/spacy_tokenizer.py +3 -3
- rasa/nlu/tokenizers/tokenizer.py +6 -7
- rasa/nlu/tokenizers/whitespace_tokenizer.py +1 -1
- rasa/nlu/utils/bilou_utils.py +7 -7
- rasa/nlu/utils/hugging_face/registry.py +22 -22
- rasa/nlu/utils/hugging_face/transformers_pre_post_processors.py +2 -1
- rasa/nlu/utils/mitie_utils.py +2 -1
- rasa/nlu/utils/pattern_utils.py +1 -1
- rasa/nlu/utils/spacy_utils.py +3 -3
- rasa/plugin.py +12 -1
- rasa/server.py +6 -3
- rasa/shared/constants.py +45 -18
- rasa/shared/core/command_payload_reader.py +15 -7
- rasa/shared/core/constants.py +34 -4
- rasa/shared/core/conversation.py +1 -2
- rasa/shared/core/domain.py +19 -20
- rasa/shared/core/events.py +60 -39
- rasa/shared/core/flows/__init__.py +0 -1
- rasa/shared/core/flows/constants.py +11 -0
- rasa/shared/core/flows/flow.py +107 -26
- rasa/shared/core/flows/flow_step.py +4 -3
- rasa/shared/core/flows/flow_step_links.py +1 -2
- rasa/shared/core/flows/flow_step_sequence.py +1 -1
- rasa/shared/core/flows/flows_list.py +3 -3
- rasa/shared/core/flows/flows_yaml_schema.json +69 -3
- rasa/shared/core/flows/nlu_trigger.py +1 -1
- rasa/shared/core/flows/steps/__init__.py +2 -2
- rasa/shared/core/flows/steps/action.py +1 -1
- rasa/shared/core/flows/steps/call.py +1 -1
- rasa/shared/core/flows/steps/collect.py +22 -40
- rasa/shared/core/flows/steps/internal.py +1 -1
- rasa/shared/core/flows/steps/link.py +1 -1
- rasa/shared/core/flows/steps/no_operation.py +2 -2
- rasa/shared/core/flows/steps/set_slots.py +1 -1
- rasa/shared/core/flows/utils.py +44 -4
- rasa/shared/core/flows/validation.py +4 -6
- rasa/shared/core/generator.py +20 -21
- rasa/shared/core/slot_mappings.py +360 -121
- rasa/shared/core/slots.py +163 -6
- rasa/shared/core/trackers.py +108 -33
- rasa/shared/core/training_data/loading.py +1 -1
- rasa/shared/core/training_data/story_reader/story_reader.py +3 -3
- rasa/shared/core/training_data/story_reader/story_step_builder.py +4 -4
- rasa/shared/core/training_data/story_reader/yaml_story_reader.py +29 -31
- rasa/shared/core/training_data/story_writer/yaml_story_writer.py +22 -24
- rasa/shared/core/training_data/structures.py +11 -12
- rasa/shared/core/training_data/visualization.py +10 -10
- rasa/shared/data.py +6 -6
- rasa/shared/engine/caching.py +0 -1
- rasa/shared/exceptions.py +2 -2
- rasa/shared/importers/importer.py +58 -2
- rasa/shared/importers/rasa.py +5 -6
- rasa/shared/importers/utils.py +1 -1
- rasa/shared/nlu/constants.py +9 -0
- rasa/shared/nlu/training_data/entities_parser.py +6 -6
- rasa/shared/nlu/training_data/features.py +3 -3
- rasa/shared/nlu/training_data/formats/__init__.py +1 -1
- rasa/shared/nlu/training_data/formats/dialogflow.py +4 -5
- rasa/shared/nlu/training_data/formats/luis.py +7 -8
- rasa/shared/nlu/training_data/formats/rasa.py +4 -5
- rasa/shared/nlu/training_data/formats/rasa_yaml.py +17 -16
- rasa/shared/nlu/training_data/formats/readerwriter.py +8 -11
- rasa/shared/nlu/training_data/formats/wit.py +3 -4
- rasa/shared/nlu/training_data/loading.py +4 -4
- rasa/shared/nlu/training_data/lookup_tables_parser.py +1 -1
- rasa/shared/nlu/training_data/message.py +13 -14
- rasa/shared/nlu/training_data/schemas/data_schema.py +1 -1
- rasa/shared/nlu/training_data/schemas/responses.yml +19 -11
- rasa/shared/nlu/training_data/synonyms_parser.py +3 -3
- rasa/shared/nlu/training_data/training_data.py +12 -13
- rasa/shared/nlu/training_data/util.py +11 -10
- rasa/shared/providers/_configs/azure_entra_id_config.py +541 -0
- rasa/shared/providers/_configs/azure_openai_client_config.py +150 -15
- rasa/shared/providers/_configs/client_config.py +3 -1
- rasa/shared/providers/_configs/default_litellm_client_config.py +9 -7
- rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +13 -11
- rasa/shared/providers/_configs/litellm_router_client_config.py +12 -10
- rasa/shared/providers/_configs/model_group_config.py +8 -5
- rasa/shared/providers/_configs/oauth_config.py +33 -0
- rasa/shared/providers/_configs/openai_client_config.py +14 -12
- rasa/shared/providers/_configs/rasa_llm_client_config.py +5 -3
- rasa/shared/providers/_configs/self_hosted_llm_client_config.py +12 -11
- rasa/shared/providers/_configs/utils.py +1 -0
- rasa/shared/providers/_ssl_verification_utils.py +5 -6
- rasa/shared/providers/_utils.py +5 -5
- rasa/shared/providers/constants.py +6 -0
- rasa/shared/providers/embedding/_base_litellm_embedding_client.py +1 -1
- rasa/shared/providers/embedding/azure_openai_embedding_client.py +32 -7
- rasa/shared/providers/embedding/embedding_client.py +1 -1
- rasa/shared/providers/embedding/litellm_router_embedding_client.py +5 -2
- rasa/shared/providers/llm/_base_litellm_client.py +43 -18
- rasa/shared/providers/llm/azure_openai_llm_client.py +90 -34
- rasa/shared/providers/llm/default_litellm_llm_client.py +4 -2
- rasa/shared/providers/llm/litellm_router_llm_client.py +32 -9
- rasa/shared/providers/llm/llm_client.py +24 -8
- rasa/shared/providers/llm/llm_response.py +61 -2
- rasa/shared/providers/llm/openai_llm_client.py +11 -5
- rasa/shared/providers/llm/rasa_llm_client.py +17 -14
- rasa/shared/providers/llm/self_hosted_llm_client.py +35 -15
- rasa/shared/providers/mappings.py +18 -19
- rasa/shared/providers/router/_base_litellm_router_client.py +48 -15
- rasa/shared/providers/router/router_client.py +3 -1
- rasa/shared/utils/cli.py +1 -1
- rasa/shared/utils/common.py +15 -1
- rasa/shared/utils/constants.py +3 -0
- rasa/shared/utils/health_check/embeddings_health_check_mixin.py +1 -1
- rasa/shared/utils/health_check/health_check.py +3 -3
- rasa/shared/utils/health_check/llm_health_check_mixin.py +1 -1
- rasa/shared/utils/io.py +1 -1
- rasa/shared/utils/llm.py +100 -18
- rasa/shared/utils/pykwalify_extensions.py +25 -1
- rasa/shared/utils/schemas/domain.yml +26 -1
- rasa/shared/utils/schemas/events.py +1 -1
- rasa/shared/utils/yaml.py +24 -20
- rasa/studio/auth.py +3 -3
- rasa/studio/config.py +1 -2
- rasa/studio/data_handler.py +3 -3
- rasa/studio/download.py +1 -1
- rasa/studio/results_logger.py +3 -3
- rasa/studio/upload.py +21 -5
- rasa/telemetry.py +127 -48
- rasa/tracing/config.py +5 -3
- rasa/tracing/constants.py +12 -0
- rasa/tracing/instrumentation/attribute_extractors.py +92 -14
- rasa/tracing/instrumentation/instrumentation.py +61 -5
- rasa/tracing/instrumentation/intentless_policy_instrumentation.py +1 -1
- rasa/tracing/instrumentation/metrics.py +52 -11
- rasa/tracing/metric_instrument_provider.py +54 -14
- rasa/utils/common.py +12 -24
- rasa/utils/endpoints.py +1 -1
- rasa/utils/io.py +7 -7
- rasa/utils/licensing.py +3 -4
- rasa/utils/log_utils.py +7 -6
- rasa/utils/ml_utils.py +1 -0
- rasa/utils/plotting.py +3 -3
- rasa/utils/sanic_error_handler.py +1 -1
- rasa/utils/tensorflow/callback.py +2 -2
- rasa/utils/tensorflow/crf.py +2 -2
- rasa/utils/tensorflow/data_generator.py +5 -5
- rasa/utils/tensorflow/environment.py +3 -3
- rasa/utils/tensorflow/feature_array.py +2 -3
- rasa/utils/tensorflow/layers.py +18 -12
- rasa/utils/tensorflow/layers_utils.py +2 -1
- rasa/utils/tensorflow/metrics.py +2 -2
- rasa/utils/tensorflow/model_data.py +7 -7
- rasa/utils/tensorflow/model_data_utils.py +10 -9
- rasa/utils/tensorflow/models.py +31 -32
- rasa/utils/tensorflow/rasa_layers.py +20 -19
- rasa/utils/tensorflow/types.py +2 -1
- rasa/utils/train_utils.py +23 -21
- rasa/utils/url_tools.py +1 -1
- rasa/validator.py +594 -115
- rasa/version.py +1 -1
- {rasa_pro-3.11.4.dist-info → rasa_pro-3.12.0.dist-info}/METADATA +23 -26
- rasa_pro-3.12.0.dist-info/RECORD +829 -0
- rasa/core/channels/inspector/dist/assets/arc-632a63ec.js +0 -1
- rasa/core/channels/inspector/dist/assets/c4Diagram-d0fbc5ce-081e0df4.js +0 -10
- rasa/core/channels/inspector/dist/assets/classDiagram-936ed81e-3df0afc2.js +0 -2
- rasa/core/channels/inspector/dist/assets/classDiagram-v2-c3cb15f1-8c5ed31e.js +0 -2
- rasa/core/channels/inspector/dist/assets/edges-f2ad444c-4fc48c3e.js +0 -4
- rasa/core/channels/inspector/dist/assets/flowDb-1972c806-9ec53a3c.js +0 -6
- rasa/core/channels/inspector/dist/assets/flowDiagram-7ea5b25a-41da787a.js +0 -4
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-8bea338b.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowchart-elk-definition-abe16c3d-ce370633.js +0 -139
- rasa/core/channels/inspector/dist/assets/ganttDiagram-9b5ea136-90a36523.js +0 -266
- rasa/core/channels/inspector/dist/assets/gitGraphDiagram-99d0ae7c-41e1aa3f.js +0 -70
- rasa/core/channels/inspector/dist/assets/index-2c4b9a3b-e6f2af62.js +0 -1
- rasa/core/channels/inspector/dist/assets/layout-498807d8.js +0 -1
- rasa/core/channels/inspector/dist/assets/linear-8a078617.js +0 -1
- rasa/core/channels/inspector/dist/assets/mindmap-definition-beec6740-396d17dd.js +0 -109
- rasa/core/channels/inspector/dist/assets/sankeyDiagram-8f13d901-53f6f391.js +0 -8
- rasa/core/channels/inspector/dist/assets/sequenceDiagram-b655622a-715c9c20.js +0 -122
- rasa/core/channels/inspector/dist/assets/stateDiagram-59f0c015-2e8fb31f.js +0 -1
- rasa/core/channels/inspector/dist/assets/stateDiagram-v2-2b26beab-7e2d2aa0.js +0 -1
- rasa/core/channels/inspector/dist/assets/styles-080da4f6-4420cea6.js +0 -110
- rasa/core/channels/inspector/dist/assets/styles-3dcbcfbf-28676cf4.js +0 -159
- rasa/core/channels/inspector/dist/assets/svgDrawCommon-4835440b-151251e9.js +0 -1
- rasa_pro-3.11.4.dist-info/RECORD +0 -779
- /rasa/dialogue_understanding/generator/{single_step → prompt_templates}/command_prompt_template.jinja2 +0 -0
- {rasa_pro-3.11.4.dist-info → rasa_pro-3.12.0.dist-info}/NOTICE +0 -0
- {rasa_pro-3.11.4.dist-info → rasa_pro-3.12.0.dist-info}/WHEEL +0 -0
- {rasa_pro-3.11.4.dist-info → rasa_pro-3.12.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import json
|
|
3
|
+
from functools import partial
|
|
4
|
+
from typing import (
|
|
5
|
+
TYPE_CHECKING,
|
|
6
|
+
Any,
|
|
7
|
+
Awaitable,
|
|
8
|
+
Callable,
|
|
9
|
+
Dict,
|
|
10
|
+
List,
|
|
11
|
+
Optional,
|
|
12
|
+
Text,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
import structlog
|
|
16
|
+
from sanic import Sanic
|
|
17
|
+
|
|
18
|
+
from rasa.core.channels.socketio import SocketBlueprint, SocketIOInput
|
|
19
|
+
from rasa.hooks import hookimpl
|
|
20
|
+
from rasa.plugin import plugin_manager
|
|
21
|
+
from rasa.shared.core.constants import ACTION_LISTEN_NAME
|
|
22
|
+
from rasa.shared.core.events import ActionExecuted
|
|
23
|
+
from rasa.shared.core.trackers import EventVerbosity
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from rasa.core.channels.channel import UserMessage
|
|
27
|
+
from rasa.shared.core.trackers import DialogueStateTracker
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
structlogger = structlog.get_logger()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def tracker_as_dump(tracker: "DialogueStateTracker") -> str:
|
|
34
|
+
"""Create a dump of the tracker state."""
|
|
35
|
+
from rasa.shared.core.trackers import get_trackers_for_conversation_sessions
|
|
36
|
+
|
|
37
|
+
multiple_tracker_sessions = get_trackers_for_conversation_sessions(tracker)
|
|
38
|
+
|
|
39
|
+
if 0 <= len(multiple_tracker_sessions) <= 1:
|
|
40
|
+
last_tracker = tracker
|
|
41
|
+
else:
|
|
42
|
+
last_tracker = multiple_tracker_sessions[-1]
|
|
43
|
+
|
|
44
|
+
state = last_tracker.current_state(EventVerbosity.AFTER_RESTART)
|
|
45
|
+
return json.dumps(state)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def does_need_action_prediction(tracker: "DialogueStateTracker") -> bool:
|
|
49
|
+
"""Check if the tracker needs an action prediction."""
|
|
50
|
+
return (
|
|
51
|
+
len(tracker.events) == 0
|
|
52
|
+
or not isinstance(tracker.events[-1], ActionExecuted)
|
|
53
|
+
or tracker.events[-1].action_name != ACTION_LISTEN_NAME
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class StudioTrackerUpdatePlugin:
|
|
58
|
+
"""Plugin for publishing tracker updates a socketio channel."""
|
|
59
|
+
|
|
60
|
+
def __init__(self, socket_channel: "StudioChatInput") -> None:
|
|
61
|
+
self.socket_channel = socket_channel
|
|
62
|
+
self.tasks: List[asyncio.Task] = []
|
|
63
|
+
|
|
64
|
+
def _cancel_tasks(self) -> None:
|
|
65
|
+
"""Cancel all remaining tasks."""
|
|
66
|
+
for task in self.tasks:
|
|
67
|
+
task.cancel()
|
|
68
|
+
self.tasks = []
|
|
69
|
+
|
|
70
|
+
def _cleanup_tasks(self) -> None:
|
|
71
|
+
"""Remove tasks that have already completed."""
|
|
72
|
+
self.tasks = [task for task in self.tasks if not task.done()]
|
|
73
|
+
|
|
74
|
+
@hookimpl # type: ignore[misc]
|
|
75
|
+
def after_new_user_message(self, tracker: "DialogueStateTracker") -> None:
|
|
76
|
+
"""Triggers a tracker update notification after a new user message."""
|
|
77
|
+
self.handle_tracker_update(tracker)
|
|
78
|
+
|
|
79
|
+
@hookimpl # type: ignore[misc]
|
|
80
|
+
def after_action_executed(self, tracker: "DialogueStateTracker") -> None:
|
|
81
|
+
"""Triggers a tracker update notification after an action is executed."""
|
|
82
|
+
self.handle_tracker_update(tracker)
|
|
83
|
+
|
|
84
|
+
def handle_tracker_update(self, tracker: "DialogueStateTracker") -> None:
|
|
85
|
+
"""Handles a tracker update when triggered by a hook."""
|
|
86
|
+
structlogger.info("studio_chat.after_tracker_update", tracker=tracker)
|
|
87
|
+
# directly create a dump to avoid the tracker getting modified by another
|
|
88
|
+
# function before it gets published (since the publishing is scheduled
|
|
89
|
+
# as an async task)
|
|
90
|
+
tracker_dump = tracker_as_dump(tracker)
|
|
91
|
+
task = asyncio.create_task(
|
|
92
|
+
self.socket_channel.publish_tracker_update(tracker.sender_id, tracker_dump)
|
|
93
|
+
)
|
|
94
|
+
self.tasks.append(task)
|
|
95
|
+
self._cleanup_tasks()
|
|
96
|
+
|
|
97
|
+
@hookimpl # type: ignore[misc]
|
|
98
|
+
def after_server_stop(self) -> None:
|
|
99
|
+
"""Cancels all remaining tasks when the server stops."""
|
|
100
|
+
self._cancel_tasks()
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class StudioChatInput(SocketIOInput):
|
|
104
|
+
"""Input channel for the communication between Rasa Studio and Rasa Pro."""
|
|
105
|
+
|
|
106
|
+
@classmethod
|
|
107
|
+
def name(cls) -> Text:
|
|
108
|
+
return "studio_chat"
|
|
109
|
+
|
|
110
|
+
def __init__(
|
|
111
|
+
self,
|
|
112
|
+
*args: Any,
|
|
113
|
+
**kwargs: Any,
|
|
114
|
+
) -> None:
|
|
115
|
+
"""Creates a ``SocketIOInput`` object."""
|
|
116
|
+
from rasa.core.agent import Agent
|
|
117
|
+
|
|
118
|
+
super().__init__(*args, **kwargs)
|
|
119
|
+
self.agent: Optional[Agent] = None
|
|
120
|
+
|
|
121
|
+
self._register_tracker_update_hook()
|
|
122
|
+
|
|
123
|
+
def _register_tracker_update_hook(self) -> None:
|
|
124
|
+
plugin_manager().register(StudioTrackerUpdatePlugin(self))
|
|
125
|
+
|
|
126
|
+
async def on_tracker_updated(self, tracker: "DialogueStateTracker") -> None:
|
|
127
|
+
"""Triggers a tracker update notification after a change to the tracker."""
|
|
128
|
+
await self.publish_tracker_update(tracker.sender_id, tracker_as_dump(tracker))
|
|
129
|
+
|
|
130
|
+
async def publish_tracker_update(self, sender_id: str, tracker_dump: Dict) -> None:
|
|
131
|
+
"""Publishes a tracker update notification to the websocket."""
|
|
132
|
+
if not self.sio:
|
|
133
|
+
structlogger.error("studio_chat.on_tracker_updated.sio_not_initialized")
|
|
134
|
+
return
|
|
135
|
+
await self.sio.emit("tracker", tracker_dump, room=sender_id)
|
|
136
|
+
|
|
137
|
+
async def on_message_proxy(
|
|
138
|
+
self,
|
|
139
|
+
on_new_message: Callable[["UserMessage"], Awaitable[Any]],
|
|
140
|
+
message: "UserMessage",
|
|
141
|
+
) -> None:
|
|
142
|
+
"""Proxies the on_new_message call to the underlying channel.
|
|
143
|
+
|
|
144
|
+
Triggers a tracker update notification after processing the message.
|
|
145
|
+
"""
|
|
146
|
+
await on_new_message(message)
|
|
147
|
+
|
|
148
|
+
if not self.agent:
|
|
149
|
+
structlogger.error("studio_chat.on_message_proxy.agent_not_initialized")
|
|
150
|
+
return
|
|
151
|
+
|
|
152
|
+
tracker = await self.agent.tracker_store.retrieve(message.sender_id)
|
|
153
|
+
if tracker is None:
|
|
154
|
+
structlogger.error("studio_chat.on_message_proxy.tracker_not_found")
|
|
155
|
+
return
|
|
156
|
+
|
|
157
|
+
await self.on_tracker_updated(tracker)
|
|
158
|
+
|
|
159
|
+
async def handle_tracker_update(self, sid: str, data: Dict) -> None:
|
|
160
|
+
from rasa.shared.core.trackers import DialogueStateTracker
|
|
161
|
+
|
|
162
|
+
structlogger.debug(
|
|
163
|
+
"studio_chat.sio.handle_tracker_update",
|
|
164
|
+
sid=sid,
|
|
165
|
+
sender_id=data["sender_id"],
|
|
166
|
+
)
|
|
167
|
+
if self.agent is None:
|
|
168
|
+
structlogger.error("studio_chat.sio.agent_not_initialized")
|
|
169
|
+
return None
|
|
170
|
+
|
|
171
|
+
if not (domain := self.agent.domain):
|
|
172
|
+
structlogger.error("studio_chat.sio.domain_not_initialized")
|
|
173
|
+
return None
|
|
174
|
+
|
|
175
|
+
async with self.agent.lock_store.lock(data["sender_id"]):
|
|
176
|
+
tracker = DialogueStateTracker.from_dict(
|
|
177
|
+
data["sender_id"], data["events"], domain.slots
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# will override an existing tracker with the same id!
|
|
181
|
+
await self.agent.tracker_store.save(tracker)
|
|
182
|
+
|
|
183
|
+
processor = self.agent.processor
|
|
184
|
+
if processor and does_need_action_prediction(tracker):
|
|
185
|
+
output_channel = self.get_output_channel()
|
|
186
|
+
|
|
187
|
+
await processor._run_prediction_loop(output_channel, tracker)
|
|
188
|
+
await processor.run_anonymization_pipeline(tracker)
|
|
189
|
+
await self.agent.tracker_store.save(tracker)
|
|
190
|
+
|
|
191
|
+
await self.on_tracker_updated(tracker)
|
|
192
|
+
|
|
193
|
+
def blueprint(
|
|
194
|
+
self, on_new_message: Callable[["UserMessage"], Awaitable[Any]]
|
|
195
|
+
) -> SocketBlueprint:
|
|
196
|
+
socket_blueprint = super().blueprint(
|
|
197
|
+
partial(self.on_message_proxy, on_new_message)
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
if not self.sio:
|
|
201
|
+
structlogger.error("studio_chat.blueprint.sio_not_initialized")
|
|
202
|
+
return socket_blueprint
|
|
203
|
+
|
|
204
|
+
@socket_blueprint.listener("after_server_start") # type: ignore[misc]
|
|
205
|
+
async def after_server_start(app: Sanic, _: asyncio.AbstractEventLoop) -> None:
|
|
206
|
+
self.agent = app.ctx.agent
|
|
207
|
+
|
|
208
|
+
@self.sio.on("update_tracker", namespace=self.namespace)
|
|
209
|
+
async def on_update_tracker(sid: Text, data: Dict) -> None:
|
|
210
|
+
await self.handle_tracker_update(sid, data)
|
|
211
|
+
|
|
212
|
+
return socket_blueprint
|
rasa/core/channels/telegram.py
CHANGED
|
@@ -1,31 +1,25 @@
|
|
|
1
|
-
import asyncio
|
|
2
1
|
import json
|
|
3
2
|
import logging
|
|
3
|
+
import typing
|
|
4
4
|
from copy import deepcopy
|
|
5
|
+
from typing import Any, Awaitable, Callable, Dict, List, Optional, Text
|
|
6
|
+
|
|
5
7
|
from sanic import Blueprint, response
|
|
6
8
|
from sanic.request import Request
|
|
7
9
|
from sanic.response import HTTPResponse
|
|
8
|
-
|
|
9
|
-
from
|
|
10
|
-
InlineKeyboardButton,
|
|
11
|
-
Update,
|
|
12
|
-
InlineKeyboardMarkup,
|
|
13
|
-
KeyboardButton,
|
|
14
|
-
ReplyKeyboardMarkup,
|
|
15
|
-
Message,
|
|
16
|
-
)
|
|
17
|
-
from aiogram.utils.exceptions import TelegramAPIError
|
|
18
|
-
from typing import Dict, Text, Any, List, Optional, Callable, Awaitable
|
|
19
|
-
|
|
20
|
-
from rasa.core.channels.channel import InputChannel, UserMessage, OutputChannel
|
|
10
|
+
|
|
11
|
+
from rasa.core.channels.channel import InputChannel, OutputChannel, UserMessage
|
|
21
12
|
from rasa.shared.constants import INTENT_MESSAGE_PREFIX
|
|
22
13
|
from rasa.shared.core.constants import USER_INTENT_RESTART
|
|
23
14
|
from rasa.shared.exceptions import RasaException
|
|
24
15
|
|
|
25
16
|
logger = logging.getLogger(__name__)
|
|
26
17
|
|
|
18
|
+
if typing.TYPE_CHECKING:
|
|
19
|
+
from aiogram.types import Message, Update
|
|
20
|
+
|
|
27
21
|
|
|
28
|
-
class TelegramOutput(
|
|
22
|
+
class TelegramOutput(OutputChannel):
|
|
29
23
|
"""Output channel for Telegram."""
|
|
30
24
|
|
|
31
25
|
# skipcq: PYL-W0236
|
|
@@ -34,20 +28,28 @@ class TelegramOutput(Bot, OutputChannel):
|
|
|
34
28
|
return "telegram"
|
|
35
29
|
|
|
36
30
|
def __init__(self, access_token: Optional[Text]) -> None:
|
|
37
|
-
|
|
31
|
+
try:
|
|
32
|
+
from aiogram import Bot
|
|
33
|
+
|
|
34
|
+
self.bot = Bot(access_token)
|
|
35
|
+
except ImportError:
|
|
36
|
+
raise ImportError(
|
|
37
|
+
"To use the Telegram channel, please install the aiogram package "
|
|
38
|
+
"with 'pip install aiogram'"
|
|
39
|
+
)
|
|
38
40
|
|
|
39
41
|
async def send_text_message(
|
|
40
42
|
self, recipient_id: Text, text: Text, **kwargs: Any
|
|
41
43
|
) -> None:
|
|
42
44
|
"""Sends text message."""
|
|
43
45
|
for message_part in text.strip().split("\n\n"):
|
|
44
|
-
await self.send_message(recipient_id, message_part)
|
|
46
|
+
await self.bot.send_message(recipient_id, message_part)
|
|
45
47
|
|
|
46
48
|
async def send_image_url(
|
|
47
49
|
self, recipient_id: Text, image: Text, **kwargs: Any
|
|
48
50
|
) -> None:
|
|
49
51
|
"""Sends an image."""
|
|
50
|
-
await self.send_photo(recipient_id, image)
|
|
52
|
+
await self.bot.send_photo(recipient_id, image)
|
|
51
53
|
|
|
52
54
|
async def send_text_with_buttons(
|
|
53
55
|
self,
|
|
@@ -67,34 +69,45 @@ class TelegramOutput(Bot, OutputChannel):
|
|
|
67
69
|
|
|
68
70
|
:button_type reply: reply keyboard
|
|
69
71
|
"""
|
|
72
|
+
from aiogram.types import InlineKeyboardButton, KeyboardButton
|
|
73
|
+
from aiogram.utils.keyboard import (
|
|
74
|
+
InlineKeyboardBuilder,
|
|
75
|
+
KeyboardBuilder,
|
|
76
|
+
ReplyKeyboardBuilder,
|
|
77
|
+
)
|
|
78
|
+
|
|
70
79
|
if button_type == "inline":
|
|
71
|
-
|
|
80
|
+
reply_markup_builder: "KeyboardBuilder" = InlineKeyboardBuilder()
|
|
72
81
|
button_list = [
|
|
73
|
-
InlineKeyboardButton(s["title"], callback_data=s["payload"])
|
|
82
|
+
InlineKeyboardButton(text=s["title"], callback_data=s["payload"])
|
|
74
83
|
for s in buttons
|
|
75
84
|
]
|
|
76
|
-
|
|
85
|
+
reply_markup_builder.row(*button_list)
|
|
86
|
+
reply_markup = reply_markup_builder.as_markup()
|
|
77
87
|
|
|
78
88
|
elif button_type == "vertical":
|
|
79
|
-
|
|
89
|
+
reply_markup_builder = InlineKeyboardBuilder()
|
|
80
90
|
[
|
|
81
|
-
|
|
82
|
-
InlineKeyboardButton(s["title"], callback_data=s["payload"])
|
|
91
|
+
reply_markup_builder.row(
|
|
92
|
+
InlineKeyboardButton(text=s["title"], callback_data=s["payload"])
|
|
83
93
|
)
|
|
84
94
|
for s in buttons
|
|
85
95
|
]
|
|
96
|
+
reply_markup = reply_markup_builder.as_markup()
|
|
86
97
|
|
|
87
98
|
elif button_type == "reply":
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
)
|
|
91
|
-
# drop button_type from button_list
|
|
92
|
-
button_list = [b for b in buttons if b.get("title")]
|
|
99
|
+
reply_markup_builder = ReplyKeyboardBuilder()
|
|
100
|
+
|
|
93
101
|
for idx, button in enumerate(buttons):
|
|
94
102
|
if isinstance(button, list):
|
|
95
|
-
|
|
103
|
+
reply_markup_builder.add(
|
|
104
|
+
*[KeyboardButton(text=s["title"]) for s in button]
|
|
105
|
+
)
|
|
96
106
|
else:
|
|
97
|
-
|
|
107
|
+
reply_markup_builder.add(KeyboardButton(text=button["title"]))
|
|
108
|
+
reply_markup = reply_markup_builder.as_markup(
|
|
109
|
+
resize_keyboard=False, one_time_keyboard=True
|
|
110
|
+
)
|
|
98
111
|
else:
|
|
99
112
|
logger.error(
|
|
100
113
|
"Trying to send text with buttons for unknown button type {}".format(
|
|
@@ -103,7 +116,7 @@ class TelegramOutput(Bot, OutputChannel):
|
|
|
103
116
|
)
|
|
104
117
|
return
|
|
105
118
|
|
|
106
|
-
await self.send_message(recipient_id, text, reply_markup=reply_markup)
|
|
119
|
+
await self.bot.send_message(recipient_id, text, reply_markup=reply_markup)
|
|
107
120
|
|
|
108
121
|
async def send_custom_json(
|
|
109
122
|
self, recipient_id: Text, json_message: Dict[Text, Any], **kwargs: Any
|
|
@@ -143,9 +156,17 @@ class TelegramOutput(Bot, OutputChannel):
|
|
|
143
156
|
for params in send_functions.keys():
|
|
144
157
|
if all(json_message.get(p) is not None for p in params):
|
|
145
158
|
args = [json_message.pop(p) for p in params]
|
|
146
|
-
api_call = getattr(self, send_functions[params])
|
|
159
|
+
api_call = getattr(self.bot, send_functions[params])
|
|
147
160
|
await api_call(recipient_id, *args, **json_message)
|
|
148
161
|
|
|
162
|
+
async def get_me(self) -> Any:
|
|
163
|
+
"""Get information about the bot itself."""
|
|
164
|
+
return await self.bot.get_me()
|
|
165
|
+
|
|
166
|
+
async def set_webhook(self, url: Text) -> None:
|
|
167
|
+
"""Set the webhook URL for telegram."""
|
|
168
|
+
await self.bot.set_webhook(url=url)
|
|
169
|
+
|
|
149
170
|
|
|
150
171
|
class TelegramInput(InputChannel):
|
|
151
172
|
"""Telegram input channel."""
|
|
@@ -178,19 +199,19 @@ class TelegramInput(InputChannel):
|
|
|
178
199
|
self.debug_mode = debug_mode
|
|
179
200
|
|
|
180
201
|
@staticmethod
|
|
181
|
-
def _is_location(message: Message) -> bool:
|
|
202
|
+
def _is_location(message: "Message") -> bool:
|
|
182
203
|
return message.location is not None
|
|
183
204
|
|
|
184
205
|
@staticmethod
|
|
185
|
-
def _is_user_message(message: Message) -> bool:
|
|
206
|
+
def _is_user_message(message: "Message") -> bool:
|
|
186
207
|
return message.text is not None
|
|
187
208
|
|
|
188
209
|
@staticmethod
|
|
189
|
-
def _is_edited_message(message: Update) -> bool:
|
|
210
|
+
def _is_edited_message(message: "Update") -> bool:
|
|
190
211
|
return message.edited_message is not None
|
|
191
212
|
|
|
192
213
|
@staticmethod
|
|
193
|
-
def _is_button(message: Update) -> bool:
|
|
214
|
+
def _is_button(message: "Update") -> bool:
|
|
194
215
|
return message.callback_query is not None
|
|
195
216
|
|
|
196
217
|
def blueprint(
|
|
@@ -205,16 +226,19 @@ class TelegramInput(InputChannel):
|
|
|
205
226
|
|
|
206
227
|
@telegram_webhook.route("/set_webhook", methods=["GET", "POST"])
|
|
207
228
|
async def set_webhook(_: Request) -> HTTPResponse:
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
229
|
+
try:
|
|
230
|
+
await self.set_webhook(out_channel)
|
|
231
|
+
except RasaException as exc:
|
|
232
|
+
logger.error(exc)
|
|
233
|
+
return response.text(str(exc))
|
|
234
|
+
|
|
235
|
+
logger.info("Webhook Setup Successful")
|
|
236
|
+
return response.text("Webhook setup successful")
|
|
215
237
|
|
|
216
238
|
@telegram_webhook.route("/webhook", methods=["GET", "POST"])
|
|
217
239
|
async def message(request: Request) -> Any:
|
|
240
|
+
from aiogram.types import Update
|
|
241
|
+
|
|
218
242
|
if request.method == "POST":
|
|
219
243
|
request_dict = request.json
|
|
220
244
|
if isinstance(request_dict, Text):
|
|
@@ -226,24 +250,49 @@ class TelegramInput(InputChannel):
|
|
|
226
250
|
return response.text("failed")
|
|
227
251
|
|
|
228
252
|
if self._is_button(update):
|
|
229
|
-
msg =
|
|
230
|
-
|
|
253
|
+
msg = (
|
|
254
|
+
update.callback_query.message
|
|
255
|
+
if update.callback_query is not None
|
|
256
|
+
else None
|
|
257
|
+
)
|
|
258
|
+
text = (
|
|
259
|
+
update.callback_query.data
|
|
260
|
+
if update.callback_query is not None
|
|
261
|
+
else None
|
|
262
|
+
)
|
|
231
263
|
elif self._is_edited_message(update):
|
|
232
264
|
msg = update.edited_message
|
|
233
|
-
text =
|
|
265
|
+
text = (
|
|
266
|
+
update.edited_message.text
|
|
267
|
+
if update.edited_message is not None
|
|
268
|
+
else None
|
|
269
|
+
)
|
|
234
270
|
else:
|
|
235
271
|
msg = update.message
|
|
236
272
|
if self._is_user_message(msg):
|
|
237
|
-
text =
|
|
273
|
+
text = (
|
|
274
|
+
msg.text.replace("/bot", "")
|
|
275
|
+
if msg is not None and msg.text is not None
|
|
276
|
+
else None
|
|
277
|
+
)
|
|
238
278
|
elif self._is_location(msg):
|
|
239
|
-
text =
|
|
240
|
-
|
|
279
|
+
text = (
|
|
280
|
+
'{{"lng":{0}, "lat":{1}}}'.format(
|
|
281
|
+
msg.location.longitude, msg.location.latitude
|
|
282
|
+
)
|
|
283
|
+
if msg is not None and msg.location is not None
|
|
284
|
+
else None
|
|
241
285
|
)
|
|
242
286
|
else:
|
|
243
287
|
return response.text("success")
|
|
244
|
-
|
|
288
|
+
|
|
245
289
|
metadata = self.get_metadata(request)
|
|
246
290
|
try:
|
|
291
|
+
if msg is not None:
|
|
292
|
+
sender_id = str(msg.chat.id)
|
|
293
|
+
else:
|
|
294
|
+
raise ValueError("No message found.")
|
|
295
|
+
|
|
247
296
|
if text == (INTENT_MESSAGE_PREFIX + USER_INTENT_RESTART):
|
|
248
297
|
await on_new_message(
|
|
249
298
|
UserMessage(
|
|
@@ -286,13 +335,14 @@ class TelegramInput(InputChannel):
|
|
|
286
335
|
|
|
287
336
|
def get_output_channel(self) -> TelegramOutput:
|
|
288
337
|
"""Loads the telegram channel."""
|
|
289
|
-
|
|
338
|
+
return TelegramOutput(self.access_token)
|
|
339
|
+
|
|
340
|
+
async def set_webhook(self, channel: TelegramOutput) -> None:
|
|
341
|
+
from aiogram.exceptions import TelegramAPIError
|
|
290
342
|
|
|
291
343
|
try:
|
|
292
|
-
|
|
344
|
+
await channel.set_webhook(url=self.webhook_url)
|
|
293
345
|
except TelegramAPIError as error:
|
|
294
346
|
raise RasaException(
|
|
295
347
|
"Failed to set channel webhook: " + str(error)
|
|
296
348
|
) from error
|
|
297
|
-
|
|
298
|
-
return channel
|
rasa/core/channels/twilio.py
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from typing import TYPE_CHECKING, Any, Awaitable, Callable, Dict, Optional, Text
|
|
3
|
+
|
|
2
4
|
from sanic import Blueprint, response
|
|
3
5
|
from sanic.request import Request
|
|
4
6
|
from sanic.response import HTTPResponse
|
|
5
7
|
from twilio.base.exceptions import TwilioRestException
|
|
6
8
|
from twilio.rest import Client
|
|
7
|
-
from typing import Dict, Text, Any, Callable, Awaitable, Optional, TYPE_CHECKING
|
|
8
9
|
|
|
9
|
-
from rasa.core.channels.channel import InputChannel
|
|
10
|
-
from rasa.core.channels.channel import UserMessage, OutputChannel
|
|
10
|
+
from rasa.core.channels.channel import InputChannel, OutputChannel, UserMessage
|
|
11
11
|
|
|
12
12
|
if TYPE_CHECKING:
|
|
13
13
|
from twilio.rest.api.v2010.account.message import MessageInstance
|
rasa/core/channels/vier_cvg.py
CHANGED
|
@@ -8,10 +8,10 @@ from dataclasses import dataclass
|
|
|
8
8
|
from functools import wraps
|
|
9
9
|
from typing import Any, Awaitable, Callable, Dict, Optional, Text
|
|
10
10
|
|
|
11
|
-
import rasa.shared.utils.io
|
|
12
11
|
import structlog
|
|
13
|
-
from rasa.core.channels.channel import InputChannel, OutputChannel, UserMessage
|
|
14
12
|
|
|
13
|
+
import rasa.shared.utils.io
|
|
14
|
+
from rasa.core.channels.channel import InputChannel, OutputChannel, UserMessage
|
|
15
15
|
from rasa.utils.beta import ensure_beta_feature_is_enabled
|
|
16
16
|
|
|
17
17
|
# ignore ResourceWarning, InsecureRequestWarning
|
|
@@ -1,26 +1,28 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import copy
|
|
2
|
-
from datetime import datetime, timezone, timedelta
|
|
3
3
|
import json
|
|
4
4
|
import uuid
|
|
5
|
-
from
|
|
5
|
+
from collections import defaultdict
|
|
6
6
|
from dataclasses import asdict
|
|
7
|
+
from datetime import datetime, timedelta, timezone
|
|
8
|
+
from typing import Any, Awaitable, Callable, Dict, List, Optional, Set, Text, Union
|
|
7
9
|
|
|
8
10
|
import structlog
|
|
9
11
|
from jsonschema import ValidationError, validate
|
|
12
|
+
from sanic import Blueprint, response
|
|
13
|
+
from sanic.exceptions import NotFound, SanicException, ServerError
|
|
14
|
+
from sanic.request import Request
|
|
15
|
+
from sanic.response import HTTPResponse
|
|
16
|
+
|
|
10
17
|
from rasa.core import jobs
|
|
11
18
|
from rasa.core.channels.channel import InputChannel, OutputChannel, UserMessage
|
|
12
19
|
from rasa.core.channels.voice_ready.utils import (
|
|
13
|
-
validate_voice_license_scope,
|
|
14
20
|
CallParameters,
|
|
21
|
+
validate_voice_license_scope,
|
|
15
22
|
)
|
|
16
23
|
from rasa.shared.constants import INTENT_MESSAGE_PREFIX
|
|
17
24
|
from rasa.shared.core.constants import USER_INTENT_SESSION_START
|
|
18
25
|
from rasa.shared.exceptions import RasaException
|
|
19
|
-
from sanic import Blueprint, response
|
|
20
|
-
from sanic.exceptions import NotFound, SanicException, ServerError
|
|
21
|
-
from sanic.request import Request
|
|
22
|
-
from sanic.response import HTTPResponse
|
|
23
|
-
|
|
24
26
|
from rasa.utils.io import remove_emojis
|
|
25
27
|
|
|
26
28
|
structlogger = structlog.get_logger()
|
|
@@ -45,8 +47,8 @@ def map_call_params(parameters: Dict[Text, Any]) -> CallParameters:
|
|
|
45
47
|
"""Map the Audiocodes parameters to the CallParameters dataclass."""
|
|
46
48
|
return CallParameters(
|
|
47
49
|
call_id=parameters.get("vaigConversationId"),
|
|
48
|
-
user_phone=parameters.get("
|
|
49
|
-
bot_phone=parameters.get("
|
|
50
|
+
user_phone=parameters.get("caller"),
|
|
51
|
+
bot_phone=parameters.get("callee"),
|
|
50
52
|
user_name=parameters.get("callerDisplayName"),
|
|
51
53
|
user_host=parameters.get("callerHost"),
|
|
52
54
|
bot_host=parameters.get("calleeHost"),
|
|
@@ -223,6 +225,16 @@ class AudiocodesInput(InputChannel):
|
|
|
223
225
|
self.scheduler_job = None
|
|
224
226
|
self.keep_alive = keep_alive
|
|
225
227
|
self.keep_alive_expiration_factor = keep_alive_expiration_factor
|
|
228
|
+
self.background_tasks: Dict[Text, Set[asyncio.Task]] = defaultdict(set)
|
|
229
|
+
|
|
230
|
+
def _create_task(self, conversation_id: Text, coro: Awaitable[Any]) -> asyncio.Task:
|
|
231
|
+
"""Create and track an asyncio task for a conversation."""
|
|
232
|
+
task: asyncio.Task = asyncio.create_task(coro)
|
|
233
|
+
self.background_tasks[conversation_id].add(task)
|
|
234
|
+
task.add_done_callback(
|
|
235
|
+
lambda t: self.background_tasks[conversation_id].discard(t)
|
|
236
|
+
)
|
|
237
|
+
return task
|
|
226
238
|
|
|
227
239
|
async def _set_scheduler_job(self) -> None:
|
|
228
240
|
if self.scheduler_job:
|
|
@@ -251,11 +263,20 @@ class AudiocodesInput(InputChannel):
|
|
|
251
263
|
)
|
|
252
264
|
now = datetime.now(timezone.utc)
|
|
253
265
|
delta = timedelta(seconds=self.keep_alive * self.keep_alive_expiration_factor)
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
266
|
+
|
|
267
|
+
# clean up conversations
|
|
268
|
+
inactive = [
|
|
269
|
+
conv_id
|
|
270
|
+
for conv_id, conv in self.conversations.items()
|
|
271
|
+
if not conv.is_active_conversation(now, delta)
|
|
272
|
+
]
|
|
273
|
+
|
|
274
|
+
# cancel tasks and remove conversations
|
|
275
|
+
for conv_id in inactive:
|
|
276
|
+
for task in self.background_tasks[conv_id]:
|
|
277
|
+
task.cancel()
|
|
278
|
+
self.background_tasks.pop(conv_id, None)
|
|
279
|
+
self.conversations.pop(conv_id, None)
|
|
259
280
|
|
|
260
281
|
def handle_start_conversation(self, body: Dict[Text, Any]) -> Dict[Text, Any]:
|
|
261
282
|
conversation_id = body["conversation"]
|
|
@@ -347,31 +368,29 @@ class AudiocodesInput(InputChannel):
|
|
|
347
368
|
structlogger.debug("audiocodes.on_activities", conversation=conversation_id)
|
|
348
369
|
conversation = self._get_conversation(request.token, conversation_id)
|
|
349
370
|
if conversation is None:
|
|
371
|
+
structlogger.warning(
|
|
372
|
+
"audiocodes.on_activities.no_conversation", request=request.json
|
|
373
|
+
)
|
|
350
374
|
return response.json({})
|
|
351
375
|
elif conversation.ws:
|
|
352
376
|
ac_output: Union[WebsocketOutput, AudiocodesOutput] = WebsocketOutput(
|
|
353
377
|
conversation.ws, conversation_id
|
|
354
378
|
)
|
|
355
|
-
|
|
356
|
-
request.json,
|
|
357
|
-
output_channel=ac_output,
|
|
358
|
-
on_new_message=on_new_message,
|
|
359
|
-
)
|
|
360
|
-
return response.json({})
|
|
379
|
+
response_json = {}
|
|
361
380
|
else:
|
|
362
381
|
# handle non websocket case where messages get returned in json
|
|
363
382
|
ac_output = AudiocodesOutput()
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
383
|
+
response_json = {
|
|
384
|
+
"conversation": conversation_id,
|
|
385
|
+
"activities": ac_output.messages,
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
# start a background task to handle activities
|
|
389
|
+
self._create_task(
|
|
390
|
+
conversation_id,
|
|
391
|
+
conversation.handle_activities(request.json, ac_output, on_new_message),
|
|
392
|
+
)
|
|
393
|
+
return response.json(response_json)
|
|
375
394
|
|
|
376
395
|
@ac_webhook.route(
|
|
377
396
|
"/conversation/<conversation_id>/disconnect", methods=["POST"]
|