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.

Files changed (354) hide show
  1. rasa/__main__.py +3 -4
  2. rasa/api.py +1 -1
  3. rasa/cli/dialogue_understanding_test.py +1 -1
  4. rasa/cli/e2e_test.py +1 -8
  5. rasa/cli/evaluate.py +2 -2
  6. rasa/cli/export.py +5 -3
  7. rasa/cli/inspect.py +7 -0
  8. rasa/cli/llm_fine_tuning.py +1 -1
  9. rasa/cli/project_templates/default/config.yml +5 -32
  10. rasa/cli/project_templates/{calm → default}/e2e_tests/cancelations/user_cancels_during_a_correction.yml +1 -1
  11. rasa/cli/project_templates/{calm → default}/e2e_tests/cancelations/user_changes_mind_on_a_whim.yml +1 -1
  12. rasa/cli/project_templates/{calm → default}/e2e_tests/corrections/user_corrects_contact_handle.yml +1 -1
  13. rasa/cli/project_templates/{calm → default}/e2e_tests/corrections/user_corrects_contact_name.yml +1 -1
  14. rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_adds_contact_to_their_list.yml +1 -1
  15. rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_lists_contacts.yml +1 -1
  16. rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_removes_contact.yml +1 -1
  17. rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_removes_contact_from_list.yml +1 -1
  18. rasa/cli/project_templates/default/endpoints.yml +18 -2
  19. rasa/cli/project_templates/defaults.py +133 -0
  20. rasa/cli/project_templates/tutorial/config.yml +1 -1
  21. rasa/cli/project_templates/tutorial/endpoints.yml +1 -1
  22. rasa/cli/run.py +1 -1
  23. rasa/cli/scaffold.py +2 -3
  24. rasa/cli/shell.py +6 -1
  25. rasa/cli/studio/download.py +0 -22
  26. rasa/cli/studio/link.py +36 -0
  27. rasa/cli/studio/pull.py +79 -0
  28. rasa/cli/studio/push.py +78 -0
  29. rasa/cli/studio/studio.py +12 -0
  30. rasa/cli/studio/train.py +1 -5
  31. rasa/cli/studio/upload.py +6 -4
  32. rasa/cli/train.py +5 -1
  33. rasa/cli/utils.py +1 -1
  34. rasa/cli/x.py +1 -1
  35. rasa/constants.py +2 -0
  36. rasa/core/__init__.py +0 -16
  37. rasa/core/actions/action.py +43 -29
  38. rasa/core/actions/action_repeat_bot_messages.py +18 -22
  39. rasa/core/actions/action_run_slot_rejections.py +1 -2
  40. rasa/core/agent.py +24 -3
  41. rasa/core/available_endpoints.py +146 -0
  42. rasa/core/brokers/kafka.py +4 -0
  43. rasa/core/brokers/pika.py +5 -2
  44. rasa/core/brokers/sql.py +1 -1
  45. rasa/core/channels/__init__.py +3 -0
  46. rasa/core/channels/botframework.py +2 -2
  47. rasa/core/channels/channel.py +2 -2
  48. rasa/core/channels/development_inspector.py +1 -1
  49. rasa/core/channels/facebook.py +1 -4
  50. rasa/core/channels/hangouts.py +8 -5
  51. rasa/core/channels/inspector/.eslintrc.cjs +12 -6
  52. rasa/core/channels/inspector/.prettierrc +5 -0
  53. rasa/core/channels/inspector/README.md +11 -5
  54. rasa/core/channels/inspector/dist/assets/{arc-9f75cc3b.js → arc-371401b1.js} +1 -1
  55. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-7f34db23.js → blockDiagram-38ab4fdb-3f126156.js} +1 -1
  56. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-948bab2c.js → c4Diagram-3d4e48cf-12f22eb7.js} +1 -1
  57. rasa/core/channels/inspector/dist/assets/channel-f1efda17.js +1 -0
  58. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-53b0dd0e.js → classDiagram-70f12bd4-03b1d386.js} +1 -1
  59. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-fdf789e7.js → classDiagram-v2-f2320105-84f69d63.js} +1 -1
  60. rasa/core/channels/inspector/dist/assets/clone-fdf164e2.js +1 -0
  61. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-87c4ece5.js → createText-2e5e7dd3-ca47fd38.js} +1 -1
  62. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-5a8b0749.js → edges-e0da2a9e-f837ca8a.js} +1 -1
  63. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-66da90e2.js → erDiagram-9861fffd-8717ac54.js} +1 -1
  64. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-10044f05.js → flowDb-956e92f1-94f38b83.js} +1 -1
  65. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-f338f66a.js → flowDiagram-66a62f08-b616f9fb.js} +1 -1
  66. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-7d7a1629.js +1 -0
  67. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-b13140aa.js → flowchart-elk-definition-4a651766-f5d24bb8.js} +1 -1
  68. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-f2b4a55a.js → ganttDiagram-c361ad54-b43ba8d9.js} +1 -1
  69. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-dedc298d.js → gitGraphDiagram-72cf32ee-c3aafaa5.js} +1 -1
  70. rasa/core/channels/inspector/dist/assets/{graph-4ede11ff.js → graph-0d0a2c10.js} +1 -1
  71. rasa/core/channels/inspector/dist/assets/{index-3862675e-65549d37.js → index-3862675e-58ea0305.js} +1 -1
  72. rasa/core/channels/inspector/dist/assets/{index-3a23e736.js → index-cce6f8a1.js} +123 -123
  73. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-65439671.js → infoDiagram-f8f76790-b8f60461.js} +1 -1
  74. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-56d03d98.js → journeyDiagram-49397b02-95be5545.js} +1 -1
  75. rasa/core/channels/inspector/dist/assets/{layout-dd48f7f4.js → layout-da885b9b.js} +1 -1
  76. rasa/core/channels/inspector/dist/assets/{line-1569ad2c.js → line-f1c817d3.js} +1 -1
  77. rasa/core/channels/inspector/dist/assets/{linear-48bf4935.js → linear-d42801e6.js} +1 -1
  78. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-688504c1.js → mindmap-definition-fc14e90a-a38923a6.js} +1 -1
  79. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-78b6d7e6.js → pieDiagram-8a3498a8-ca6e71e9.js} +1 -1
  80. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-048b84b3.js → quadrantDiagram-120e2f19-b290dae9.js} +1 -1
  81. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-dd67f107.js → requirementDiagram-deff3bca-03f02ceb.js} +1 -1
  82. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-8128436e.js → sankeyDiagram-04a897e0-c49eee40.js} +1 -1
  83. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-1a0d1461.js → sequenceDiagram-704730f1-b2cd6a3d.js} +1 -1
  84. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-46d388ed.js → stateDiagram-587899a1-e53a2028.js} +1 -1
  85. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-ea42951a.js → stateDiagram-v2-d93cdb3a-e1982a03.js} +1 -1
  86. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-7427ed0c.js → styles-6aaf32cf-d0226ca5.js} +1 -1
  87. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-ff5e5a16.js → styles-9a916d00-0e21dc00.js} +1 -1
  88. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-7b3680cf.js → styles-c10674c1-9588494e.js} +1 -1
  89. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-f860f2ad.js → svgDrawCommon-08f97a94-be478d4f.js} +1 -1
  90. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-2eebf0c8.js → timeline-definition-85554ec2-74631749.js} +1 -1
  91. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-5d7f4e96.js → xychartDiagram-e933f94c-a043552f.js} +1 -1
  92. rasa/core/channels/inspector/dist/index.html +1 -1
  93. rasa/core/channels/inspector/package.json +3 -1
  94. rasa/core/channels/inspector/src/App.tsx +91 -90
  95. rasa/core/channels/inspector/src/components/Chat.tsx +45 -41
  96. rasa/core/channels/inspector/src/components/DiagramFlow.tsx +40 -40
  97. rasa/core/channels/inspector/src/components/DialogueInformation.tsx +57 -57
  98. rasa/core/channels/inspector/src/components/DialogueStack.tsx +36 -27
  99. rasa/core/channels/inspector/src/components/ExpandIcon.tsx +4 -4
  100. rasa/core/channels/inspector/src/components/FullscreenButton.tsx +7 -7
  101. rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +28 -12
  102. rasa/core/channels/inspector/src/components/NoActiveFlow.tsx +9 -9
  103. rasa/core/channels/inspector/src/components/RasaLogo.tsx +5 -5
  104. rasa/core/channels/inspector/src/components/RecruitmentPanel.tsx +55 -60
  105. rasa/core/channels/inspector/src/components/SaraDiagrams.tsx +5 -5
  106. rasa/core/channels/inspector/src/components/Slots.tsx +22 -22
  107. rasa/core/channels/inspector/src/components/Welcome.tsx +28 -31
  108. rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +245 -0
  109. rasa/core/channels/inspector/src/helpers/audio/microphone-processor.js +12 -0
  110. rasa/core/channels/inspector/src/helpers/audio/playback-processor.js +36 -0
  111. rasa/core/channels/inspector/src/helpers/conversation.ts +7 -7
  112. rasa/core/channels/inspector/src/helpers/formatters.test.ts +181 -181
  113. rasa/core/channels/inspector/src/helpers/formatters.ts +111 -111
  114. rasa/core/channels/inspector/src/helpers/utils.ts +78 -61
  115. rasa/core/channels/inspector/src/main.tsx +8 -8
  116. rasa/core/channels/inspector/src/theme/Button/Button.ts +8 -8
  117. rasa/core/channels/inspector/src/theme/Heading/Heading.ts +7 -7
  118. rasa/core/channels/inspector/src/theme/Input/Input.ts +9 -9
  119. rasa/core/channels/inspector/src/theme/Link/Link.ts +6 -6
  120. rasa/core/channels/inspector/src/theme/Modal/Modal.ts +13 -13
  121. rasa/core/channels/inspector/src/theme/Table/Table.tsx +10 -10
  122. rasa/core/channels/inspector/src/theme/Tooltip/Tooltip.ts +5 -5
  123. rasa/core/channels/inspector/src/theme/base/breakpoints.ts +7 -7
  124. rasa/core/channels/inspector/src/theme/base/colors.ts +64 -64
  125. rasa/core/channels/inspector/src/theme/base/fonts/fontFaces.css +21 -18
  126. rasa/core/channels/inspector/src/theme/base/radii.ts +8 -8
  127. rasa/core/channels/inspector/src/theme/base/shadows.ts +5 -5
  128. rasa/core/channels/inspector/src/theme/base/sizes.ts +5 -5
  129. rasa/core/channels/inspector/src/theme/base/space.ts +12 -12
  130. rasa/core/channels/inspector/src/theme/base/styles.ts +5 -5
  131. rasa/core/channels/inspector/src/theme/base/typography.ts +12 -12
  132. rasa/core/channels/inspector/src/theme/base/zIndices.ts +3 -3
  133. rasa/core/channels/inspector/src/theme/index.ts +38 -38
  134. rasa/core/channels/inspector/src/types.ts +56 -50
  135. rasa/core/channels/inspector/yarn.lock +5 -0
  136. rasa/core/channels/mattermost.py +1 -1
  137. rasa/core/channels/rasa_chat.py +2 -4
  138. rasa/core/channels/rest.py +5 -4
  139. rasa/core/channels/socketio.py +56 -41
  140. rasa/core/channels/studio_chat.py +329 -68
  141. rasa/core/channels/vier_cvg.py +1 -2
  142. rasa/core/channels/voice_ready/audiocodes.py +4 -11
  143. rasa/core/channels/voice_ready/jambonz.py +5 -6
  144. rasa/core/channels/voice_ready/twilio_voice.py +13 -12
  145. rasa/core/channels/voice_ready/utils.py +22 -0
  146. rasa/core/channels/voice_stream/audiocodes.py +13 -16
  147. rasa/core/channels/voice_stream/browser_audio.py +1 -1
  148. rasa/core/channels/voice_stream/genesys.py +37 -18
  149. rasa/core/channels/voice_stream/jambonz.py +232 -0
  150. rasa/core/channels/voice_stream/tts/__init__.py +8 -0
  151. rasa/core/channels/voice_stream/twilio_media_streams.py +15 -12
  152. rasa/core/channels/voice_stream/voice_channel.py +71 -27
  153. rasa/core/concurrent_lock_store.py +24 -10
  154. rasa/core/evaluation/marker_tracker_loader.py +1 -1
  155. rasa/core/exporter.py +37 -1
  156. rasa/core/http_interpreter.py +3 -7
  157. rasa/core/information_retrieval/faiss.py +18 -11
  158. rasa/core/information_retrieval/ingestion/faq_parser.py +158 -0
  159. rasa/core/jobs.py +2 -1
  160. rasa/core/lock_store.py +151 -60
  161. rasa/core/nlg/contextual_response_rephraser.py +17 -7
  162. rasa/core/nlg/generator.py +5 -22
  163. rasa/core/nlg/interpolator.py +2 -3
  164. rasa/core/nlg/response.py +6 -43
  165. rasa/core/nlg/summarize.py +1 -1
  166. rasa/core/nlg/translate.py +0 -8
  167. rasa/core/policies/enterprise_search_policy.py +305 -189
  168. rasa/core/policies/enterprise_search_policy_config.py +241 -0
  169. rasa/core/policies/enterprise_search_prompt_with_relevancy_check_and_citation_template.jinja2 +67 -0
  170. rasa/core/policies/flow_policy.py +1 -1
  171. rasa/core/policies/flows/flow_executor.py +102 -17
  172. rasa/core/policies/intentless_policy.py +56 -17
  173. rasa/core/processor.py +70 -49
  174. rasa/core/run.py +33 -11
  175. rasa/core/tracker_stores/__init__.py +0 -0
  176. rasa/core/{auth_retry_tracker_store.py → tracker_stores/auth_retry_tracker_store.py} +66 -1
  177. rasa/core/tracker_stores/dynamo_tracker_store.py +256 -0
  178. rasa/core/tracker_stores/mongo_tracker_store.py +223 -0
  179. rasa/core/tracker_stores/redis_tracker_store.py +252 -0
  180. rasa/core/tracker_stores/sql_tracker_store.py +582 -0
  181. rasa/core/tracker_stores/tracker_store.py +839 -0
  182. rasa/core/training/interactive.py +1 -1
  183. rasa/core/utils.py +24 -95
  184. rasa/dialogue_understanding/coexistence/intent_based_router.py +2 -1
  185. rasa/dialogue_understanding/coexistence/llm_based_router.py +13 -11
  186. rasa/dialogue_understanding/commands/can_not_handle_command.py +2 -0
  187. rasa/dialogue_understanding/commands/cancel_flow_command.py +3 -1
  188. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +2 -0
  189. rasa/dialogue_understanding/commands/clarify_command.py +6 -2
  190. rasa/dialogue_understanding/commands/command_syntax_manager.py +1 -0
  191. rasa/dialogue_understanding/commands/correct_slots_command.py +5 -6
  192. rasa/dialogue_understanding/commands/error_command.py +1 -1
  193. rasa/dialogue_understanding/commands/human_handoff_command.py +3 -3
  194. rasa/dialogue_understanding/commands/knowledge_answer_command.py +2 -0
  195. rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +2 -0
  196. rasa/dialogue_understanding/commands/set_slot_command.py +8 -4
  197. rasa/dialogue_understanding/commands/skip_question_command.py +3 -3
  198. rasa/dialogue_understanding/commands/start_flow_command.py +7 -3
  199. rasa/dialogue_understanding/generator/__init__.py +7 -1
  200. rasa/dialogue_understanding/generator/command_generator.py +4 -2
  201. rasa/dialogue_understanding/generator/command_parser.py +2 -2
  202. rasa/dialogue_understanding/generator/command_parser_validator.py +63 -0
  203. rasa/dialogue_understanding/generator/llm_based_command_generator.py +1 -2
  204. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +3 -2
  205. rasa/dialogue_understanding/generator/nlu_command_adapter.py +2 -2
  206. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_template.jinja2 +0 -2
  207. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +1 -0
  208. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +1 -0
  209. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +79 -0
  210. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +79 -0
  211. rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +26 -461
  212. rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +147 -0
  213. rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +461 -0
  214. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +20 -64
  215. rasa/dialogue_understanding/patterns/cancel.py +1 -2
  216. rasa/dialogue_understanding/patterns/clarify.py +1 -1
  217. rasa/dialogue_understanding/patterns/correction.py +2 -2
  218. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +42 -27
  219. rasa/dialogue_understanding/patterns/domain_for_patterns.py +190 -0
  220. rasa/dialogue_understanding/processor/command_processor.py +6 -7
  221. rasa/dialogue_understanding_test/command_metric_calculation.py +7 -40
  222. rasa/dialogue_understanding_test/command_metrics.py +38 -0
  223. rasa/dialogue_understanding_test/du_test_case.py +58 -25
  224. rasa/dialogue_understanding_test/du_test_result.py +228 -132
  225. rasa/dialogue_understanding_test/du_test_runner.py +11 -2
  226. rasa/dialogue_understanding_test/du_test_schema.yml +3 -3
  227. rasa/dialogue_understanding_test/io.py +35 -8
  228. rasa/e2e_test/constants.py +1 -1
  229. rasa/e2e_test/e2e_test_runner.py +1 -1
  230. rasa/e2e_test/e2e_test_schema.yml +3 -3
  231. rasa/engine/constants.py +1 -1
  232. rasa/engine/graph.py +2 -2
  233. rasa/engine/recipes/default_recipe.py +1 -1
  234. rasa/engine/validation.py +3 -2
  235. rasa/hooks.py +2 -30
  236. rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +2 -6
  237. rasa/model_manager/model_api.py +89 -1
  238. rasa/model_manager/runner_service.py +20 -4
  239. rasa/model_manager/socket_bridge.py +0 -7
  240. rasa/model_manager/trainer_service.py +10 -4
  241. rasa/plugin.py +2 -15
  242. rasa/privacy/__init__.py +0 -0
  243. rasa/privacy/constants.py +83 -0
  244. rasa/privacy/event_broker_utils.py +77 -0
  245. rasa/privacy/privacy_config.py +281 -0
  246. rasa/privacy/privacy_config_schema.json +86 -0
  247. rasa/privacy/privacy_filter.py +393 -0
  248. rasa/privacy/privacy_manager.py +594 -0
  249. rasa/server.py +23 -2
  250. rasa/shared/constants.py +17 -0
  251. rasa/shared/core/command_payload_reader.py +1 -5
  252. rasa/shared/core/constants.py +4 -3
  253. rasa/shared/core/domain.py +172 -11
  254. rasa/shared/core/events.py +100 -6
  255. rasa/shared/core/flows/flow.py +30 -5
  256. rasa/shared/core/flows/flow_step.py +19 -3
  257. rasa/shared/core/flows/flow_step_links.py +15 -0
  258. rasa/shared/core/flows/flow_step_sequence.py +6 -0
  259. rasa/shared/core/flows/flows_yaml_schema.json +3 -0
  260. rasa/shared/core/flows/nlu_trigger.py +13 -0
  261. rasa/shared/core/flows/steps/action.py +7 -4
  262. rasa/shared/core/flows/steps/call.py +11 -4
  263. rasa/shared/core/flows/steps/collect.py +71 -6
  264. rasa/shared/core/flows/steps/internal.py +6 -1
  265. rasa/shared/core/flows/steps/link.py +7 -4
  266. rasa/shared/core/flows/steps/no_operation.py +7 -4
  267. rasa/shared/core/flows/steps/set_slots.py +8 -4
  268. rasa/shared/core/flows/validation.py +25 -5
  269. rasa/shared/core/flows/yaml_flows_io.py +106 -5
  270. rasa/shared/core/slots.py +29 -1
  271. rasa/shared/core/trackers.py +21 -10
  272. rasa/shared/core/training_data/story_reader/yaml_story_reader.py +1 -4
  273. rasa/shared/importers/importer.py +8 -0
  274. rasa/shared/providers/_configs/azure_openai_client_config.py +2 -2
  275. rasa/shared/providers/_configs/default_litellm_client_config.py +1 -1
  276. rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +1 -1
  277. rasa/shared/providers/_configs/openai_client_config.py +1 -1
  278. rasa/shared/providers/_configs/rasa_llm_client_config.py +1 -1
  279. rasa/shared/providers/_configs/self_hosted_llm_client_config.py +1 -1
  280. rasa/shared/providers/_configs/utils.py +0 -99
  281. rasa/shared/providers/llm/default_litellm_llm_client.py +2 -2
  282. rasa/shared/utils/common.py +43 -1
  283. rasa/shared/utils/configs.py +110 -0
  284. rasa/shared/utils/constants.py +0 -3
  285. rasa/shared/utils/llm.py +245 -8
  286. rasa/shared/utils/pykwalify_extensions.py +0 -9
  287. rasa/shared/utils/yaml.py +32 -0
  288. rasa/studio/constants.py +1 -0
  289. rasa/studio/data_handler.py +33 -12
  290. rasa/studio/download.py +117 -435
  291. rasa/studio/link.py +211 -0
  292. rasa/studio/prompts.py +221 -0
  293. rasa/studio/pull/__init__.py +0 -0
  294. rasa/studio/pull/data.py +222 -0
  295. rasa/studio/pull/domains.py +60 -0
  296. rasa/studio/pull/pull.py +239 -0
  297. rasa/studio/push.py +138 -0
  298. rasa/studio/results_logger.py +6 -1
  299. rasa/studio/train.py +1 -1
  300. rasa/studio/upload.py +243 -72
  301. rasa/studio/utils.py +33 -0
  302. rasa/telemetry.py +83 -26
  303. rasa/tracing/config.py +4 -5
  304. rasa/tracing/constants.py +19 -1
  305. rasa/tracing/instrumentation/attribute_extractors.py +68 -16
  306. rasa/tracing/instrumentation/instrumentation.py +54 -3
  307. rasa/tracing/instrumentation/metrics.py +98 -15
  308. rasa/tracing/metric_instrument_provider.py +75 -3
  309. rasa/utils/common.py +43 -22
  310. rasa/utils/endpoints.py +22 -1
  311. rasa/utils/licensing.py +2 -3
  312. rasa/utils/log_utils.py +1 -45
  313. rasa/validator.py +2 -8
  314. rasa/version.py +1 -1
  315. {rasa_pro-3.12.21.dist-info → rasa_pro-3.13.0.dist-info}/METADATA +13 -14
  316. {rasa_pro-3.12.21.dist-info → rasa_pro-3.13.0.dist-info}/RECORD +333 -309
  317. rasa/anonymization/__init__.py +0 -2
  318. rasa/anonymization/anonymisation_rule_yaml_reader.py +0 -91
  319. rasa/anonymization/anonymization_pipeline.py +0 -286
  320. rasa/anonymization/anonymization_rule_executor.py +0 -266
  321. rasa/anonymization/anonymization_rule_orchestrator.py +0 -119
  322. rasa/anonymization/schemas/config.yml +0 -47
  323. rasa/anonymization/utils.py +0 -118
  324. rasa/cli/project_templates/calm/config.yml +0 -10
  325. rasa/cli/project_templates/calm/credentials.yml +0 -33
  326. rasa/cli/project_templates/calm/endpoints.yml +0 -58
  327. rasa/cli/project_templates/default/actions/actions.py +0 -27
  328. rasa/cli/project_templates/default/data/nlu.yml +0 -91
  329. rasa/cli/project_templates/default/data/rules.yml +0 -13
  330. rasa/cli/project_templates/default/data/stories.yml +0 -30
  331. rasa/cli/project_templates/default/domain.yml +0 -34
  332. rasa/cli/project_templates/default/tests/test_stories.yml +0 -91
  333. rasa/core/channels/inspector/dist/assets/channel-dfa68278.js +0 -1
  334. rasa/core/channels/inspector/dist/assets/clone-edb7f119.js +0 -1
  335. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-65e7c670.js +0 -1
  336. rasa/core/channels/inspector/src/helpers/audiostream.ts +0 -191
  337. rasa/core/tracker_store.py +0 -1792
  338. /rasa/cli/project_templates/{calm → default}/actions/action_template.py +0 -0
  339. /rasa/cli/project_templates/{calm → default}/actions/add_contact.py +0 -0
  340. /rasa/cli/project_templates/{calm → default}/actions/db.py +0 -0
  341. /rasa/cli/project_templates/{calm → default}/actions/list_contacts.py +0 -0
  342. /rasa/cli/project_templates/{calm → default}/actions/remove_contact.py +0 -0
  343. /rasa/cli/project_templates/{calm → default}/data/flows/add_contact.yml +0 -0
  344. /rasa/cli/project_templates/{calm → default}/data/flows/list_contacts.yml +0 -0
  345. /rasa/cli/project_templates/{calm → default}/data/flows/remove_contact.yml +0 -0
  346. /rasa/cli/project_templates/{calm → default}/db/contacts.json +0 -0
  347. /rasa/cli/project_templates/{calm → default}/domain/add_contact.yml +0 -0
  348. /rasa/cli/project_templates/{calm → default}/domain/list_contacts.yml +0 -0
  349. /rasa/cli/project_templates/{calm → default}/domain/remove_contact.yml +0 -0
  350. /rasa/cli/project_templates/{calm → default}/domain/shared.yml +0 -0
  351. /rasa/{cli/project_templates/calm/actions → core/information_retrieval/ingestion}/__init__.py +0 -0
  352. {rasa_pro-3.12.21.dist-info → rasa_pro-3.13.0.dist-info}/NOTICE +0 -0
  353. {rasa_pro-3.12.21.dist-info → rasa_pro-3.13.0.dist-info}/WHEEL +0 -0
  354. {rasa_pro-3.12.21.dist-info → rasa_pro-3.13.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,393 @@
1
+ import copy
2
+ import datetime
3
+ import json
4
+ import os
5
+ from pathlib import Path
6
+ from typing import Any, Dict, List, Optional
7
+
8
+ import structlog
9
+
10
+ from rasa.privacy.constants import (
11
+ DEFAULT_PII_MODEL,
12
+ ENTITIES_KEY,
13
+ ENTITY_LABEL_KEY,
14
+ GLINER_LABELS,
15
+ GLINER_MODEL_PATH_ENV_VAR_NAME,
16
+ HUGGINGFACE_CACHE_DIR_ENV_VAR_NAME,
17
+ TEXT_KEY,
18
+ VALUE_KEY,
19
+ )
20
+ from rasa.privacy.privacy_config import AnonymizationMethod, AnonymizationType
21
+ from rasa.shared.core.events import BotUttered, Event, SlotSet, UserUttered
22
+
23
+ structlogger = structlog.get_logger(__name__)
24
+
25
+
26
+ class PrivacyFilter:
27
+ """A class to anonymise sensitive information."""
28
+
29
+ def __init__(self, anonymization_rules: Dict[str, AnonymizationMethod]) -> None:
30
+ """Initialise the PrivacyFilter."""
31
+ self.anonymization_rules = anonymization_rules
32
+ self.labels = GLINER_LABELS
33
+ self.model = self._load_gliner_model()
34
+
35
+ def anonymize(
36
+ self, events: List[Event], prior_sensitive_slot_events: List[Event]
37
+ ) -> List[Event]:
38
+ """Anonymize sensitive information in the events of the current turn.
39
+
40
+ The order of priority for PII detection is:
41
+ - firstly, the slot-based approach i.e. identify any defined slots in
42
+ the anonymization rules that could have been set in this turn and
43
+ anonymise the plaintext slot values in all 3 event types
44
+ (UserUttered, BotUttered, SlotSet)
45
+ - secondly, the GLiNER model based approach i.e. identify any PII entities
46
+ and anonymise the text in UserUttered events or values of
47
+ SlotSet events that fill from_text slots.
48
+ """
49
+ anonymized_events: List[Event] = []
50
+ anonymized_slots = self._anonymize_sensitive_slots(
51
+ (events + prior_sensitive_slot_events)
52
+ )
53
+
54
+ for event in events:
55
+ anonymized_event = self._anonymize_event(event, anonymized_slots)
56
+ anonymized_events.append(anonymized_event)
57
+
58
+ return anonymized_events
59
+
60
+ @staticmethod
61
+ def _load_gliner_model() -> Optional[Any]:
62
+ """Load the GLiNER model for PII detection."""
63
+ local_model_path = os.getenv(GLINER_MODEL_PATH_ENV_VAR_NAME)
64
+ cache_dir_env_value = os.getenv(HUGGINGFACE_CACHE_DIR_ENV_VAR_NAME)
65
+ cache_dir = Path(cache_dir_env_value).resolve() if cache_dir_env_value else None
66
+ model_path = (
67
+ Path(local_model_path).resolve() if local_model_path else DEFAULT_PII_MODEL
68
+ )
69
+ local_files_only = isinstance(model_path, Path) and model_path.exists()
70
+
71
+ structlogger.debug(
72
+ "rasa.privacy.privacy_filter.loading_gliner_model",
73
+ local_files_only=local_files_only,
74
+ )
75
+
76
+ try:
77
+ from gliner import GLiNER
78
+
79
+ return GLiNER.from_pretrained(
80
+ model_path,
81
+ cache_dir=cache_dir,
82
+ local_files_only=local_files_only,
83
+ )
84
+ except ImportError:
85
+ structlogger.warning(
86
+ "rasa.privacy.privacy_filter.gliner_import_error",
87
+ event_info="Optional GLiNER library is not installed. "
88
+ "Please install it if you wish to use additional "
89
+ "PII detection to the slot based approach.",
90
+ )
91
+ return None
92
+
93
+ def _anonymize_sensitive_slots(self, events: List[Event]) -> Dict[str, SlotSet]:
94
+ """Identify and anonymize sensitive slot events.
95
+
96
+ Returns a dictionary where the keys represent a concatenation of the slot key
97
+ and its original value, and the values are the anonymized SlotSet events.
98
+ """
99
+ sensitive_slots = self._find_sensitive_slots(events)
100
+
101
+ if not sensitive_slots:
102
+ structlogger.debug("rasa.privacy.privacy_filter.no_sensitive_slots_found")
103
+ return {}
104
+
105
+ anonymized_slots = {}
106
+ for slot in sensitive_slots:
107
+ slot_value = (
108
+ slot.value if isinstance(slot.value, str) else json.dumps(slot.value)
109
+ )
110
+ anonymized_slots[f"{slot.key}:{slot_value}"] = (
111
+ self._anonymize_sensitive_slot_event(slot)
112
+ )
113
+
114
+ return anonymized_slots
115
+
116
+ def _find_sensitive_slots(self, processed_events: List[Event]) -> List[SlotSet]:
117
+ """Find all slot events that contain sensitive information.
118
+
119
+ These sensitive slots are defined in the anonymization rules and
120
+ have a non-empty value.
121
+ """
122
+ return [
123
+ copy.deepcopy(slot_event)
124
+ for slot_event in processed_events
125
+ if isinstance(slot_event, SlotSet)
126
+ and slot_event.key in self.anonymization_rules
127
+ and bool(slot_event.value)
128
+ ]
129
+
130
+ def _anonymize_sensitive_slot_event(
131
+ self,
132
+ slot_event: SlotSet,
133
+ ) -> SlotSet:
134
+ """Anonymize the sensitive slot event if it contains sensitive information.
135
+
136
+ A sensitive slot event is defined as a SlotSet event that has a key
137
+ in the anonymization rules and a non-empty value.
138
+ """
139
+ slot_value = slot_event.value
140
+ if not bool(slot_value):
141
+ return slot_event
142
+
143
+ anonymized_value = self._anonymize_value(slot_event)
144
+ slot_event.value = anonymized_value
145
+
146
+ return slot_event
147
+
148
+ def _anonymize_event(
149
+ self, event: Event, anonymized_slots: Dict[str, SlotSet]
150
+ ) -> Event:
151
+ if isinstance(event, SlotSet):
152
+ return self._anonymize_slot_event(event, anonymized_slots)
153
+ elif isinstance(event, UserUttered):
154
+ return self._anonymize_user_event(event, anonymized_slots)
155
+ elif isinstance(event, BotUttered):
156
+ return self._anonymize_bot_event(event, anonymized_slots)
157
+ else:
158
+ return event
159
+
160
+ def _anonymize_slot_event(
161
+ self,
162
+ event: SlotSet,
163
+ anonymized_slots: Dict[str, SlotSet],
164
+ ) -> SlotSet:
165
+ """Anonymize the slot event if it contains sensitive information."""
166
+ event_value = (
167
+ event.value if isinstance(event.value, str) else json.dumps(event.value)
168
+ )
169
+ # obtain the anonymized slot event, otherwise return the original event
170
+ slot_event = anonymized_slots.get(f"{event.key}:{event_value}", event)
171
+
172
+ # apply the edge case anonymization
173
+ slot_value = (
174
+ slot_event.value
175
+ if isinstance(slot_event.value, str)
176
+ else json.dumps(slot_event.value)
177
+ )
178
+ anonymized_value = self._anonymize_edge_cases(slot_value, anonymized_slots)
179
+
180
+ slot_event.value = (
181
+ anonymized_value
182
+ if isinstance(slot_event.value, str)
183
+ else json.loads(anonymized_value)
184
+ )
185
+ slot_event.anonymized_at = datetime.datetime.now(datetime.timezone.utc)
186
+ return slot_event
187
+
188
+ def _anonymize_user_event(
189
+ self,
190
+ user_event: UserUttered,
191
+ anonymized_slots: Dict[str, SlotSet],
192
+ ) -> UserUttered:
193
+ """Anonymize the user event if it contains sensitive information."""
194
+ if not user_event.text:
195
+ structlogger.debug(
196
+ "rasa.privacy.privacy_filter.user_event_no_text",
197
+ )
198
+ return user_event
199
+
200
+ original_parse_data: Dict[str, Any] = (
201
+ copy.deepcopy(user_event.parse_data) if user_event.parse_data else {}
202
+ )
203
+ anonymized_parse_data: Dict[str, Any] = {}
204
+
205
+ for key, slot in anonymized_slots.items():
206
+ original_slot_value = key.split(":", 1)[1]
207
+ anonymized_text = self._smart_replace(
208
+ user_event.text, original_slot_value, slot.value
209
+ )
210
+ user_event.text = anonymized_text
211
+
212
+ anonymized_parse_data[TEXT_KEY] = anonymized_text
213
+ for entity in original_parse_data.get(ENTITIES_KEY, []):
214
+ entity_value = entity[VALUE_KEY]
215
+ if entity_value == original_slot_value:
216
+ anonymized_entities: List[Dict[str, Any]] = (
217
+ anonymized_parse_data.get(ENTITIES_KEY, [])
218
+ )
219
+ anonymized_entities.append({**entity, VALUE_KEY: slot.value})
220
+ anonymized_parse_data[ENTITIES_KEY] = anonymized_entities
221
+
222
+ user_event.parse_data = anonymized_parse_data # type: ignore[assignment]
223
+ user_event.text = self._anonymize_edge_cases(user_event.text, anonymized_slots)
224
+ # cover the edge case anonymization for the parse data text field
225
+ parse_data_text = user_event.parse_data.get(TEXT_KEY, "")
226
+ user_event.parse_data[TEXT_KEY] = self._anonymize_edge_cases( # type: ignore[literal-required]
227
+ parse_data_text, anonymized_slots
228
+ )
229
+
230
+ user_event.anonymized_at = datetime.datetime.now(datetime.timezone.utc)
231
+
232
+ return user_event
233
+
234
+ def _anonymize_bot_event(
235
+ self,
236
+ bot_event: BotUttered,
237
+ anonymized_slots: Dict[str, SlotSet],
238
+ ) -> BotUttered:
239
+ """Anonymize the bot event if it contains sensitive information."""
240
+ if not bot_event.text:
241
+ structlogger.debug(
242
+ "rasa.privacy.privacy_filter.bot_event_no_text",
243
+ )
244
+ return bot_event
245
+
246
+ for key, slot in anonymized_slots.items():
247
+ original_slot_value = key.split(":", 1)[1]
248
+ anonymized_text = self._smart_replace(
249
+ bot_event.text, original_slot_value, slot.value
250
+ )
251
+ bot_event.text = anonymized_text
252
+
253
+ bot_event.text = self._anonymize_edge_cases(bot_event.text, anonymized_slots)
254
+ bot_event.anonymized_at = datetime.datetime.now(datetime.timezone.utc)
255
+ return bot_event
256
+
257
+ def _anonymize_value(self, slot: SlotSet) -> str:
258
+ """Anonymize the given slot value using the specified anonymization method."""
259
+ slot_name = slot.key
260
+ slot_value = slot.value
261
+ anonymization_method = self.anonymization_rules[slot_name]
262
+
263
+ if anonymization_method.method_type == AnonymizationType.REDACT:
264
+ return self._redact(slot_value, anonymization_method)
265
+
266
+ if anonymization_method.method_type == AnonymizationType.MASK:
267
+ return self._mask(slot_name)
268
+
269
+ # we won't reach this case, because the json schema specifies
270
+ # the allowed methods, this is to satisfy the type checker
271
+ return ""
272
+
273
+ @staticmethod
274
+ def _redact(slot_value: Any, anonymization_method: AnonymizationMethod) -> str:
275
+ """Redact the given slot value using the specified anonymization method."""
276
+ if anonymization_method.keep_left is not None:
277
+ left_part = slot_value[: anonymization_method.keep_left]
278
+ else:
279
+ left_part = ""
280
+
281
+ if anonymization_method.keep_right is not None:
282
+ right_part = slot_value[-anonymization_method.keep_right :]
283
+ else:
284
+ right_part = ""
285
+
286
+ return (
287
+ left_part
288
+ + anonymization_method.redaction_char
289
+ * (len(slot_value) - len(left_part) - len(right_part))
290
+ + right_part
291
+ )
292
+
293
+ @staticmethod
294
+ def _mask(slot_name: str) -> str:
295
+ """Mask the given slot value using the slot name."""
296
+ return f"[{slot_name.upper()}]"
297
+
298
+ @staticmethod
299
+ def _strip_square_brackets(string: str) -> str:
300
+ """Strip square brackets from the start and end of the string if present."""
301
+ if len(string) >= 2 and string[0] == "[" and string[-1] == "]":
302
+ return string[1:-1]
303
+ return string
304
+
305
+ def _anonymize_edge_cases(
306
+ self, text: str, anonymized_slots: Dict[str, SlotSet]
307
+ ) -> str:
308
+ """Anonymize edge cases in the text using GLiNER model.
309
+
310
+ This method is used to detect PII entities in the text that are not
311
+ covered by the slot-based anonymization rules. For example, when
312
+ the user message contains PII entities that are not defined as slots,
313
+ or when the slot is filled from a text input that could contain multiple
314
+ PII entities, such as a from_text slot.
315
+
316
+ This method uses the GLiNER model to predict entities in the text
317
+ and replaces them with masked values.
318
+ If the GLiNER model is not loaded, it will skip this step and return
319
+ the original text.
320
+ """
321
+ if self.model is None:
322
+ structlogger.debug(
323
+ "rasa.privacy.privacy_filter.gliner_model_not_loaded",
324
+ event_info="GLiNER model is not loaded, skipping PII detection.",
325
+ )
326
+ return text
327
+
328
+ entities = self.model.predict_entities(text, self.labels, threshold=0.85)
329
+
330
+ all_anonymized_slot_values = [
331
+ self._strip_square_brackets(str(slot.value))
332
+ for slot in anonymized_slots.values()
333
+ ]
334
+
335
+ for entity in entities:
336
+ structlogger.debug(
337
+ "rasa.privacy.privacy_filter.pii_entity_found",
338
+ entity=entity[ENTITY_LABEL_KEY],
339
+ )
340
+
341
+ entity_value = entity[TEXT_KEY]
342
+
343
+ if entity_value in all_anonymized_slot_values:
344
+ # the entity that was found is already anonymized,
345
+ # we shouldn't override the already anonymized value
346
+ # with a masked value
347
+ structlogger.debug(
348
+ "rasa.privacy.privacy_filter.pii_entity_already_anonymized",
349
+ entity=entity[ENTITY_LABEL_KEY],
350
+ )
351
+ continue
352
+
353
+ text = text.replace(entity_value, self._mask(entity[ENTITY_LABEL_KEY]))
354
+
355
+ return text
356
+
357
+ @staticmethod
358
+ def _smart_replace(text: str, original_value: str, replacement: str) -> str:
359
+ """Replace original_value with replacement in text.
360
+
361
+ This method performs a string replacement in the text,
362
+ with special handling for floats.
363
+ If original_value is a float string like "24.0",
364
+ also tries replacing the integer version "24".
365
+
366
+ Args:
367
+ text (str): The text to perform replacements on
368
+ original_value (str): The value to replace
369
+ replacement (str): The replacement value
370
+
371
+ Returns:
372
+ str: The text with replacements applied
373
+ """
374
+ # First try the original replacement
375
+ result = text.replace(original_value, replacement)
376
+ if text != result:
377
+ return result
378
+
379
+ # If replacement didn't happen and it's a float,
380
+ # try replacing the integer version
381
+ if "." in original_value:
382
+ try:
383
+ float_val = float(original_value)
384
+ if float_val.is_integer():
385
+ int_version = str(int(float_val))
386
+ result = result.replace(int_version, replacement)
387
+ except ValueError:
388
+ structlogger.warning(
389
+ "rasa.privacy.privacy_filter.smart_replace_float_error",
390
+ event_info="Unable to anonymize float value.",
391
+ )
392
+
393
+ return result