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
@@ -1,3 +1,4 @@
1
+ import dataclasses
1
2
  import glob
2
3
  import importlib.resources
3
4
  import json
@@ -11,10 +12,8 @@ from jinja2 import Template
11
12
  from pydantic import ValidationError
12
13
 
13
14
  import rasa.shared.utils.io
15
+ from rasa.core.available_endpoints import AvailableEndpoints
14
16
  from rasa.core.constants import (
15
- POLICY_MAX_HISTORY,
16
- POLICY_PRIORITY,
17
- SEARCH_POLICY_PRIORITY,
18
17
  UTTER_SOURCE_METADATA_KEY,
19
18
  )
20
19
  from rasa.core.information_retrieval import (
@@ -24,8 +23,15 @@ from rasa.core.information_retrieval import (
24
23
  create_from_endpoint_config,
25
24
  )
26
25
  from rasa.core.information_retrieval.faiss import FAISS_Store
26
+ from rasa.core.policies.enterprise_search_policy_config import (
27
+ DEFAULT_EMBEDDINGS_CONFIG,
28
+ DEFAULT_ENTERPRISE_SEARCH_CONFIG,
29
+ DEFAULT_LLM_CONFIG,
30
+ DEFAULT_VECTOR_STORE_TYPE,
31
+ SOURCE_PROPERTY,
32
+ EnterpriseSearchPolicyConfig,
33
+ )
27
34
  from rasa.core.policies.policy import Policy, PolicyPrediction
28
- from rasa.core.utils import AvailableEndpoints
29
35
  from rasa.dialogue_understanding.generator.constants import (
30
36
  LLM_CONFIG_KEY,
31
37
  )
@@ -48,16 +54,11 @@ from rasa.graph_components.providers.forms_provider import Forms
48
54
  from rasa.graph_components.providers.responses_provider import Responses
49
55
  from rasa.shared.constants import (
50
56
  EMBEDDINGS_CONFIG_KEY,
51
- MAX_COMPLETION_TOKENS_CONFIG_KEY,
52
- MAX_RETRIES_CONFIG_KEY,
53
57
  MODEL_CONFIG_KEY,
54
58
  MODEL_GROUP_ID_CONFIG_KEY,
55
59
  MODEL_NAME_CONFIG_KEY,
56
- OPENAI_PROVIDER,
57
- PROMPT_CONFIG_KEY,
58
60
  PROVIDER_CONFIG_KEY,
59
- TEMPERATURE_CONFIG_KEY,
60
- TIMEOUT_CONFIG_KEY,
61
+ RASA_PATTERN_CANNOT_HANDLE_NO_RELEVANT_ANSWER,
61
62
  )
62
63
  from rasa.shared.core.constants import (
63
64
  ACTION_CANCEL_FLOW,
@@ -80,7 +81,6 @@ from rasa.shared.nlu.training_data.training_data import TrainingData
80
81
  from rasa.shared.providers.embedding._langchain_embedding_client_adapter import (
81
82
  _LangchainEmbeddingClientAdapter,
82
83
  )
83
- from rasa.shared.providers.llm.llm_client import LLMClient
84
84
  from rasa.shared.providers.llm.llm_response import LLMResponse, measure_llm_latency
85
85
  from rasa.shared.utils.cli import print_error_and_exit
86
86
  from rasa.shared.utils.constants import (
@@ -93,12 +93,9 @@ from rasa.shared.utils.health_check.embeddings_health_check_mixin import (
93
93
  from rasa.shared.utils.health_check.llm_health_check_mixin import LLMHealthCheckMixin
94
94
  from rasa.shared.utils.io import deep_container_fingerprint
95
95
  from rasa.shared.utils.llm import (
96
- DEFAULT_OPENAI_CHAT_MODEL_NAME,
97
- DEFAULT_OPENAI_EMBEDDING_MODEL_NAME,
98
96
  embedder_factory,
99
97
  get_prompt_template,
100
98
  llm_factory,
101
- resolve_model_client_config,
102
99
  sanitize_message_for_prompt,
103
100
  tracker_as_readable_transcript,
104
101
  )
@@ -115,41 +112,10 @@ if TYPE_CHECKING:
115
112
 
116
113
  from rasa.utils.log_utils import log_llm
117
114
 
118
- logger = structlog.get_logger()
115
+ structlogger = structlog.get_logger()
119
116
 
120
117
  dotenv.load_dotenv("./.env")
121
118
 
122
- SOURCE_PROPERTY = "source"
123
- VECTOR_STORE_TYPE_PROPERTY = "type"
124
- VECTOR_STORE_PROPERTY = "vector_store"
125
- VECTOR_STORE_THRESHOLD_PROPERTY = "threshold"
126
- TRACE_TOKENS_PROPERTY = "trace_prompt_tokens"
127
- CITATION_ENABLED_PROPERTY = "citation_enabled"
128
- USE_LLM_PROPERTY = "use_generative_llm"
129
- MAX_MESSAGES_IN_QUERY_KEY = "max_messages_in_query"
130
-
131
- DEFAULT_VECTOR_STORE_TYPE = "faiss"
132
- DEFAULT_VECTOR_STORE_THRESHOLD = 0.0
133
- DEFAULT_VECTOR_STORE = {
134
- VECTOR_STORE_TYPE_PROPERTY: DEFAULT_VECTOR_STORE_TYPE,
135
- SOURCE_PROPERTY: "./docs",
136
- VECTOR_STORE_THRESHOLD_PROPERTY: DEFAULT_VECTOR_STORE_THRESHOLD,
137
- }
138
-
139
- DEFAULT_LLM_CONFIG = {
140
- PROVIDER_CONFIG_KEY: OPENAI_PROVIDER,
141
- MODEL_CONFIG_KEY: DEFAULT_OPENAI_CHAT_MODEL_NAME,
142
- TIMEOUT_CONFIG_KEY: 10,
143
- TEMPERATURE_CONFIG_KEY: 0.0,
144
- MAX_COMPLETION_TOKENS_CONFIG_KEY: 256,
145
- MAX_RETRIES_CONFIG_KEY: 1,
146
- }
147
-
148
- DEFAULT_EMBEDDINGS_CONFIG = {
149
- PROVIDER_CONFIG_KEY: OPENAI_PROVIDER,
150
- MODEL_CONFIG_KEY: DEFAULT_OPENAI_EMBEDDING_MODEL_NAME,
151
- }
152
-
153
119
  ENTERPRISE_SEARCH_PROMPT_FILE_NAME = "enterprise_search_policy_prompt.jinja2"
154
120
  ENTERPRISE_SEARCH_CONFIG_FILE_NAME = "config.json"
155
121
 
@@ -164,6 +130,15 @@ DEFAULT_ENTERPRISE_SEARCH_PROMPT_WITH_CITATION_TEMPLATE = importlib.resources.re
164
130
  "rasa.core.policies", "enterprise_search_prompt_with_citation_template.jinja2"
165
131
  )
166
132
 
133
+ DEFAULT_ENTERPRISE_SEARCH_PROMPT_WITH_RELEVANCY_CHECK_AND_CITATION_TEMPLATE = (
134
+ importlib.resources.read_text(
135
+ "rasa.core.policies",
136
+ "enterprise_search_prompt_with_relevancy_check_and_citation_template.jinja2",
137
+ )
138
+ )
139
+
140
+ _ENTERPRISE_SEARCH_ANSWER_NOT_RELEVANT_PATTERN = re.compile(r"\[NO_RAG_ANSWER\]")
141
+
167
142
  _ENTERPRISE_SEARCH_CITATION_PATTERN = re.compile(r"\[([^\]]+)\]")
168
143
 
169
144
 
@@ -175,6 +150,12 @@ class VectorStoreConfigurationError(RasaException):
175
150
  """Exception raised for errors in vector store configuration."""
176
151
 
177
152
 
153
+ @dataclasses.dataclass
154
+ class _RelevancyCheckResponse:
155
+ answer: Optional[str]
156
+ relevant: bool
157
+
158
+
178
159
  @DefaultV1Recipe.register(
179
160
  DefaultV1Recipe.ComponentType.POLICY_WITH_END_TO_END_SUPPORT, is_trainable=True
180
161
  )
@@ -206,10 +187,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
206
187
  @staticmethod
207
188
  def get_default_config() -> Dict[str, Any]:
208
189
  """Returns the default config of the policy."""
209
- return {
210
- POLICY_PRIORITY: SEARCH_POLICY_PRIORITY,
211
- VECTOR_STORE_PROPERTY: DEFAULT_VECTOR_STORE,
212
- }
190
+ return DEFAULT_ENTERPRISE_SEARCH_CONFIG
213
191
 
214
192
  def __init__(
215
193
  self,
@@ -224,76 +202,71 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
224
202
  """Constructs a new Policy object."""
225
203
  super().__init__(config, model_storage, resource, execution_context, featurizer)
226
204
 
227
- # Resolve LLM config
228
- self.config[LLM_CONFIG_KEY] = resolve_model_client_config(
229
- self.config.get(LLM_CONFIG_KEY), EnterpriseSearchPolicy.__name__
230
- )
231
- # Resolve embeddings config
232
- self.config[EMBEDDINGS_CONFIG_KEY] = resolve_model_client_config(
233
- self.config.get(EMBEDDINGS_CONFIG_KEY), EnterpriseSearchPolicy.__name__
234
- )
205
+ parsed_config = EnterpriseSearchPolicyConfig.from_dict(config)
235
206
 
236
207
  # Vector store object and configuration
237
208
  self.vector_store = vector_store
238
- self.vector_store_config = self.config.get(
239
- VECTOR_STORE_PROPERTY, DEFAULT_VECTOR_STORE
240
- )
209
+ self.vector_store_config = parsed_config.vector_store_config
210
+ self.vector_search_threshold = parsed_config.vector_store_threshold
211
+ self.vector_store_type = parsed_config.vector_store_type
241
212
 
242
- # Embeddings configuration for encoding the search query
243
- self.embeddings_config = (
244
- self.config[EMBEDDINGS_CONFIG_KEY] or DEFAULT_EMBEDDINGS_CONFIG
245
- )
213
+ # Resolved embeddings configuration for encoding the search query
214
+ self.embeddings_config = parsed_config.embeddings_config
246
215
 
247
- # LLM Configuration for response generation
248
- self.llm_config = self.config[LLM_CONFIG_KEY] or DEFAULT_LLM_CONFIG
216
+ # Resolved LLM Configuration for response generation
217
+ self.llm_config = parsed_config.llm_config
249
218
 
250
219
  # Maximum number of turns to include in the prompt
251
- self.max_history = self.config.get(POLICY_MAX_HISTORY)
220
+ self.max_history = parsed_config.max_history
252
221
 
253
222
  # Maximum number of messages to include in the search query
254
- self.max_messages_in_query = self.config.get(MAX_MESSAGES_IN_QUERY_KEY, 2)
223
+ self.max_messages_in_query = parsed_config.max_messages_in_query
224
+
225
+ # Boolean to enable/disable tracing of prompt tokens
226
+ self.trace_prompt_tokens = parsed_config.trace_prompt_tokens
255
227
 
256
- # boolean to enable/disable tracing of prompt tokens
257
- self.trace_prompt_tokens = self.config.get(TRACE_TOKENS_PROPERTY, False)
228
+ # Boolean to enable/disable the use of LLM for response generation
229
+ self.use_llm = parsed_config.use_generative_llm
258
230
 
259
- # boolean to enable/disable the use of LLM for response generation
260
- self.use_llm = self.config.get(USE_LLM_PROPERTY, True)
231
+ # Boolean to enable/disable citation generation. This flag enables citation
232
+ # logic, but it only takes effect if `use_llm` is True.
233
+ self.citation_enabled = parsed_config.enable_citation
261
234
 
262
- # boolean to enable/disable citation generation
263
- self.citation_enabled = self.config.get(CITATION_ENABLED_PROPERTY, False)
235
+ # Boolean to enable/disable the use of relevancy check alongside answer
236
+ # generation. This flag enables citation logic, but it only takes effect if
237
+ # `use_llm` is True.
238
+ self.relevancy_check_enabled = parsed_config.check_relevancy
264
239
 
240
+ # Resolve the prompt template. The prompt will only be used if the 'use_llm' is
241
+ # set to True.
265
242
  self.prompt_template = prompt_template or get_prompt_template(
266
- self.config.get(PROMPT_CONFIG_KEY),
267
- DEFAULT_ENTERPRISE_SEARCH_PROMPT_TEMPLATE,
268
- log_source_component=EnterpriseSearchPolicy.__name__,
269
- log_source_method=LOG_COMPONENT_SOURCE_METHOD_INIT,
270
- )
271
- self.citation_prompt_template = get_prompt_template(
272
- self.config.get(PROMPT_CONFIG_KEY),
273
- DEFAULT_ENTERPRISE_SEARCH_PROMPT_WITH_CITATION_TEMPLATE,
243
+ jinja_file_path=parsed_config.prompt_template,
244
+ default_prompt_template=self._select_default_prompt_template_based_on_features(
245
+ parsed_config.check_relevancy, parsed_config.enable_citation
246
+ ),
274
247
  log_source_component=EnterpriseSearchPolicy.__name__,
275
248
  log_source_method=LOG_COMPONENT_SOURCE_METHOD_INIT,
276
249
  )
277
- # If citation is enabled, use the citation prompt template
278
- if self.citation_enabled:
279
- self.prompt_template = self.citation_prompt_template
280
250
 
281
251
  @classmethod
282
- def _create_plain_embedder(cls, config: Dict[Text, Any]) -> "Embeddings":
252
+ def _create_plain_embedder(cls, embeddings_config: Dict[Text, Any]) -> "Embeddings":
283
253
  """Creates an embedder based on the given configuration.
284
254
 
255
+ Args:
256
+ embeddings_config: A resolved embeddings configuration. Resolved means the
257
+ configuration is either:
258
+ - A reference to a model group that has already been expanded into
259
+ its corresponding configuration using the information from
260
+ `endpoints.yml`, or
261
+ - A full configuration for the embedder defined directly (i.e. not
262
+ relying on model groups or indirections).
263
+
285
264
  Returns:
286
- The embedder.
265
+ The embedder.
287
266
  """
288
267
  # Copy the config so original config is not modified
289
- config = config.copy()
290
- # Resolve config and instantiate the embedding client
291
- config[EMBEDDINGS_CONFIG_KEY] = resolve_model_client_config(
292
- config.get(EMBEDDINGS_CONFIG_KEY), EnterpriseSearchPolicy.__name__
293
- )
294
- client = embedder_factory(
295
- config.get(EMBEDDINGS_CONFIG_KEY), DEFAULT_EMBEDDINGS_CONFIG
296
- )
268
+ embeddings_config = embeddings_config.copy()
269
+ client = embedder_factory(embeddings_config, DEFAULT_EMBEDDINGS_CONFIG)
297
270
  # Wrap the embedding client in the adapter
298
271
  return _LangchainEmbeddingClientAdapter(client)
299
272
 
@@ -359,18 +332,18 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
359
332
  can load the policy from the resource.
360
333
  """
361
334
  # Perform health checks for both LLM and embeddings client configs
362
- self._perform_health_checks(self.config, "enterprise_search_policy.train")
363
-
364
- store_type = self.vector_store_config.get(VECTOR_STORE_TYPE_PROPERTY)
335
+ self._perform_health_checks(
336
+ self.llm_config, self.embeddings_config, "enterprise_search_policy.train"
337
+ )
365
338
 
366
339
  # telemetry call to track training start
367
340
  track_enterprise_search_policy_train_started()
368
341
 
369
342
  # validate embedding configuration
370
343
  try:
371
- embeddings = self._create_plain_embedder(self.config)
344
+ embeddings = self._create_plain_embedder(self.embeddings_config)
372
345
  except (ValidationError, Exception) as e:
373
- logger.error(
346
+ structlogger.error(
374
347
  "enterprise_search_policy.train.embedder_instantiation_failed",
375
348
  message="Unable to instantiate the embedding client.",
376
349
  error=e,
@@ -380,8 +353,8 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
380
353
  f"required environment variables. Error: {e}"
381
354
  )
382
355
 
383
- if store_type == DEFAULT_VECTOR_STORE_TYPE:
384
- logger.info("enterprise_search_policy.train.faiss")
356
+ if self.vector_store_type == DEFAULT_VECTOR_STORE_TYPE:
357
+ structlogger.info("enterprise_search_policy.train.faiss")
385
358
  docs_folder = self.vector_store_config.get(SOURCE_PROPERTY)
386
359
  self._validate_documents_folder(docs_folder)
387
360
  with self._model_storage.write_to(self._resource) as path:
@@ -390,13 +363,17 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
390
363
  embeddings=embeddings,
391
364
  index_path=path,
392
365
  create_index=True,
366
+ parse_as_faq_pairs=not self.use_llm,
393
367
  )
394
368
  else:
395
- logger.info("enterprise_search_policy.train.custom", store_type=store_type)
369
+ structlogger.info(
370
+ "enterprise_search_policy.train.custom",
371
+ store_type=self.vector_store_type,
372
+ )
396
373
 
397
374
  # telemetry call to track training completion
398
375
  track_enterprise_search_policy_train_completed(
399
- vector_store_type=store_type,
376
+ vector_store_type=self.vector_store_type,
400
377
  embeddings_type=self.embeddings_config.get(PROVIDER_CONFIG_KEY),
401
378
  embeddings_model=self.embeddings_config.get(MODEL_CONFIG_KEY)
402
379
  or self.embeddings_config.get(MODEL_NAME_CONFIG_KEY),
@@ -408,6 +385,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
408
385
  or self.llm_config.get(MODEL_NAME_CONFIG_KEY),
409
386
  llm_model_group_id=self.llm_config.get(MODEL_GROUP_ID_CONFIG_KEY),
410
387
  citation_enabled=self.citation_enabled,
388
+ relevancy_check_enabled=self.relevancy_check_enabled,
411
389
  )
412
390
  self.persist()
413
391
  return self._resource
@@ -418,8 +396,11 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
418
396
  rasa.shared.utils.io.write_text_file(
419
397
  self.prompt_template, path / ENTERPRISE_SEARCH_PROMPT_FILE_NAME
420
398
  )
399
+ config = self.config.copy()
400
+ config[LLM_CONFIG_KEY] = self.llm_config
401
+ config[EMBEDDINGS_CONFIG_KEY] = self.embeddings_config
421
402
  rasa.shared.utils.io.dump_obj_as_json_to_file(
422
- path / ENTERPRISE_SEARCH_CONFIG_FILE_NAME, self.config
403
+ path / ENTERPRISE_SEARCH_CONFIG_FILE_NAME, config
423
404
  )
424
405
 
425
406
  def _prepare_slots_for_template(
@@ -458,9 +439,8 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
458
439
  endpoints: Endpoints configuration.
459
440
  """
460
441
  config = endpoints.vector_store if endpoints else None
461
- store_type = self.vector_store_config.get(VECTOR_STORE_TYPE_PROPERTY)
462
- if config is None and store_type != DEFAULT_VECTOR_STORE_TYPE:
463
- logger.error(
442
+ if config is None and self.vector_store_type != DEFAULT_VECTOR_STORE_TYPE:
443
+ structlogger.error(
464
444
  "enterprise_search_policy._connect_vector_store_or_raise.no_config"
465
445
  )
466
446
  raise VectorStoreConfigurationError(
@@ -470,7 +450,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
470
450
  try:
471
451
  self.vector_store.connect(config) # type: ignore
472
452
  except Exception as e:
473
- logger.error(
453
+ structlogger.error(
474
454
  "enterprise_search_policy._connect_vector_store_or_raise.connect_error",
475
455
  error=e,
476
456
  config=config,
@@ -496,14 +476,14 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
496
476
  transcript.append(sanitize_message_for_prompt(event.text))
497
477
 
498
478
  search_query = " ".join(transcript[-history:][::-1])
499
- logger.debug("search_query", search_query=search_query)
479
+ structlogger.debug("search_query", search_query=search_query)
500
480
  return search_query
501
481
 
502
482
  async def predict_action_probabilities( # type: ignore[override]
503
483
  self,
504
484
  tracker: DialogueStateTracker,
505
485
  domain: Domain,
506
- endpoints: Optional[AvailableEndpoints],
486
+ endpoints: Optional[AvailableEndpoints] = None,
507
487
  rule_only_data: Optional[Dict[Text, Any]] = None,
508
488
  **kwargs: Any,
509
489
  ) -> PolicyPrediction:
@@ -522,23 +502,20 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
522
502
  The prediction.
523
503
  """
524
504
  logger_key = "enterprise_search_policy.predict_action_probabilities"
525
- vector_search_threshold = self.vector_store_config.get(
526
- VECTOR_STORE_THRESHOLD_PROPERTY, DEFAULT_VECTOR_STORE_THRESHOLD
527
- )
528
- llm = llm_factory(self.config.get(LLM_CONFIG_KEY), DEFAULT_LLM_CONFIG)
505
+
529
506
  if not self.supports_current_stack_frame(
530
507
  tracker, False, False
531
508
  ) or self.should_abstain_in_coexistence(tracker, True):
532
509
  return self._prediction(self._default_predictions(domain))
533
510
 
534
511
  if not self.vector_store:
535
- logger.error(f"{logger_key}.no_vector_store")
512
+ structlogger.error(f"{logger_key}.no_vector_store")
536
513
  return self._create_prediction_internal_error(domain, tracker)
537
514
 
538
515
  try:
539
516
  self._connect_vector_store_or_raise(endpoints)
540
517
  except (VectorStoreConfigurationError, VectorStoreConnectionError) as e:
541
- logger.error(f"{logger_key}.connection_error", error=e)
518
+ structlogger.error(f"{logger_key}.connection_error", error=e)
542
519
  return self._create_prediction_internal_error(domain, tracker)
543
520
 
544
521
  search_query = self._prepare_search_query(
@@ -550,20 +527,19 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
550
527
  documents = await self.vector_store.search(
551
528
  query=search_query,
552
529
  tracker_state=tracker_state,
553
- threshold=vector_search_threshold,
530
+ threshold=self.vector_search_threshold,
554
531
  )
555
532
  except InformationRetrievalException as e:
556
- logger.error(f"{logger_key}.search_error", error=e)
533
+ structlogger.error(f"{logger_key}.search_error", error=e)
557
534
  return self._create_prediction_internal_error(domain, tracker)
558
535
 
559
536
  if not documents.results:
560
- logger.info(f"{logger_key}.no_documents")
537
+ structlogger.info(f"{logger_key}.no_documents")
561
538
  return self._create_prediction_cannot_handle(domain, tracker)
562
539
 
563
540
  if self.use_llm:
564
541
  prompt = self._render_prompt(tracker, documents.results)
565
- llm_response = await self._generate_llm_answer(llm, prompt)
566
- llm_response = LLMResponse.ensure_llm_response(llm_response)
542
+ llm_response = await self._invoke_llm(prompt)
567
543
 
568
544
  self._add_prompt_and_llm_response_to_latest_message(
569
545
  tracker=tracker,
@@ -573,24 +549,38 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
573
549
  )
574
550
 
575
551
  if llm_response is None or not llm_response.choices:
576
- logger.debug(f"{logger_key}.no_llm_response")
552
+ structlogger.debug(f"{logger_key}.no_llm_response")
577
553
  response = None
578
554
  else:
579
555
  llm_answer = llm_response.choices[0]
580
556
 
557
+ if self.relevancy_check_enabled:
558
+ relevancy_response = self._parse_llm_relevancy_check_response(
559
+ llm_answer
560
+ )
561
+ if not relevancy_response.relevant:
562
+ structlogger.debug(f"{logger_key}.answer_not_relevant")
563
+ return self._create_prediction_cannot_handle(
564
+ domain,
565
+ tracker,
566
+ RASA_PATTERN_CANNOT_HANDLE_NO_RELEVANT_ANSWER,
567
+ )
568
+
581
569
  if self.citation_enabled:
582
570
  llm_answer = self.post_process_citations(llm_answer)
583
571
 
584
- logger.debug(f"{logger_key}.llm_answer", llm_answer=llm_answer)
572
+ structlogger.debug(
573
+ f"{logger_key}.llm_answer", prompt=prompt, llm_answer=llm_answer
574
+ )
585
575
  response = llm_answer
586
576
  else:
587
577
  response = documents.results[0].metadata.get("answer", None)
588
578
  if not response:
589
- logger.error(
579
+ structlogger.error(
590
580
  f"{logger_key}.answer_key_missing_in_metadata",
591
581
  search_results=documents.results,
592
582
  )
593
- logger.debug(
583
+ structlogger.debug(
594
584
  "enterprise_search_policy.predict_action_probabilities.no_llm",
595
585
  search_results=documents,
596
586
  )
@@ -610,7 +600,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
610
600
 
611
601
  # telemetry call to track policy prediction
612
602
  track_enterprise_search_policy_predict(
613
- vector_store_type=self.vector_store_config.get(VECTOR_STORE_TYPE_PROPERTY),
603
+ vector_store_type=self.vector_store_type,
614
604
  embeddings_type=self.embeddings_config.get(PROVIDER_CONFIG_KEY),
615
605
  embeddings_model=self.embeddings_config.get(MODEL_CONFIG_KEY)
616
606
  or self.embeddings_config.get(MODEL_NAME_CONFIG_KEY),
@@ -622,6 +612,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
622
612
  or self.llm_config.get(MODEL_NAME_CONFIG_KEY),
623
613
  llm_model_group_id=self.llm_config.get(MODEL_GROUP_ID_CONFIG_KEY),
624
614
  citation_enabled=self.citation_enabled,
615
+ relevancy_check_enabled=self.relevancy_check_enabled,
625
616
  )
626
617
  return self._create_prediction(
627
618
  domain=domain, tracker=tracker, action_metadata=action_metadata
@@ -645,11 +636,12 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
645
636
  ),
646
637
  "docs": documents,
647
638
  "slots": self._prepare_slots_for_template(tracker),
639
+ "check_relevancy": self.relevancy_check_enabled,
648
640
  "citation_enabled": self.citation_enabled,
649
641
  }
650
642
  prompt = Template(self.prompt_template).render(**inputs)
651
643
  log_llm(
652
- logger=logger,
644
+ logger=structlogger,
653
645
  log_module="EnterpriseSearchPolicy",
654
646
  log_event="enterprise_search_policy._render_prompt.prompt_rendered",
655
647
  prompt=prompt,
@@ -657,9 +649,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
657
649
  return prompt
658
650
 
659
651
  @measure_llm_latency
660
- async def _generate_llm_answer(
661
- self, llm: LLMClient, prompt: Text
662
- ) -> Optional[LLMResponse]:
652
+ async def _invoke_llm(self, prompt: Text) -> Optional[LLMResponse]:
663
653
  """Fetches an LLM completion for the provided prompt.
664
654
 
665
655
  Args:
@@ -669,17 +659,32 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
669
659
  Returns:
670
660
  An LLMResponse object, or None if the call fails.
671
661
  """
662
+ llm = llm_factory(self.llm_config, DEFAULT_LLM_CONFIG)
672
663
  try:
673
- return await llm.acompletion(prompt)
664
+ response = await llm.acompletion(prompt)
665
+ return LLMResponse.ensure_llm_response(response)
674
666
  except Exception as e:
675
667
  # unfortunately, langchain does not wrap LLM exceptions which means
676
668
  # we have to catch all exceptions here
677
- logger.error(
669
+ structlogger.error(
678
670
  "enterprise_search_policy._generate_llm_answer.llm_error",
679
671
  error=e,
680
672
  )
681
673
  return None
682
674
 
675
+ def _parse_llm_relevancy_check_response(
676
+ self, llm_answer: str
677
+ ) -> _RelevancyCheckResponse:
678
+ """Checks if the LLM response is relevant by parsing it."""
679
+ answer_relevant = not _ENTERPRISE_SEARCH_ANSWER_NOT_RELEVANT_PATTERN.search(
680
+ llm_answer
681
+ )
682
+ structlogger.debug("")
683
+ return _RelevancyCheckResponse(
684
+ answer=llm_answer if answer_relevant else None,
685
+ relevant=answer_relevant,
686
+ )
687
+
683
688
  def _create_prediction(
684
689
  self,
685
690
  domain: Domain,
@@ -714,10 +719,18 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
714
719
  )
715
720
 
716
721
  def _create_prediction_cannot_handle(
717
- self, domain: Domain, tracker: DialogueStateTracker
722
+ self,
723
+ domain: Domain,
724
+ tracker: DialogueStateTracker,
725
+ reason: Optional[str] = None,
718
726
  ) -> PolicyPrediction:
727
+ cannot_handle_stack_frame = (
728
+ CannotHandlePatternFlowStackFrame(reason=reason)
729
+ if reason is not None
730
+ else CannotHandlePatternFlowStackFrame()
731
+ )
719
732
  return self._create_prediction_for_pattern(
720
- domain, tracker, CannotHandlePatternFlowStackFrame()
733
+ domain, tracker, cannot_handle_stack_frame
721
734
  )
722
735
 
723
736
  def _create_prediction_for_pattern(
@@ -775,7 +788,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
775
788
  "Please specify a valid path to the documents source directory in the "
776
789
  "vector_store configuration."
777
790
  )
778
- logger.error(
791
+ structlogger.error(
779
792
  "enterprise_search_policy.train.faiss.invalid_source_directory",
780
793
  message=error_message,
781
794
  )
@@ -787,7 +800,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
787
800
  f"Document source directory is empty: '{docs_folder}'. "
788
801
  "Please add documents to this directory or specify a different one."
789
802
  )
790
- logger.error(
803
+ structlogger.error(
791
804
  "enterprise_search_policy.train.faiss.source_directory_empty",
792
805
  message=error_message,
793
806
  )
@@ -803,70 +816,93 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
803
816
  **kwargs: Any,
804
817
  ) -> "EnterpriseSearchPolicy":
805
818
  """Loads a trained policy (see parent class for full docstring)."""
819
+ parsed_config = EnterpriseSearchPolicyConfig.from_dict(config)
820
+
806
821
  # Perform health checks for both LLM and embeddings client configs
807
- cls._perform_health_checks(config, "enterprise_search_policy.load")
822
+ cls._perform_health_checks(
823
+ parsed_config.llm_config,
824
+ parsed_config.embeddings_config,
825
+ "enterprise_search_policy.load",
826
+ )
808
827
 
809
- prompt_template = None
828
+ prompt_template = cls._load_prompt_template(model_storage, resource)
829
+ embeddings = cls._create_plain_embedder(parsed_config.embeddings_config)
830
+ vector_store = cls._load_vector_store(
831
+ embeddings,
832
+ parsed_config.vector_store_type,
833
+ parsed_config.use_generative_llm,
834
+ model_storage,
835
+ resource,
836
+ )
837
+
838
+ structlogger.info("enterprise_search_policy.load", config=config)
839
+
840
+ return cls(
841
+ config,
842
+ model_storage,
843
+ resource,
844
+ execution_context,
845
+ vector_store=vector_store,
846
+ prompt_template=prompt_template,
847
+ )
848
+
849
+ @classmethod
850
+ def _load_prompt_template(
851
+ cls, model_storage: ModelStorage, resource: Resource
852
+ ) -> Optional[str]:
810
853
  try:
811
854
  with model_storage.read_from(resource) as path:
812
- prompt_template = rasa.shared.utils.io.read_file(
855
+ return rasa.shared.utils.io.read_file(
813
856
  path / ENTERPRISE_SEARCH_PROMPT_FILE_NAME
814
857
  )
815
858
  except (FileNotFoundError, FileIOException) as e:
816
- logger.warning(
859
+ structlogger.warning(
817
860
  "enterprise_search_policy.load.failed", error=e, resource=resource.name
818
861
  )
862
+ return None
819
863
 
820
- store_type = config.get(VECTOR_STORE_PROPERTY, {}).get(
821
- VECTOR_STORE_TYPE_PROPERTY
822
- )
823
-
824
- embeddings = cls._create_plain_embedder(config)
825
-
826
- logger.info("enterprise_search_policy.load", config=config)
864
+ @classmethod
865
+ def _load_vector_store(
866
+ cls,
867
+ embeddings: "Embeddings",
868
+ store_type: str,
869
+ use_generative_llm: bool,
870
+ model_storage: ModelStorage,
871
+ resource: Resource,
872
+ ) -> InformationRetrieval:
827
873
  if store_type == DEFAULT_VECTOR_STORE_TYPE:
828
874
  # if a vector store is not specified,
829
875
  # default to using FAISS with the index stored in the model
830
876
  # TODO figure out a way to get path without context manager
831
877
  with model_storage.read_from(resource) as path:
832
- vector_store = FAISS_Store(
878
+ return FAISS_Store(
833
879
  embeddings=embeddings,
834
880
  index_path=path,
835
881
  docs_folder=None,
836
882
  create_index=False,
883
+ parse_as_faq_pairs=not use_generative_llm,
837
884
  )
838
885
  else:
839
- vector_store = create_from_endpoint_config(
886
+ return create_from_endpoint_config(
840
887
  config_type=store_type,
841
888
  embeddings=embeddings,
842
- ) # type: ignore
843
-
844
- return cls(
845
- config,
846
- model_storage,
847
- resource,
848
- execution_context,
849
- vector_store=vector_store,
850
- prompt_template=prompt_template,
851
- )
889
+ )
852
890
 
853
891
  @classmethod
854
- def _get_local_knowledge_data(cls, config: Dict[str, Any]) -> Optional[List[str]]:
892
+ def _get_local_knowledge_data(
893
+ cls, store_type: str, source: Optional[str] = None
894
+ ) -> Optional[List[str]]:
855
895
  """This is required only for local knowledge base types.
856
896
 
857
897
  e.g. FAISS, to ensure that the graph component is retrained when the knowledge
858
898
  base is updated.
859
899
  """
860
- merged_config = {**cls.get_default_config(), **config}
861
-
862
- store_type = merged_config.get(VECTOR_STORE_PROPERTY, {}).get(
863
- VECTOR_STORE_TYPE_PROPERTY
864
- )
865
- if store_type != DEFAULT_VECTOR_STORE_TYPE:
866
- return None
867
-
868
- source = merged_config.get(VECTOR_STORE_PROPERTY, {}).get(SOURCE_PROPERTY)
869
- if not source or not os.path.exists(source) or not os.path.isdir(source):
900
+ if (
901
+ store_type != DEFAULT_VECTOR_STORE_TYPE
902
+ or not source
903
+ or not os.path.exists(source)
904
+ or not os.path.isdir(source)
905
+ ):
870
906
  return None
871
907
 
872
908
  docs = FAISS_Store.load_documents(source)
@@ -882,21 +918,28 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
882
918
  @classmethod
883
919
  def fingerprint_addon(cls, config: Dict[str, Any]) -> Optional[str]:
884
920
  """Add a fingerprint of enterprise search policy for the graph."""
885
- local_knowledge_data = cls._get_local_knowledge_data(config)
921
+ parsed_config = EnterpriseSearchPolicyConfig.from_dict(config)
886
922
 
923
+ # Resolve the prompt template
924
+ default_prompt_template = cls._select_default_prompt_template_based_on_features(
925
+ parsed_config.check_relevancy, parsed_config.enable_citation
926
+ )
887
927
  prompt_template = get_prompt_template(
888
- config.get(PROMPT_CONFIG_KEY),
889
- DEFAULT_ENTERPRISE_SEARCH_PROMPT_TEMPLATE,
928
+ jinja_file_path=parsed_config.prompt_template,
929
+ default_prompt_template=default_prompt_template,
890
930
  log_source_component=EnterpriseSearchPolicy.__name__,
891
931
  log_source_method=LOG_COMPONENT_SOURCE_METHOD_FINGERPRINT_ADDON,
892
932
  )
893
933
 
894
- llm_config = resolve_model_client_config(
895
- config.get(LLM_CONFIG_KEY), EnterpriseSearchPolicy.__name__
896
- )
897
- embedding_config = resolve_model_client_config(
898
- config.get(EMBEDDINGS_CONFIG_KEY), EnterpriseSearchPolicy.__name__
934
+ # Fetch the local knowledge data in case FAISS is used
935
+ local_knowledge_data = cls._get_local_knowledge_data(
936
+ parsed_config.vector_store_type, parsed_config.vector_store_source
899
937
  )
938
+
939
+ # Get the resolved LLM and embeddings configurations
940
+ llm_config = parsed_config.llm_config
941
+ embedding_config = parsed_config.embeddings_config
942
+
900
943
  return deep_container_fingerprint(
901
944
  [prompt_template, local_knowledge_data, llm_config, embedding_config]
902
945
  )
@@ -922,7 +965,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
922
965
  Returns:
923
966
  The post-processed LLM answer.
924
967
  """
925
- logger.debug(
968
+ structlogger.debug(
926
969
  "enterprise_search_policy.post_process_citations", llm_answer=llm_answer
927
970
  )
928
971
 
@@ -1085,24 +1128,97 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
1085
1128
 
1086
1129
  @classmethod
1087
1130
  def _perform_health_checks(
1088
- cls, config: Dict[Text, Any], log_source_method: str
1131
+ cls,
1132
+ llm_config: Dict[Text, Any],
1133
+ embeddings_config: Dict[Text, Any],
1134
+ log_source_method: str,
1089
1135
  ) -> None:
1090
- # Perform health check of the LLM client config
1091
- llm_config = resolve_model_client_config(config.get(LLM_CONFIG_KEY, {}))
1136
+ """
1137
+ Perform the health checks using resolved LLM and embeddings configurations.
1138
+ Resolved means the configuration is either:
1139
+ - A reference to a model group that has already been expanded into
1140
+ its corresponding configuration using the information from
1141
+ `endpoints.yml`, or
1142
+ - A full configuration for the embedder defined directly (i.e. not
1143
+ relying on model groups or indirections).
1144
+
1145
+ Args:
1146
+ llm_config: A resolved LLM configuration.
1147
+ embeddings_config: A resolved embeddings configuration.
1148
+ log_source_method: The method health checks has been called from.
1149
+
1150
+ """
1092
1151
  cls.perform_llm_health_check(
1093
1152
  llm_config,
1094
1153
  DEFAULT_LLM_CONFIG,
1095
1154
  log_source_method,
1096
1155
  EnterpriseSearchPolicy.__name__,
1097
1156
  )
1098
-
1099
- # Perform health check of the embeddings client config
1100
- embeddings_config = resolve_model_client_config(
1101
- config.get(EMBEDDINGS_CONFIG_KEY, {})
1102
- )
1103
1157
  cls.perform_embeddings_health_check(
1104
1158
  embeddings_config,
1105
1159
  DEFAULT_EMBEDDINGS_CONFIG,
1106
1160
  log_source_method,
1107
1161
  EnterpriseSearchPolicy.__name__,
1108
1162
  )
1163
+
1164
+ @classmethod
1165
+ def get_system_default_prompt_based_on_config(cls, config: Dict[str, Any]) -> str:
1166
+ """
1167
+ Resolves the default prompt template for Enterprise Search Policy based on
1168
+ the component's configuration.
1169
+
1170
+ - The old prompt is selected when both citation and relevancy check are either
1171
+ disabled or not set in the configuration.
1172
+ - The citation prompt is used when citation is enabled and relevancy check is
1173
+ either disabled or not set in the configuration.
1174
+ - The relevancy check prompt is only used when relevancy check is enabled.
1175
+
1176
+ Args:
1177
+ config: The component's configuration.
1178
+
1179
+ Returns:
1180
+ The resolved jinja prompt template as a string.
1181
+ """
1182
+ # Get the feature flags
1183
+ parsed_config = EnterpriseSearchPolicyConfig.from_dict(config)
1184
+ # Based on the enabled features (citation, relevancy check) fetch the
1185
+ # appropriate default prompt
1186
+ default_prompt = cls._select_default_prompt_template_based_on_features(
1187
+ parsed_config.check_relevancy, parsed_config.enable_citation
1188
+ )
1189
+
1190
+ return default_prompt
1191
+
1192
+ @classmethod
1193
+ def _select_default_prompt_template_based_on_features(
1194
+ cls,
1195
+ relevancy_check_enabled: bool,
1196
+ citation_enabled: bool,
1197
+ ) -> str:
1198
+ """
1199
+ Returns the appropriate default prompt template based on the feature flags.
1200
+
1201
+ The selection follows this priority:
1202
+ 1. If relevancy check is enabled, return the prompt that includes both relevancy
1203
+ and citation blocks.
1204
+ 2. If only citation is enabled, return the prompt with citation blocks.
1205
+ 3. Otherwise, fall back to the legacy default prompt template.
1206
+
1207
+ Args:
1208
+ relevancy_check_enabled: Whether the LLM-generated answer should undergo
1209
+ relevancy evaluation.
1210
+ citation_enabled: Whether citations should be included in the generated
1211
+ answer.
1212
+
1213
+ Returns:
1214
+ The default prompt template corresponding to the enabled features.
1215
+ """
1216
+ if relevancy_check_enabled:
1217
+ # ES prompt that has relevancy check and citations blocks
1218
+ return DEFAULT_ENTERPRISE_SEARCH_PROMPT_WITH_RELEVANCY_CHECK_AND_CITATION_TEMPLATE # noqa: E501
1219
+ elif citation_enabled:
1220
+ # ES prompt with citation's block - backward compatibility
1221
+ return DEFAULT_ENTERPRISE_SEARCH_PROMPT_WITH_CITATION_TEMPLATE
1222
+ else:
1223
+ # Legacy ES prompt - backward compatibility
1224
+ return DEFAULT_ENTERPRISE_SEARCH_PROMPT_TEMPLATE