rasa-pro 3.13.0.dev20250613__py3-none-any.whl → 3.13.0rc2__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 (160) hide show
  1. rasa/cli/e2e_test.py +0 -7
  2. rasa/cli/export.py +2 -0
  3. rasa/cli/project_templates/tutorial/config.yml +1 -1
  4. rasa/cli/project_templates/tutorial/endpoints.yml +1 -1
  5. rasa/cli/studio/download.py +1 -23
  6. rasa/cli/studio/link.py +0 -17
  7. rasa/cli/studio/pull.py +3 -2
  8. rasa/cli/studio/push.py +1 -1
  9. rasa/cli/studio/train.py +1 -5
  10. rasa/cli/studio/upload.py +1 -1
  11. rasa/core/agent.py +6 -0
  12. rasa/core/channels/__init__.py +3 -0
  13. rasa/core/channels/development_inspector.py +1 -1
  14. rasa/core/channels/facebook.py +1 -4
  15. rasa/core/channels/inspector/README.md +3 -3
  16. rasa/core/channels/inspector/dist/assets/{arc-c4b064fc.js → arc-371401b1.js} +1 -1
  17. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-215b5026.js → blockDiagram-38ab4fdb-3f126156.js} +1 -1
  18. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-2b54a0a3.js → c4Diagram-3d4e48cf-12f22eb7.js} +1 -1
  19. rasa/core/channels/inspector/dist/assets/channel-f1efda17.js +1 -0
  20. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-daacea5f.js → classDiagram-70f12bd4-03b1d386.js} +1 -1
  21. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-930d4dc2.js → classDiagram-v2-f2320105-84f69d63.js} +1 -1
  22. rasa/core/channels/inspector/dist/assets/clone-fdf164e2.js +1 -0
  23. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-83c206ba.js → createText-2e5e7dd3-ca47fd38.js} +1 -1
  24. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-b0eb01d0.js → edges-e0da2a9e-f837ca8a.js} +1 -1
  25. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-17586500.js → erDiagram-9861fffd-8717ac54.js} +1 -1
  26. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-be2a1776.js → flowDb-956e92f1-94f38b83.js} +1 -1
  27. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-c2120ebd.js → flowDiagram-66a62f08-b616f9fb.js} +1 -1
  28. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-7d7a1629.js +1 -0
  29. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-a6ab5c48.js → flowchart-elk-definition-4a651766-f5d24bb8.js} +1 -1
  30. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-ef613457.js → ganttDiagram-c361ad54-b43ba8d9.js} +1 -1
  31. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-d59185b3.js → gitGraphDiagram-72cf32ee-c3aafaa5.js} +1 -1
  32. rasa/core/channels/inspector/dist/assets/{graph-0f155405.js → graph-0d0a2c10.js} +1 -1
  33. rasa/core/channels/inspector/dist/assets/{index-3862675e-d5f1d1b7.js → index-3862675e-58ea0305.js} +1 -1
  34. rasa/core/channels/inspector/dist/assets/{index-47737d3a.js → index-cce6f8a1.js} +3 -3
  35. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-b07d141f.js → infoDiagram-f8f76790-b8f60461.js} +1 -1
  36. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-1936d429.js → journeyDiagram-49397b02-95be5545.js} +1 -1
  37. rasa/core/channels/inspector/dist/assets/{layout-dde8d0f3.js → layout-da885b9b.js} +1 -1
  38. rasa/core/channels/inspector/dist/assets/{line-0c2c7ee0.js → line-f1c817d3.js} +1 -1
  39. rasa/core/channels/inspector/dist/assets/{linear-35dd89a4.js → linear-d42801e6.js} +1 -1
  40. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-56192851.js → mindmap-definition-fc14e90a-a38923a6.js} +1 -1
  41. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-fc21ed78.js → pieDiagram-8a3498a8-ca6e71e9.js} +1 -1
  42. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-25e98518.js → quadrantDiagram-120e2f19-b290dae9.js} +1 -1
  43. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-546ff1f5.js → requirementDiagram-deff3bca-03f02ceb.js} +1 -1
  44. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-02d8b82d.js → sankeyDiagram-04a897e0-c49eee40.js} +1 -1
  45. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-3ca5a92e.js → sequenceDiagram-704730f1-b2cd6a3d.js} +1 -1
  46. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-128ea07c.js → stateDiagram-587899a1-e53a2028.js} +1 -1
  47. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-95f290af.js → stateDiagram-v2-d93cdb3a-e1982a03.js} +1 -1
  48. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-4984898a.js → styles-6aaf32cf-d0226ca5.js} +1 -1
  49. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-1bf266ba.js → styles-9a916d00-0e21dc00.js} +1 -1
  50. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-60521c63.js → styles-c10674c1-9588494e.js} +1 -1
  51. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-a25b6e12.js → svgDrawCommon-08f97a94-be478d4f.js} +1 -1
  52. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-0fc086bf.js → timeline-definition-85554ec2-74631749.js} +1 -1
  53. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-44ee592e.js → xychartDiagram-e933f94c-a043552f.js} +1 -1
  54. rasa/core/channels/inspector/dist/index.html +1 -1
  55. rasa/core/channels/inspector/src/components/RecruitmentPanel.tsx +1 -1
  56. rasa/core/channels/socketio.py +56 -41
  57. rasa/core/channels/studio_chat.py +311 -8
  58. rasa/core/channels/voice_ready/audiocodes.py +1 -1
  59. rasa/core/channels/voice_ready/jambonz.py +5 -6
  60. rasa/core/channels/voice_ready/twilio_voice.py +13 -12
  61. rasa/core/channels/voice_ready/utils.py +22 -0
  62. rasa/core/channels/voice_stream/asr/azure.py +9 -0
  63. rasa/core/channels/voice_stream/audiocodes.py +5 -11
  64. rasa/core/channels/voice_stream/browser_audio.py +1 -1
  65. rasa/core/channels/voice_stream/genesys.py +35 -16
  66. rasa/core/channels/voice_stream/jambonz.py +232 -0
  67. rasa/core/channels/voice_stream/tts/__init__.py +8 -0
  68. rasa/core/channels/voice_stream/twilio_media_streams.py +12 -7
  69. rasa/core/channels/voice_stream/voice_channel.py +53 -15
  70. rasa/core/exporter.py +36 -0
  71. rasa/core/information_retrieval/faiss.py +18 -11
  72. rasa/core/information_retrieval/ingestion/faq_parser.py +158 -0
  73. rasa/core/nlg/contextual_response_rephraser.py +10 -1
  74. rasa/core/policies/enterprise_search_policy.py +189 -263
  75. rasa/core/policies/enterprise_search_policy_config.py +241 -0
  76. rasa/core/policies/enterprise_search_prompt_with_relevancy_check_and_citation_template.jinja2 +6 -5
  77. rasa/core/policies/intentless_policy.py +47 -10
  78. rasa/core/processor.py +6 -0
  79. rasa/core/utils.py +11 -2
  80. rasa/dialogue_understanding/coexistence/llm_based_router.py +13 -11
  81. rasa/dialogue_understanding/commands/__init__.py +4 -0
  82. rasa/dialogue_understanding/commands/cancel_flow_command.py +4 -2
  83. rasa/dialogue_understanding/commands/clarify_command.py +2 -2
  84. rasa/dialogue_understanding/commands/correct_slots_command.py +5 -6
  85. rasa/dialogue_understanding/commands/error_command.py +1 -1
  86. rasa/dialogue_understanding/commands/human_handoff_command.py +1 -3
  87. rasa/dialogue_understanding/commands/set_slot_command.py +4 -4
  88. rasa/dialogue_understanding/commands/skip_question_command.py +1 -3
  89. rasa/dialogue_understanding/commands/start_flow_command.py +3 -3
  90. rasa/dialogue_understanding/generator/command_generator.py +11 -1
  91. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +3 -2
  92. rasa/dialogue_understanding/generator/nlu_command_adapter.py +2 -2
  93. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_template.jinja2 +0 -2
  94. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +1 -0
  95. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +1 -0
  96. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +79 -0
  97. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +1 -0
  98. rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +2 -2
  99. rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +2 -18
  100. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +17 -11
  101. rasa/dialogue_understanding/patterns/cancel.py +1 -2
  102. rasa/dialogue_understanding/patterns/clarify.py +1 -1
  103. rasa/dialogue_understanding/patterns/correction.py +2 -2
  104. rasa/dialogue_understanding/processor/command_processor.py +11 -12
  105. rasa/dialogue_understanding/stack/utils.py +3 -1
  106. rasa/e2e_test/constants.py +1 -1
  107. rasa/e2e_test/e2e_test_coverage_report.py +1 -1
  108. rasa/engine/graph.py +2 -2
  109. rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +2 -6
  110. rasa/model_manager/runner_service.py +20 -4
  111. rasa/model_manager/trainer_service.py +6 -0
  112. rasa/privacy/privacy_manager.py +26 -11
  113. rasa/shared/constants.py +14 -0
  114. rasa/shared/core/command_payload_reader.py +1 -5
  115. rasa/shared/core/events.py +1 -3
  116. rasa/shared/core/flows/constants.py +2 -0
  117. rasa/shared/core/flows/flow.py +126 -12
  118. rasa/shared/core/flows/flows_list.py +18 -1
  119. rasa/shared/core/flows/steps/link.py +7 -2
  120. rasa/shared/core/flows/validation.py +25 -5
  121. rasa/shared/core/training_data/story_reader/yaml_story_reader.py +1 -4
  122. rasa/shared/providers/_configs/azure_openai_client_config.py +2 -2
  123. rasa/shared/providers/_configs/default_litellm_client_config.py +1 -1
  124. rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +1 -1
  125. rasa/shared/providers/_configs/openai_client_config.py +1 -1
  126. rasa/shared/providers/_configs/rasa_llm_client_config.py +1 -1
  127. rasa/shared/providers/_configs/self_hosted_llm_client_config.py +1 -1
  128. rasa/shared/providers/_configs/utils.py +0 -99
  129. rasa/shared/utils/common.py +1 -1
  130. rasa/shared/utils/configs.py +110 -0
  131. rasa/shared/utils/constants.py +0 -3
  132. rasa/shared/utils/llm.py +123 -8
  133. rasa/shared/utils/pykwalify_extensions.py +0 -9
  134. rasa/studio/constants.py +1 -0
  135. rasa/studio/data_handler.py +30 -9
  136. rasa/studio/download.py +171 -0
  137. rasa/studio/link.py +13 -2
  138. rasa/studio/prompts.py +221 -0
  139. rasa/studio/pull/__init__.py +0 -0
  140. rasa/studio/{download/flows.py → pull/data.py} +2 -131
  141. rasa/studio/{download → pull}/domains.py +1 -1
  142. rasa/studio/pull/pull.py +239 -0
  143. rasa/studio/push.py +7 -0
  144. rasa/studio/train.py +1 -1
  145. rasa/studio/upload.py +61 -5
  146. rasa/studio/utils.py +33 -0
  147. rasa/tracing/instrumentation/attribute_extractors.py +21 -7
  148. rasa/utils/common.py +11 -0
  149. rasa/version.py +1 -1
  150. {rasa_pro-3.13.0.dev20250613.dist-info → rasa_pro-3.13.0rc2.dist-info}/METADATA +4 -4
  151. {rasa_pro-3.13.0.dev20250613.dist-info → rasa_pro-3.13.0rc2.dist-info}/RECORD +155 -147
  152. rasa/core/channels/inspector/dist/assets/channel-3730f5fd.js +0 -1
  153. rasa/core/channels/inspector/dist/assets/clone-e847561e.js +0 -1
  154. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-efbbfe00.js +0 -1
  155. rasa/studio/download/download.py +0 -416
  156. rasa/studio/pull.py +0 -94
  157. /rasa/{studio/download → core/information_retrieval/ingestion}/__init__.py +0 -0
  158. {rasa_pro-3.13.0.dev20250613.dist-info → rasa_pro-3.13.0rc2.dist-info}/NOTICE +0 -0
  159. {rasa_pro-3.13.0.dev20250613.dist-info → rasa_pro-3.13.0rc2.dist-info}/WHEEL +0 -0
  160. {rasa_pro-3.13.0.dev20250613.dist-info → rasa_pro-3.13.0rc2.dist-info}/entry_points.txt +0 -0
@@ -8,6 +8,7 @@ from rasa.dialogue_understanding.commands import (
8
8
  Command,
9
9
  CorrectSlotsCommand,
10
10
  ErrorCommand,
11
+ HandleCodeChangeCommand,
11
12
  SetSlotCommand,
12
13
  StartFlowCommand,
13
14
  )
@@ -398,15 +399,24 @@ class CommandGenerator:
398
399
  The filtered commands.
399
400
  """
400
401
  from rasa.dialogue_understanding.processor.command_processor import (
402
+ find_updated_flows,
401
403
  get_current_collect_step,
402
404
  )
403
405
 
404
406
  if tracker is None:
405
- structlogger.error(
407
+ structlogger.debug(
406
408
  "command_generator.filter_commands_during_force_slot_filling.tracker_not_found",
407
409
  )
408
410
  return commands
409
411
 
412
+ updated_flows = find_updated_flows(tracker, available_flows)
413
+ if updated_flows:
414
+ structlogger.debug(
415
+ "command_generator.filter_commands_during_force_slot_filling.running_flows_were_updated",
416
+ updated_flow_ids=updated_flows,
417
+ )
418
+ return [HandleCodeChangeCommand()]
419
+
410
420
  stack = tracker.stack
411
421
  step = get_current_collect_step(stack, available_flows)
412
422
 
@@ -125,8 +125,9 @@ class MultiStepLLMCommandGenerator(LLMBasedCommandGenerator):
125
125
  raise_deprecation_warning(
126
126
  message=(
127
127
  "Support for `MultiStepLLMCommandGenerator` will be removed in Rasa "
128
- "`4.0.0`. Please modify your assistant's configuration to use other "
129
- "LLM command generators like the `SingleStepLLMCommandGenerator`."
128
+ "`4.0.0`. Please modify your assistant's configuration to use the "
129
+ "`CompactLLMCommandGenerator` or `SearchReadyLLMCommandGenerator` "
130
+ "instead."
130
131
  )
131
132
  )
132
133
 
@@ -190,9 +190,9 @@ class NLUCommandAdapter(GraphComponent, CommandGenerator):
190
190
  if len(commands) > 1:
191
191
  structlogger.warning(
192
192
  "nlu_command_adapter.predict_commands",
193
- messag=f"Two many flows found that are triggered by the "
193
+ message=f"Too many flows found that are triggered by the "
194
194
  f"intent '{message.get(INTENT)['name']}'. Take the first one.",
195
- commands=commands,
195
+ commands=[command.__class__.__name__ for command in commands],
196
196
  )
197
197
  commands = [commands[0]]
198
198
 
@@ -41,9 +41,7 @@ Based on this information generate a list of actions you want to take. Your job
41
41
  * Responding to knowledge-oriented user messages, described by "SearchAndReply()"
42
42
  * Responding to a casual, non-task-oriented user message, described by "ChitChat()".
43
43
  * Handing off to a human, in case the user seems frustrated or explicitly asks to speak to one, described by "HumanHandoff()".
44
- {% if is_repeat_command_enabled %}
45
44
  * Repeat the last bot messages, described by "RepeatLastBotMessages()". This is useful when the user asks to repeat the last bot messages.
46
- {% endif %}
47
45
 
48
46
  ===
49
47
  Write out the actions you want to take, one per line, in the order they should take place.
@@ -11,6 +11,7 @@ Your task is to analyze the current conversation context and generate a list of
11
11
  * `provide info`: Responding to the user's questions by supplying relevant information, such as answering FAQs or explaining services.
12
12
  * `offtopic reply`: Responding to casual or social user messages that are unrelated to any flows, engaging in friendly conversation and addressing off-topic remarks.
13
13
  * `hand over`: Handing over to a human, in case the user seems frustrated or explicitly asks to speak to one.
14
+ * `repeat message`: Repeating the last bot message.
14
15
 
15
16
  --
16
17
 
@@ -19,6 +19,7 @@ Use the following structured data:
19
19
  * `provide info`: Responding to the user's questions by supplying relevant information, such as answering FAQs or explaining services.
20
20
  * `offtopic reply`: Responding to casual or social user messages that are unrelated to any flows, engaging in friendly conversation and addressing off-topic remarks.
21
21
  * `hand over`: Handing over to a human, in case the user seems frustrated or explicitly asks to speak to one.
22
+ * `repeat message`: Repeating the last bot message.
22
23
 
23
24
  ---
24
25
 
@@ -0,0 +1,79 @@
1
+ ## Task Description
2
+ Your task is to analyze the current conversation context and generate a list of actions to start new business processes that we call flows, to extract slots, or respond to off-topic and knowledge requests.
3
+
4
+ ---
5
+
6
+ ## Available Actions:
7
+ * `start flow flow_name`: Start a flow. For example, `start flow transfer_money` or `start flow list_contacts`.
8
+ * `set slot slot_name slot_value`: Set a slot for the active flow. For example, `set slot transfer_money_recipient Freddy`. Can be used to correct and change previously set values.
9
+ * `disambiguate flows flow_name1 flow_name2 ... flow_name_n`: When a message could refer to multiple flows, list the possible flows as options to clarify. Example: `disambiguate flows list_contacts add_contact remove_contact`.
10
+ * `search and reply`: Provide a response from the knowledge base to address the user's inquiry when no flows fit, including domain knowledge, FAQs, and all off-topic or social messages.
11
+ * `cancel flow`: Cancel the current flow if the user requests it.
12
+ * `repeat message`: Repeat the last bot message.
13
+
14
+ ---
15
+
16
+ ## General Instructions
17
+ ### Start Flow
18
+ * Only start a flow if the user's message is clear and fully addressed by that flow's description and purpose.
19
+ * Pay close attention to exact wording and scope in the flow description — do not assume or “stretch” the intended use of a flow.
20
+ ### Set Slot
21
+ * Do not fill slots with abstract values or placeholders.
22
+ * For categorical slots, try to match the user message with allowed slot values. Use "other" if you cannot match it.
23
+ * Set the boolean slots based on the user's response. Map positive responses to `True`, and negative to `False`.
24
+ * Extract text slot values exactly as provided by the user. Avoid assumptions, format changes, or partial extractions.
25
+ ### Disambiguate Flows
26
+ * Use `disambiguate flows` when the user's message matches multiple flows and you cannot decide which flow is most appropriate.
27
+ * If the user message is short and not precise enough to start a flow or `search and reply`, disambiguate.
28
+ * If a single flow is a strong/plausible fit, prefer starting that flow directly.
29
+ * If a user's message unambiguously and distinctly matches multiple flows, start all relevant flows at once (rather than disambiguating).
30
+ ### Search and Reply
31
+ * Only start `search and reply` if the user intent is clear.
32
+ * Flow Priority: If you are unsure between starting a flow or `search and reply`, always prioritize starting a flow.
33
+ ### Cancel Flow
34
+ * Do not cancel any flow unless the user explicitly requests it.
35
+ * Multiple flows can be started without cancelling the previous, if the user wants to pursue multiple processes.
36
+ ### General Tips
37
+ * Only use information provided by the user.
38
+ * Strictly adhere to the provided action format.
39
+ * Focus on the last message and take it one step at a time.
40
+ * Use the previous conversation steps only to aid understanding.
41
+
42
+ ---
43
+
44
+ ## Decision Rule Table
45
+ | Condition | Action |
46
+ |-------------------------------------------------------|--------------------|
47
+ | Flow perfectly matches user's message | start flow |
48
+ | Multiple flows are equally strong, relevant matches | disambiguate flows |
49
+ | User's message is unclear or imprecise | disambiguate flows |
50
+ | No flow fits at all, but knowledge base may help | search and reply |
51
+
52
+ ---
53
+
54
+ ## Available Flows and Slots
55
+ Use the following structured data:
56
+ ```json
57
+ {"flows":[{% for flow in available_flows %}{"name":"{{ flow.name }}","description":{{ flow.description | to_json_escaped_string }}{% if flow.slots %},"slots":[{% for slot in flow.slots %}{"name":"{{ slot.name }}"{% if slot.description %},"description":{{ slot.description | to_json_escaped_string }}{% endif %}{% if slot.allowed_values %},"allowed_values":{{ slot.allowed_values }}{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]}
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Current State
63
+ {% if current_flow != None %}Use the following structured data:
64
+ ```json
65
+ {"active_flow":"{{ current_flow }}","current_step":{"requested_slot":"{{ current_slot }}","requested_slot_description":{{ current_slot_description | to_json_escaped_string }}},"slots":[{% for slot in flow_slots %}{"name":"{{ slot.name }}","value":"{{ slot.value }}","type":"{{ slot.type }}"{% if slot.description %},"description":{{ slot.description | to_json_escaped_string }}{% endif %}{% if slot.allowed_values %},"allowed_values":"{{ slot.allowed_values }}"{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]}
66
+ ```{% else %}
67
+ You are currently not inside any flow.{% endif %}
68
+
69
+ ---
70
+
71
+ ## Conversation History
72
+ {{ current_conversation }}
73
+
74
+ ---
75
+
76
+ ## Task
77
+ Create an action list with one action per line in response to the user's last message: """{{ user_message }}""".
78
+
79
+ Your action list:
@@ -17,6 +17,7 @@ Use the following structured data:
17
17
  * `disambiguate flows flow_name1 flow_name2 ... flow_name_n`: When a message could refer to multiple flows, list the possible flows as options to clarify. Example: `disambiguate flows list_contacts add_contact remove_contact`.
18
18
  * `search and reply`: Provide a response from the knowledge base to address the user’s inquiry when no flows fit, including domain knowledge, FAQs, and all off-topic or social messages.
19
19
  * `cancel flow`: Cancel the current flow if the user requests it.
20
+ * `repeat message`: Repeat the last bot message.
20
21
 
21
22
  ---
22
23
 
@@ -59,10 +59,10 @@ MODEL_PROMPT_MAPPER = {
59
59
  ),
60
60
  f"{AWS_BEDROCK_PROVIDER}/anthropic."
61
61
  f"{MODEL_NAME_CLAUDE_3_5_SONNET_20240620}-v1:0": (
62
- "command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2"
62
+ "command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2"
63
63
  ),
64
64
  f"{ANTHROPIC_PROVIDER}/{MODEL_NAME_CLAUDE_3_5_SONNET_20240620}": (
65
- "command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2"
65
+ "command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2"
66
66
  ),
67
67
  }
68
68
 
@@ -61,7 +61,6 @@ from rasa.shared.utils.llm import (
61
61
  sanitize_message_for_prompt,
62
62
  tracker_as_readable_transcript,
63
63
  )
64
- from rasa.utils.beta import BetaNotEnabledException, ensure_beta_feature_is_enabled
65
64
  from rasa.utils.log_utils import log_llm
66
65
 
67
66
  structlogger = structlog.get_logger()
@@ -106,14 +105,13 @@ class SingleStepBasedLLMCommandGenerator(LLMBasedCommandGenerator, ABC):
106
105
  )
107
106
 
108
107
  self.trace_prompt_tokens = self.config.get("trace_prompt_tokens", False)
109
- self.repeat_command_enabled = self.is_repeat_command_enabled()
110
108
 
111
109
  ### Implementations of LLMBasedCommandGenerator parent
112
110
  @staticmethod
113
111
  def get_default_config() -> Dict[str, Any]:
114
112
  """The component's default config (see parent class for full docstring)."""
115
113
  return {
116
- PROMPT_TEMPLATE_CONFIG_KEY: None,
114
+ PROMPT_TEMPLATE_CONFIG_KEY: None, # TODO: remove in Rasa 4.0.0
117
115
  USER_INPUT_CONFIG_KEY: None,
118
116
  LLM_CONFIG_KEY: None,
119
117
  FLOW_RETRIEVAL_KEY: FlowRetrieval.get_default_config(),
@@ -212,7 +210,7 @@ class SingleStepBasedLLMCommandGenerator(LLMBasedCommandGenerator, ABC):
212
210
  event_info=(
213
211
  "ProviderClientAPIException occurred while predicting commands."
214
212
  ),
215
- commands=commands,
213
+ commands=commands, # no PII
216
214
  )
217
215
 
218
216
  if not commands and not prior_commands:
@@ -414,24 +412,10 @@ class SingleStepBasedLLMCommandGenerator(LLMBasedCommandGenerator, ABC):
414
412
  "current_slot_type": current_slot_type,
415
413
  "current_slot_allowed_values": current_slot_allowed_values,
416
414
  "user_message": latest_user_message,
417
- "is_repeat_command_enabled": self.repeat_command_enabled,
418
415
  }
419
416
 
420
417
  return self.compile_template(self.prompt_template).render(**inputs)
421
418
 
422
- def is_repeat_command_enabled(self) -> bool:
423
- """Check for feature flag"""
424
- RASA_PRO_BETA_REPEAT_COMMAND_ENV_VAR_NAME = "RASA_PRO_BETA_REPEAT_COMMAND"
425
- try:
426
- ensure_beta_feature_is_enabled(
427
- "Repeat Command",
428
- env_flag=RASA_PRO_BETA_REPEAT_COMMAND_ENV_VAR_NAME,
429
- )
430
- except BetaNotEnabledException:
431
- return False
432
-
433
- return True
434
-
435
419
  @classmethod
436
420
  def fingerprint_addon(cls: Any, config: Dict[str, Any]) -> Optional[str]:
437
421
  """Add a fingerprint for the graph."""
@@ -16,7 +16,11 @@ from rasa.shared.constants import (
16
16
  PROMPT_CONFIG_KEY,
17
17
  PROMPT_TEMPLATE_CONFIG_KEY,
18
18
  )
19
- from rasa.shared.utils.llm import get_prompt_template
19
+ from rasa.shared.utils.io import raise_deprecation_warning
20
+ from rasa.shared.utils.llm import (
21
+ check_prompt_config_keys_and_warn_if_deprecated,
22
+ get_prompt_template,
23
+ )
20
24
 
21
25
  DEFAULT_COMMAND_PROMPT_TEMPLATE = importlib.resources.read_text(
22
26
  "rasa.dialogue_understanding.generator.prompt_templates",
@@ -44,6 +48,14 @@ class SingleStepLLMCommandGenerator(SingleStepBasedLLMCommandGenerator):
44
48
  prompt_template: Optional[Text] = None,
45
49
  **kwargs: Any,
46
50
  ) -> None:
51
+ raise_deprecation_warning(
52
+ message=(
53
+ "Support for `SingleStepLLMCommandGenerator` will be removed in Rasa "
54
+ "`4.0.0`. Please modify your assistant's configuration to use the "
55
+ "`CompactLLMCommandGenerator` or `SearchReadyLLMCommandGenerator` "
56
+ "instead."
57
+ )
58
+ )
47
59
  super().__init__(
48
60
  config,
49
61
  model_storage,
@@ -52,16 +64,10 @@ class SingleStepLLMCommandGenerator(SingleStepBasedLLMCommandGenerator):
52
64
  **kwargs,
53
65
  )
54
66
 
55
- # Set the prompt template
56
- if config.get(PROMPT_CONFIG_KEY):
57
- structlogger.warning(
58
- "single_step_llm_command_generator.init",
59
- event_info=(
60
- "The config parameter 'prompt' is deprecated "
61
- "and will be removed in Rasa 4.0.0. "
62
- "Please use the config parameter 'prompt_template' instead. "
63
- ),
64
- )
67
+ # Warn if the prompt config key is used to set the prompt template
68
+ check_prompt_config_keys_and_warn_if_deprecated(
69
+ config, "single_step_llm_command_generator"
70
+ )
65
71
 
66
72
  @staticmethod
67
73
  def get_component_command_syntax_version() -> CommandSyntaxVersion:
@@ -90,7 +90,7 @@ class ActionCancelFlow(action.Action):
90
90
  return []
91
91
 
92
92
  if not isinstance(top, CancelPatternFlowStackFrame):
93
- structlogger.warning("action.cancel_flow.no_cancel_frame", top=top)
93
+ structlogger.warning("action.cancel_flow.no_cancel_frame")
94
94
  return []
95
95
 
96
96
  for canceled_frame_id in top.canceled_frames:
@@ -105,7 +105,6 @@ class ActionCancelFlow(action.Action):
105
105
  else:
106
106
  structlogger.warning(
107
107
  "action.cancel_flow.frame_not_found",
108
- dialogue_stack=stack,
109
108
  frame_id=canceled_frame_id,
110
109
  )
111
110
 
@@ -89,7 +89,7 @@ class ActionClarifyFlows(action.Action):
89
89
  return []
90
90
 
91
91
  if not isinstance(top, ClarifyPatternFlowStackFrame):
92
- structlogger.warning("action.clarify_flows.no_clarification_frame", top=top)
92
+ structlogger.warning("action.clarify_flows.no_clarification_frame")
93
93
  return []
94
94
 
95
95
  options_string = self.assemble_options_string(top.names)
@@ -114,7 +114,8 @@ class ActionCorrectFlowSlot(action.Action):
114
114
 
115
115
  if not isinstance(top, CorrectionPatternFlowStackFrame):
116
116
  structlogger.warning(
117
- "action.correct_flow_slot.no_correction_frame", top=top
117
+ "action.correct_flow_slot.no_correction_frame",
118
+ top=top, # no PII
118
119
  )
119
120
  return []
120
121
 
@@ -246,7 +247,6 @@ def reset_stack_on_tracker_to_prior_state(
246
247
  "action.correct_flow_slot.no_target_frame_found",
247
248
  reset_step_id=reset_step_id,
248
249
  reset_flow_id=reset_flow_id,
249
- stack_to_reset_to=stack_to_reset_to,
250
250
  )
251
251
  return tracker.stack
252
252
 
@@ -214,18 +214,18 @@ def execute_commands(
214
214
  commands: List[Command] = get_commands_from_tracker(tracker)
215
215
  original_tracker = tracker.copy()
216
216
 
217
- commands = clean_up_commands(
218
- commands, tracker, all_flows, execution_context, story_graph, domain
219
- )
220
-
221
217
  updated_flows = find_updated_flows(tracker, all_flows)
222
218
  if updated_flows:
223
- # Override commands
219
+ # if there are updated flows, we need to handle the code change
224
220
  structlogger.debug(
225
221
  "command_processor.execute_commands.running_flows_were_updated",
226
222
  updated_flow_ids=updated_flows,
227
223
  )
228
224
  commands = [HandleCodeChangeCommand()]
225
+ else:
226
+ commands = clean_up_commands(
227
+ commands, tracker, all_flows, execution_context, story_graph, domain
228
+ )
229
229
 
230
230
  # store current flow hashes if they changed
231
231
  new_hashes = calculate_flow_fingerprints(all_flows)
@@ -348,7 +348,6 @@ def get_current_collect_step(
348
348
  # but no flow that triggered it. this should never happen.
349
349
  structlogger.warning(
350
350
  "command_processor.get_current_collect_step.no_flow_on_stack",
351
- stack=dialogue_stack,
352
351
  )
353
352
  return None
354
353
 
@@ -358,7 +357,7 @@ def get_current_collect_step(
358
357
  # step from it
359
358
  structlogger.warning(
360
359
  "command_processor.get_current_collect_step.no_step_for_frame",
361
- frame=frame_that_triggered_collect_infos,
360
+ frame=frame_that_triggered_collect_infos.frame_id,
362
361
  )
363
362
  return None
364
363
 
@@ -640,9 +639,9 @@ def clean_up_slot_command(
640
639
  resulting_commands.append(command)
641
640
  return resulting_commands
642
641
 
643
- if (slot := tracker.slots.get(command.name)) is not None and slot.value == str(
644
- command.value
645
- ):
642
+ if (slot := tracker.slots.get(command.name)) is not None and str(
643
+ slot.value
644
+ ) == str(command.value):
646
645
  # the slot is already set, we don't need to set it again
647
646
  structlogger.debug(
648
647
  "command_processor.clean_up_slot_command.skip_command_slot_already_set",
@@ -724,7 +723,7 @@ def clean_up_chitchat_command(
724
723
  )
725
724
  structlogger.warn(
726
725
  "command_processor.clean_up_chitchat_command.pattern_chitchat_not_found",
727
- command=resulting_commands[0],
726
+ command=resulting_commands[0], # no PII
728
727
  )
729
728
  return resulting_commands
730
729
 
@@ -742,7 +741,7 @@ def clean_up_chitchat_command(
742
741
  )
743
742
  structlogger.warn(
744
743
  "command_processor.clean_up_chitchat_command.replace_chitchat_answer_with_cannot_handle",
745
- command=resulting_commands[0],
744
+ command=resulting_commands[0], # no PII
746
745
  pattern_chitchat_uses_action_trigger_chitchat=has_action_trigger_chitchat,
747
746
  defined_intentless_policy_in_config=defines_intentless_policy,
748
747
  )
@@ -209,7 +209,9 @@ def get_collect_steps_excluding_ask_before_filling_for_active_flow(
209
209
  All collect steps that are part of the current active flow,
210
210
  excluding the collect steps that have to be asked before filling.
211
211
  """
212
- active_frame = top_user_flow_frame(dialogue_stack)
212
+ active_frame = top_user_flow_frame(
213
+ dialogue_stack, ignore_call_and_link_frames=False
214
+ )
213
215
  if active_frame is None:
214
216
  return set()
215
217
  active_flow = active_frame.flow(all_flows)
@@ -40,7 +40,7 @@ DEFAULT_GROUNDEDNESS_PROMPT_TEMPLATE_FILE_NAME = "groundedness_prompt_template.j
40
40
  DEFAULT_ANSWER_RELEVANCE_PROMPT_TEMPLATE_FILE_NAME = (
41
41
  "answer_relevance_prompt_template.jinja2"
42
42
  )
43
- DEFAULT_E2E_TESTING_MODEL = "gpt-4o-mini"
43
+ DEFAULT_E2E_TESTING_MODEL = "gpt-4.1-mini-2025-04-14"
44
44
  KEY_SCORE = "score"
45
45
  KEY_JUSTIFICATION = "justification"
46
46
  KEY_EXTRA_PARAMETERS = "extra_parameters"
@@ -21,7 +21,7 @@ from rasa.shared.core.flows.flow_path import FlowPath, FlowPathsList, PathNode
21
21
  FLOW_NAME_COL_NAME = "Flow Name"
22
22
  NUM_STEPS_COL_NAME = "Num Steps"
23
23
  MISSING_STEPS_COL_NAME = "Missing Steps"
24
- LINE_NUMBERS_COL_NAME = "Line Numbers"
24
+ LINE_NUMBERS_COL_NAME = "Line Numbers for Missing Steps"
25
25
  COVERAGE_COL_NAME = "Coverage"
26
26
 
27
27
  FLOWS_KEY = "flows"
rasa/engine/graph.py CHANGED
@@ -500,9 +500,9 @@ class GraphNode:
500
500
  structlogger.warning(
501
501
  "graph.node.input_not_resolved",
502
502
  node_name=self._node_name,
503
- input_name=i,
503
+ input_name=i, # no PII
504
504
  event_info=(
505
- "Node input was not resolved, there is no putput. "
505
+ "Node input was not resolved, there is no output. "
506
506
  "Another component should have provided this as an output."
507
507
  ),
508
508
  )
@@ -22,11 +22,7 @@ from rasa.shared.constants import (
22
22
  from rasa.shared.exceptions import ProviderClientAPIException
23
23
  from rasa.shared.providers.mappings import OPENAI_PROVIDER
24
24
  from rasa.shared.utils.constants import LOG_COMPONENT_SOURCE_METHOD_INIT
25
- from rasa.shared.utils.llm import (
26
- USER,
27
- get_prompt_template,
28
- llm_factory,
29
- )
25
+ from rasa.shared.utils.llm import USER, get_prompt_template, llm_factory
30
26
 
31
27
  SEPARATOR = "\n\n"
32
28
  BACKUP_SEPARATOR = "\nUSER:"
@@ -39,7 +35,7 @@ DEFAULT_REPHRASING_PROMPT_TEMPLATE = importlib.resources.read_text(
39
35
 
40
36
  DEFAULT_LLM_CONFIG = {
41
37
  PROVIDER_CONFIG_KEY: OPENAI_PROVIDER,
42
- MODEL_CONFIG_KEY: "gpt-4o-mini",
38
+ MODEL_CONFIG_KEY: "gpt-4.1-mini-2025-04-14",
43
39
  TIMEOUT_CONFIG_KEY: 7,
44
40
  TEMPERATURE_CONFIG_KEY: 0.0,
45
41
  MAX_COMPLETION_TOKENS_CONFIG_KEY: 4096,
@@ -2,7 +2,8 @@ import os
2
2
  import shutil
3
3
  import subprocess
4
4
  from enum import Enum
5
- from typing import Dict, Optional
5
+ from pathlib import Path
6
+ from typing import Dict, Optional, Union
6
7
 
7
8
  import aiohttp
8
9
  import structlog
@@ -18,6 +19,7 @@ from rasa.model_manager.utils import (
18
19
  write_encoded_data_to_file,
19
20
  )
20
21
  from rasa.model_manager.warm_rasa_process import start_rasa_process
22
+ from rasa.studio.prompts import handle_prompts
21
23
 
22
24
  structlogger = structlog.get_logger()
23
25
 
@@ -121,11 +123,25 @@ def get_open_port() -> int:
121
123
 
122
124
 
123
125
  def write_encoded_config_data_to_files(
124
- encoded_configs: Dict[str, bytes], base_path: str
126
+ encoded_configs: Dict[str, Union[bytes, Dict[str, str]]], base_path: str
125
127
  ) -> None:
126
128
  """Write the encoded config data to files."""
127
- for key, value in encoded_configs.items():
128
- write_encoded_data_to_file(value, subpath(base_path, f"{key}.yml"))
129
+ endpoints_encoded = encoded_configs.get("endpoints")
130
+ if endpoints_encoded:
131
+ write_encoded_data_to_file(
132
+ endpoints_encoded, subpath(base_path, "endpoints.yml")
133
+ )
134
+ config_encoded = encoded_configs.get("config")
135
+ if config_encoded:
136
+ write_encoded_data_to_file(config_encoded, subpath(base_path, "config.yml"))
137
+ credentials_encoded = encoded_configs.get("credentials")
138
+ if credentials_encoded:
139
+ write_encoded_data_to_file(
140
+ credentials_encoded, subpath(base_path, "credentials.yml")
141
+ )
142
+
143
+ if prompts := encoded_configs.get("prompts"):
144
+ handle_prompts(prompts, Path(base_path))
129
145
 
130
146
 
131
147
  def prepare_bot_directory(
@@ -2,6 +2,7 @@ import os
2
2
  import shutil
3
3
  import subprocess
4
4
  from enum import Enum
5
+ from pathlib import Path
5
6
  from typing import Any, Dict, Optional
6
7
 
7
8
  import structlog
@@ -20,6 +21,7 @@ from rasa.model_manager.warm_rasa_process import (
20
21
  start_rasa_process,
21
22
  )
22
23
  from rasa.model_training import generate_random_model_name
24
+ from rasa.studio.prompts import handle_prompts
23
25
 
24
26
  structlogger = structlog.get_logger()
25
27
 
@@ -208,6 +210,7 @@ def write_training_data_to_files(
208
210
  "stories": "base64 encoded stories.yml",
209
211
  "rules": "base64 encoded rules.yml",
210
212
  "nlu": "base64 encoded nlu.yml"
213
+ "prompts": "dictionary with the prompts",
211
214
  }
212
215
  ```
213
216
  """
@@ -230,6 +233,9 @@ def write_training_data_to_files(
230
233
  subpath(training_base_path + "/" + parent_path, file_name),
231
234
  )
232
235
 
236
+ if prompts := encoded_training_data.get("prompts"):
237
+ handle_prompts(prompts, Path(training_base_path))
238
+
233
239
 
234
240
  def prepare_training_directory(
235
241
  training_base_path: str, assistant_id: str, encoded_training_data: Dict[str, Any]
@@ -12,7 +12,7 @@ import structlog
12
12
  from apscheduler.schedulers.background import BackgroundScheduler
13
13
 
14
14
  import rasa.shared.core.trackers
15
- from rasa.core.tracker_stores.tracker_store import TrackerStore
15
+ from rasa.core.tracker_stores.tracker_store import FailSafeTrackerStore, TrackerStore
16
16
  from rasa.privacy.constants import (
17
17
  TEXT_KEY,
18
18
  USER_CHAT_INACTIVITY_IN_MINUTES_ENV_VAR_NAME,
@@ -63,6 +63,7 @@ class BackgroundPrivacyManager:
63
63
  self,
64
64
  endpoints: Optional["AvailableEndpoints"],
65
65
  event_loop: Optional["AbstractEventLoop"] = None,
66
+ in_memory_tracker_store: Optional[TrackerStore] = None,
66
67
  ):
67
68
  self.config = (
68
69
  PrivacyConfig.from_dict(endpoints.privacy)
@@ -76,15 +77,28 @@ class BackgroundPrivacyManager:
76
77
  os.getenv(USER_CHAT_INACTIVITY_IN_MINUTES_ENV_VAR_NAME, 30)
77
78
  )
78
79
 
79
- # we recreate the tracker store here to ensure
80
- # that this instance has no event brokers
81
- # that could publish events during the tracker store
82
- # background jobs
83
- self.tracker_store = (
84
- TrackerStore.create(endpoints.tracker_store)
85
- if endpoints
86
- else TrackerStore.create(None)
87
- )
80
+ if in_memory_tracker_store is not None:
81
+ # if an in-memory tracker store is provided,
82
+ # we need to keep the reference to it
83
+ # so that the background jobs can access it.
84
+ # We also set the event broker to None
85
+ # to prevent it from publishing events
86
+ # during the tracker store background jobs
87
+ in_memory_tracker_store.event_broker = None
88
+ tracker_store = in_memory_tracker_store
89
+ else:
90
+ # we recreate the tracker store here to ensure
91
+ # that this instance has no event brokers
92
+ # that could publish events during the tracker store
93
+ # background jobs
94
+ tracker_store = (
95
+ TrackerStore.create(endpoints.tracker_store)
96
+ if endpoints
97
+ else TrackerStore.create(None)
98
+ )
99
+
100
+ self.tracker_store = FailSafeTrackerStore(tracker_store)
101
+
88
102
  self.event_brokers: List["EventBroker"] = []
89
103
  self.event_loop = event_loop
90
104
 
@@ -124,9 +138,10 @@ class BackgroundPrivacyManager:
124
138
  cls,
125
139
  endpoints: Optional["AvailableEndpoints"],
126
140
  event_loop: Optional["AbstractEventLoop"] = None,
141
+ in_memory_tracker_store: Optional[TrackerStore] = None,
127
142
  ) -> BackgroundPrivacyManager:
128
143
  """Create an instance of BackgroundPrivacyManager."""
129
- instance = cls(endpoints, event_loop)
144
+ instance = cls(endpoints, event_loop, in_memory_tracker_store)
130
145
  return await instance.initialize(endpoints)
131
146
 
132
147
  def stop(self) -> None: