rasa-pro 3.12.18__py3-none-any.whl → 3.13.0a1.dev1__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 (330) hide show
  1. rasa/__main__.py +3 -4
  2. rasa/api.py +1 -1
  3. rasa/builder/create_openai_vector_store.py +69 -0
  4. rasa/builder/llm-helper-schema.json +69 -0
  5. rasa/builder/prompt_to_bot.py +645 -0
  6. rasa/builder/scrape_rasa_docs.py +97 -0
  7. rasa/builder/skill_to_bot_prompt.jinja +158 -0
  8. rasa/cli/dialogue_understanding_test.py +1 -1
  9. rasa/cli/e2e_test.py +1 -1
  10. rasa/cli/evaluate.py +2 -2
  11. rasa/cli/export.py +3 -3
  12. rasa/cli/llm_fine_tuning.py +1 -1
  13. rasa/cli/project_templates/default/config.yml +5 -32
  14. rasa/cli/project_templates/{calm → default}/e2e_tests/cancelations/user_cancels_during_a_correction.yml +1 -1
  15. rasa/cli/project_templates/{calm → default}/e2e_tests/cancelations/user_changes_mind_on_a_whim.yml +1 -1
  16. rasa/cli/project_templates/{calm → default}/e2e_tests/corrections/user_corrects_contact_handle.yml +1 -1
  17. rasa/cli/project_templates/{calm → default}/e2e_tests/corrections/user_corrects_contact_name.yml +1 -1
  18. rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_adds_contact_to_their_list.yml +1 -1
  19. rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_lists_contacts.yml +1 -1
  20. rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_removes_contact.yml +1 -1
  21. rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_removes_contact_from_list.yml +1 -1
  22. rasa/cli/project_templates/default/endpoints.yml +18 -2
  23. rasa/cli/project_templates/defaults.py +133 -0
  24. rasa/cli/run.py +1 -1
  25. rasa/cli/scaffold.py +2 -3
  26. rasa/cli/studio/download.py +1 -1
  27. rasa/cli/studio/link.py +53 -0
  28. rasa/cli/studio/pull.py +78 -0
  29. rasa/cli/studio/push.py +78 -0
  30. rasa/cli/studio/studio.py +12 -0
  31. rasa/cli/studio/upload.py +5 -3
  32. rasa/cli/train.py +1 -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 +18 -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/botframework.py +2 -2
  46. rasa/core/channels/channel.py +2 -2
  47. rasa/core/channels/development_inspector.py +1 -1
  48. rasa/core/channels/facebook.py +1 -4
  49. rasa/core/channels/hangouts.py +8 -5
  50. rasa/core/channels/inspector/.eslintrc.cjs +12 -6
  51. rasa/core/channels/inspector/.prettierrc +5 -0
  52. rasa/core/channels/inspector/README.md +11 -5
  53. rasa/core/channels/inspector/dist/assets/{arc-9f75cc3b.js → arc-02053cc1.js} +1 -1
  54. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-7f34db23.js → blockDiagram-38ab4fdb-008b6289.js} +1 -1
  55. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-948bab2c.js → c4Diagram-3d4e48cf-fb2597be.js} +1 -1
  56. rasa/core/channels/inspector/dist/assets/channel-078dada8.js +1 -0
  57. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-53b0dd0e.js → classDiagram-70f12bd4-7f847e00.js} +1 -1
  58. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-fdf789e7.js → classDiagram-v2-f2320105-ba1d689b.js} +1 -1
  59. rasa/core/channels/inspector/dist/assets/clone-5b4516de.js +1 -0
  60. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-87c4ece5.js → createText-2e5e7dd3-dd8e67c4.js} +1 -1
  61. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-5a8b0749.js → edges-e0da2a9e-10784939.js} +1 -1
  62. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-66da90e2.js → erDiagram-9861fffd-24947ae6.js} +1 -1
  63. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-10044f05.js → flowDb-956e92f1-a9ced505.js} +1 -1
  64. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-f338f66a.js → flowDiagram-66a62f08-afda9c7c.js} +1 -1
  65. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-f9613071.js +1 -0
  66. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-b13140aa.js → flowchart-elk-definition-4a651766-6ef530b8.js} +1 -1
  67. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-f2b4a55a.js → ganttDiagram-c361ad54-0c7dd39a.js} +1 -1
  68. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-dedc298d.js → gitGraphDiagram-72cf32ee-b57239d6.js} +1 -1
  69. rasa/core/channels/inspector/dist/assets/{graph-4ede11ff.js → graph-9ed57cec.js} +1 -1
  70. rasa/core/channels/inspector/dist/assets/{index-3862675e-65549d37.js → index-3862675e-233090de.js} +1 -1
  71. rasa/core/channels/inspector/dist/assets/{index-3a23e736.js → index-72184470.js} +123 -123
  72. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-65439671.js → infoDiagram-f8f76790-aa116649.js} +1 -1
  73. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-56d03d98.js → journeyDiagram-49397b02-e51877cc.js} +1 -1
  74. rasa/core/channels/inspector/dist/assets/{layout-dd48f7f4.js → layout-3ca3798c.js} +1 -1
  75. rasa/core/channels/inspector/dist/assets/{line-1569ad2c.js → line-26ee10d3.js} +1 -1
  76. rasa/core/channels/inspector/dist/assets/{linear-48bf4935.js → linear-aedded32.js} +1 -1
  77. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-688504c1.js → mindmap-definition-fc14e90a-d8957261.js} +1 -1
  78. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-78b6d7e6.js → pieDiagram-8a3498a8-d771f885.js} +1 -1
  79. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-048b84b3.js → quadrantDiagram-120e2f19-09fdf50c.js} +1 -1
  80. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-dd67f107.js → requirementDiagram-deff3bca-9f0af02e.js} +1 -1
  81. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-8128436e.js → sankeyDiagram-04a897e0-84415b37.js} +1 -1
  82. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-1a0d1461.js → sequenceDiagram-704730f1-8dec4055.js} +1 -1
  83. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-46d388ed.js → stateDiagram-587899a1-c5431d07.js} +1 -1
  84. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-ea42951a.js → stateDiagram-v2-d93cdb3a-274e77d9.js} +1 -1
  85. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-7427ed0c.js → styles-6aaf32cf-e364a1d7.js} +1 -1
  86. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-ff5e5a16.js → styles-9a916d00-0dae36f6.js} +1 -1
  87. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-7b3680cf.js → styles-c10674c1-c4641675.js} +1 -1
  88. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-f860f2ad.js → svgDrawCommon-08f97a94-831fe9a1.js} +1 -1
  89. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-2eebf0c8.js → timeline-definition-85554ec2-c3304b3a.js} +1 -1
  90. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-5d7f4e96.js → xychartDiagram-e933f94c-da799369.js} +1 -1
  91. rasa/core/channels/inspector/dist/index.html +1 -1
  92. rasa/core/channels/inspector/package.json +3 -1
  93. rasa/core/channels/inspector/src/App.tsx +91 -90
  94. rasa/core/channels/inspector/src/components/Chat.tsx +45 -41
  95. rasa/core/channels/inspector/src/components/DiagramFlow.tsx +40 -40
  96. rasa/core/channels/inspector/src/components/DialogueInformation.tsx +57 -57
  97. rasa/core/channels/inspector/src/components/DialogueStack.tsx +36 -27
  98. rasa/core/channels/inspector/src/components/ExpandIcon.tsx +4 -4
  99. rasa/core/channels/inspector/src/components/FullscreenButton.tsx +7 -7
  100. rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +28 -12
  101. rasa/core/channels/inspector/src/components/NoActiveFlow.tsx +9 -9
  102. rasa/core/channels/inspector/src/components/RasaLogo.tsx +5 -5
  103. rasa/core/channels/inspector/src/components/RecruitmentPanel.tsx +55 -60
  104. rasa/core/channels/inspector/src/components/SaraDiagrams.tsx +5 -5
  105. rasa/core/channels/inspector/src/components/Slots.tsx +22 -22
  106. rasa/core/channels/inspector/src/components/Welcome.tsx +28 -31
  107. rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +245 -0
  108. rasa/core/channels/inspector/src/helpers/audio/microphone-processor.js +12 -0
  109. rasa/core/channels/inspector/src/helpers/audio/playback-processor.js +36 -0
  110. rasa/core/channels/inspector/src/helpers/conversation.ts +7 -7
  111. rasa/core/channels/inspector/src/helpers/formatters.test.ts +181 -181
  112. rasa/core/channels/inspector/src/helpers/formatters.ts +111 -111
  113. rasa/core/channels/inspector/src/helpers/utils.ts +78 -61
  114. rasa/core/channels/inspector/src/main.tsx +8 -8
  115. rasa/core/channels/inspector/src/theme/Button/Button.ts +8 -8
  116. rasa/core/channels/inspector/src/theme/Heading/Heading.ts +7 -7
  117. rasa/core/channels/inspector/src/theme/Input/Input.ts +9 -9
  118. rasa/core/channels/inspector/src/theme/Link/Link.ts +6 -6
  119. rasa/core/channels/inspector/src/theme/Modal/Modal.ts +13 -13
  120. rasa/core/channels/inspector/src/theme/Table/Table.tsx +10 -10
  121. rasa/core/channels/inspector/src/theme/Tooltip/Tooltip.ts +5 -5
  122. rasa/core/channels/inspector/src/theme/base/breakpoints.ts +7 -7
  123. rasa/core/channels/inspector/src/theme/base/colors.ts +64 -64
  124. rasa/core/channels/inspector/src/theme/base/fonts/fontFaces.css +21 -18
  125. rasa/core/channels/inspector/src/theme/base/radii.ts +8 -8
  126. rasa/core/channels/inspector/src/theme/base/shadows.ts +5 -5
  127. rasa/core/channels/inspector/src/theme/base/sizes.ts +5 -5
  128. rasa/core/channels/inspector/src/theme/base/space.ts +12 -12
  129. rasa/core/channels/inspector/src/theme/base/styles.ts +5 -5
  130. rasa/core/channels/inspector/src/theme/base/typography.ts +12 -12
  131. rasa/core/channels/inspector/src/theme/base/zIndices.ts +3 -3
  132. rasa/core/channels/inspector/src/theme/index.ts +38 -38
  133. rasa/core/channels/inspector/src/types.ts +56 -50
  134. rasa/core/channels/inspector/yarn.lock +5 -0
  135. rasa/core/channels/mattermost.py +1 -1
  136. rasa/core/channels/rasa_chat.py +2 -4
  137. rasa/core/channels/rest.py +5 -4
  138. rasa/core/channels/socketio.py +56 -41
  139. rasa/core/channels/studio_chat.py +337 -71
  140. rasa/core/channels/vier_cvg.py +1 -2
  141. rasa/core/channels/voice_ready/audiocodes.py +4 -11
  142. rasa/core/channels/voice_stream/audiocodes.py +8 -5
  143. rasa/core/channels/voice_stream/browser_audio.py +1 -1
  144. rasa/core/channels/voice_stream/genesys.py +2 -2
  145. rasa/core/channels/voice_stream/tts/__init__.py +8 -0
  146. rasa/core/channels/voice_stream/twilio_media_streams.py +10 -5
  147. rasa/core/channels/voice_stream/voice_channel.py +65 -23
  148. rasa/core/concurrent_lock_store.py +24 -10
  149. rasa/core/evaluation/marker_tracker_loader.py +1 -1
  150. rasa/core/exporter.py +1 -1
  151. rasa/core/http_interpreter.py +3 -7
  152. rasa/core/information_retrieval/faiss.py +18 -11
  153. rasa/core/information_retrieval/ingestion/__init__.py +0 -0
  154. rasa/core/information_retrieval/ingestion/faq_parser.py +158 -0
  155. rasa/core/jobs.py +2 -1
  156. rasa/core/lock_store.py +151 -60
  157. rasa/core/nlg/contextual_response_rephraser.py +17 -7
  158. rasa/core/nlg/generator.py +5 -22
  159. rasa/core/nlg/interpolator.py +2 -3
  160. rasa/core/nlg/response.py +6 -43
  161. rasa/core/nlg/summarize.py +1 -1
  162. rasa/core/nlg/translate.py +0 -8
  163. rasa/core/policies/enterprise_search_policy.py +262 -62
  164. rasa/core/policies/enterprise_search_prompt_with_relevancy_check_and_citation_template.jinja2 +63 -0
  165. rasa/core/policies/flow_policy.py +1 -1
  166. rasa/core/policies/flows/flow_executor.py +96 -17
  167. rasa/core/policies/intentless_policy.py +56 -17
  168. rasa/core/processor.py +64 -49
  169. rasa/core/run.py +33 -11
  170. rasa/core/tracker_stores/__init__.py +0 -0
  171. rasa/core/{auth_retry_tracker_store.py → tracker_stores/auth_retry_tracker_store.py} +5 -1
  172. rasa/core/tracker_stores/dynamo_tracker_store.py +218 -0
  173. rasa/core/tracker_stores/mongo_tracker_store.py +206 -0
  174. rasa/core/tracker_stores/redis_tracker_store.py +219 -0
  175. rasa/core/tracker_stores/sql_tracker_store.py +555 -0
  176. rasa/core/tracker_stores/tracker_store.py +805 -0
  177. rasa/core/training/interactive.py +1 -1
  178. rasa/core/utils.py +24 -95
  179. rasa/dialogue_understanding/coexistence/intent_based_router.py +2 -1
  180. rasa/dialogue_understanding/coexistence/llm_based_router.py +9 -6
  181. rasa/dialogue_understanding/commands/can_not_handle_command.py +2 -0
  182. rasa/dialogue_understanding/commands/cancel_flow_command.py +5 -1
  183. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +2 -0
  184. rasa/dialogue_understanding/commands/clarify_command.py +4 -0
  185. rasa/dialogue_understanding/commands/command_syntax_manager.py +1 -0
  186. rasa/dialogue_understanding/commands/correct_slots_command.py +1 -3
  187. rasa/dialogue_understanding/commands/human_handoff_command.py +2 -0
  188. rasa/dialogue_understanding/commands/knowledge_answer_command.py +2 -0
  189. rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +2 -0
  190. rasa/dialogue_understanding/commands/set_slot_command.py +4 -0
  191. rasa/dialogue_understanding/commands/skip_question_command.py +2 -0
  192. rasa/dialogue_understanding/commands/start_flow_command.py +4 -0
  193. rasa/dialogue_understanding/generator/__init__.py +7 -1
  194. rasa/dialogue_understanding/generator/command_generator.py +4 -2
  195. rasa/dialogue_understanding/generator/command_parser.py +2 -2
  196. rasa/dialogue_understanding/generator/command_parser_validator.py +63 -0
  197. rasa/dialogue_understanding/generator/llm_based_command_generator.py +1 -2
  198. rasa/dialogue_understanding/generator/nlu_command_adapter.py +2 -2
  199. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +78 -0
  200. rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +26 -461
  201. rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +147 -0
  202. rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +477 -0
  203. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +11 -64
  204. rasa/dialogue_understanding/patterns/cancel.py +1 -2
  205. rasa/dialogue_understanding/patterns/clarify.py +1 -1
  206. rasa/dialogue_understanding/patterns/correction.py +2 -2
  207. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +37 -25
  208. rasa/dialogue_understanding/patterns/domain_for_patterns.py +190 -0
  209. rasa/dialogue_understanding/processor/command_processor.py +6 -7
  210. rasa/dialogue_understanding/stack/utils.py +3 -1
  211. rasa/dialogue_understanding_test/command_metric_calculation.py +7 -40
  212. rasa/dialogue_understanding_test/command_metrics.py +38 -0
  213. rasa/dialogue_understanding_test/du_test_case.py +58 -25
  214. rasa/dialogue_understanding_test/du_test_result.py +228 -132
  215. rasa/dialogue_understanding_test/du_test_runner.py +11 -2
  216. rasa/dialogue_understanding_test/du_test_schema.yml +3 -3
  217. rasa/dialogue_understanding_test/io.py +35 -8
  218. rasa/e2e_test/e2e_test_runner.py +1 -1
  219. rasa/e2e_test/e2e_test_schema.yml +3 -3
  220. rasa/engine/constants.py +1 -1
  221. rasa/engine/graph.py +2 -2
  222. rasa/engine/recipes/default_recipe.py +1 -1
  223. rasa/engine/validation.py +3 -2
  224. rasa/hooks.py +2 -30
  225. rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +1 -5
  226. rasa/model_manager/model_api.py +90 -2
  227. rasa/model_manager/socket_bridge.py +0 -7
  228. rasa/model_manager/trainer_service.py +15 -12
  229. rasa/plugin.py +2 -15
  230. rasa/privacy/__init__.py +0 -0
  231. rasa/privacy/constants.py +83 -0
  232. rasa/privacy/event_broker_utils.py +77 -0
  233. rasa/privacy/privacy_config.py +281 -0
  234. rasa/privacy/privacy_config_schema.json +86 -0
  235. rasa/privacy/privacy_filter.py +340 -0
  236. rasa/privacy/privacy_manager.py +576 -0
  237. rasa/server.py +23 -2
  238. rasa/shared/constants.py +14 -0
  239. rasa/shared/core/command_payload_reader.py +1 -5
  240. rasa/shared/core/constants.py +4 -3
  241. rasa/shared/core/domain.py +172 -11
  242. rasa/shared/core/events.py +100 -6
  243. rasa/shared/core/flows/flow.py +35 -8
  244. rasa/shared/core/flows/flow_step.py +26 -4
  245. rasa/shared/core/flows/flow_step_links.py +15 -0
  246. rasa/shared/core/flows/flow_step_sequence.py +6 -0
  247. rasa/shared/core/flows/flows_yaml_schema.json +3 -0
  248. rasa/shared/core/flows/nlu_trigger.py +13 -0
  249. rasa/shared/core/flows/steps/action.py +7 -4
  250. rasa/shared/core/flows/steps/call.py +11 -4
  251. rasa/shared/core/flows/steps/collect.py +71 -6
  252. rasa/shared/core/flows/steps/internal.py +6 -1
  253. rasa/shared/core/flows/steps/link.py +7 -4
  254. rasa/shared/core/flows/steps/no_operation.py +7 -4
  255. rasa/shared/core/flows/steps/set_slots.py +8 -4
  256. rasa/shared/core/flows/validation.py +16 -3
  257. rasa/shared/core/flows/yaml_flows_io.py +106 -5
  258. rasa/shared/core/slots.py +33 -1
  259. rasa/shared/core/trackers.py +4 -10
  260. rasa/shared/core/training_data/story_reader/yaml_story_reader.py +1 -4
  261. rasa/shared/importers/importer.py +14 -0
  262. rasa/shared/importers/static.py +63 -0
  263. rasa/shared/providers/llm/default_litellm_llm_client.py +2 -2
  264. rasa/shared/utils/common.py +43 -1
  265. rasa/shared/utils/llm.py +155 -3
  266. rasa/shared/utils/yaml.py +32 -0
  267. rasa/studio/data_handler.py +3 -3
  268. rasa/studio/download/__init__.py +0 -0
  269. rasa/studio/download/domains.py +49 -0
  270. rasa/studio/download/download.py +416 -0
  271. rasa/studio/download/flows.py +351 -0
  272. rasa/studio/link.py +200 -0
  273. rasa/studio/pull.py +94 -0
  274. rasa/studio/push.py +131 -0
  275. rasa/studio/results_logger.py +6 -1
  276. rasa/studio/upload.py +185 -71
  277. rasa/telemetry.py +83 -26
  278. rasa/tracing/config.py +4 -5
  279. rasa/tracing/constants.py +19 -1
  280. rasa/tracing/instrumentation/attribute_extractors.py +47 -9
  281. rasa/tracing/instrumentation/instrumentation.py +54 -3
  282. rasa/tracing/instrumentation/metrics.py +98 -15
  283. rasa/tracing/metric_instrument_provider.py +75 -3
  284. rasa/utils/common.py +37 -27
  285. rasa/utils/endpoints.py +22 -1
  286. rasa/utils/licensing.py +2 -3
  287. rasa/utils/log_utils.py +1 -45
  288. rasa/validator.py +9 -11
  289. rasa/version.py +1 -1
  290. {rasa_pro-3.12.18.dist-info → rasa_pro-3.13.0a1.dev1.dist-info}/METADATA +12 -13
  291. {rasa_pro-3.12.18.dist-info → rasa_pro-3.13.0a1.dev1.dist-info}/RECORD +308 -283
  292. rasa/anonymization/__init__.py +0 -2
  293. rasa/anonymization/anonymisation_rule_yaml_reader.py +0 -91
  294. rasa/anonymization/anonymization_pipeline.py +0 -286
  295. rasa/anonymization/anonymization_rule_executor.py +0 -266
  296. rasa/anonymization/anonymization_rule_orchestrator.py +0 -119
  297. rasa/anonymization/schemas/config.yml +0 -47
  298. rasa/anonymization/utils.py +0 -118
  299. rasa/cli/project_templates/calm/config.yml +0 -10
  300. rasa/cli/project_templates/calm/credentials.yml +0 -33
  301. rasa/cli/project_templates/calm/endpoints.yml +0 -58
  302. rasa/cli/project_templates/default/actions/actions.py +0 -27
  303. rasa/cli/project_templates/default/data/nlu.yml +0 -91
  304. rasa/cli/project_templates/default/data/rules.yml +0 -13
  305. rasa/cli/project_templates/default/data/stories.yml +0 -30
  306. rasa/cli/project_templates/default/domain.yml +0 -34
  307. rasa/cli/project_templates/default/tests/test_stories.yml +0 -91
  308. rasa/core/channels/inspector/dist/assets/channel-dfa68278.js +0 -1
  309. rasa/core/channels/inspector/dist/assets/clone-edb7f119.js +0 -1
  310. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-65e7c670.js +0 -1
  311. rasa/core/channels/inspector/src/helpers/audiostream.ts +0 -191
  312. rasa/core/tracker_store.py +0 -1792
  313. rasa/studio/download.py +0 -489
  314. /rasa/{cli/project_templates/calm/actions → builder}/__init__.py +0 -0
  315. /rasa/cli/project_templates/{calm → default}/actions/action_template.py +0 -0
  316. /rasa/cli/project_templates/{calm → default}/actions/add_contact.py +0 -0
  317. /rasa/cli/project_templates/{calm → default}/actions/db.py +0 -0
  318. /rasa/cli/project_templates/{calm → default}/actions/list_contacts.py +0 -0
  319. /rasa/cli/project_templates/{calm → default}/actions/remove_contact.py +0 -0
  320. /rasa/cli/project_templates/{calm → default}/data/flows/add_contact.yml +0 -0
  321. /rasa/cli/project_templates/{calm → default}/data/flows/list_contacts.yml +0 -0
  322. /rasa/cli/project_templates/{calm → default}/data/flows/remove_contact.yml +0 -0
  323. /rasa/cli/project_templates/{calm → default}/db/contacts.json +0 -0
  324. /rasa/cli/project_templates/{calm → default}/domain/add_contact.yml +0 -0
  325. /rasa/cli/project_templates/{calm → default}/domain/list_contacts.yml +0 -0
  326. /rasa/cli/project_templates/{calm → default}/domain/remove_contact.yml +0 -0
  327. /rasa/cli/project_templates/{calm → default}/domain/shared.yml +0 -0
  328. {rasa_pro-3.12.18.dist-info → rasa_pro-3.13.0a1.dev1.dist-info}/NOTICE +0 -0
  329. {rasa_pro-3.12.18.dist-info → rasa_pro-3.13.0a1.dev1.dist-info}/WHEEL +0 -0
  330. {rasa_pro-3.12.18.dist-info → rasa_pro-3.13.0a1.dev1.dist-info}/entry_points.txt +0 -0
@@ -14,7 +14,7 @@ from sanic import ( # type: ignore[attr-defined]
14
14
  response,
15
15
  )
16
16
 
17
- from rasa.core.channels import InputChannel, UserMessage
17
+ from rasa.core.channels import UserMessage
18
18
  from rasa.core.channels.channel import (
19
19
  create_auth_requested_response_provider,
20
20
  requires_basic_auth,
@@ -102,16 +102,22 @@ class TwilioMediaStreamsInputChannel(VoiceInputChannel):
102
102
  server_url: str,
103
103
  asr_config: Dict,
104
104
  tts_config: Dict,
105
- monitor_silence: bool = False,
106
105
  username: Optional[Text] = None,
107
106
  password: Optional[Text] = None,
108
107
  ):
109
- super().__init__(server_url, asr_config, tts_config, monitor_silence)
108
+ super().__init__(
109
+ server_url=server_url,
110
+ asr_config=asr_config,
111
+ tts_config=tts_config,
112
+ )
110
113
  self.username = username
111
114
  self.password = password
112
115
 
113
116
  @classmethod
114
- def from_credentials(cls, credentials: Optional[Dict[str, Any]]) -> InputChannel:
117
+ def from_credentials(
118
+ cls,
119
+ credentials: Optional[Dict[str, Any]],
120
+ ) -> VoiceInputChannel:
115
121
  credentials = credentials or {}
116
122
 
117
123
  username = credentials.get("username")
@@ -126,7 +132,6 @@ class TwilioMediaStreamsInputChannel(VoiceInputChannel):
126
132
  credentials["server_url"],
127
133
  credentials["asr"],
128
134
  credentials["tts"],
129
- credentials.get("monitor_silence", False),
130
135
  username=username,
131
136
  password=password,
132
137
  )
@@ -31,8 +31,10 @@ from rasa.core.channels.voice_stream.tts.azure import AzureTTS
31
31
  from rasa.core.channels.voice_stream.tts.cartesia import CartesiaTTS
32
32
  from rasa.core.channels.voice_stream.tts.tts_cache import TTSCache
33
33
  from rasa.core.channels.voice_stream.tts.tts_engine import TTSEngine, TTSError
34
- from rasa.core.channels.voice_stream.util import generate_silence
35
- from rasa.shared.core.constants import SLOT_SILENCE_TIMEOUT
34
+ from rasa.core.channels.voice_stream.util import (
35
+ generate_silence,
36
+ )
37
+ from rasa.shared.core.constants import SILENCE_TIMEOUT_SLOT
36
38
  from rasa.shared.utils.cli import print_error_and_exit
37
39
  from rasa.shared.utils.common import (
38
40
  class_from_module_path,
@@ -42,6 +44,11 @@ from rasa.utils.io import remove_emojis
42
44
 
43
45
  logger = structlog.get_logger(__name__)
44
46
 
47
+ # define constants for the voice channel
48
+ USER_CONVERSATION_SESSION_END = "/session_end"
49
+ USER_CONVERSATION_SESSION_START = "/session_start"
50
+ USER_CONVERSATION_SILENCE_TIMEOUT = "/silence_timeout"
51
+
45
52
 
46
53
  @dataclass
47
54
  class VoiceChannelAction:
@@ -166,8 +173,12 @@ class VoiceOutputChannel(OutputChannel):
166
173
  def update_silence_timeout(self) -> None:
167
174
  """Updates the silence timeout for the session."""
168
175
  if self.tracker_state:
169
- call_state.silence_timeout = ( # type: ignore[attr-defined]
170
- self.tracker_state["slots"][SLOT_SILENCE_TIMEOUT]
176
+ call_state.silence_timeout = self.tracker_state["slots"][ # type: ignore[attr-defined]
177
+ SILENCE_TIMEOUT_SLOT
178
+ ]
179
+ logger.debug(
180
+ "voice_channel.silence_timeout_updated",
181
+ silence_timeout=call_state.silence_timeout,
171
182
  )
172
183
 
173
184
  async def send_text_with_buttons(
@@ -189,6 +200,7 @@ class VoiceOutputChannel(OutputChannel):
189
200
  collected_audio_bytes = RasaAudioBytes(b"")
190
201
  seconds_marker = -1
191
202
  last_sent_offset = 0
203
+ logger.debug("voice_channel.sending_audio", text=text)
192
204
 
193
205
  # Send start marker before first chunk
194
206
  try:
@@ -274,26 +286,34 @@ class VoiceOutputChannel(OutputChannel):
274
286
 
275
287
 
276
288
  class VoiceInputChannel(InputChannel):
289
+ # All children of this class require a voice license to be used.
290
+ requires_voice_license = True
291
+
277
292
  def __init__(
278
293
  self,
279
294
  server_url: str,
280
295
  asr_config: Dict,
281
296
  tts_config: Dict,
282
- monitor_silence: bool = False,
283
297
  ):
284
- validate_voice_license_scope()
298
+ if self.requires_voice_license:
299
+ validate_voice_license_scope()
300
+
285
301
  self.server_url = server_url
286
302
  self.asr_config = asr_config
287
303
  self.tts_config = tts_config
288
- self.monitor_silence = monitor_silence
289
304
  self.tts_cache = TTSCache(tts_config.get("cache_size", 1000))
290
305
 
306
+ logger.info(
307
+ "voice_channel.initialized",
308
+ server_url=self.server_url,
309
+ asr_config=self.asr_config,
310
+ tts_config=self.tts_config,
311
+ )
312
+
291
313
  async def monitor_silence_timeout(self, asr_event_queue: asyncio.Queue) -> None:
292
314
  timeout = call_state.silence_timeout
293
315
  if not timeout:
294
316
  return
295
- if not self.monitor_silence:
296
- return
297
317
  logger.debug("voice_channel.silence_timeout_watch_started", timeout=timeout)
298
318
  await asyncio.sleep(timeout)
299
319
  await asr_event_queue.put(UserSilence())
@@ -308,13 +328,15 @@ class VoiceInputChannel(InputChannel):
308
328
  call_state.silence_timeout_watcher = None # type: ignore[attr-defined]
309
329
 
310
330
  @classmethod
311
- def from_credentials(cls, credentials: Optional[Dict[str, Any]]) -> InputChannel:
331
+ def from_credentials(
332
+ cls,
333
+ credentials: Optional[Dict[str, Any]],
334
+ ) -> InputChannel:
312
335
  credentials = credentials or {}
313
336
  return cls(
314
337
  credentials["server_url"],
315
338
  credentials["asr"],
316
339
  credentials["tts"],
317
- credentials.get("monitor_silence", False),
318
340
  )
319
341
 
320
342
  def channel_bytes_to_rasa_audio_bytes(self, input_bytes: bytes) -> RasaAudioBytes:
@@ -334,9 +356,9 @@ class VoiceInputChannel(InputChannel):
334
356
  ) -> None:
335
357
  output_channel = self.create_output_channel(channel_websocket, tts_engine)
336
358
  message = UserMessage(
337
- "/session_start",
338
- output_channel,
339
- call_parameters.stream_id,
359
+ text=USER_CONVERSATION_SESSION_START,
360
+ output_channel=output_channel,
361
+ sender_id=call_parameters.stream_id,
340
362
  input_channel=self.name(),
341
363
  metadata=asdict(call_parameters),
342
364
  )
@@ -371,17 +393,17 @@ class VoiceInputChannel(InputChannel):
371
393
 
372
394
  async def consume_audio_bytes() -> None:
373
395
  async for message in channel_websocket:
374
- is_bot_speaking_before = call_state.is_bot_speaking
396
+ was_bot_speaking_before = call_state.is_bot_speaking
375
397
  channel_action = self.map_input_message(message, channel_websocket)
376
398
  is_bot_speaking_after = call_state.is_bot_speaking
377
399
 
378
- if not is_bot_speaking_before and is_bot_speaking_after:
400
+ if not was_bot_speaking_before and is_bot_speaking_after:
379
401
  logger.debug("voice_channel.bot_started_speaking")
380
402
  # relevant when the bot speaks multiple messages in one turn
381
403
  self._cancel_silence_timeout_watcher()
382
404
 
383
405
  # we just stopped speaking, starting a watcher for silence timeout
384
- if is_bot_speaking_before and not is_bot_speaking_after:
406
+ if was_bot_speaking_before and not is_bot_speaking_after:
385
407
  logger.debug("voice_channel.bot_stopped_speaking")
386
408
  self._cancel_silence_timeout_watcher()
387
409
  call_state.silence_timeout_watcher = ( # type: ignore[attr-defined]
@@ -393,6 +415,9 @@ class VoiceInputChannel(InputChannel):
393
415
  await asr_engine.send_audio_chunks(channel_action.audio_bytes)
394
416
  elif isinstance(channel_action, EndConversationAction):
395
417
  # end stream event came from the other side
418
+ await self.handle_disconnect(
419
+ channel_websocket, on_new_message, tts_engine, call_parameters
420
+ )
396
421
  break
397
422
 
398
423
  async def receive_asr_events() -> None:
@@ -449,9 +474,9 @@ class VoiceInputChannel(InputChannel):
449
474
  call_state.is_user_speaking = False # type: ignore[attr-defined]
450
475
  output_channel = self.create_output_channel(voice_websocket, tts_engine)
451
476
  message = UserMessage(
452
- e.text,
453
- output_channel,
454
- call_parameters.stream_id,
477
+ text=e.text,
478
+ output_channel=output_channel,
479
+ sender_id=call_parameters.stream_id,
455
480
  input_channel=self.name(),
456
481
  metadata=asdict(call_parameters),
457
482
  )
@@ -462,10 +487,27 @@ class VoiceInputChannel(InputChannel):
462
487
  elif isinstance(e, UserSilence):
463
488
  output_channel = self.create_output_channel(voice_websocket, tts_engine)
464
489
  message = UserMessage(
465
- "/silence_timeout",
466
- output_channel,
467
- call_parameters.stream_id,
490
+ text=USER_CONVERSATION_SILENCE_TIMEOUT,
491
+ output_channel=output_channel,
492
+ sender_id=call_parameters.stream_id,
468
493
  input_channel=self.name(),
469
494
  metadata=asdict(call_parameters),
470
495
  )
471
496
  await on_new_message(message)
497
+
498
+ async def handle_disconnect(
499
+ self,
500
+ channel_websocket: Websocket,
501
+ on_new_message: Callable[[UserMessage], Awaitable[Any]],
502
+ tts_engine: TTSEngine,
503
+ call_parameters: CallParameters,
504
+ ) -> None:
505
+ """Handle disconnection from the channel."""
506
+ output_channel = self.create_output_channel(channel_websocket, tts_engine)
507
+ message = UserMessage(
508
+ text=USER_CONVERSATION_SESSION_END,
509
+ output_channel=output_channel,
510
+ sender_id=call_parameters.stream_id,
511
+ input_channel=self.name(),
512
+ )
513
+ await on_new_message(message)
@@ -1,9 +1,10 @@
1
1
  import json
2
- import logging
3
2
  import time
4
3
  from collections import deque
5
4
  from typing import Deque, Optional, Text
6
5
 
6
+ import structlog
7
+
7
8
  from rasa.core.lock import Ticket, TicketLock
8
9
  from rasa.core.lock_store import (
9
10
  DEFAULT_SOCKET_TIMEOUT_IN_SECONDS,
@@ -19,7 +20,7 @@ DEFAULT_PORT = 6379
19
20
 
20
21
  DEFAULT_HOSTNAME = "localhost"
21
22
 
22
- logger = logging.getLogger(__name__)
23
+ structlogger = structlog.getLogger(__name__)
23
24
 
24
25
  LAST_ISSUED_TICKET_NUMBER_SUFFIX = "last_issued_ticket_number"
25
26
 
@@ -105,7 +106,10 @@ class ConcurrentRedisLockStore(LockStore):
105
106
 
106
107
  self.key_prefix = DEFAULT_CONCURRENT_REDIS_LOCK_STORE_KEY_PREFIX
107
108
  if key_prefix:
108
- logger.debug(f"Setting non-default redis key prefix: '{key_prefix}'.")
109
+ structlogger.debug(
110
+ "concurrent_redis_lock_store._set_key_prefix.non_default_key_prefix",
111
+ event_info=f"Setting non-default redis key prefix: '{key_prefix}'.",
112
+ )
109
113
  self._set_key_prefix(key_prefix)
110
114
 
111
115
  super().__init__()
@@ -116,9 +120,13 @@ class ConcurrentRedisLockStore(LockStore):
116
120
  key_prefix + ":" + DEFAULT_CONCURRENT_REDIS_LOCK_STORE_KEY_PREFIX
117
121
  )
118
122
  else:
119
- logger.warning(
120
- f"Omitting provided non-alphanumeric redis key prefix: '{key_prefix}'. "
121
- f"Using default '{self.key_prefix}' instead."
123
+ structlogger.warning(
124
+ "concurrent_redis_lock_store._set_key_prefix.default_instead_of_invalid_key_prefix",
125
+ event_info=(
126
+ f"Omitting provided non-alphanumeric "
127
+ f"redis key prefix: '{key_prefix}'. "
128
+ f"Using default '{self.key_prefix}' instead."
129
+ ),
122
130
  )
123
131
 
124
132
  def issue_ticket(
@@ -129,7 +137,10 @@ class ConcurrentRedisLockStore(LockStore):
129
137
  It's configured with `lock_lifetime` and associated with `conversation_id`.
130
138
  Creates a new lock if none is found.
131
139
  """
132
- logger.debug(f"Issuing ticket for conversation '{conversation_id}'.")
140
+ structlogger.debug(
141
+ "concurrent_redis_lock_store.issue_ticket",
142
+ event_info=f"Issuing ticket for conversation '{conversation_id}'.",
143
+ )
133
144
  try:
134
145
  lock = self.get_or_create_lock(conversation_id)
135
146
  lock.remove_expired_tickets()
@@ -164,9 +175,12 @@ class ConcurrentRedisLockStore(LockStore):
164
175
  redis_keys = self.red.keys(pattern)
165
176
 
166
177
  if not redis_keys:
167
- logger.debug(
168
- f"The lock store does not contain any key-value "
169
- f"items for conversation '{conversation_id}'."
178
+ structlogger.debug(
179
+ "concurrent_redis_lock_store.delete_lock_key_not_found",
180
+ event_info=(
181
+ f"The lock store does not contain any key-value "
182
+ f"items for conversation '{conversation_id}'."
183
+ ),
170
184
  )
171
185
  return None
172
186
 
@@ -2,7 +2,7 @@ import random
2
2
  from typing import Any, AsyncIterator, Iterable, List, Optional, Text
3
3
 
4
4
  import rasa.shared.utils.io
5
- from rasa.core.tracker_store import TrackerStore
5
+ from rasa.core.tracker_stores.tracker_store import TrackerStore
6
6
  from rasa.shared.core.trackers import DialogueStateTracker
7
7
  from rasa.shared.exceptions import RasaException
8
8
 
rasa/core/exporter.py CHANGED
@@ -10,7 +10,7 @@ import rasa.shared.utils.io
10
10
  from rasa.core.brokers.broker import EventBroker
11
11
  from rasa.core.brokers.pika import PikaEventBroker
12
12
  from rasa.core.constants import RASA_EXPORT_PROCESS_ID_HEADER_NAME
13
- from rasa.core.tracker_store import TrackerStore
13
+ from rasa.core.tracker_stores.tracker_store import TrackerStore
14
14
  from rasa.exceptions import (
15
15
  NoConversationsInTrackerStoreError,
16
16
  NoEventsToMigrateError,
@@ -1,4 +1,3 @@
1
- import copy
2
1
  import logging
3
2
  from typing import Any, Dict, Optional, Text
4
3
 
@@ -49,7 +48,6 @@ class RasaNLUHttpInterpreter:
49
48
  if not self.endpoint_config or self.endpoint_config.url is None:
50
49
  structlogger.error(
51
50
  "http.parse.text",
52
- text=copy.deepcopy(text),
53
51
  event_info="No rasa NLU server specified!",
54
52
  )
55
53
  return None
@@ -71,18 +69,16 @@ class RasaNLUHttpInterpreter:
71
69
  if resp.status == 200:
72
70
  return await resp.json()
73
71
  else:
74
- response_text = await resp.text()
75
72
  structlogger.error(
76
73
  "http.parse.text.failure",
77
- text=copy.deepcopy(text),
78
- response_text=copy.deepcopy(response_text),
74
+ event_info="Failed to parse text",
79
75
  )
80
76
  return None
81
- except Exception: # skipcq: PYL-W0703
77
+ except Exception as e: # skipcq: PYL-W0703
82
78
  # need to catch all possible exceptions when doing http requests
83
79
  # (timeouts, value errors, parser errors, ...)
84
80
  structlogger.exception(
85
81
  "http.parse.text.exception",
86
- text=copy.deepcopy(text),
82
+ event_info=f"Exception occurred while parsing text. Error: {e}",
87
83
  )
88
84
  return None
@@ -12,6 +12,7 @@ from rasa.core.information_retrieval import (
12
12
  InformationRetrievalException,
13
13
  SearchResultList,
14
14
  )
15
+ from rasa.core.information_retrieval.ingestion.faq_parser import _format_faq_documents
15
16
  from rasa.utils.endpoints import EndpointConfig
16
17
  from rasa.utils.ml_utils import persist_faiss_vector_store
17
18
 
@@ -31,10 +32,12 @@ class FAISS_Store(InformationRetrieval):
31
32
  index_path: str,
32
33
  docs_folder: Optional[str],
33
34
  create_index: Optional[bool] = False,
35
+ parse_as_faq_pairs: Optional[bool] = False,
34
36
  ):
35
37
  """Initializes the FAISS Store."""
36
38
  self.chunk_size = 1000
37
39
  self.chunk_overlap = 20
40
+ self.parse_as_faq_pairs = parse_as_faq_pairs
38
41
 
39
42
  path = Path(index_path) / "documents_faiss"
40
43
  if create_index:
@@ -86,21 +89,25 @@ class FAISS_Store(InformationRetrieval):
86
89
  if not docs_folder:
87
90
  raise ValueError("parameter `docs_folder` needs to be specified")
88
91
 
89
- docs = self.load_documents(docs_folder)
90
- splitter = RecursiveCharacterTextSplitter(
91
- chunk_size=self.chunk_size,
92
- chunk_overlap=self.chunk_overlap,
93
- length_function=len,
94
- )
95
- doc_chunks = splitter.split_documents(docs)
92
+ documents = self.load_documents(docs_folder)
93
+
94
+ if not self.parse_as_faq_pairs:
95
+ splitter = RecursiveCharacterTextSplitter(
96
+ chunk_size=self.chunk_size,
97
+ chunk_overlap=self.chunk_overlap,
98
+ length_function=len,
99
+ )
100
+ parsed_documents = splitter.split_documents(documents)
101
+ else:
102
+ parsed_documents = _format_faq_documents(documents)
96
103
 
97
104
  logger.info(
98
105
  "information_retrieval.faiss_store._create_document_index",
99
- len_chunks=len(doc_chunks),
106
+ len_chunks=len(parsed_documents),
100
107
  )
101
- if doc_chunks:
102
- texts = [chunk.page_content for chunk in doc_chunks]
103
- metadatas = [chunk.metadata for chunk in doc_chunks]
108
+ if parsed_documents:
109
+ texts = [document.page_content for document in parsed_documents]
110
+ metadatas = [document.metadata for document in parsed_documents]
104
111
  return FAISS.from_texts(texts, embedding, metadatas=metadatas, ids=None)
105
112
  else:
106
113
  raise ValueError(f"No documents found at '{docs_folder}'.")
File without changes
@@ -0,0 +1,158 @@
1
+ """Utilities for parsing FAQ-style documents (Q/A pairs) used in extractive search."""
2
+
3
+ import re
4
+ from collections import defaultdict
5
+ from typing import TYPE_CHECKING, List
6
+
7
+ import structlog
8
+
9
+ from rasa.shared.constants import (
10
+ DOCUMENT_TYPE_FAQ,
11
+ FAQ_DOCUMENT_ENTRY_SEPARATOR,
12
+ FAQ_DOCUMENT_LINE_SEPARATOR,
13
+ FAQ_DOCUMENT_METADATA_ANSWER,
14
+ FAQ_DOCUMENT_METADATA_TITLE,
15
+ FAQ_DOCUMENT_METADATA_TYPE,
16
+ FAQ_INPUT_DATA_ANSWER_LINE_PREFIX,
17
+ FAQ_INPUT_DATA_QUESTION_LINE_PREFIX,
18
+ )
19
+
20
+ if TYPE_CHECKING:
21
+ from langchain.schema import Document
22
+
23
+ _FAQ_PAIR_PATTERN = re.compile(
24
+ rf"{re.escape(FAQ_INPUT_DATA_QUESTION_LINE_PREFIX)}\s*"
25
+ rf"(?P<question>.*?)\s*{FAQ_DOCUMENT_LINE_SEPARATOR}\s*"
26
+ rf"{re.escape(FAQ_INPUT_DATA_ANSWER_LINE_PREFIX)}\s*"
27
+ rf"(?P<answer>.*)",
28
+ re.DOTALL,
29
+ )
30
+
31
+
32
+ structlogger = structlog.get_logger()
33
+
34
+
35
+ def _format_faq_documents(documents: List["Document"]) -> List["Document"]:
36
+ """Splits each loaded file into individual FAQs.
37
+
38
+ Args:
39
+ documents: Documents representing whole files containing FAQs.
40
+
41
+ Returns:
42
+ List of Document objects, each containing a separate FAQ.
43
+
44
+ Examples:
45
+ An example of a file containing FAQs:
46
+
47
+ Q: Who is Finley?
48
+ A: Finley is your smart assistant for the FinX App. You can add him to your
49
+ favorite messenger and tell him what you need help with.
50
+
51
+ Q: How does Finley work?
52
+ A: Finley is powered by the latest chatbot technology leveraging a unique
53
+ interplay of large language models and secure logic.
54
+
55
+ More details in documentation: https://rasa.com/docs/reference/config/policies/extractive-search/
56
+ """
57
+ structured_faqs = []
58
+ from langchain.schema import Document
59
+
60
+ for document in documents:
61
+ chunks = document.page_content.strip().split(FAQ_DOCUMENT_ENTRY_SEPARATOR)
62
+
63
+ for chunk in chunks:
64
+ match = _FAQ_PAIR_PATTERN.match(chunk.strip())
65
+
66
+ if not match:
67
+ structlogger.warning(
68
+ "faq_parser.format_faq_documents.invalid_chunk_skipped",
69
+ event_info=(
70
+ "Chunk does not match expected QA format. "
71
+ "Please refer to the documentation: "
72
+ "https://rasa.com/docs/reference/config/"
73
+ "policies/extractive-search/"
74
+ ),
75
+ chunk_preview=chunk[:100],
76
+ )
77
+ continue
78
+
79
+ question = match.group("question").strip()
80
+ answer = match.group("answer").strip()
81
+ title = _sanitize_title(question)
82
+
83
+ formatted_document = Document(
84
+ page_content=question,
85
+ metadata={
86
+ FAQ_DOCUMENT_METADATA_TITLE: title,
87
+ FAQ_DOCUMENT_METADATA_TYPE: DOCUMENT_TYPE_FAQ,
88
+ FAQ_DOCUMENT_METADATA_ANSWER: answer,
89
+ },
90
+ )
91
+
92
+ structured_faqs.append(formatted_document)
93
+
94
+ structlogger.debug(
95
+ "faq_parser.format_faq_documents.parsed_chunk",
96
+ event_info="Parsed chunk.",
97
+ title=title,
98
+ question=question,
99
+ answer=answer,
100
+ parsed_chunk_preview=chunk[:100],
101
+ )
102
+
103
+ structlogger.debug(
104
+ "faq_parser.format_faq_documents.parsed_chunks",
105
+ event_info=(
106
+ f"Retrieved {len(structured_faqs)} FAQ pair(s)"
107
+ f"from {len(documents)} document(s)."
108
+ ),
109
+ num_structured_faqs=len(structured_faqs),
110
+ num_documents=len(documents),
111
+ )
112
+ _check_and_parsed_faq_documents_for_duplicates(structured_faqs)
113
+ return structured_faqs
114
+
115
+
116
+ def _sanitize_title(title: str) -> str:
117
+ title = title.lower()
118
+ # Remove all whitespaces with "_"
119
+ title = re.sub(r"\s+", "_", title)
120
+ # Remove all non alpha-numeric characters
121
+ title = re.sub(r"[^\w]", "", title)
122
+ # Collapse multiple "_"
123
+ title = re.sub(r"_+", "_", title)
124
+ # Clean up edges
125
+ return title.strip("_")
126
+
127
+
128
+ def _check_and_parsed_faq_documents_for_duplicates(documents: List["Document"]) -> None:
129
+ seen_qa_pairs = set()
130
+ seen_questions: defaultdict = defaultdict(list)
131
+
132
+ for doc in documents:
133
+ question = doc.page_content.strip()
134
+ answer = doc.metadata.get(FAQ_DOCUMENT_METADATA_ANSWER, "").strip()
135
+
136
+ if not question or not answer:
137
+ continue
138
+
139
+ if (question, answer) in seen_qa_pairs:
140
+ structlogger.warning(
141
+ "faq_parser.duplicate_qa_pair_found",
142
+ event_info="Duplicate QA pair found.",
143
+ question=question,
144
+ answer_preview=answer,
145
+ )
146
+ continue
147
+
148
+ if question in seen_questions and seen_questions[question] != answer:
149
+ structlogger.warning(
150
+ "faq_parser.inconsistent_answer",
151
+ event_info="Duplicate question with different answer found.",
152
+ question=question,
153
+ previous_answers=seen_questions[question],
154
+ new_answer=answer,
155
+ )
156
+
157
+ seen_qa_pairs.add((question, answer))
158
+ seen_questions[question].append(answer)
rasa/core/jobs.py CHANGED
@@ -1,12 +1,13 @@
1
1
  import asyncio
2
2
  import logging
3
+ from typing import Optional
3
4
 
4
5
  from apscheduler.schedulers.asyncio import AsyncIOScheduler
5
6
  from pytz import UnknownTimeZoneError, utc
6
7
 
7
8
  import rasa.shared.utils.io
8
9
 
9
- __scheduler = None
10
+ __scheduler: Optional[AsyncIOScheduler] = None
10
11
 
11
12
  logger = logging.getLogger(__name__)
12
13