rasa-pro 3.14.0a20__py3-none-any.whl → 3.14.0a23__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 (331) hide show
  1. rasa/__main__.py +15 -3
  2. rasa/agents/__init__.py +0 -0
  3. rasa/agents/agent_factory.py +122 -0
  4. rasa/agents/agent_manager.py +211 -0
  5. rasa/agents/constants.py +43 -0
  6. rasa/agents/core/__init__.py +0 -0
  7. rasa/agents/core/agent_protocol.py +107 -0
  8. rasa/agents/core/types.py +81 -0
  9. rasa/agents/exceptions.py +38 -0
  10. rasa/agents/protocol/__init__.py +5 -0
  11. rasa/agents/protocol/a2a/__init__.py +0 -0
  12. rasa/agents/protocol/a2a/a2a_agent.py +879 -0
  13. rasa/agents/protocol/mcp/__init__.py +0 -0
  14. rasa/agents/protocol/mcp/mcp_base_agent.py +726 -0
  15. rasa/agents/protocol/mcp/mcp_open_agent.py +327 -0
  16. rasa/agents/protocol/mcp/mcp_task_agent.py +522 -0
  17. rasa/agents/schemas/__init__.py +13 -0
  18. rasa/agents/schemas/agent_input.py +38 -0
  19. rasa/agents/schemas/agent_output.py +26 -0
  20. rasa/agents/schemas/agent_tool_result.py +65 -0
  21. rasa/agents/schemas/agent_tool_schema.py +186 -0
  22. rasa/agents/templates/__init__.py +0 -0
  23. rasa/agents/templates/mcp_open_agent_prompt_template.jinja2 +20 -0
  24. rasa/agents/templates/mcp_task_agent_prompt_template.jinja2 +22 -0
  25. rasa/agents/utils.py +206 -0
  26. rasa/agents/validation.py +485 -0
  27. rasa/api.py +24 -9
  28. rasa/builder/config.py +6 -2
  29. rasa/builder/guardrails/{lakera.py → clients.py} +55 -5
  30. rasa/builder/guardrails/constants.py +3 -0
  31. rasa/builder/guardrails/models.py +45 -10
  32. rasa/builder/guardrails/policy_checker.py +324 -0
  33. rasa/builder/guardrails/utils.py +42 -276
  34. rasa/builder/llm_service.py +32 -5
  35. rasa/builder/models.py +1 -0
  36. rasa/builder/project_generator.py +6 -1
  37. rasa/builder/service.py +16 -13
  38. rasa/builder/training_service.py +18 -24
  39. rasa/builder/validation_service.py +1 -1
  40. rasa/cli/arguments/default_arguments.py +12 -0
  41. rasa/cli/arguments/run.py +2 -0
  42. rasa/cli/arguments/train.py +2 -0
  43. rasa/cli/data.py +10 -8
  44. rasa/cli/dialogue_understanding_test.py +10 -7
  45. rasa/cli/e2e_test.py +9 -6
  46. rasa/cli/evaluate.py +4 -2
  47. rasa/cli/export.py +5 -2
  48. rasa/cli/inspect.py +8 -4
  49. rasa/cli/interactive.py +5 -4
  50. rasa/cli/llm_fine_tuning.py +11 -6
  51. rasa/cli/project_templates/finance/actions/general/__init__.py +0 -0
  52. rasa/cli/project_templates/finance/actions/general/action_human_handoff.py +49 -0
  53. rasa/cli/project_templates/finance/data/general/bot_challenge.yml +6 -0
  54. rasa/cli/project_templates/finance/data/general/goodbye.yml +1 -1
  55. rasa/cli/project_templates/finance/data/general/human_handoff.yml +1 -1
  56. rasa/cli/project_templates/finance/data/system/patterns/pattern_session_start.yml +1 -1
  57. rasa/cli/project_templates/finance/domain/general/_shared.yml +0 -14
  58. rasa/cli/project_templates/finance/domain/general/bot_challenge.yml +4 -0
  59. rasa/cli/project_templates/finance/domain/general/goodbye.yml +7 -0
  60. rasa/cli/project_templates/finance/domain/general/human_handoff.yml +3 -6
  61. rasa/cli/project_templates/finance/domain/general/welcome.yml +29 -1
  62. rasa/cli/project_templates/finance/tests/e2e_test_cases/accounts/check_balance.yml +9 -0
  63. rasa/cli/project_templates/finance/tests/e2e_test_cases/accounts/download_statements.yml +43 -0
  64. rasa/cli/project_templates/finance/tests/e2e_test_cases/cards/block_card.yml +55 -0
  65. rasa/cli/project_templates/finance/tests/e2e_test_cases/general/bot_challenge.yml +8 -0
  66. rasa/cli/project_templates/finance/tests/e2e_test_cases/general/feedback.yml +46 -0
  67. rasa/cli/project_templates/finance/tests/e2e_test_cases/general/goodbye.yml +9 -0
  68. rasa/cli/project_templates/finance/tests/e2e_test_cases/general/hello.yml +8 -0
  69. rasa/cli/project_templates/finance/tests/e2e_test_cases/general/human_handoff.yml +35 -0
  70. rasa/cli/project_templates/finance/tests/e2e_test_cases/general/patterns.yml +22 -0
  71. rasa/cli/project_templates/finance/tests/e2e_test_cases/transfers/transfer_money.yml +56 -0
  72. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/feedback.yml +1 -1
  73. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/hello.yml +1 -1
  74. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/human_handoff.yml +1 -1
  75. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/patterns.yml +1 -1
  76. rasa/cli/project_templates/tutorial/credentials.yml +10 -0
  77. rasa/cli/run.py +12 -10
  78. rasa/cli/scaffold.py +4 -4
  79. rasa/cli/shell.py +9 -5
  80. rasa/cli/studio/studio.py +1 -1
  81. rasa/cli/test.py +34 -14
  82. rasa/cli/train.py +41 -28
  83. rasa/cli/utils.py +1 -393
  84. rasa/cli/validation/__init__.py +0 -0
  85. rasa/cli/validation/bot_config.py +223 -0
  86. rasa/cli/validation/config_path_validation.py +257 -0
  87. rasa/cli/x.py +8 -4
  88. rasa/constants.py +7 -1
  89. rasa/core/actions/action.py +51 -10
  90. rasa/core/actions/action_run_slot_rejections.py +1 -1
  91. rasa/core/actions/direct_custom_actions_executor.py +9 -2
  92. rasa/core/actions/grpc_custom_action_executor.py +1 -1
  93. rasa/core/agent.py +19 -2
  94. rasa/core/available_agents.py +229 -0
  95. rasa/core/brokers/kafka.py +1 -1
  96. rasa/core/channels/__init__.py +82 -35
  97. rasa/core/channels/development_inspector.py +3 -3
  98. rasa/core/channels/inspector/README.md +25 -13
  99. rasa/core/channels/inspector/dist/assets/{arc-35222594.js → arc-6177260a.js} +1 -1
  100. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-a0efbfd3.js → blockDiagram-38ab4fdb-b054f038.js} +1 -1
  101. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-0584c0f2.js → c4Diagram-3d4e48cf-f25427d5.js} +1 -1
  102. rasa/core/channels/inspector/dist/assets/channel-bf9cbb34.js +1 -0
  103. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-39f40dbe.js → classDiagram-70f12bd4-c7a2af53.js} +1 -1
  104. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-1ad755f3.js → classDiagram-v2-f2320105-58db65c0.js} +1 -1
  105. rasa/core/channels/inspector/dist/assets/clone-8f9083bb.js +1 -0
  106. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-b0f4f0fe.js → createText-2e5e7dd3-088372e2.js} +1 -1
  107. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-9039bff9.js → edges-e0da2a9e-58676240.js} +1 -1
  108. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-65c9b127.js → erDiagram-9861fffd-0c14d7c6.js} +1 -1
  109. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-4f08b38e.js → flowDb-956e92f1-ea63f85c.js} +1 -1
  110. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-e95c362a.js → flowDiagram-66a62f08-a2af48cd.js} +1 -1
  111. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-9ecd5b59.js +1 -0
  112. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-703c3015.js → flowchart-elk-definition-4a651766-6937abe7.js} +1 -1
  113. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-699328ea.js → ganttDiagram-c361ad54-7473f357.js} +1 -1
  114. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-04cf4b05.js → gitGraphDiagram-72cf32ee-d0c9405e.js} +1 -1
  115. rasa/core/channels/inspector/dist/assets/{graph-ee94449e.js → graph-0a6f8466.js} +1 -1
  116. rasa/core/channels/inspector/dist/assets/{index-3862675e-940162b4.js → index-3862675e-7610671a.js} +1 -1
  117. rasa/core/channels/inspector/dist/assets/index-74e01d94.js +1354 -0
  118. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-c79c2866.js → infoDiagram-f8f76790-be397dc7.js} +1 -1
  119. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-84489d30.js → journeyDiagram-49397b02-4cefbf62.js} +1 -1
  120. rasa/core/channels/inspector/dist/assets/{layout-a9aa9858.js → layout-e7fbc2bf.js} +1 -1
  121. rasa/core/channels/inspector/dist/assets/{line-eb73cf26.js → line-a8aa457c.js} +1 -1
  122. rasa/core/channels/inspector/dist/assets/{linear-b3399f9a.js → linear-3351e0d2.js} +1 -1
  123. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-b095bf1a.js → mindmap-definition-fc14e90a-b8cbf605.js} +1 -1
  124. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-07644b66.js → pieDiagram-8a3498a8-f327f774.js} +1 -1
  125. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-573a3f9c.js → quadrantDiagram-120e2f19-2854c591.js} +1 -1
  126. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-d457e1e1.js → requirementDiagram-deff3bca-964985d5.js} +1 -1
  127. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-9d26e1a2.js → sankeyDiagram-04a897e0-edeb4f33.js} +1 -1
  128. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-3a9cde10.js → sequenceDiagram-704730f1-fcf70125.js} +1 -1
  129. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-4f3e8cec.js → stateDiagram-587899a1-0e770395.js} +1 -1
  130. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-e617e5bf.js → stateDiagram-v2-d93cdb3a-af8dcd22.js} +1 -1
  131. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-eab30d2f.js → styles-6aaf32cf-36a9e70d.js} +1 -1
  132. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-09994be2.js → styles-9a916d00-884a8b5b.js} +1 -1
  133. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-b7110364.js → styles-c10674c1-dc097813.js} +1 -1
  134. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-3ebc92ad.js → svgDrawCommon-08f97a94-5a2c7eed.js} +1 -1
  135. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-7d13d2f2.js → timeline-definition-85554ec2-e89c4f6e.js} +1 -1
  136. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-488385e1.js → xychartDiagram-e933f94c-afb6fe56.js} +1 -1
  137. rasa/core/channels/inspector/dist/index.html +1 -1
  138. rasa/core/channels/inspector/package.json +18 -18
  139. rasa/core/channels/inspector/src/App.tsx +29 -4
  140. rasa/core/channels/inspector/src/components/DialogueAgentStack.tsx +108 -0
  141. rasa/core/channels/inspector/src/components/{DialogueStack.tsx → DialogueHistoryStack.tsx} +4 -2
  142. rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +7 -4
  143. rasa/core/channels/inspector/src/helpers/formatters.test.ts +4 -0
  144. rasa/core/channels/inspector/src/helpers/formatters.ts +24 -3
  145. rasa/core/channels/inspector/src/helpers/utils.test.ts +127 -0
  146. rasa/core/channels/inspector/src/helpers/utils.ts +66 -1
  147. rasa/core/channels/inspector/src/theme/base/styles.ts +19 -1
  148. rasa/core/channels/inspector/src/types.ts +21 -0
  149. rasa/core/channels/inspector/yarn.lock +336 -189
  150. rasa/core/channels/studio_chat.py +6 -6
  151. rasa/core/channels/telegram.py +4 -9
  152. rasa/core/channels/voice_stream/browser_audio.py +2 -0
  153. rasa/core/channels/voice_stream/genesys.py +1 -1
  154. rasa/core/channels/voice_stream/tts/deepgram.py +140 -0
  155. rasa/core/channels/voice_stream/twilio_media_streams.py +5 -1
  156. rasa/core/channels/voice_stream/voice_channel.py +3 -0
  157. rasa/core/config/__init__.py +0 -0
  158. rasa/core/{available_endpoints.py → config/available_endpoints.py} +51 -16
  159. rasa/core/config/configuration.py +260 -0
  160. rasa/core/config/credentials.py +19 -0
  161. rasa/core/config/message_procesing_config.py +34 -0
  162. rasa/core/constants.py +5 -0
  163. rasa/core/iam_credentials_providers/aws_iam_credentials_providers.py +88 -3
  164. rasa/core/iam_credentials_providers/credentials_provider_protocol.py +2 -1
  165. rasa/core/lock_store.py +6 -4
  166. rasa/core/nlg/generator.py +1 -1
  167. rasa/core/policies/enterprise_search_policy.py +5 -3
  168. rasa/core/policies/flow_policy.py +4 -4
  169. rasa/core/policies/flows/agent_executor.py +632 -0
  170. rasa/core/policies/flows/flow_executor.py +137 -76
  171. rasa/core/policies/flows/mcp_tool_executor.py +298 -0
  172. rasa/core/policies/intentless_policy.py +1 -1
  173. rasa/core/policies/ted_policy.py +20 -12
  174. rasa/core/policies/unexpected_intent_policy.py +6 -0
  175. rasa/core/processor.py +68 -44
  176. rasa/core/redis_connection_factory.py +78 -20
  177. rasa/core/run.py +37 -8
  178. rasa/core/test.py +4 -0
  179. rasa/core/tracker_stores/sql_tracker_store.py +1 -1
  180. rasa/core/tracker_stores/tracker_store.py +3 -7
  181. rasa/core/train.py +1 -1
  182. rasa/core/training/interactive.py +20 -18
  183. rasa/core/training/story_conflict.py +5 -5
  184. rasa/core/utils.py +22 -23
  185. rasa/dialogue_understanding/commands/__init__.py +8 -0
  186. rasa/dialogue_understanding/commands/cancel_flow_command.py +19 -5
  187. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +21 -2
  188. rasa/dialogue_understanding/commands/clarify_command.py +20 -2
  189. rasa/dialogue_understanding/commands/continue_agent_command.py +91 -0
  190. rasa/dialogue_understanding/commands/knowledge_answer_command.py +21 -2
  191. rasa/dialogue_understanding/commands/restart_agent_command.py +162 -0
  192. rasa/dialogue_understanding/commands/start_flow_command.py +68 -7
  193. rasa/dialogue_understanding/commands/utils.py +124 -2
  194. rasa/dialogue_understanding/generator/command_parser.py +4 -0
  195. rasa/dialogue_understanding/generator/llm_based_command_generator.py +50 -12
  196. rasa/dialogue_understanding/generator/llm_command_generator.py +1 -1
  197. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +1 -1
  198. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +66 -0
  199. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +66 -0
  200. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +89 -0
  201. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +88 -0
  202. rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +42 -7
  203. rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +40 -3
  204. rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +20 -3
  205. rasa/dialogue_understanding/patterns/cancel.py +27 -6
  206. rasa/dialogue_understanding/patterns/clarify.py +3 -14
  207. rasa/dialogue_understanding/patterns/continue_interrupted.py +239 -6
  208. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +46 -8
  209. rasa/dialogue_understanding/processor/command_processor.py +136 -15
  210. rasa/dialogue_understanding/stack/dialogue_stack.py +98 -2
  211. rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +57 -0
  212. rasa/dialogue_understanding/stack/utils.py +57 -3
  213. rasa/dialogue_understanding/utils.py +24 -4
  214. rasa/dialogue_understanding_test/du_test_runner.py +8 -3
  215. rasa/e2e_test/e2e_test_runner.py +13 -3
  216. rasa/engine/caching.py +2 -2
  217. rasa/engine/constants.py +1 -1
  218. rasa/engine/loader.py +12 -0
  219. rasa/engine/recipes/default_components.py +138 -49
  220. rasa/engine/recipes/default_recipe.py +108 -11
  221. rasa/engine/runner/dask.py +8 -5
  222. rasa/engine/validation.py +19 -6
  223. rasa/graph_components/validators/default_recipe_validator.py +86 -28
  224. rasa/hooks.py +5 -5
  225. rasa/llm_fine_tuning/utils.py +2 -2
  226. rasa/model_training.py +60 -47
  227. rasa/nlu/classifiers/diet_classifier.py +198 -98
  228. rasa/nlu/classifiers/logistic_regression_classifier.py +1 -4
  229. rasa/nlu/classifiers/mitie_intent_classifier.py +3 -0
  230. rasa/nlu/classifiers/sklearn_intent_classifier.py +1 -3
  231. rasa/nlu/extractors/crf_entity_extractor.py +9 -10
  232. rasa/nlu/extractors/mitie_entity_extractor.py +3 -0
  233. rasa/nlu/extractors/spacy_entity_extractor.py +3 -0
  234. rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +4 -0
  235. rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +5 -0
  236. rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +2 -0
  237. rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +3 -0
  238. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +4 -2
  239. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +4 -0
  240. rasa/nlu/selectors/response_selector.py +10 -2
  241. rasa/nlu/tokenizers/jieba_tokenizer.py +3 -4
  242. rasa/nlu/tokenizers/mitie_tokenizer.py +3 -2
  243. rasa/nlu/tokenizers/spacy_tokenizer.py +3 -2
  244. rasa/nlu/utils/mitie_utils.py +3 -0
  245. rasa/nlu/utils/spacy_utils.py +3 -2
  246. rasa/plugin.py +8 -8
  247. rasa/privacy/privacy_manager.py +12 -3
  248. rasa/server.py +15 -3
  249. rasa/shared/agents/__init__.py +0 -0
  250. rasa/shared/agents/auth/__init__.py +0 -0
  251. rasa/shared/agents/auth/agent_auth_factory.py +105 -0
  252. rasa/shared/agents/auth/agent_auth_manager.py +92 -0
  253. rasa/shared/agents/auth/auth_strategy/__init__.py +19 -0
  254. rasa/shared/agents/auth/auth_strategy/agent_auth_strategy.py +52 -0
  255. rasa/shared/agents/auth/auth_strategy/api_key_auth_strategy.py +42 -0
  256. rasa/shared/agents/auth/auth_strategy/bearer_token_auth_strategy.py +28 -0
  257. rasa/shared/agents/auth/auth_strategy/oauth2_auth_strategy.py +167 -0
  258. rasa/shared/agents/auth/constants.py +12 -0
  259. rasa/shared/agents/auth/types.py +12 -0
  260. rasa/shared/agents/utils.py +35 -0
  261. rasa/shared/constants.py +8 -0
  262. rasa/shared/core/constants.py +16 -1
  263. rasa/shared/core/domain.py +0 -7
  264. rasa/shared/core/events.py +327 -0
  265. rasa/shared/core/flows/constants.py +5 -0
  266. rasa/shared/core/flows/flow.py +1 -1
  267. rasa/shared/core/flows/flows_list.py +21 -5
  268. rasa/shared/core/flows/flows_yaml_schema.json +119 -184
  269. rasa/shared/core/flows/steps/call.py +49 -5
  270. rasa/shared/core/flows/steps/collect.py +98 -13
  271. rasa/shared/core/flows/validation.py +372 -8
  272. rasa/shared/core/flows/yaml_flows_io.py +3 -2
  273. rasa/shared/core/slots.py +2 -2
  274. rasa/shared/core/trackers.py +5 -2
  275. rasa/shared/exceptions.py +16 -0
  276. rasa/shared/importers/rasa.py +1 -1
  277. rasa/shared/importers/utils.py +9 -3
  278. rasa/shared/providers/llm/_base_litellm_client.py +41 -9
  279. rasa/shared/providers/llm/litellm_router_llm_client.py +8 -4
  280. rasa/shared/providers/llm/llm_client.py +7 -3
  281. rasa/shared/providers/llm/llm_response.py +66 -0
  282. rasa/shared/providers/llm/self_hosted_llm_client.py +8 -4
  283. rasa/shared/utils/common.py +24 -0
  284. rasa/shared/utils/health_check/health_check.py +7 -3
  285. rasa/shared/utils/llm.py +39 -16
  286. rasa/shared/utils/mcp/__init__.py +0 -0
  287. rasa/shared/utils/mcp/server_connection.py +247 -0
  288. rasa/shared/utils/mcp/utils.py +20 -0
  289. rasa/shared/utils/schemas/events.py +42 -0
  290. rasa/shared/utils/yaml.py +3 -1
  291. rasa/studio/pull/pull.py +3 -2
  292. rasa/studio/train.py +8 -7
  293. rasa/studio/upload.py +3 -6
  294. rasa/telemetry.py +69 -5
  295. rasa/tracing/config.py +45 -12
  296. rasa/tracing/constants.py +14 -0
  297. rasa/tracing/instrumentation/attribute_extractors.py +142 -9
  298. rasa/tracing/instrumentation/instrumentation.py +626 -21
  299. rasa/tracing/instrumentation/intentless_policy_instrumentation.py +4 -4
  300. rasa/tracing/instrumentation/metrics.py +32 -0
  301. rasa/tracing/metric_instrument_provider.py +68 -0
  302. rasa/utils/common.py +92 -1
  303. rasa/utils/endpoints.py +11 -2
  304. rasa/utils/log_utils.py +96 -5
  305. rasa/utils/ml_utils.py +1 -1
  306. rasa/utils/pypred.py +38 -0
  307. rasa/utils/tensorflow/__init__.py +7 -0
  308. rasa/utils/tensorflow/callback.py +136 -101
  309. rasa/utils/tensorflow/crf.py +1 -1
  310. rasa/utils/tensorflow/data_generator.py +21 -8
  311. rasa/utils/tensorflow/layers.py +21 -11
  312. rasa/utils/tensorflow/metrics.py +7 -3
  313. rasa/utils/tensorflow/models.py +56 -8
  314. rasa/utils/tensorflow/rasa_layers.py +8 -6
  315. rasa/utils/tensorflow/transformer.py +2 -3
  316. rasa/utils/train_utils.py +54 -24
  317. rasa/validator.py +17 -13
  318. rasa/version.py +1 -1
  319. {rasa_pro-3.14.0a20.dist-info → rasa_pro-3.14.0a23.dist-info}/METADATA +48 -42
  320. {rasa_pro-3.14.0a20.dist-info → rasa_pro-3.14.0a23.dist-info}/RECORD +323 -251
  321. rasa/builder/scrape_rasa_docs.py +0 -97
  322. rasa/cli/project_templates/finance/data/general/agent_details.yml +0 -6
  323. rasa/cli/project_templates/finance/domain/_system/patterns/pattern_session_start.yml +0 -11
  324. rasa/cli/project_templates/finance/domain/general/agent_details.yml +0 -31
  325. rasa/core/channels/inspector/dist/assets/channel-8e08bed9.js +0 -1
  326. rasa/core/channels/inspector/dist/assets/clone-78c82dea.js +0 -1
  327. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-2b08f601.js +0 -1
  328. rasa/core/channels/inspector/dist/assets/index-c941dcb3.js +0 -1336
  329. {rasa_pro-3.14.0a20.dist-info → rasa_pro-3.14.0a23.dist-info}/NOTICE +0 -0
  330. {rasa_pro-3.14.0a20.dist-info → rasa_pro-3.14.0a23.dist-info}/WHEEL +0 -0
  331. {rasa_pro-3.14.0a20.dist-info → rasa_pro-3.14.0a23.dist-info}/entry_points.txt +0 -0
@@ -2,111 +2,146 @@ import logging
2
2
  from pathlib import Path
3
3
  from typing import Any, Dict, Optional, Text
4
4
 
5
- import tensorflow as tf
6
- from tqdm import tqdm
5
+ from rasa.utils.tensorflow import TENSORFLOW_AVAILABLE
6
+
7
+ if TENSORFLOW_AVAILABLE:
8
+ import tensorflow as tf
9
+ from tqdm import tqdm
10
+ else:
11
+ # Placeholder values when TensorFlow is not available
12
+ tf = None
13
+ tqdm = None
7
14
 
8
15
  import rasa.shared.utils.io
9
16
 
10
17
  logger = logging.getLogger(__name__)
11
18
 
12
19
 
13
- class RasaTrainingLogger(tf.keras.callbacks.Callback):
14
- """Callback for logging the status of training."""
15
-
16
- def __init__(self, epochs: int, silent: bool) -> None:
17
- """Initializes the callback.
18
-
19
- Args:
20
- epochs: Total number of epochs.
21
- silent: If 'True' the entire progressbar wrapper is disabled.
22
- """
23
- super().__init__()
24
-
25
- disable = silent or rasa.shared.utils.io.is_logging_disabled()
26
- self.progress_bar = tqdm(range(epochs), desc="Epochs", disable=disable)
27
-
28
- def on_epoch_end(self, epoch: int, logs: Optional[Dict[Text, Any]] = None) -> None:
29
- """Updates the logging output on every epoch end.
30
-
31
- Args:
32
- epoch: The current epoch.
33
- logs: The training metrics.
34
- """
35
- self.progress_bar.update(1)
36
- self.progress_bar.set_postfix(logs)
37
-
38
- def on_train_end(self, logs: Optional[Dict[Text, Any]] = None) -> None:
39
- """Closes the progress bar after training.
40
-
41
- Args:
42
- logs: The training metrics.
43
- """
44
- self.progress_bar.close()
45
-
46
-
47
- class RasaModelCheckpoint(tf.keras.callbacks.Callback):
48
- """Callback for saving intermediate model checkpoints."""
49
-
50
- def __init__(self, checkpoint_dir: Path) -> None:
51
- """Initializes the callback.
52
-
53
- Args:
54
- checkpoint_dir: Directory to store checkpoints to.
55
- """
56
- super().__init__()
57
-
58
- self.checkpoint_file = checkpoint_dir / "checkpoint.tf_model"
59
- self.best_metrics_so_far: Dict[Text, Any] = {}
60
-
61
- def on_epoch_end(self, epoch: int, logs: Optional[Dict[Text, Any]] = None) -> None:
62
- """Save the model on epoch end if the model has improved.
63
-
64
- Args:
65
- epoch: The current epoch.
66
- logs: The training metrics.
67
- """
68
- if self._does_model_improve(logs):
69
- logger.debug(f"Creating model checkpoint at epoch={epoch + 1} ...")
70
- self.model.save_weights(
71
- self.checkpoint_file, overwrite=True, save_format="tf"
72
- )
73
-
74
- def _does_model_improve(self, curr_results: Dict[Text, Any]) -> bool:
75
- """Checks whether the current results are better than the best so far.
76
-
77
- Results are considered better if each metric is equal or better than the best so
78
- far, and at least one is better.
79
-
80
- Args:
81
- curr_results: The training metrics for this epoch.
82
- """
83
- curr_metric_names = [
84
- k
85
- for k in curr_results.keys()
86
- if k.startswith("val") and (k.endswith("_acc") or k.endswith("_f1"))
87
- ]
88
- # the "val" prefix is prepended to metrics in fit if _should_eval returns true
89
- # for this particular epoch
90
- if len(curr_metric_names) == 0:
91
- # the metrics are not validation metrics
92
- return False
93
- # initialize best_metrics_so_far with the first results
94
- if not self.best_metrics_so_far:
95
- for metric_name in curr_metric_names:
96
- self.best_metrics_so_far[metric_name] = float(curr_results[metric_name])
97
- return True
98
-
99
- at_least_one_improved = False
100
- improved_metrics = {}
101
- for metric_name in self.best_metrics_so_far.keys():
102
- if float(curr_results[metric_name]) < self.best_metrics_so_far[metric_name]:
103
- # at least one of the values is worse
20
+ if TENSORFLOW_AVAILABLE:
21
+
22
+ class RasaTrainingLogger(tf.keras.callbacks.Callback):
23
+ """Callback for logging the status of training."""
24
+
25
+ def __init__(self, epochs: int, silent: bool) -> None:
26
+ """Initializes the callback.
27
+
28
+ Args:
29
+ epochs: Total number of epochs.
30
+ silent: If 'True' the entire progressbar wrapper is disabled.
31
+ """
32
+ super().__init__()
33
+
34
+ disable = silent or rasa.shared.utils.io.is_logging_disabled()
35
+ self.progress_bar = tqdm(range(epochs), desc="Epochs", disable=disable)
36
+
37
+ def on_epoch_end(
38
+ self, epoch: int, logs: Optional[Dict[Text, Any]] = None
39
+ ) -> None:
40
+ """Updates the logging output on every epoch end.
41
+
42
+ Args:
43
+ epoch: The current epoch.
44
+ logs: The training metrics.
45
+ """
46
+ self.progress_bar.update(1)
47
+ self.progress_bar.set_postfix(logs)
48
+
49
+ def on_train_end(self, logs: Optional[Dict[Text, Any]] = None) -> None:
50
+ """Closes the progress bar after training.
51
+
52
+ Args:
53
+ logs: The training metrics.
54
+ """
55
+ self.progress_bar.close()
56
+
57
+ class RasaModelCheckpoint(tf.keras.callbacks.Callback):
58
+ """Callback for saving intermediate model checkpoints."""
59
+
60
+ def __init__(self, checkpoint_dir: Path) -> None:
61
+ """Initializes the callback.
62
+
63
+ Args:
64
+ checkpoint_dir: Directory to store checkpoints to.
65
+ """
66
+ super().__init__()
67
+
68
+ self.checkpoint_file = checkpoint_dir / "checkpoint.weights.h5"
69
+ self.best_metrics_so_far: Dict[Text, Any] = {}
70
+
71
+ def on_epoch_end(
72
+ self, epoch: int, logs: Optional[Dict[Text, Any]] = None
73
+ ) -> None:
74
+ """Save the model on epoch end if the model has improved.
75
+
76
+ Args:
77
+ epoch: The current epoch.
78
+ logs: The training metrics.
79
+ """
80
+ if self._does_model_improve(logs):
81
+ logger.debug(f"Creating model checkpoint at epoch={epoch + 1} ...")
82
+ # Ensure model is built before saving weights
83
+ if not self.model.built:
84
+ # Build the model with dummy data to ensure it's built
85
+ import tensorflow as tf
86
+
87
+ dummy_input = tf.zeros((1, 1))
88
+ _ = self.model(dummy_input)
89
+
90
+ # Ensure the directory exists before saving
91
+ import os
92
+
93
+ os.makedirs(os.path.dirname(self.checkpoint_file), exist_ok=True)
94
+ self.model.save_weights(self.checkpoint_file, overwrite=True)
95
+
96
+ def _does_model_improve(self, curr_results: Dict[Text, Any]) -> bool:
97
+ """Checks whether the current results are better than the best so far.
98
+
99
+ Results are considered better if each metric is
100
+ equal or better than the best so far, and at least one is better.
101
+
102
+ Args:
103
+ curr_results: The training metrics for this epoch.
104
+ """
105
+ curr_metric_names = [
106
+ k
107
+ for k in curr_results.keys()
108
+ if k.startswith("val") and (k.endswith("_acc") or k.endswith("_f1"))
109
+ ]
110
+ # the "val" prefix is prepended to metrics in fit
111
+ # if _should_eval returns true
112
+ # for this particular epoch
113
+ if len(curr_metric_names) == 0:
114
+ # the metrics are not validation metrics
104
115
  return False
105
- if float(curr_results[metric_name]) > self.best_metrics_so_far[metric_name]:
106
- at_least_one_improved = True
107
- improved_metrics[metric_name] = float(curr_results[metric_name])
108
-
109
- # all current values >= previous best and at least one is better
110
- if at_least_one_improved:
111
- self.best_metrics_so_far.update(improved_metrics)
112
- return at_least_one_improved
116
+ # initialize best_metrics_so_far with the first results
117
+ if not self.best_metrics_so_far:
118
+ for metric_name in curr_metric_names:
119
+ self.best_metrics_so_far[metric_name] = float(
120
+ curr_results[metric_name]
121
+ )
122
+ return True
123
+
124
+ at_least_one_improved = False
125
+ improved_metrics = {}
126
+ for metric_name in self.best_metrics_so_far.keys():
127
+ if (
128
+ float(curr_results[metric_name])
129
+ < self.best_metrics_so_far[metric_name]
130
+ ):
131
+ # at least one of the values is worse
132
+ return False
133
+ if (
134
+ float(curr_results[metric_name])
135
+ > self.best_metrics_so_far[metric_name]
136
+ ):
137
+ at_least_one_improved = True
138
+ improved_metrics[metric_name] = float(curr_results[metric_name])
139
+
140
+ # all current values >= previous best and at least one is better
141
+ if at_least_one_improved:
142
+ self.best_metrics_so_far.update(improved_metrics)
143
+ return at_least_one_improved
144
+ else:
145
+ # Placeholder classes when TensorFlow is not available
146
+ RasaTrainingLogger = None # type: ignore
147
+ RasaModelCheckpoint = None # type: ignore
@@ -9,7 +9,7 @@ from tensorflow.types.experimental import TensorLike
9
9
  # (modified to our neeeds)
10
10
 
11
11
 
12
- class CrfDecodeForwardRnnCell(tf.keras.layers.AbstractRNNCell):
12
+ class CrfDecodeForwardRnnCell(tf.keras.layers.Layer):
13
13
  """Computes the forward decoding in a linear-chain CRF."""
14
14
 
15
15
  def __init__(self, transition_params: TensorLike, **kwargs: Any) -> None:
@@ -71,13 +71,22 @@ class RasaDataGenerator(Sequence):
71
71
  # balancing on the next epoch
72
72
  return data
73
73
 
74
+ @staticmethod
75
+ def _create_default_array() -> np.ndarray:
76
+ """Create a default empty array for missing features.
77
+
78
+ Returns:
79
+ A default empty array with shape (0, 1) and dtype float32.
80
+ """
81
+ return np.zeros((0, 1), dtype=np.float32)
82
+
74
83
  @staticmethod
75
84
  def prepare_batch(
76
85
  data: Data,
77
86
  start: Optional[int] = None,
78
87
  end: Optional[int] = None,
79
88
  tuple_sizes: Optional[Dict[Text, int]] = None,
80
- ) -> Tuple[Optional[np.ndarray], ...]:
89
+ ) -> Tuple[np.ndarray, ...]:
81
90
  """Slices model data into batch using given start and end value.
82
91
 
83
92
  Args:
@@ -85,8 +94,8 @@ class RasaDataGenerator(Sequence):
85
94
  start: The start index of the batch
86
95
  end: The end index of the batch
87
96
  tuple_sizes: In case the feature is not present we propagate the batch with
88
- None. Tuple sizes contains the number of how many None values to add for
89
- what kind of feature.
97
+ default arrays. Tuple sizes contains the number of how many default values
98
+ to add for what kind of feature.
90
99
 
91
100
  Returns:
92
101
  The features of the batch.
@@ -95,12 +104,14 @@ class RasaDataGenerator(Sequence):
95
104
 
96
105
  for key, attribute_data in data.items():
97
106
  for sub_key, f_data in attribute_data.items():
98
- # add None for not present values during processing
107
+ # add default arrays for not present values during processing
99
108
  if not f_data:
100
109
  if tuple_sizes:
101
- batch_data += [None] * tuple_sizes[key]
110
+ batch_data += [
111
+ RasaDataGenerator._create_default_array()
112
+ ] * tuple_sizes[key]
102
113
  else:
103
- batch_data.append(None)
114
+ batch_data.append(RasaDataGenerator._create_default_array())
104
115
  continue
105
116
 
106
117
  for v in f_data:
@@ -409,8 +420,10 @@ class RasaBatchDataGenerator(RasaDataGenerator):
409
420
  end = start + self._current_batch_size
410
421
 
411
422
  # return input and target data, as our target data is inside the input
412
- # data return None for the target data
413
- return self.prepare_batch(self._data, start, end), None
423
+ # data return default array for the target data
424
+ return self.prepare_batch(
425
+ self._data, start, end
426
+ ), RasaDataGenerator._create_default_array()
414
427
 
415
428
  def on_epoch_end(self) -> None:
416
429
  """Update the data after every epoch."""
@@ -3,9 +3,7 @@ from typing import Any, Callable, List, Optional, Text, Tuple, Union
3
3
 
4
4
  import tensorflow as tf
5
5
  import tensorflow.keras.backend as K
6
-
7
- # TODO: The following is not (yet) available via tf.keras
8
- from keras.src.utils.control_flow_util import smart_cond
6
+ from tensorflow.python.keras.utils.control_flow_util import smart_cond
9
7
 
10
8
  import rasa.utils.tensorflow.crf
11
9
  import rasa.utils.tensorflow.layers_utils as layers_utils
@@ -278,6 +276,7 @@ class RandomlyConnectedDense(tf.keras.layers.Dense):
278
276
  kernel_constraint: Constraint function applied to
279
277
  the `kernel` weights matrix.
280
278
  bias_constraint: Constraint function applied to the bias vector.
279
+ **kwargs: Additional keyword arguments passed to the parent class.
281
280
  """
282
281
  super().__init__(**kwargs)
283
282
 
@@ -298,16 +297,19 @@ class RandomlyConnectedDense(tf.keras.layers.Dense):
298
297
  self.kernel_mask = None
299
298
  return
300
299
 
301
- # Construct mask with given density and guarantee that every output is
302
- # connected to at least one input
303
- kernel_mask = self._minimal_mask() + self._random_mask()
300
+ # Use callable initializer for TensorFlow 2.19.1 compatibility
301
+ def kernel_mask_initializer() -> tf.Tensor:
302
+ # Construct mask with given density and guarantee that every output is
303
+ # connected to at least one input
304
+ kernel_mask = self._minimal_mask() + self._random_mask()
304
305
 
305
- # We might accidently have added a random connection on top of
306
- # a fixed connection
307
- kernel_mask = tf.clip_by_value(kernel_mask, 0, 1)
306
+ # We might accidently have added a random connection on top of
307
+ # a fixed connection
308
+ kernel_mask = tf.clip_by_value(kernel_mask, 0, 1)
309
+ return kernel_mask
308
310
 
309
311
  self.kernel_mask = tf.Variable(
310
- initial_value=kernel_mask, trainable=False, name="kernel_mask"
312
+ initial_value=kernel_mask_initializer, trainable=False, name="kernel_mask"
311
313
  )
312
314
 
313
315
  def _random_mask(self) -> tf.Tensor:
@@ -367,7 +369,12 @@ class RandomlyConnectedDense(tf.keras.layers.Dense):
367
369
  Returns:
368
370
  The processed inputs.
369
371
  """
370
- if self.density < 1.0:
372
+ # Apply kernel masking if needed (Keras 3.x compatibility check)
373
+ if (
374
+ self.density < 1.0
375
+ and hasattr(self, "kernel_mask")
376
+ and self.kernel_mask is not None
377
+ ):
371
378
  # Set fraction of the `kernel` weights to zero according to precomputed mask
372
379
  self.kernel.assign(self.kernel * self.kernel_mask)
373
380
  return super().call(inputs)
@@ -724,6 +731,7 @@ class DotProductLoss(tf.keras.layers.Layer):
724
731
  Currently, the only possible value is `SOFTMAX`.
725
732
  similarity_type: Similarity measure to use, either `cosine` or `inner`.
726
733
  name: Optional name of the layer.
734
+ **kwargs: Additional keyword arguments passed to the parent class.
727
735
 
728
736
  Raises:
729
737
  TFLayerConfigException: When `similarity_type` is not one of `COSINE` or
@@ -883,6 +891,7 @@ class SingleLabelDotProductLoss(DotProductLoss):
883
891
  values are approximately bounded.
884
892
  model_confidence: Normalization of confidence values during inference.
885
893
  Currently, the only possible value is `SOFTMAX`.
894
+ **kwargs: Additional keyword arguments passed to the parent class.
886
895
  """
887
896
  super().__init__(
888
897
  num_candidates,
@@ -1244,6 +1253,7 @@ class MultiLabelDotProductLoss(DotProductLoss):
1244
1253
  Used inside _loss_cross_entropy() only.
1245
1254
  model_confidence: Normalization of confidence values during inference.
1246
1255
  Currently, the only possible value is `SOFTMAX`.
1256
+ **kwargs: Additional keyword arguments passed to the parent class.
1247
1257
  """
1248
1258
  super().__init__(
1249
1259
  num_candidates,
@@ -1,7 +1,6 @@
1
1
  from typing import Any, Dict, Optional
2
2
 
3
3
  import tensorflow as tf
4
- from tensorflow.keras import backend as K
5
4
  from tensorflow.types.experimental import TensorLike
6
5
 
7
6
  # original code taken from
@@ -118,7 +117,7 @@ class FBetaScore(tf.keras.metrics.Metric):
118
117
 
119
118
  def _zero_wt_init(name: Any) -> Any:
120
119
  return self.add_weight(
121
- name, shape=self.init_shape, initializer="zeros", dtype=self.dtype
120
+ name=name, shape=self.init_shape, initializer="zeros", dtype=self.dtype
122
121
  )
123
122
 
124
123
  self.true_positives = _zero_wt_init("true_positives")
@@ -197,7 +196,12 @@ class FBetaScore(tf.keras.metrics.Metric):
197
196
 
198
197
  def reset_state(self) -> None:
199
198
  reset_value = tf.zeros(self.init_shape, dtype=self.dtype)
200
- K.batch_set_value([(v, reset_value) for v in self.variables])
199
+ # In Keras 3.x, self.variables contains string names, not variable objects,
200
+ # so each metric variable is reset using assign() instead of K.batch_set_value()
201
+ self.true_positives.assign(reset_value)
202
+ self.false_positives.assign(reset_value)
203
+ self.false_negatives.assign(reset_value)
204
+ self.weights_intermediate.assign(reset_value)
201
205
 
202
206
  def reset_states(self) -> None:
203
207
  # Backwards compatibility alias of `reset_state`. New classes should
@@ -8,7 +8,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Text, Tuple, Union
8
8
  import numpy as np
9
9
  import tensorflow as tf
10
10
  from keras import Model
11
- from keras.src.utils import tf_utils
12
11
 
13
12
  import rasa.utils.train_utils
14
13
  from rasa.shared.constants import DIAGNOSTIC_DATA
@@ -78,6 +77,7 @@ class RasaModel(Model):
78
77
 
79
78
  Args:
80
79
  random_seed: set the random seed to get reproducible results
80
+ **kwargs: Additional keyword arguments passed to the parent class
81
81
  """
82
82
  # make sure that keras releases resources from previously trained model
83
83
  tf.keras.backend.clear_session()
@@ -273,7 +273,8 @@ class RasaModel(Model):
273
273
  if self._run_eagerly:
274
274
  # Once we take advantage of TF's distributed training, this is where
275
275
  # scheduled functions will be forced to execute and return actual values.
276
- outputs = tf_utils.sync_to_numpy_or_python_type(self.predict_step(batch_in))
276
+ step_output = self.predict_step(batch_in)
277
+ outputs = self._convert_tensors_to_numpy(step_output)
277
278
  if DIAGNOSTIC_DATA in outputs:
278
279
  outputs[DIAGNOSTIC_DATA] = self._empty_lists_to_none_in_dict(
279
280
  outputs[DIAGNOSTIC_DATA]
@@ -287,9 +288,8 @@ class RasaModel(Model):
287
288
 
288
289
  # Once we take advantage of TF's distributed training, this is where
289
290
  # scheduled functions will be forced to execute and return actual values.
290
- outputs = tf_utils.sync_to_numpy_or_python_type(
291
- self._tf_predict_step(list(batch_in))
292
- )
291
+ step_output = self._tf_predict_step(list(batch_in))
292
+ outputs = self._convert_tensors_to_numpy(step_output)
293
293
  if DIAGNOSTIC_DATA in outputs:
294
294
  outputs[DIAGNOSTIC_DATA] = self._empty_lists_to_none_in_dict(
295
295
  outputs[DIAGNOSTIC_DATA]
@@ -388,6 +388,35 @@ class RasaModel(Model):
388
388
 
389
389
  return {k: _recurse(v) for k, v in input_dict.items()}
390
390
 
391
+ def _convert_tensors_to_numpy(
392
+ self, step_output: Dict[Text, Any]
393
+ ) -> Dict[Text, Any]:
394
+ """ "Recursively convert TensorFlow tensors to numpy arrays for Keras 3.x
395
+ compatibility.
396
+ Replaces the deprecated tf_utils.sync_to_numpy_or_python_type() function.
397
+ Converts tensors (objects with 'numpy' method) to numpy arrays,
398
+ leaves others unchanged.
399
+ """
400
+
401
+ def to_numpy(obj: Any) -> Any:
402
+ if hasattr(obj, "numpy"):
403
+ try:
404
+ return obj.numpy()
405
+ except Exception:
406
+ # Fallback: return as-is if not convertible
407
+ return obj
408
+ # Dict: recurse into values
409
+ if isinstance(obj, dict):
410
+ return {k: to_numpy(v) for k, v in obj.items()}
411
+ # List/Tuple: recurse preserving type
412
+ if isinstance(obj, list):
413
+ return [to_numpy(v) for v in obj]
414
+ if isinstance(obj, tuple):
415
+ return tuple(to_numpy(v) for v in obj)
416
+ return obj
417
+
418
+ return {key: to_numpy(value) for key, value in step_output.items()}
419
+
391
420
  def _get_metric_results(self, prefix: Optional[Text] = "") -> Dict[Text, float]:
392
421
  return {
393
422
  f"{prefix}{metric.name}": metric.result()
@@ -403,7 +432,21 @@ class RasaModel(Model):
403
432
  overwrite: If 'True' an already existing model with the same file name will
404
433
  be overwritten.
405
434
  """
406
- self.save_weights(model_file_name, overwrite=overwrite, save_format="tf")
435
+ # Ensure filename ends with .weights.h5 and model is built for Keras 3.x
436
+ # compatibility
437
+ model_file_name = str(model_file_name)
438
+ if not model_file_name.endswith(".weights.h5"):
439
+ model_file_name += ".weights.h5"
440
+
441
+ if not self.built:
442
+ import tensorflow as tf
443
+
444
+ _ = self(tf.zeros((1, 1)))
445
+
446
+ # TensorFlow 2.19: save weights with different file extension
447
+ if not model_file_name.endswith(".weights.h5"):
448
+ model_file_name += ".weights.h5"
449
+ self.save_weights(model_file_name, overwrite=overwrite)
407
450
 
408
451
  @classmethod
409
452
  def load(
@@ -438,18 +481,23 @@ class RasaModel(Model):
438
481
  learning_rate = kwargs.get("config", {}).get(LEARNING_RATE, 0.001)
439
482
  run_eagerly = kwargs.get("config", {}).get(RUN_EAGERLY)
440
483
 
441
- # need to train on 1 example to build weights of the correct size
442
484
  model.compile(
443
485
  optimizer=tf.keras.optimizers.Adam(learning_rate), run_eagerly=run_eagerly
444
486
  )
445
487
  data_generator = RasaBatchDataGenerator(model_data_example, batch_size=1)
446
488
  model.fit(data_generator, verbose=False)
489
+
490
+ # Ensure model is built before loading weights
491
+ if not model.built:
492
+ sample_batch = next(iter(data_generator))
493
+ _ = model(sample_batch)
494
+
447
495
  # load trained weights
448
496
  model.load_weights(model_file_name)
449
497
 
450
498
  # predict on one data example to speed up prediction during inference
451
499
  # the first prediction always takes a bit longer to trace tf function
452
- if not finetune_mode and predict_data_example:
500
+ if predict_data_example:
453
501
  model.run_inference(predict_data_example)
454
502
 
455
503
  logger.debug("Finished loading the model.")
@@ -291,7 +291,7 @@ class ConcatenateSparseDenseFeatures(RasaCustomLayer):
291
291
  [
292
292
  config[DENSE_DIMENSION][attribute]
293
293
  if signature.is_sparse
294
- else signature.units
294
+ else (signature.units or 0)
295
295
  for signature in feature_type_signature
296
296
  ]
297
297
  )
@@ -301,12 +301,12 @@ class ConcatenateSparseDenseFeatures(RasaCustomLayer):
301
301
  ) -> tf.Tensor:
302
302
  """Turns sparse tensor into dense, possibly adds dropout before and/or after."""
303
303
  if self.SPARSE_DROPOUT in self._tf_layers:
304
- feature = self._tf_layers[self.SPARSE_DROPOUT](feature, training)
304
+ feature = self._tf_layers[self.SPARSE_DROPOUT](feature, training=training)
305
305
 
306
306
  feature = self._tf_layers[self.SPARSE_TO_DENSE](feature)
307
307
 
308
308
  if self.DENSE_DROPOUT in self._tf_layers:
309
- feature = self._tf_layers[self.DENSE_DROPOUT](feature, training)
309
+ feature = self._tf_layers[self.DENSE_DROPOUT](feature, training=training)
310
310
 
311
311
  return feature
312
312
 
@@ -944,7 +944,7 @@ class RasaSequenceLayer(RasaCustomLayer):
944
944
  # Note that only sequence-level features are masked, nothing happens to the
945
945
  # sentence-level features in the combined features tensor.
946
946
  seq_sent_features, mlm_boolean_mask = self._tf_layers[self.MLM_INPUT_MASK](
947
- seq_sent_features, mask_sequence, training
947
+ seq_sent_features, mask_sequence, training=training
948
948
  )
949
949
 
950
950
  return seq_sent_features, token_ids, mlm_boolean_mask
@@ -1002,7 +1002,9 @@ class RasaSequenceLayer(RasaCustomLayer):
1002
1002
  ]((sequence_features, sentence_features, sequence_feature_lengths))
1003
1003
 
1004
1004
  # Apply one or more dense layers.
1005
- seq_sent_features = self._tf_layers[self.FFNN](seq_sent_features, training)
1005
+ seq_sent_features = self._tf_layers[self.FFNN](
1006
+ seq_sent_features, training=training
1007
+ )
1006
1008
 
1007
1009
  # If using masked language modeling, mask the transformer inputs and get labels
1008
1010
  # for the masked tokens and a boolean mask. Note that TED does not use MLM loss,
@@ -1031,7 +1033,7 @@ class RasaSequenceLayer(RasaCustomLayer):
1031
1033
  if self._has_transformer:
1032
1034
  mask_padding = 1 - mask_combined_sequence_sentence
1033
1035
  outputs, attention_weights = self._tf_layers[self.TRANSFORMER](
1034
- seq_sent_features_masked, mask_padding, training
1036
+ seq_sent_features_masked, mask_padding, training=training
1035
1037
  )
1036
1038
  outputs = tf.nn.gelu(outputs)
1037
1039
  else:
@@ -2,10 +2,8 @@ from typing import Optional, Text, Tuple, Union
2
2
 
3
3
  import numpy as np
4
4
  import tensorflow as tf
5
-
6
- # TODO: The following is not (yet) available via tf.keras
7
- from keras.src.utils.control_flow_util import smart_cond
8
5
  from tensorflow.keras import backend as K
6
+ from tensorflow.python.keras.utils.control_flow_util import smart_cond
9
7
 
10
8
  from rasa.utils.tensorflow.exceptions import TFLayerConfigException
11
9
  from rasa.utils.tensorflow.layers import RandomlyConnectedDense
@@ -280,6 +278,7 @@ class MultiHeadAttention(tf.keras.layers.Layer):
280
278
  value: A tensor with shape (..., length, depth).
281
279
  pad_mask: Float tensor with shape broadcastable
282
280
  to (..., length, length). Defaults to None.
281
+ training: A tensor
283
282
 
284
283
  Returns:
285
284
  output: A tensor with shape (..., length, depth).