rasa-pro 3.13.0.dev5__py3-none-any.whl → 3.13.0.dev8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of rasa-pro might be problematic. Click here for more details.

Files changed (266) hide show
  1. rasa/__main__.py +0 -3
  2. rasa/api.py +5 -1
  3. rasa/cli/arguments/default_arguments.py +13 -1
  4. rasa/cli/arguments/train.py +2 -0
  5. rasa/cli/dialogue_understanding_test.py +1 -1
  6. rasa/cli/e2e_test.py +1 -1
  7. rasa/cli/evaluate.py +2 -2
  8. rasa/cli/export.py +3 -3
  9. rasa/cli/llm_fine_tuning.py +12 -11
  10. rasa/cli/project_templates/defaults.py +133 -0
  11. rasa/cli/run.py +1 -1
  12. rasa/cli/studio/link.py +53 -0
  13. rasa/cli/studio/pull.py +78 -0
  14. rasa/cli/studio/push.py +78 -0
  15. rasa/cli/studio/studio.py +12 -0
  16. rasa/cli/studio/upload.py +8 -0
  17. rasa/cli/train.py +2 -1
  18. rasa/cli/utils.py +1 -1
  19. rasa/cli/x.py +1 -1
  20. rasa/constants.py +4 -0
  21. rasa/core/__init__.py +0 -16
  22. rasa/core/actions/action.py +5 -1
  23. rasa/core/actions/action_repeat_bot_messages.py +18 -22
  24. rasa/core/actions/action_run_slot_rejections.py +0 -1
  25. rasa/core/agent.py +18 -3
  26. rasa/core/available_endpoints.py +146 -0
  27. rasa/core/brokers/kafka.py +4 -0
  28. rasa/core/brokers/pika.py +5 -2
  29. rasa/core/brokers/sql.py +1 -1
  30. rasa/core/channels/botframework.py +2 -2
  31. rasa/core/channels/channel.py +2 -2
  32. rasa/core/channels/hangouts.py +8 -5
  33. rasa/core/channels/inspector/.eslintrc.cjs +12 -6
  34. rasa/core/channels/inspector/.prettierrc +5 -0
  35. rasa/core/channels/inspector/README.md +10 -4
  36. rasa/core/channels/inspector/dist/assets/{arc-9f75cc3b.js → arc-c4b064fc.js} +1 -1
  37. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-7f34db23.js → blockDiagram-38ab4fdb-215b5026.js} +1 -1
  38. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-948bab2c.js → c4Diagram-3d4e48cf-2b54a0a3.js} +1 -1
  39. rasa/core/channels/inspector/dist/assets/channel-3730f5fd.js +1 -0
  40. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-53b0dd0e.js → classDiagram-70f12bd4-daacea5f.js} +1 -1
  41. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-fdf789e7.js → classDiagram-v2-f2320105-930d4dc2.js} +1 -1
  42. rasa/core/channels/inspector/dist/assets/clone-e847561e.js +1 -0
  43. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-87c4ece5.js → createText-2e5e7dd3-83c206ba.js} +1 -1
  44. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-5a8b0749.js → edges-e0da2a9e-b0eb01d0.js} +1 -1
  45. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-66da90e2.js → erDiagram-9861fffd-17586500.js} +1 -1
  46. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-10044f05.js → flowDb-956e92f1-be2a1776.js} +1 -1
  47. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-f338f66a.js → flowDiagram-66a62f08-c2120ebd.js} +1 -1
  48. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-efbbfe00.js +1 -0
  49. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-b13140aa.js → flowchart-elk-definition-4a651766-a6ab5c48.js} +1 -1
  50. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-f2b4a55a.js → ganttDiagram-c361ad54-ef613457.js} +1 -1
  51. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-dedc298d.js → gitGraphDiagram-72cf32ee-d59185b3.js} +1 -1
  52. rasa/core/channels/inspector/dist/assets/{graph-4ede11ff.js → graph-0f155405.js} +1 -1
  53. rasa/core/channels/inspector/dist/assets/{index-3862675e-65549d37.js → index-3862675e-d5f1d1b7.js} +1 -1
  54. rasa/core/channels/inspector/dist/assets/{index-3a23e736.js → index-47737d3a.js} +123 -123
  55. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-65439671.js → infoDiagram-f8f76790-b07d141f.js} +1 -1
  56. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-56d03d98.js → journeyDiagram-49397b02-1936d429.js} +1 -1
  57. rasa/core/channels/inspector/dist/assets/{layout-dd48f7f4.js → layout-dde8d0f3.js} +1 -1
  58. rasa/core/channels/inspector/dist/assets/{line-1569ad2c.js → line-0c2c7ee0.js} +1 -1
  59. rasa/core/channels/inspector/dist/assets/{linear-48bf4935.js → linear-35dd89a4.js} +1 -1
  60. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-688504c1.js → mindmap-definition-fc14e90a-56192851.js} +1 -1
  61. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-78b6d7e6.js → pieDiagram-8a3498a8-fc21ed78.js} +1 -1
  62. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-048b84b3.js → quadrantDiagram-120e2f19-25e98518.js} +1 -1
  63. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-dd67f107.js → requirementDiagram-deff3bca-546ff1f5.js} +1 -1
  64. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-8128436e.js → sankeyDiagram-04a897e0-02d8b82d.js} +1 -1
  65. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-1a0d1461.js → sequenceDiagram-704730f1-3ca5a92e.js} +1 -1
  66. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-46d388ed.js → stateDiagram-587899a1-128ea07c.js} +1 -1
  67. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-ea42951a.js → stateDiagram-v2-d93cdb3a-95f290af.js} +1 -1
  68. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-7427ed0c.js → styles-6aaf32cf-4984898a.js} +1 -1
  69. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-ff5e5a16.js → styles-9a916d00-1bf266ba.js} +1 -1
  70. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-7b3680cf.js → styles-c10674c1-60521c63.js} +1 -1
  71. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-f860f2ad.js → svgDrawCommon-08f97a94-a25b6e12.js} +1 -1
  72. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-2eebf0c8.js → timeline-definition-85554ec2-0fc086bf.js} +1 -1
  73. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-5d7f4e96.js → xychartDiagram-e933f94c-44ee592e.js} +1 -1
  74. rasa/core/channels/inspector/dist/index.html +1 -1
  75. rasa/core/channels/inspector/package.json +3 -1
  76. rasa/core/channels/inspector/src/App.tsx +91 -90
  77. rasa/core/channels/inspector/src/components/Chat.tsx +45 -41
  78. rasa/core/channels/inspector/src/components/DiagramFlow.tsx +40 -40
  79. rasa/core/channels/inspector/src/components/DialogueInformation.tsx +57 -57
  80. rasa/core/channels/inspector/src/components/DialogueStack.tsx +36 -27
  81. rasa/core/channels/inspector/src/components/ExpandIcon.tsx +4 -4
  82. rasa/core/channels/inspector/src/components/FullscreenButton.tsx +7 -7
  83. rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +28 -12
  84. rasa/core/channels/inspector/src/components/NoActiveFlow.tsx +9 -9
  85. rasa/core/channels/inspector/src/components/RasaLogo.tsx +5 -5
  86. rasa/core/channels/inspector/src/components/RecruitmentPanel.tsx +55 -60
  87. rasa/core/channels/inspector/src/components/SaraDiagrams.tsx +5 -5
  88. rasa/core/channels/inspector/src/components/Slots.tsx +22 -22
  89. rasa/core/channels/inspector/src/components/Welcome.tsx +28 -31
  90. rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +245 -0
  91. rasa/core/channels/inspector/src/helpers/audio/microphone-processor.js +12 -0
  92. rasa/core/channels/inspector/src/helpers/audio/playback-processor.js +36 -0
  93. rasa/core/channels/inspector/src/helpers/conversation.ts +7 -7
  94. rasa/core/channels/inspector/src/helpers/formatters.test.ts +181 -181
  95. rasa/core/channels/inspector/src/helpers/formatters.ts +111 -111
  96. rasa/core/channels/inspector/src/helpers/utils.ts +78 -61
  97. rasa/core/channels/inspector/src/main.tsx +8 -8
  98. rasa/core/channels/inspector/src/theme/Button/Button.ts +8 -8
  99. rasa/core/channels/inspector/src/theme/Heading/Heading.ts +7 -7
  100. rasa/core/channels/inspector/src/theme/Input/Input.ts +9 -9
  101. rasa/core/channels/inspector/src/theme/Link/Link.ts +6 -6
  102. rasa/core/channels/inspector/src/theme/Modal/Modal.ts +13 -13
  103. rasa/core/channels/inspector/src/theme/Table/Table.tsx +10 -10
  104. rasa/core/channels/inspector/src/theme/Tooltip/Tooltip.ts +5 -5
  105. rasa/core/channels/inspector/src/theme/base/breakpoints.ts +7 -7
  106. rasa/core/channels/inspector/src/theme/base/colors.ts +64 -64
  107. rasa/core/channels/inspector/src/theme/base/fonts/fontFaces.css +21 -18
  108. rasa/core/channels/inspector/src/theme/base/radii.ts +8 -8
  109. rasa/core/channels/inspector/src/theme/base/shadows.ts +5 -5
  110. rasa/core/channels/inspector/src/theme/base/sizes.ts +5 -5
  111. rasa/core/channels/inspector/src/theme/base/space.ts +12 -12
  112. rasa/core/channels/inspector/src/theme/base/styles.ts +5 -5
  113. rasa/core/channels/inspector/src/theme/base/typography.ts +12 -12
  114. rasa/core/channels/inspector/src/theme/base/zIndices.ts +3 -3
  115. rasa/core/channels/inspector/src/theme/index.ts +38 -38
  116. rasa/core/channels/inspector/src/types.ts +56 -50
  117. rasa/core/channels/inspector/yarn.lock +5 -0
  118. rasa/core/channels/mattermost.py +1 -1
  119. rasa/core/channels/rasa_chat.py +2 -4
  120. rasa/core/channels/rest.py +5 -4
  121. rasa/core/channels/studio_chat.py +3 -2
  122. rasa/core/channels/vier_cvg.py +1 -2
  123. rasa/core/channels/voice_ready/audiocodes.py +35 -25
  124. rasa/core/channels/voice_stream/audiocodes.py +7 -4
  125. rasa/core/channels/voice_stream/genesys.py +2 -2
  126. rasa/core/channels/voice_stream/twilio_media_streams.py +10 -5
  127. rasa/core/channels/voice_stream/voice_channel.py +33 -22
  128. rasa/core/evaluation/marker_tracker_loader.py +1 -1
  129. rasa/core/exporter.py +1 -1
  130. rasa/core/http_interpreter.py +3 -7
  131. rasa/core/jobs.py +2 -1
  132. rasa/core/nlg/contextual_response_rephraser.py +38 -11
  133. rasa/core/nlg/generator.py +0 -1
  134. rasa/core/nlg/interpolator.py +2 -3
  135. rasa/core/nlg/summarize.py +40 -6
  136. rasa/core/persistor.py +55 -20
  137. rasa/core/policies/enterprise_search_policy.py +290 -66
  138. rasa/core/policies/enterprise_search_prompt_with_relevancy_check_and_citation_template.jinja2 +63 -0
  139. rasa/core/policies/flow_policy.py +1 -1
  140. rasa/core/policies/flows/flow_executor.py +96 -17
  141. rasa/core/policies/intentless_policy.py +24 -16
  142. rasa/core/processor.py +106 -53
  143. rasa/core/run.py +40 -13
  144. rasa/core/tracker_stores/__init__.py +0 -0
  145. rasa/core/{auth_retry_tracker_store.py → tracker_stores/auth_retry_tracker_store.py} +5 -1
  146. rasa/core/tracker_stores/dynamo_tracker_store.py +218 -0
  147. rasa/core/tracker_stores/mongo_tracker_store.py +206 -0
  148. rasa/core/tracker_stores/redis_tracker_store.py +219 -0
  149. rasa/core/tracker_stores/sql_tracker_store.py +555 -0
  150. rasa/core/tracker_stores/tracker_store.py +805 -0
  151. rasa/core/training/interactive.py +1 -1
  152. rasa/core/utils.py +24 -91
  153. rasa/dialogue_understanding/coexistence/intent_based_router.py +2 -1
  154. rasa/dialogue_understanding/coexistence/llm_based_router.py +8 -3
  155. rasa/dialogue_understanding/commands/can_not_handle_command.py +2 -0
  156. rasa/dialogue_understanding/commands/cancel_flow_command.py +2 -0
  157. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +2 -0
  158. rasa/dialogue_understanding/commands/clarify_command.py +6 -2
  159. rasa/dialogue_understanding/commands/command_syntax_manager.py +1 -0
  160. rasa/dialogue_understanding/commands/human_handoff_command.py +2 -0
  161. rasa/dialogue_understanding/commands/knowledge_answer_command.py +2 -0
  162. rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +2 -0
  163. rasa/dialogue_understanding/commands/set_slot_command.py +11 -1
  164. rasa/dialogue_understanding/commands/skip_question_command.py +2 -0
  165. rasa/dialogue_understanding/commands/start_flow_command.py +4 -0
  166. rasa/dialogue_understanding/commands/utils.py +26 -2
  167. rasa/dialogue_understanding/generator/__init__.py +7 -1
  168. rasa/dialogue_understanding/generator/command_generator.py +4 -2
  169. rasa/dialogue_understanding/generator/command_parser.py +2 -2
  170. rasa/dialogue_understanding/generator/command_parser_validator.py +63 -0
  171. rasa/dialogue_understanding/generator/constants.py +2 -2
  172. rasa/dialogue_understanding/generator/llm_based_command_generator.py +1 -1
  173. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +78 -0
  174. rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +28 -463
  175. rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +147 -0
  176. rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +477 -0
  177. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +8 -58
  178. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +37 -25
  179. rasa/dialogue_understanding/patterns/domain_for_patterns.py +190 -0
  180. rasa/dialogue_understanding/processor/command_processor.py +3 -3
  181. rasa/dialogue_understanding/processor/command_processor_component.py +3 -3
  182. rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +17 -4
  183. rasa/dialogue_understanding/utils.py +68 -12
  184. rasa/dialogue_understanding_test/du_test_case.py +1 -1
  185. rasa/dialogue_understanding_test/du_test_runner.py +4 -22
  186. rasa/dialogue_understanding_test/test_case_simulation/test_case_tracker_simulator.py +2 -6
  187. rasa/e2e_test/e2e_test_runner.py +1 -1
  188. rasa/engine/constants.py +1 -1
  189. rasa/engine/recipes/default_recipe.py +26 -2
  190. rasa/engine/validation.py +3 -2
  191. rasa/hooks.py +2 -30
  192. rasa/keys +1 -0
  193. rasa/llm_fine_tuning/annotation_module.py +39 -9
  194. rasa/llm_fine_tuning/conversations.py +3 -0
  195. rasa/llm_fine_tuning/llm_data_preparation_module.py +66 -49
  196. rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +4 -2
  197. rasa/llm_fine_tuning/paraphrasing/rephrase_validator.py +52 -44
  198. rasa/llm_fine_tuning/paraphrasing_module.py +10 -12
  199. rasa/llm_fine_tuning/storage.py +4 -4
  200. rasa/llm_fine_tuning/utils.py +63 -1
  201. rasa/model_manager/config.py +3 -1
  202. rasa/model_manager/model_api.py +89 -2
  203. rasa/model_manager/runner_service.py +8 -4
  204. rasa/model_manager/trainer_service.py +5 -4
  205. rasa/model_training.py +12 -3
  206. rasa/nlu/extractors/crf_entity_extractor.py +66 -16
  207. rasa/plugin.py +2 -12
  208. rasa/privacy/__init__.py +0 -0
  209. rasa/privacy/constants.py +83 -0
  210. rasa/privacy/event_broker_utils.py +77 -0
  211. rasa/privacy/privacy_config.py +281 -0
  212. rasa/privacy/privacy_config_schema.json +86 -0
  213. rasa/privacy/privacy_filter.py +340 -0
  214. rasa/privacy/privacy_manager.py +576 -0
  215. rasa/server.py +29 -4
  216. rasa/shared/constants.py +6 -0
  217. rasa/shared/core/constants.py +4 -3
  218. rasa/shared/core/domain.py +7 -0
  219. rasa/shared/core/events.py +99 -3
  220. rasa/shared/core/flows/flow.py +1 -2
  221. rasa/shared/core/flows/flows_yaml_schema.json +3 -0
  222. rasa/shared/core/flows/steps/collect.py +46 -2
  223. rasa/shared/core/slots.py +28 -0
  224. rasa/shared/exceptions.py +4 -0
  225. rasa/shared/providers/_configs/azure_openai_client_config.py +4 -0
  226. rasa/shared/providers/_configs/openai_client_config.py +4 -0
  227. rasa/shared/providers/embedding/_base_litellm_embedding_client.py +3 -0
  228. rasa/shared/providers/llm/_base_litellm_client.py +5 -2
  229. rasa/shared/utils/llm.py +161 -6
  230. rasa/shared/utils/yaml.py +32 -0
  231. rasa/studio/data_handler.py +3 -3
  232. rasa/studio/download/download.py +37 -60
  233. rasa/studio/download/flows.py +23 -31
  234. rasa/studio/link.py +200 -0
  235. rasa/studio/pull.py +94 -0
  236. rasa/studio/push.py +131 -0
  237. rasa/studio/upload.py +117 -67
  238. rasa/telemetry.py +84 -27
  239. rasa/tracing/config.py +4 -5
  240. rasa/tracing/constants.py +19 -1
  241. rasa/tracing/instrumentation/attribute_extractors.py +11 -3
  242. rasa/tracing/instrumentation/instrumentation.py +54 -3
  243. rasa/tracing/instrumentation/metrics.py +98 -15
  244. rasa/tracing/metric_instrument_provider.py +75 -3
  245. rasa/utils/common.py +1 -27
  246. rasa/utils/licensing.py +1 -2
  247. rasa/utils/log_utils.py +1 -45
  248. rasa/validator.py +2 -8
  249. rasa/version.py +1 -1
  250. {rasa_pro-3.13.0.dev5.dist-info → rasa_pro-3.13.0.dev8.dist-info}/METADATA +8 -9
  251. {rasa_pro-3.13.0.dev5.dist-info → rasa_pro-3.13.0.dev8.dist-info}/RECORD +254 -231
  252. rasa/anonymization/__init__.py +0 -2
  253. rasa/anonymization/anonymisation_rule_yaml_reader.py +0 -91
  254. rasa/anonymization/anonymization_pipeline.py +0 -286
  255. rasa/anonymization/anonymization_rule_executor.py +0 -266
  256. rasa/anonymization/anonymization_rule_orchestrator.py +0 -119
  257. rasa/anonymization/schemas/config.yml +0 -47
  258. rasa/anonymization/utils.py +0 -118
  259. rasa/core/channels/inspector/dist/assets/channel-dfa68278.js +0 -1
  260. rasa/core/channels/inspector/dist/assets/clone-edb7f119.js +0 -1
  261. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-65e7c670.js +0 -1
  262. rasa/core/channels/inspector/src/helpers/audiostream.ts +0 -191
  263. rasa/core/tracker_store.py +0 -1792
  264. {rasa_pro-3.13.0.dev5.dist-info → rasa_pro-3.13.0.dev8.dist-info}/NOTICE +0 -0
  265. {rasa_pro-3.13.0.dev5.dist-info → rasa_pro-3.13.0.dev8.dist-info}/WHEEL +0 -0
  266. {rasa_pro-3.13.0.dev5.dist-info → rasa_pro-3.13.0.dev8.dist-info}/entry_points.txt +0 -0
@@ -1,2 +0,0 @@
1
- ENV_LOG_LEVEL_PRESIDIO = "LOG_LEVEL_PRESIDIO"
2
- ENV_LOG_LEVEL_FAKER = "LOG_LEVEL_FAKER"
@@ -1,91 +0,0 @@
1
- from typing import List, Optional, Text
2
-
3
- import pycountry
4
-
5
- from rasa.anonymization.anonymization_rule_executor import (
6
- AnonymizationRule,
7
- AnonymizationRuleList,
8
- )
9
- from rasa.anonymization.utils import (
10
- read_endpoint_config,
11
- validate_anonymization_yaml,
12
- )
13
- from rasa.shared.exceptions import RasaException
14
-
15
- KEY_ANONYMIZATION_RULES = "anonymization"
16
-
17
-
18
- class AnonymizationRulesYamlReader:
19
- """Reads anonymization rules in YAML."""
20
-
21
- def __init__(self, endpoints_filename: Optional[Text] = None) -> None:
22
- """Initializes the reader with the endpoints' filename."""
23
- self.endpoints_filename = endpoints_filename
24
-
25
- def read_anonymization_rules(self) -> List[AnonymizationRuleList]:
26
- """Reads Anonymization rules from a YAML file.
27
-
28
- Returns:
29
- Parsed Anonymization rules.
30
- """
31
- yaml_content = read_endpoint_config(
32
- self.endpoints_filename, KEY_ANONYMIZATION_RULES
33
- )
34
- if yaml_content is None:
35
- return []
36
-
37
- validate_anonymization_yaml(yaml_content)
38
-
39
- anonymization_rules = []
40
-
41
- for key, value in yaml_content.items():
42
- if key == KEY_ANONYMIZATION_RULES:
43
- metadata = value.get("metadata", {})
44
- rule_lists = value.get("rule_lists", [])
45
-
46
- lang_code = metadata.get("language")
47
- self.validate_language(lang_code)
48
-
49
- model_provider = metadata.get("model_provider")
50
- model_name = metadata.get("model_name")
51
-
52
- for rule in rule_lists:
53
- identifier = rule.get("id")
54
- rules = rule.get("rules", [])
55
- rule_list = []
56
-
57
- for item in rules:
58
- entity_name = item.get("entity")
59
- substitution = item.get("substitution", "mask")
60
- value = item.get("value")
61
-
62
- rule_obj = AnonymizationRule(
63
- entity_name=entity_name,
64
- substitution=substitution,
65
- value=value,
66
- )
67
- rule_list.append(rule_obj)
68
- anonymization_rule_list_obj = AnonymizationRuleList(
69
- id=identifier,
70
- rule_list=rule_list,
71
- language=lang_code,
72
- model_provider=model_provider,
73
- models=model_name,
74
- )
75
-
76
- anonymization_rules.append(anonymization_rule_list_obj)
77
-
78
- return anonymization_rules
79
-
80
- def validate_language(self, lang_code: Text) -> None:
81
- """Checks if the language is a valid ISO 639-2 code."""
82
- language = pycountry.languages.get(alpha_2=lang_code)
83
- if language is None:
84
- raise RasaException(
85
- f"Provided language code '{lang_code}' is invalid. "
86
- f"In order to proceed with anonymization, "
87
- f"please provide a valid ISO 639-2 language code in "
88
- f"the {self.endpoints_filename} file."
89
- )
90
-
91
- return None
@@ -1,286 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import copy
4
- import json
5
- import logging
6
- import queue
7
- from typing import Any, Dict, List, Optional, Text
8
-
9
- from apscheduler.schedulers.background import BackgroundScheduler
10
-
11
- from rasa.anonymization.anonymisation_rule_yaml_reader import (
12
- AnonymizationRulesYamlReader,
13
- )
14
- from rasa.anonymization.anonymization_rule_executor import AnonymizationRuleList
15
- from rasa.anonymization.anonymization_rule_orchestrator import (
16
- AnonymizationRuleOrchestrator,
17
- )
18
- from rasa.core.brokers.kafka import KafkaEventBroker
19
- from rasa.shared.core.events import Event
20
- from rasa.utils.endpoints import EndpointConfig, read_endpoint_config
21
- from rasa.utils.singleton import Singleton
22
-
23
- logger = logging.getLogger(__name__)
24
-
25
-
26
- class AnonymizationPipeline:
27
- def run(self, event: Dict[Text, Any]) -> None:
28
- """Run the anonymization pipeline on the given event.
29
-
30
- Args:
31
- event: The event to anonymize
32
- """
33
- ...
34
-
35
- def log_run(self, data: Any) -> Any:
36
- """Anonymize the log data.
37
-
38
- Args:
39
- data: log data to anonymize
40
-
41
- Returns:
42
- Anonymized log data
43
- """
44
- ...
45
-
46
- def stop(self) -> None:
47
- """Stop the anonymization pipeline."""
48
- ...
49
-
50
-
51
- class BackgroundAnonymizationPipeline(AnonymizationPipeline):
52
- EVENT_QUEUE_PROCESSING_TIMEOUT_IN_SECONDS = 2.0
53
-
54
- def __init__(self, anonymization_pipeline: AnonymizationPipeline):
55
- self.anonymization_pipeline = anonymization_pipeline
56
-
57
- # Order of the initialisation is important
58
- # The event queue must be created before the scheduler
59
- # The can_consume_event_queue must be set to True before the scheduler starts
60
- self.event_queue: queue.Queue = queue.Queue()
61
-
62
- # This flag is used to stop the scheduler
63
- self.can_consume_from_event_queue = True
64
- self.event_anonymisation_scheduler = BackgroundScheduler()
65
- self.event_anonymisation_scheduler.add_job(
66
- self._consumer_queue, max_instances=1
67
- )
68
- self.event_anonymisation_scheduler.start()
69
-
70
- def stop(self) -> None:
71
- logger.debug("Shutting down the anonymization pipeline...")
72
- self.can_consume_from_event_queue = False
73
- self.event_anonymisation_scheduler.shutdown()
74
-
75
- def run(self, event: Dict[Text, Any]) -> None:
76
- self.event_queue.put(event)
77
-
78
- def log_run(self, data: Any) -> Any:
79
- return self.anonymization_pipeline.log_run(data)
80
-
81
- def _consumer_queue(self) -> None:
82
- while self.can_consume_from_event_queue:
83
- try:
84
- # Wait for 2 seconds for an event to be added to the queue
85
- # If no event is added to the queue, continue
86
- # This is done to avoid the scheduler to be stuck in the while loop
87
- # when we want to stop the scheduler
88
- event = self.event_queue.get(
89
- timeout=self.EVENT_QUEUE_PROCESSING_TIMEOUT_IN_SECONDS
90
- )
91
- self.anonymization_pipeline.run(event)
92
- self.event_queue.task_done()
93
- except queue.Empty:
94
- continue
95
-
96
-
97
- class SyncAnonymizationPipeline(AnonymizationPipeline):
98
- """Pipeline for anonymizing events."""
99
-
100
- def __init__(self, orchestrators: List[AnonymizationRuleOrchestrator]) -> None:
101
- """Initializes the pipeline."""
102
- self.orchestrators = orchestrators
103
-
104
- def stop(self) -> None:
105
- pass
106
-
107
- def run(self, event: Dict[Text, Any]) -> None:
108
- """Runs the anonymization pipeline."""
109
- logger.debug("Running the anonymization pipeline for event...")
110
-
111
- for orchestrator in self.orchestrators:
112
- anonymized_event = orchestrator.anonymize_event(event)
113
- is_anonymized = True if event != anonymized_event else False
114
- orchestrator.publish_event(anonymized_event, is_anonymized)
115
-
116
- def log_run(self, data: Any) -> Any:
117
- """Runs the anonymization pipeline for logging."""
118
- logger.debug("Running the anonymization pipeline for logs....")
119
-
120
- anonymized_data = None
121
-
122
- # this is to make sure that the original data is not modified
123
- data_copy = copy.deepcopy(data)
124
-
125
- for orchestrator in self.orchestrators:
126
- # orchestrator for anonymizing logs has its event broker set to None
127
- if isinstance(orchestrator.event_broker, KafkaEventBroker):
128
- continue
129
-
130
- if isinstance(data_copy, str):
131
- anonymized_data = orchestrator.anonymize_log_message(data_copy)
132
-
133
- elif isinstance(data_copy, list):
134
- anonymized_data = [
135
- Event.from_parameters(orchestrator.anonymize_event(item.as_dict()))
136
- if isinstance(item, Event)
137
- else orchestrator.anonymize_log_message(str(item["value"]))
138
- if isinstance(item, dict) and item.get("value") is not None
139
- else item
140
- for item in data_copy
141
- ]
142
-
143
- elif isinstance(data_copy, dict) and "event" in data_copy:
144
- anonymized_data = orchestrator.anonymize_event(data_copy)
145
-
146
- elif isinstance(data_copy, dict):
147
- anonymized_data = {}
148
-
149
- for key, value in data_copy.items():
150
- try:
151
- serialized_value = json.dumps(value)
152
- except TypeError as error:
153
- logger.error(
154
- f"Failed to serialize value of type '{type(value)}' "
155
- f"for key '{key}' before anonymization. "
156
- f"Encountered error: {error}. "
157
- f"Setting value to None."
158
- )
159
- serialized_value = None
160
-
161
- anonymized_data[key] = (
162
- orchestrator.anonymize_log_message(serialized_value)
163
- if serialized_value is not None
164
- else None
165
- )
166
-
167
- else:
168
- logger.debug("Unsupported data type for logging anonymization.")
169
-
170
- if anonymized_data:
171
- return anonymized_data
172
- return data
173
-
174
-
175
- class AnonymizationPipelineProvider(metaclass=Singleton):
176
- """Represents a provider for anonymization pipeline."""
177
-
178
- anonymization_pipeline: Optional[AnonymizationPipeline] = None
179
-
180
- def register_anonymization_pipeline(self, pipeline: AnonymizationPipeline) -> None:
181
- """Register an anonymization pipeline.
182
-
183
- Args:
184
- pipeline: The anonymization pipeline to register.
185
- """
186
- self.anonymization_pipeline = pipeline
187
-
188
- def get_anonymization_pipeline(self) -> Optional[AnonymizationPipeline]:
189
- """Get the anonymization pipeline.
190
-
191
- Returns:
192
- The anonymization pipeline.
193
- """
194
- return self.anonymization_pipeline
195
-
196
-
197
- def load_anonymization_pipeline(endpoints_file: Optional[Text]) -> None:
198
- """Creates an anonymization pipeline."""
199
- yaml_reader = AnonymizationRulesYamlReader(endpoints_filename=endpoints_file)
200
- anonymization_rules = yaml_reader.read_anonymization_rules()
201
-
202
- if anonymization_rules is None:
203
- return None
204
-
205
- event_broker_config = read_endpoint_config(
206
- endpoints_file, endpoint_type="event_broker"
207
- )
208
- logging_config = read_endpoint_config(endpoints_file, endpoint_type="logger")
209
-
210
- orchestrators = _load_orchestrators(
211
- logging_config, event_broker_config, anonymization_rules
212
- )
213
-
214
- if not orchestrators:
215
- return None
216
-
217
- pipeline = SyncAnonymizationPipeline(orchestrators)
218
- async_anonymization_pipeline = BackgroundAnonymizationPipeline(pipeline)
219
- provider = AnonymizationPipelineProvider()
220
- provider.register_anonymization_pipeline(async_anonymization_pipeline)
221
-
222
- return None
223
-
224
-
225
- def create_event_broker(
226
- topic_name: Text, event_broker_config: EndpointConfig
227
- ) -> Optional[KafkaEventBroker]:
228
- """Create a KafkaEventBroker object.
229
-
230
- Returns None if the event broker config is not of type 'kafka'.
231
- """
232
- if event_broker_config.type != "kafka":
233
- logger.warning(
234
- f"Unsupported event broker config provided. "
235
- f"Expected type 'kafka' but got "
236
- f"'{event_broker_config.type}'. "
237
- f"Setting event broker to None."
238
- )
239
- event_broker = None
240
- else:
241
- logger.debug(f"Setting topic to '{topic_name}'.")
242
- event_broker_config.kwargs["topic"] = topic_name
243
- event_broker = KafkaEventBroker(
244
- event_broker_config.url, **event_broker_config.kwargs
245
- )
246
-
247
- return event_broker
248
-
249
-
250
- def _load_orchestrators(
251
- logging_config: EndpointConfig,
252
- event_broker_config: EndpointConfig,
253
- anonymization_rules: List[AnonymizationRuleList],
254
- ) -> List[AnonymizationRuleOrchestrator]:
255
- orchestrators = []
256
-
257
- if logging_config:
258
- formatter = logging_config.kwargs.get("formatter", "")
259
- logging_rule = formatter.get("anonymization_rules")
260
-
261
- for rule_list in anonymization_rules:
262
- if rule_list.id == logging_rule:
263
- orchestrators.append(AnonymizationRuleOrchestrator(None, rule_list))
264
-
265
- if event_broker_config:
266
- anonymization_topics = event_broker_config.kwargs.get(
267
- "anonymization_topics", []
268
- )
269
- visited_topics = []
270
-
271
- for rule_list in anonymization_rules:
272
- for topic in anonymization_topics:
273
- topic_name = topic.get("name")
274
-
275
- if topic_name in visited_topics:
276
- continue
277
-
278
- if rule_list.id == topic.get("anonymization_rules"):
279
- event_broker = create_event_broker(topic_name, event_broker_config)
280
-
281
- orchestrators.append(
282
- AnonymizationRuleOrchestrator(event_broker, rule_list)
283
- )
284
-
285
- visited_topics.append(topic_name)
286
- return orchestrators
@@ -1,266 +0,0 @@
1
- import logging
2
- import typing
3
- from dataclasses import dataclass
4
- from typing import Any, Dict, List, Optional, Text, Union
5
-
6
- from faker import Faker
7
-
8
- from rasa.shared.exceptions import RasaException
9
- from rasa.utils.singleton import Singleton
10
-
11
- if typing.TYPE_CHECKING:
12
- from presidio_analyzer import AnalyzerEngine
13
- from presidio_analyzer.nlp_engine.nlp_engine import NlpEngine
14
- from presidio_anonymizer.entities import OperatorConfig
15
-
16
- DEFAULT_PRESIDIO_LANG_CODE = "en"
17
- DEFAULT_PRESIDIO_MODEL_NAME = "en_core_web_lg"
18
- DEFAULT_PRESIDIO_MODEL_PROVIDER = "spacy"
19
-
20
- logger = logging.getLogger(__name__)
21
-
22
-
23
- @dataclass
24
- class AnonymizationRule:
25
- """A rule for anonymizing a given text."""
26
-
27
- entity_name: Text
28
- substitution: Text = "mask"
29
- value: Optional[Text] = None
30
-
31
-
32
- @dataclass
33
- class AnonymizationRuleList:
34
- """A list of anonymization rules."""
35
-
36
- id: Text
37
- rule_list: List[AnonymizationRule]
38
- language: Text = DEFAULT_PRESIDIO_LANG_CODE
39
- model_provider: Text = DEFAULT_PRESIDIO_MODEL_PROVIDER
40
- models: Union[Text, Dict[Text, Text]] = DEFAULT_PRESIDIO_MODEL_NAME
41
-
42
-
43
- class AnonymizationAnalyzer(metaclass=Singleton):
44
- """Anonymization analyzer."""
45
-
46
- presidio_analyzer_engine = None
47
-
48
- def __init__(self, anonymization_rule_list: AnonymizationRuleList):
49
- """Initialise the anonymization analyzer."""
50
- if self.presidio_analyzer_engine is None:
51
- self.presidio_analyzer_engine = self._get_analyzer_engine(
52
- anonymization_rule_list
53
- )
54
-
55
- @staticmethod
56
- def _get_analyzer_engine(
57
- anonymization_rule_list: AnonymizationRuleList,
58
- ) -> "AnalyzerEngine":
59
- """Returns an analyzer engine for all the anonymization rule lists."""
60
- from presidio_analyzer import AnalyzerEngine
61
-
62
- try:
63
- nlp_engine = AnonymizationAnalyzer._build_presidio_nlp_engine(
64
- anonymization_rule_list
65
- )
66
- except (OSError, ImportError) as exception:
67
- raise RasaException(
68
- "Failed to load Presidio nlp engine. "
69
- "Please check that you have provided "
70
- "a valid model name."
71
- ) from exception
72
-
73
- return AnalyzerEngine(
74
- nlp_engine=nlp_engine,
75
- supported_languages=[anonymization_rule_list.language],
76
- )
77
-
78
- @staticmethod
79
- def _build_presidio_nlp_engine(
80
- anonymization_rule_list: AnonymizationRuleList,
81
- ) -> "NlpEngine":
82
- """Creates an instance of the Presidio nlp engine."""
83
- from presidio_analyzer.nlp_engine import (
84
- SpacyNlpEngine,
85
- StanzaNlpEngine,
86
- TransformersNlpEngine,
87
- )
88
-
89
- if anonymization_rule_list.model_provider == "transformers":
90
- nlp_engine = TransformersNlpEngine(
91
- models={
92
- anonymization_rule_list.language: anonymization_rule_list.models
93
- },
94
- )
95
- elif anonymization_rule_list.model_provider == "stanza":
96
- nlp_engine = StanzaNlpEngine(
97
- models={
98
- anonymization_rule_list.language: anonymization_rule_list.models
99
- },
100
- )
101
- else:
102
- nlp_engine = SpacyNlpEngine(
103
- models={
104
- anonymization_rule_list.language: anonymization_rule_list.models
105
- },
106
- )
107
-
108
- return nlp_engine
109
-
110
-
111
- class AnonymizationRuleExecutor:
112
- """Executes a given anonymization rule set on a given text."""
113
-
114
- def __init__(self, anonymization_rule_list: AnonymizationRuleList):
115
- """Initialize the anonymization rule executor."""
116
- from presidio_anonymizer import AnonymizerEngine
117
-
118
- self.anonymization_rule_list = anonymization_rule_list
119
-
120
- is_valid_rule_list = self._validate_anonymization_rule_list(
121
- anonymization_rule_list
122
- )
123
-
124
- self.analyzer = (
125
- AnonymizationAnalyzer(anonymization_rule_list)
126
- if is_valid_rule_list
127
- else None
128
- )
129
-
130
- self.anonymizer_engine = AnonymizerEngine() # type: ignore
131
-
132
- @staticmethod
133
- def _validate_anonymization_rule_list(
134
- anonymization_rule_list: AnonymizationRuleList,
135
- ) -> bool:
136
- """Validates the given anonymization rule list object."""
137
- if (
138
- anonymization_rule_list.language != DEFAULT_PRESIDIO_LANG_CODE
139
- and anonymization_rule_list.models == DEFAULT_PRESIDIO_MODEL_NAME
140
- ):
141
- logger.debug(
142
- f"Anonymization rule list language is "
143
- f"'{anonymization_rule_list.language}', "
144
- f"but no specific model name was provided. "
145
- f"You must specify the spaCy model name in the"
146
- f"endpoints yaml file. "
147
- f"Cannot proceed with anonymization."
148
- )
149
- return False
150
-
151
- return True
152
-
153
- def run(self, text: Text) -> Optional[Text]:
154
- """Anonymizes the given text using the given anonymization rule list."""
155
- if (
156
- self.analyzer is None
157
- or not self.anonymization_rule_list
158
- or self.analyzer.presidio_analyzer_engine is None
159
- ):
160
- return text
161
-
162
- if not self.anonymization_rule_list.rule_list:
163
- return text
164
-
165
- analyzer_results = self.analyzer.presidio_analyzer_engine.analyze(
166
- text=text,
167
- entities=[
168
- rule.entity_name for rule in self.anonymization_rule_list.rule_list
169
- ],
170
- language=self.anonymization_rule_list.language,
171
- )
172
-
173
- operators = self.get_operators()
174
-
175
- anonymized_text = self.anonymizer_engine.anonymize(
176
- text=text,
177
- analyzer_results=analyzer_results,
178
- operators=operators,
179
- )
180
-
181
- return anonymized_text.text
182
-
183
- @staticmethod
184
- @typing.no_type_check # faker is not typed correctly
185
- def _get_supported_faker_entities() -> Dict[Text, Any]:
186
- faker = Faker(["en_US", "es_ES", "it_IT"])
187
-
188
- # Presidio entities: https://microsoft.github.io/presidio/supported_entities/
189
- # Faker providers: https://faker.readthedocs.io/en/master/providers.html
190
- # Unsupported entities by faker:
191
- # CRYPTO, NRP, MEDICAL_LICENSE, US_BANK_NUMBER, US_DRIVER_LICENSE
192
- # UK_NHS, IT_FISCAL_CODE, IT_DRIVER_LICENSE, IT_PASSPORT, IT_IDENTITY_CARD
193
- # SG_NRIC_FIN, AU_ABN, AU_ACN, AU_TFN, AU_MEDICARE
194
- supported_entities = {
195
- "PERSON": lambda value: faker["en_US"].name(),
196
- "PHONE_NUMBER": lambda value: faker["en_US"].phone_number(),
197
- "EMAIL_ADDRESS": lambda value: faker["en_US"].ascii_email(),
198
- "CREDIT_CARD": lambda value: faker["en_US"].credit_card_number(),
199
- "IBAN_CODE": lambda value: faker["en_US"].iban(),
200
- "DATE_TIME": lambda value: faker["en_US"].date(),
201
- "IP_ADDRESS": lambda value: faker["en_US"].ipv4(),
202
- "URL": lambda value: faker["en_US"].url(),
203
- # This faker method returns a tuple of
204
- # (latitude, longitude, place name, country code, timezone)
205
- "LOCATION": lambda value: faker["en_US"].location_on_land()[2],
206
- # USA
207
- "US_ITIN": lambda value: faker["en_US"].itin(),
208
- "US_PASSPORT": lambda value: faker["en_US"].passport_number(),
209
- "US_SSN": lambda value: faker["en_US"].ssn(),
210
- # Spain
211
- "ES_NIF": lambda value: faker["es_ES"].nif(),
212
- # Italy
213
- "IT_VAT_CODE": lambda value: faker["it_IT"].company_vat(),
214
- }
215
-
216
- return supported_entities
217
-
218
- @staticmethod
219
- def _mask_anonymize(value: Text) -> Text:
220
- return "*" * len(value)
221
-
222
- def get_substitution_func(self, rule: AnonymizationRule) -> Optional[Any]:
223
- """Returns a function that anonymizes the given text.
224
-
225
- Args:
226
- rule: The anonymization rule to use.
227
-
228
- Returns:
229
- A function that anonymizes the given text.
230
- """
231
- if rule.substitution == "faker":
232
- supported_faker_entities = self._get_supported_faker_entities()
233
-
234
- if rule.entity_name not in supported_faker_entities:
235
- logger.debug(
236
- f"Unsupported faker entity: {rule.entity_name}. "
237
- f"Supported entities are: {supported_faker_entities.keys()}"
238
- f"Using mask anonymization instead."
239
- )
240
- func = self._mask_anonymize
241
- else:
242
- func = supported_faker_entities.get(rule.entity_name)
243
- elif rule.substitution == "mask":
244
- func = self._mask_anonymize
245
- else:
246
- raise RasaException(f"Unknown substitution type: {rule.substitution}")
247
-
248
- return func
249
-
250
- def get_operators(self) -> Dict[Text, "OperatorConfig"]:
251
- """Returns a dictionary of operators for the given anonymization rule list."""
252
- from presidio_anonymizer.entities import OperatorConfig
253
-
254
- operators = {}
255
-
256
- for rule in self.anonymization_rule_list.rule_list:
257
- if rule.substitution == "text":
258
- operators[rule.entity_name] = OperatorConfig(
259
- "replace", {"new_value": rule.value}
260
- )
261
- else:
262
- operators[rule.entity_name] = OperatorConfig(
263
- "custom", {"lambda": self.get_substitution_func(rule)}
264
- )
265
-
266
- return operators