rasa-pro 3.13.7__py3-none-any.whl → 3.14.0.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rasa-pro might be problematic. Click here for more details.
- rasa/agents/__init__.py +0 -0
- rasa/agents/agent_factory.py +122 -0
- rasa/agents/agent_manager.py +162 -0
- rasa/agents/constants.py +31 -0
- rasa/agents/core/__init__.py +0 -0
- rasa/agents/core/agent_protocol.py +108 -0
- rasa/agents/core/types.py +70 -0
- rasa/agents/exceptions.py +8 -0
- rasa/agents/protocol/__init__.py +5 -0
- rasa/agents/protocol/a2a/__init__.py +0 -0
- rasa/agents/protocol/a2a/a2a_agent.py +51 -0
- rasa/agents/protocol/mcp/__init__.py +0 -0
- rasa/agents/protocol/mcp/mcp_base_agent.py +697 -0
- rasa/agents/protocol/mcp/mcp_open_agent.py +275 -0
- rasa/agents/protocol/mcp/mcp_task_agent.py +447 -0
- rasa/agents/schemas/__init__.py +6 -0
- rasa/agents/schemas/agent_input.py +24 -0
- rasa/agents/schemas/agent_output.py +26 -0
- rasa/agents/schemas/agent_tool_result.py +51 -0
- rasa/agents/schemas/agent_tool_schema.py +112 -0
- rasa/agents/templates/__init__.py +0 -0
- rasa/agents/templates/mcp_open_agent_prompt_template.jinja2 +15 -0
- rasa/agents/templates/mcp_task_agent_prompt_template.jinja2 +13 -0
- rasa/agents/utils.py +72 -0
- rasa/api.py +5 -0
- rasa/cli/arguments/default_arguments.py +12 -0
- rasa/cli/arguments/run.py +2 -0
- rasa/cli/dialogue_understanding_test.py +4 -0
- rasa/cli/e2e_test.py +4 -0
- rasa/cli/inspect.py +3 -0
- rasa/cli/llm_fine_tuning.py +5 -0
- rasa/cli/run.py +4 -0
- rasa/cli/shell.py +3 -0
- rasa/cli/train.py +2 -2
- rasa/constants.py +6 -0
- rasa/core/actions/action.py +69 -39
- rasa/core/actions/action_run_slot_rejections.py +1 -1
- rasa/core/agent.py +16 -0
- rasa/core/available_agents.py +196 -0
- rasa/core/available_endpoints.py +30 -0
- rasa/core/channels/development_inspector.py +47 -14
- rasa/core/channels/inspector/dist/assets/{arc-0b11fe30.js → arc-2e78c586.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-9eef30a7.js → blockDiagram-38ab4fdb-806b712e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-03e94f28.js → c4Diagram-3d4e48cf-0745efa9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/channel-c436ca7c.js +1 -0
- rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-95c09eba.js → classDiagram-70f12bd4-7bd1082b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-38e8446c.js → classDiagram-v2-f2320105-d937ba49.js} +1 -1
- rasa/core/channels/inspector/dist/assets/clone-50dd656b.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-57dc3038.js → createText-2e5e7dd3-a2a564ca.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-4bac0545.js → edges-e0da2a9e-b5256940.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-81795c90.js → erDiagram-9861fffd-e6883ad2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-89489ae6.js → flowDb-956e92f1-e576fc02.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-cd152627.js → flowDiagram-66a62f08-2e298d01.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-2b2aeaf8.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-3da369bc.js → flowchart-elk-definition-4a651766-dd7b150a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-85ec16f8.js → ganttDiagram-c361ad54-5b79575c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-495bc140.js → gitGraphDiagram-72cf32ee-3016f40a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-1ec4d266.js → graph-3e19170f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/index-1bd9135e.js +1353 -0
- rasa/core/channels/inspector/dist/assets/{index-3862675e-0a0e97c9.js → index-3862675e-eb9c86de.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-4d54bcde.js → infoDiagram-f8f76790-b4280e4d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-dc097114.js → journeyDiagram-49397b02-556091f8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-1a08981e.js → layout-08436411.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-95f7f1d3.js → line-683c4f3b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-97e69543.js → linear-cee6d791.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-8c71ff03.js → mindmap-definition-fc14e90a-a0bf0b1a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-f14c71c7.js → pieDiagram-8a3498a8-3730d5c4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-f1d3c9ff.js → quadrantDiagram-120e2f19-12a20fed.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-bfa2412f.js → requirementDiagram-deff3bca-b9732102.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-53f2c97b.js → sankeyDiagram-04a897e0-a2e72776.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-319d7c0e.js → sequenceDiagram-704730f1-8b7a76bb.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-76a09418.js → stateDiagram-587899a1-e65853ac.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-a67f15d4.js → stateDiagram-v2-d93cdb3a-6f58a44b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-0654e7c3.js → styles-6aaf32cf-df25b934.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-1394bb9d.js → styles-9a916d00-88357141.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-e4c5bdae.js → styles-c10674c1-d600174d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-50957104.js → svgDrawCommon-08f97a94-4adc3e0b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-b0885a6a.js → timeline-definition-85554ec2-42816fa1.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-79e6541a.js → xychartDiagram-e933f94c-621eb66a.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +2 -2
- rasa/core/channels/inspector/index.html +1 -1
- rasa/core/channels/inspector/src/App.tsx +53 -7
- rasa/core/channels/inspector/src/components/Chat.tsx +3 -2
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +1 -1
- rasa/core/channels/inspector/src/components/DialogueStack.tsx +7 -5
- rasa/core/channels/inspector/src/components/LatencyDisplay.tsx +268 -0
- rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +6 -2
- rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +8 -3
- rasa/core/channels/inspector/src/helpers/formatters.ts +24 -3
- rasa/core/channels/inspector/src/theme/base/styles.ts +19 -1
- rasa/core/channels/inspector/src/types.ts +12 -0
- rasa/core/channels/studio_chat.py +125 -34
- rasa/core/channels/voice_ready/twilio_voice.py +1 -1
- rasa/core/channels/voice_stream/audiocodes.py +9 -6
- rasa/core/channels/voice_stream/browser_audio.py +39 -4
- rasa/core/channels/voice_stream/call_state.py +13 -2
- rasa/core/channels/voice_stream/genesys.py +16 -13
- rasa/core/channels/voice_stream/jambonz.py +13 -11
- rasa/core/channels/voice_stream/twilio_media_streams.py +14 -13
- rasa/core/channels/voice_stream/util.py +11 -1
- rasa/core/channels/voice_stream/voice_channel.py +101 -29
- rasa/core/constants.py +4 -0
- rasa/core/nlg/contextual_response_rephraser.py +11 -7
- rasa/core/nlg/generator.py +21 -5
- rasa/core/nlg/response.py +43 -6
- rasa/core/nlg/translate.py +8 -0
- rasa/core/policies/enterprise_search_policy.py +4 -2
- rasa/core/policies/flow_policy.py +2 -2
- rasa/core/policies/flows/flow_executor.py +374 -35
- rasa/core/policies/flows/mcp_tool_executor.py +240 -0
- rasa/core/processor.py +6 -1
- rasa/core/run.py +8 -1
- rasa/core/utils.py +21 -1
- rasa/dialogue_understanding/commands/__init__.py +8 -0
- rasa/dialogue_understanding/commands/cancel_flow_command.py +97 -4
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +11 -0
- rasa/dialogue_understanding/commands/continue_agent_command.py +91 -0
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +11 -0
- rasa/dialogue_understanding/commands/restart_agent_command.py +146 -0
- rasa/dialogue_understanding/commands/start_flow_command.py +129 -8
- rasa/dialogue_understanding/commands/utils.py +6 -2
- rasa/dialogue_understanding/generator/command_parser.py +4 -0
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +50 -12
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +61 -0
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +61 -0
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +81 -0
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +81 -0
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +7 -6
- rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +7 -6
- rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +41 -2
- rasa/dialogue_understanding/patterns/continue_interrupted.py +163 -1
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +51 -7
- rasa/dialogue_understanding/stack/dialogue_stack.py +123 -2
- rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +57 -0
- rasa/dialogue_understanding/stack/utils.py +3 -2
- rasa/dialogue_understanding_test/du_test_runner.py +7 -2
- rasa/dialogue_understanding_test/du_test_schema.yml +3 -3
- rasa/e2e_test/e2e_test_runner.py +5 -0
- rasa/e2e_test/e2e_test_schema.yml +3 -3
- rasa/model_manager/model_api.py +1 -1
- rasa/model_manager/socket_bridge.py +8 -2
- rasa/server.py +10 -0
- rasa/shared/agents/__init__.py +0 -0
- rasa/shared/agents/utils.py +35 -0
- rasa/shared/constants.py +5 -0
- rasa/shared/core/constants.py +12 -1
- rasa/shared/core/domain.py +5 -5
- rasa/shared/core/events.py +319 -0
- rasa/shared/core/flows/flows_list.py +2 -2
- rasa/shared/core/flows/flows_yaml_schema.json +101 -186
- rasa/shared/core/flows/steps/call.py +51 -5
- rasa/shared/core/flows/validation.py +45 -7
- rasa/shared/core/flows/yaml_flows_io.py +3 -3
- rasa/shared/providers/llm/_base_litellm_client.py +39 -7
- rasa/shared/providers/llm/litellm_router_llm_client.py +8 -4
- rasa/shared/providers/llm/llm_client.py +7 -3
- rasa/shared/providers/llm/llm_response.py +49 -0
- rasa/shared/providers/llm/self_hosted_llm_client.py +8 -4
- rasa/shared/utils/common.py +2 -1
- rasa/shared/utils/llm.py +28 -5
- rasa/shared/utils/mcp/__init__.py +0 -0
- rasa/shared/utils/mcp/server_connection.py +157 -0
- rasa/shared/utils/schemas/events.py +42 -0
- rasa/studio/upload.py +4 -7
- rasa/tracing/instrumentation/instrumentation.py +4 -2
- rasa/utils/common.py +53 -0
- rasa/utils/licensing.py +21 -10
- rasa/utils/plotting.py +1 -1
- rasa/version.py +1 -1
- {rasa_pro-3.13.7.dist-info → rasa_pro-3.14.0.dev1.dist-info}/METADATA +16 -15
- {rasa_pro-3.13.7.dist-info → rasa_pro-3.14.0.dev1.dist-info}/RECORD +174 -137
- rasa/core/channels/inspector/dist/assets/channel-51d02e9e.js +0 -1
- rasa/core/channels/inspector/dist/assets/clone-cc738fa6.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-0c716443.js +0 -1
- rasa/core/channels/inspector/dist/assets/index-c804b295.js +0 -1335
- {rasa_pro-3.13.7.dist-info → rasa_pro-3.14.0.dev1.dist-info}/NOTICE +0 -0
- {rasa_pro-3.13.7.dist-info → rasa_pro-3.14.0.dev1.dist-info}/WHEEL +0 -0
- {rasa_pro-3.13.7.dist-info → rasa_pro-3.14.0.dev1.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Any, Dict, List, Optional
|
|
6
|
+
|
|
7
|
+
from rasa.dialogue_understanding.commands.command import Command
|
|
8
|
+
from rasa.dialogue_understanding.commands.command_syntax_manager import (
|
|
9
|
+
CommandSyntaxManager,
|
|
10
|
+
CommandSyntaxVersion,
|
|
11
|
+
)
|
|
12
|
+
from rasa.dialogue_understanding.stack.dialogue_stack import DialogueStack
|
|
13
|
+
from rasa.dialogue_understanding.stack.frames.flow_stack_frame import (
|
|
14
|
+
AgentStackFrame,
|
|
15
|
+
AgentState,
|
|
16
|
+
)
|
|
17
|
+
from rasa.shared.core.events import AgentStarted, Event
|
|
18
|
+
from rasa.shared.core.flows import FlowsList
|
|
19
|
+
from rasa.shared.core.trackers import DialogueStateTracker
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class RestartAgentCommand(Command):
|
|
24
|
+
"""A command to restart an agentic loop within a flow."""
|
|
25
|
+
|
|
26
|
+
agent_id: str
|
|
27
|
+
|
|
28
|
+
@classmethod
|
|
29
|
+
def command(cls) -> str:
|
|
30
|
+
"""Returns the command type."""
|
|
31
|
+
return "restart agent"
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def from_dict(cls, data: Dict[str, Any]) -> RestartAgentCommand:
|
|
35
|
+
"""Converts the dictionary to a command.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
The converted dictionary.
|
|
39
|
+
"""
|
|
40
|
+
try:
|
|
41
|
+
return RestartAgentCommand(agent_id=data["agent_id"])
|
|
42
|
+
except KeyError as e:
|
|
43
|
+
raise ValueError(
|
|
44
|
+
f"Missing parameter '{e}' while parsing RestartAgentCommand."
|
|
45
|
+
) from e
|
|
46
|
+
|
|
47
|
+
def run_command_on_tracker(
|
|
48
|
+
self,
|
|
49
|
+
tracker: DialogueStateTracker,
|
|
50
|
+
all_flows: FlowsList,
|
|
51
|
+
original_tracker: DialogueStateTracker,
|
|
52
|
+
) -> List[Event]:
|
|
53
|
+
"""Runs the command on the tracker.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
tracker: The tracker to run the command on.
|
|
57
|
+
all_flows: All flows in the assistant.
|
|
58
|
+
original_tracker: The tracker before any command was executed.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
The events to apply to the tracker.
|
|
62
|
+
"""
|
|
63
|
+
stack = tracker.stack
|
|
64
|
+
|
|
65
|
+
# get the agent flow
|
|
66
|
+
agent_flow_id = self._get_agent_flow(original_tracker)
|
|
67
|
+
|
|
68
|
+
# create a new agent stack frame to restart the agent
|
|
69
|
+
restart_agent_frame = self.create_restart_agent_stack_frame(agent_flow_id)
|
|
70
|
+
|
|
71
|
+
# if the stack contains an agent stack frame with status
|
|
72
|
+
# "waiting for input" update the status to "interrupted"
|
|
73
|
+
self.update_agent_stack_frames_on_stack(stack)
|
|
74
|
+
|
|
75
|
+
# push the stack frame on the top of the stack
|
|
76
|
+
stack.push(restart_agent_frame)
|
|
77
|
+
return tracker.create_stack_updated_events(stack)
|
|
78
|
+
|
|
79
|
+
def __hash__(self) -> int:
|
|
80
|
+
return hash(self.command())
|
|
81
|
+
|
|
82
|
+
def __eq__(self, other: object) -> bool:
|
|
83
|
+
return isinstance(other, RestartAgentCommand)
|
|
84
|
+
|
|
85
|
+
def to_dsl(self) -> str:
|
|
86
|
+
"""Converts the command to a DSL string."""
|
|
87
|
+
mapper = {
|
|
88
|
+
CommandSyntaxVersion.v1: f"RestartAgent({self.agent_id})",
|
|
89
|
+
CommandSyntaxVersion.v2: f"restart agent {self.agent_id}",
|
|
90
|
+
CommandSyntaxVersion.v3: f"restart agent {self.agent_id}",
|
|
91
|
+
}
|
|
92
|
+
return mapper.get(
|
|
93
|
+
CommandSyntaxManager.get_syntax_version(),
|
|
94
|
+
mapper[CommandSyntaxManager.get_default_syntax_version()],
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
@classmethod
|
|
98
|
+
def from_dsl(cls, match: re.Match, **kwargs: Any) -> RestartAgentCommand:
|
|
99
|
+
"""Converts a DSL string to a command."""
|
|
100
|
+
return RestartAgentCommand(agent_id=str(match.group(1).strip()))
|
|
101
|
+
|
|
102
|
+
@staticmethod
|
|
103
|
+
def regex_pattern() -> str:
|
|
104
|
+
mapper = {
|
|
105
|
+
CommandSyntaxVersion.v1: r"RestartAgent\(['\"]?([a-zA-Z0-9_-]+)['\"]?\)",
|
|
106
|
+
CommandSyntaxVersion.v2: (
|
|
107
|
+
r"""^[\s\W\d]*restart agent ['"`]?([a-zA-Z0-9_-]+)['"`]*"""
|
|
108
|
+
),
|
|
109
|
+
CommandSyntaxVersion.v3: (
|
|
110
|
+
r"""^[\s\W\d]*restart agent ['"`]?([a-zA-Z0-9_-]+)['"`]*"""
|
|
111
|
+
),
|
|
112
|
+
}
|
|
113
|
+
return mapper.get(
|
|
114
|
+
CommandSyntaxManager.get_syntax_version(),
|
|
115
|
+
mapper[CommandSyntaxManager.get_default_syntax_version()],
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
def create_restart_agent_stack_frame(self, agent_flow_id: str) -> AgentStackFrame:
|
|
119
|
+
# Create a new AgentStackFrame for restarting the agent
|
|
120
|
+
return AgentStackFrame(
|
|
121
|
+
frame_id=f"restart_agent_{self.agent_id}",
|
|
122
|
+
flow_id=agent_flow_id,
|
|
123
|
+
step_id=f"call_{self.agent_id}",
|
|
124
|
+
agent_id=self.agent_id,
|
|
125
|
+
state=AgentState.WAITING_FOR_INPUT,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
def update_agent_stack_frames_on_stack(self, stack: DialogueStack) -> None:
|
|
129
|
+
for frame in stack.frames:
|
|
130
|
+
if (
|
|
131
|
+
isinstance(frame, AgentStackFrame)
|
|
132
|
+
and frame.state == AgentState.WAITING_FOR_INPUT
|
|
133
|
+
):
|
|
134
|
+
frame.state = AgentState.INTERRUPTED
|
|
135
|
+
|
|
136
|
+
def _get_agent_flow(self, tracker: DialogueStateTracker) -> Optional[str]:
|
|
137
|
+
# find events associated with the agent
|
|
138
|
+
agent_started_events = [
|
|
139
|
+
event
|
|
140
|
+
for event in tracker.events
|
|
141
|
+
if type(event) == AgentStarted and event.agent_id == self.agent_id
|
|
142
|
+
]
|
|
143
|
+
# take the last one if the agent was started multiple times
|
|
144
|
+
if agent_started_events:
|
|
145
|
+
return agent_started_events[-1].flow_id
|
|
146
|
+
return None
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
-
from typing import Any, Dict, List, Optional
|
|
5
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
6
6
|
|
|
7
7
|
import structlog
|
|
8
8
|
|
|
@@ -11,7 +11,13 @@ from rasa.dialogue_understanding.commands.command_syntax_manager import (
|
|
|
11
11
|
CommandSyntaxManager,
|
|
12
12
|
CommandSyntaxVersion,
|
|
13
13
|
)
|
|
14
|
+
from rasa.dialogue_understanding.stack.dialogue_stack import DialogueStack
|
|
15
|
+
from rasa.dialogue_understanding.stack.frames.dialogue_stack_frame import (
|
|
16
|
+
DialogueStackFrame,
|
|
17
|
+
)
|
|
14
18
|
from rasa.dialogue_understanding.stack.frames.flow_stack_frame import (
|
|
19
|
+
AgentStackFrame,
|
|
20
|
+
AgentState,
|
|
15
21
|
FlowStackFrameType,
|
|
16
22
|
UserFlowStackFrame,
|
|
17
23
|
)
|
|
@@ -19,7 +25,13 @@ from rasa.dialogue_understanding.stack.utils import (
|
|
|
19
25
|
top_user_flow_frame,
|
|
20
26
|
user_flows_on_the_stack,
|
|
21
27
|
)
|
|
22
|
-
from rasa.shared.core.events import
|
|
28
|
+
from rasa.shared.core.events import (
|
|
29
|
+
AgentInterrupted,
|
|
30
|
+
AgentResumed,
|
|
31
|
+
Event,
|
|
32
|
+
FlowInterrupted,
|
|
33
|
+
FlowResumed,
|
|
34
|
+
)
|
|
23
35
|
from rasa.shared.core.flows import FlowsList
|
|
24
36
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
25
37
|
|
|
@@ -71,12 +83,7 @@ class StartFlowCommand(Command):
|
|
|
71
83
|
original_stack = original_tracker.stack
|
|
72
84
|
applied_events: List[Event] = []
|
|
73
85
|
|
|
74
|
-
if self.flow in
|
|
75
|
-
structlogger.debug(
|
|
76
|
-
"start_flow_command.skip_command.already_started_flow", command=self
|
|
77
|
-
)
|
|
78
|
-
return []
|
|
79
|
-
elif self.flow not in all_flows.flow_ids:
|
|
86
|
+
if self.flow not in all_flows.flow_ids:
|
|
80
87
|
structlogger.debug(
|
|
81
88
|
"start_flow_command.skip_command.start_invalid_flow_id", command=self
|
|
82
89
|
)
|
|
@@ -87,9 +94,23 @@ class StartFlowCommand(Command):
|
|
|
87
94
|
original_user_frame.flow(all_flows) if original_user_frame else None
|
|
88
95
|
)
|
|
89
96
|
|
|
97
|
+
# if the original top flow is the same as the flow to start, the flow is
|
|
98
|
+
# already active, do nothing
|
|
99
|
+
if original_top_flow is not None and original_top_flow.id == self.flow:
|
|
100
|
+
return []
|
|
101
|
+
|
|
102
|
+
# if the flow is already on the stack, resume it
|
|
103
|
+
if (
|
|
104
|
+
self.flow in user_flows_on_the_stack(stack)
|
|
105
|
+
and original_user_frame is not None
|
|
106
|
+
):
|
|
107
|
+
return self.resume_flow(tracker, stack, original_user_frame)
|
|
108
|
+
|
|
90
109
|
frame_type = FlowStackFrameType.REGULAR
|
|
91
110
|
|
|
92
111
|
if original_top_flow:
|
|
112
|
+
# if the original top flow is not the same as the flow to start,
|
|
113
|
+
# interrupt the current active flow
|
|
93
114
|
frame_type = FlowStackFrameType.INTERRUPT
|
|
94
115
|
|
|
95
116
|
if original_user_frame is not None:
|
|
@@ -99,6 +120,24 @@ class StartFlowCommand(Command):
|
|
|
99
120
|
)
|
|
100
121
|
)
|
|
101
122
|
|
|
123
|
+
# If there is an active agent frame, interrupt it
|
|
124
|
+
active_agent_stack_frame = stack.find_active_agent_frame()
|
|
125
|
+
if active_agent_stack_frame:
|
|
126
|
+
structlogger.debug(
|
|
127
|
+
"start_flow_command.interrupt_agent",
|
|
128
|
+
command=self,
|
|
129
|
+
agent_id=active_agent_stack_frame.agent_id,
|
|
130
|
+
frame_id=active_agent_stack_frame.frame_id,
|
|
131
|
+
flow_id=active_agent_stack_frame.flow_id,
|
|
132
|
+
)
|
|
133
|
+
active_agent_stack_frame.state = AgentState.INTERRUPTED
|
|
134
|
+
applied_events.append(
|
|
135
|
+
AgentInterrupted(
|
|
136
|
+
active_agent_stack_frame.agent_id,
|
|
137
|
+
active_agent_stack_frame.flow_id,
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
|
|
102
141
|
structlogger.debug("start_flow_command.start_flow", command=self)
|
|
103
142
|
stack.push(UserFlowStackFrame(flow_id=self.flow, frame_type=frame_type))
|
|
104
143
|
return applied_events + tracker.create_stack_updated_events(stack)
|
|
@@ -144,3 +183,85 @@ class StartFlowCommand(Command):
|
|
|
144
183
|
CommandSyntaxManager.get_syntax_version(),
|
|
145
184
|
mapper[CommandSyntaxManager.get_default_syntax_version()],
|
|
146
185
|
)
|
|
186
|
+
|
|
187
|
+
def resume_flow(
|
|
188
|
+
self,
|
|
189
|
+
tracker: DialogueStateTracker,
|
|
190
|
+
stack: DialogueStack,
|
|
191
|
+
original_user_frame: UserFlowStackFrame,
|
|
192
|
+
) -> List[Event]:
|
|
193
|
+
"""Resumes a flow by reordering frames."""
|
|
194
|
+
applied_events: List[Event] = []
|
|
195
|
+
|
|
196
|
+
# Resume existing flow by reordering frames
|
|
197
|
+
frames_to_resume, user_frame_to_resume = self._collect_frames_to_resume(
|
|
198
|
+
stack, self.flow
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
# if the flow is not on the stack, do nothing
|
|
202
|
+
# this should not happen, but just in case
|
|
203
|
+
if user_frame_to_resume is None:
|
|
204
|
+
structlogger.error(
|
|
205
|
+
"start_flow_command.resume_flow.no_user_frame_to_resume",
|
|
206
|
+
command=self,
|
|
207
|
+
)
|
|
208
|
+
return []
|
|
209
|
+
|
|
210
|
+
# move the frames to the top of the stack, e.g. reorder the frames
|
|
211
|
+
# on the stack
|
|
212
|
+
stack.move_frames_to_top(frames_to_resume)
|
|
213
|
+
agent_stack_frame = next(
|
|
214
|
+
(frame for frame in frames_to_resume if isinstance(frame, AgentStackFrame)),
|
|
215
|
+
None,
|
|
216
|
+
)
|
|
217
|
+
if agent_stack_frame:
|
|
218
|
+
agent_id = agent_stack_frame.agent_id
|
|
219
|
+
applied_events.append(AgentResumed(agent_id, agent_stack_frame.flow_id))
|
|
220
|
+
|
|
221
|
+
# Create flow interruption and resumption events
|
|
222
|
+
applied_events.extend(
|
|
223
|
+
[
|
|
224
|
+
# the current active flow is interrupted
|
|
225
|
+
FlowInterrupted(
|
|
226
|
+
original_user_frame.flow_id, original_user_frame.step_id
|
|
227
|
+
),
|
|
228
|
+
# the flow, which was on the stack, is resumed
|
|
229
|
+
FlowResumed(user_frame_to_resume.flow_id, user_frame_to_resume.step_id),
|
|
230
|
+
]
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
return applied_events + tracker.create_stack_updated_events(stack)
|
|
234
|
+
|
|
235
|
+
def _collect_frames_to_resume(
|
|
236
|
+
self, stack: DialogueStack, target_flow_id: str
|
|
237
|
+
) -> Tuple[List[DialogueStackFrame], Optional[UserFlowStackFrame]]:
|
|
238
|
+
"""Collect frames that need to be resumed for the target flow.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
stack: The stack to collect frames from.
|
|
242
|
+
target_flow_id: The ID of the flow to resume.
|
|
243
|
+
|
|
244
|
+
Returns:
|
|
245
|
+
A tuple containing (frames_to_resume, frame_to_resume).
|
|
246
|
+
"""
|
|
247
|
+
frames_to_resume: List[DialogueStackFrame] = []
|
|
248
|
+
frame_found = False
|
|
249
|
+
frame_to_resume = None
|
|
250
|
+
|
|
251
|
+
for frame in stack.frames:
|
|
252
|
+
if isinstance(frame, UserFlowStackFrame) and (
|
|
253
|
+
frame.frame_type == FlowStackFrameType.REGULAR
|
|
254
|
+
or frame.frame_type == FlowStackFrameType.INTERRUPT
|
|
255
|
+
):
|
|
256
|
+
if frame.flow_id == target_flow_id:
|
|
257
|
+
frames_to_resume.append(frame)
|
|
258
|
+
frame_to_resume = frame
|
|
259
|
+
frame_found = True
|
|
260
|
+
continue
|
|
261
|
+
elif frame_found:
|
|
262
|
+
break
|
|
263
|
+
|
|
264
|
+
if frame_found:
|
|
265
|
+
frames_to_resume.append(frame)
|
|
266
|
+
|
|
267
|
+
return list(frames_to_resume), frame_to_resume
|
|
@@ -6,7 +6,10 @@ from rasa.dialogue_understanding.patterns.validate_slot import (
|
|
|
6
6
|
ValidateSlotPatternFlowStackFrame,
|
|
7
7
|
)
|
|
8
8
|
from rasa.shared.constants import ACTION_ASK_PREFIX, UTTER_ASK_PREFIX
|
|
9
|
-
from rasa.shared.core.events import
|
|
9
|
+
from rasa.shared.core.events import (
|
|
10
|
+
Event,
|
|
11
|
+
SlotSet,
|
|
12
|
+
)
|
|
10
13
|
from rasa.shared.core.flows import FlowsList
|
|
11
14
|
from rasa.shared.core.slots import Slot
|
|
12
15
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
@@ -103,7 +106,8 @@ def create_validate_frames_from_slot_set_events(
|
|
|
103
106
|
Args:
|
|
104
107
|
tracker: The dialogue state tracker.
|
|
105
108
|
events: List of events to process.
|
|
106
|
-
|
|
109
|
+
validate_frames: List to collect validation frames.
|
|
110
|
+
should_break: whether to break after the first non-SlotSet event.
|
|
107
111
|
if True, break out of the event loop as soon as the first non-SlotSet
|
|
108
112
|
event is encountered.
|
|
109
113
|
if False, continue processing the events until the end.
|
|
@@ -9,9 +9,11 @@ from rasa.dialogue_understanding.commands import (
|
|
|
9
9
|
ChitChatAnswerCommand,
|
|
10
10
|
ClarifyCommand,
|
|
11
11
|
Command,
|
|
12
|
+
ContinueAgentCommand,
|
|
12
13
|
HumanHandoffCommand,
|
|
13
14
|
KnowledgeAnswerCommand,
|
|
14
15
|
RepeatBotMessagesCommand,
|
|
16
|
+
RestartAgentCommand,
|
|
15
17
|
SetSlotCommand,
|
|
16
18
|
SkipQuestionCommand,
|
|
17
19
|
StartFlowCommand,
|
|
@@ -34,6 +36,8 @@ DEFAULT_COMMANDS = [
|
|
|
34
36
|
HumanHandoffCommand,
|
|
35
37
|
ClarifyCommand,
|
|
36
38
|
RepeatBotMessagesCommand,
|
|
39
|
+
ContinueAgentCommand,
|
|
40
|
+
RestartAgentCommand,
|
|
37
41
|
]
|
|
38
42
|
|
|
39
43
|
|
|
@@ -7,6 +7,7 @@ from jinja2 import Environment, Template, select_autoescape
|
|
|
7
7
|
|
|
8
8
|
import rasa.dialogue_understanding.generator.utils
|
|
9
9
|
import rasa.shared.utils.io
|
|
10
|
+
from rasa.core.available_agents import AvailableAgents
|
|
10
11
|
from rasa.dialogue_understanding.commands import (
|
|
11
12
|
Command,
|
|
12
13
|
SetSlotCommand,
|
|
@@ -31,6 +32,7 @@ from rasa.engine.storage.resource import Resource
|
|
|
31
32
|
from rasa.engine.storage.storage import ModelStorage
|
|
32
33
|
from rasa.shared.core.constants import SetSlotExtractor
|
|
33
34
|
from rasa.shared.core.domain import Domain
|
|
35
|
+
from rasa.shared.core.events import AgentStarted
|
|
34
36
|
from rasa.shared.core.flows import Flow, FlowsList, FlowStep
|
|
35
37
|
from rasa.shared.core.flows.steps.collect import CollectInformationFlowStep
|
|
36
38
|
from rasa.shared.core.slot_mappings import SlotFillingManager
|
|
@@ -225,8 +227,7 @@ class LLMBasedCommandGenerator(
|
|
|
225
227
|
|
|
226
228
|
@lru_cache
|
|
227
229
|
def compile_template(self, template: str) -> Template:
|
|
228
|
-
"""
|
|
229
|
-
Compile the prompt template and register custom filters.
|
|
230
|
+
"""Compile the prompt template and register custom filters.
|
|
230
231
|
|
|
231
232
|
Compiling the template is an expensive operation,
|
|
232
233
|
so we cache the result.
|
|
@@ -361,20 +362,24 @@ class LLMBasedCommandGenerator(
|
|
|
361
362
|
)
|
|
362
363
|
|
|
363
364
|
def prepare_flows_for_template(
|
|
364
|
-
self,
|
|
365
|
+
self,
|
|
366
|
+
flows: FlowsList,
|
|
367
|
+
tracker: DialogueStateTracker,
|
|
368
|
+
add_agent_info: bool = False,
|
|
365
369
|
) -> List[Dict[str, Any]]:
|
|
366
370
|
"""Format data on available flows for insertion into the prompt template.
|
|
367
371
|
|
|
368
372
|
Args:
|
|
369
373
|
flows: The flows available to the user.
|
|
370
374
|
tracker: The tracker containing the current state of the conversation.
|
|
375
|
+
add_agent_info: Whether to add agent info to flows or not.
|
|
371
376
|
|
|
372
377
|
Returns:
|
|
373
378
|
The inputs for the prompt template.
|
|
374
379
|
"""
|
|
375
|
-
result = []
|
|
380
|
+
result: List[Dict[str, Any]] = []
|
|
376
381
|
for flow in flows.user_flows:
|
|
377
|
-
slots_with_info = [
|
|
382
|
+
slots_with_info: List[Dict[str, Any]] = [
|
|
378
383
|
{
|
|
379
384
|
"name": q.collect,
|
|
380
385
|
"description": q.description,
|
|
@@ -383,13 +388,46 @@ class LLMBasedCommandGenerator(
|
|
|
383
388
|
for q in flow.get_collect_steps()
|
|
384
389
|
if self.is_extractable(q, tracker)
|
|
385
390
|
]
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
391
|
+
|
|
392
|
+
agent_info: List[Dict[str, Any]] = []
|
|
393
|
+
if add_agent_info:
|
|
394
|
+
# add information about agents that have been started for this flow
|
|
395
|
+
agent_events = [
|
|
396
|
+
event
|
|
397
|
+
for event in tracker.events
|
|
398
|
+
if isinstance(event, AgentStarted) and event.flow_id == flow.id
|
|
399
|
+
]
|
|
400
|
+
available_agents = [
|
|
401
|
+
AvailableAgents.get_agent_config(event.agent_id)
|
|
402
|
+
for event in agent_events
|
|
403
|
+
]
|
|
404
|
+
if available_agents:
|
|
405
|
+
agent_info = [
|
|
406
|
+
{
|
|
407
|
+
"name": available_agent.agent.name,
|
|
408
|
+
"description": available_agent.agent.description,
|
|
409
|
+
}
|
|
410
|
+
for available_agent in available_agents
|
|
411
|
+
if available_agent is not None
|
|
412
|
+
]
|
|
413
|
+
|
|
414
|
+
if agent_info:
|
|
415
|
+
result.append(
|
|
416
|
+
{
|
|
417
|
+
"name": flow.id,
|
|
418
|
+
"description": flow.description,
|
|
419
|
+
"slots": slots_with_info,
|
|
420
|
+
"agent_info": agent_info,
|
|
421
|
+
}
|
|
422
|
+
)
|
|
423
|
+
else:
|
|
424
|
+
result.append(
|
|
425
|
+
{
|
|
426
|
+
"name": flow.id,
|
|
427
|
+
"description": flow.description,
|
|
428
|
+
"slots": slots_with_info,
|
|
429
|
+
}
|
|
430
|
+
)
|
|
393
431
|
return result
|
|
394
432
|
|
|
395
433
|
@staticmethod
|
|
@@ -0,0 +1,61 @@
|
|
|
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 small talk and knowledge requests.
|
|
3
|
+
|
|
4
|
+
--
|
|
5
|
+
|
|
6
|
+
## Available Actions:
|
|
7
|
+
* `start flow flow_name`: Starting a flow. For example, `start flow transfer_money` or `start flow list_contacts`.
|
|
8
|
+
* `set slot slot_name slot_value`: Slot setting. For example, `set slot transfer_money_recipient Freddy`. Can be used to correct and change previously set values.
|
|
9
|
+
* `cancel flow`: Cancelling the current flow.
|
|
10
|
+
* `disambiguate flows flow_name1 flow_name2 ... flow_name_n`: Disambiguate which flow should be started when user input is ambiguous by listing the potential flows as options. For example, `disambiguate flows list_contacts add_contact remove_contact ...` if the user just wrote "contacts".
|
|
11
|
+
* `provide info`: Responding to the user's questions by supplying relevant information, such as answering FAQs or explaining services.
|
|
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
|
+
* `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.
|
|
15
|
+
{% if active_agent %} * `continue agent`: Continue the currently active agent {{ active_agent.name }}.{% endif %}
|
|
16
|
+
{% if completed_agents %}* `restart agent agent_name`: Restart the agent with the given name, in case the user wants to change some answer to a previous question asked by the agent. For example, `restart agent car_research_agent` if the user chnaged his mind about the car he wants to buy.{% endif %}
|
|
17
|
+
|
|
18
|
+
--
|
|
19
|
+
|
|
20
|
+
## General Tips
|
|
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 response. Map positive responses to `True`, and negative to `False`.
|
|
24
|
+
* Always refer to the slot description to determine what information should be extracted and how it should be formatted.
|
|
25
|
+
* For text slots, extract values exactly as provided by the user unless the slot description specifies otherwise. Preserve formatting and avoid rewording, truncation, or making assumptions.
|
|
26
|
+
* Only use information provided by the user.
|
|
27
|
+
* Use clarification in ambiguous cases.
|
|
28
|
+
* Multiple flows can be started. If a user wants to digress into a second flow, you do not need to cancel the current flow.
|
|
29
|
+
* Do not cancel the flow unless the user explicitly requests it.
|
|
30
|
+
* Strictly adhere to the provided action format.
|
|
31
|
+
* Focus on the last message and take it one step at a time.
|
|
32
|
+
* Use the previous conversation steps only to aid understanding.
|
|
33
|
+
|
|
34
|
+
--
|
|
35
|
+
|
|
36
|
+
## Available Flows and Slots
|
|
37
|
+
Use the following structured data:
|
|
38
|
+
```json
|
|
39
|
+
{"flows":[{% for flow in available_flows %}{"name":"{{ flow.name }}","description":{{ flow.description | to_json_escaped_string }}{% if flow.agent_info %},"sub-agents":[{% for agent in flow.agent_info %}{"name":"{{ agent.name }}","description":{{ agent.description | to_json_escaped_string }}}{% if not loop.last %},{% endif %}{% endfor %}]{% endif %}{% 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 %}]}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
--
|
|
43
|
+
|
|
44
|
+
## Current State
|
|
45
|
+
{% if current_flow != None %}Use the following structured data:
|
|
46
|
+
```json
|
|
47
|
+
{"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 or slot.allowed_values else "" }}{% if slot.description %}"description": {{ slot.description | to_json_escaped_string }}{{ "," if slot.allowed_values else "" }}{% endif %}{% if slot.allowed_values %}"allowed_values": "{{ slot.allowed_values }}"{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]{% if active_agent or completed_agents %},{% endif %}{% if active_agent %}"active_agent": {"name": "{{ active_agent.name }}","description": "{{ active_agent.description }}"}{% if completed_agents %},{% endif %}{% endif %}{% if completed_agents %}"completed_agents": [{% for agent in completed_agents %}{"name": "{{ agent.name }}","description": "{{ agent.description }}"}{% if not loop.last %},{% endif %}{% endfor %}]{% endif %}}
|
|
48
|
+
```{% else %}
|
|
49
|
+
You are currently not inside any flow.{% endif %}
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Conversation History
|
|
54
|
+
{{ current_conversation }}
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Task
|
|
59
|
+
Create an action list with one action per line in response to the user's last message: """{{ user_message }}""".
|
|
60
|
+
|
|
61
|
+
Your action list:
|
|
@@ -0,0 +1,61 @@
|
|
|
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 small talk and knowledge requests.
|
|
3
|
+
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Available Flows and Slots
|
|
7
|
+
Use the following structured data:
|
|
8
|
+
```json
|
|
9
|
+
{"flows":[{% for flow in available_flows %}{"name":"{{ flow.name }}","description":{{ flow.description | to_json_escaped_string }}{% if flow.agent_info %},"sub-agents":[{% for agent in flow.agent_info %}{"name":"{{ agent.name }}","description":{{ agent.description | to_json_escaped_string }}}{% if not loop.last %},{% endif %}{% endfor %}]{% endif %}{% 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 %}]}
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Available Actions:
|
|
15
|
+
* `start flow flow_name`: Starting a flow. For example, `start flow transfer_money` or `start flow list_contacts`.
|
|
16
|
+
* `set slot slot_name slot_value`: Slot setting. For example, `set slot transfer_money_recipient Freddy`. Can be used to correct and change previously set values.
|
|
17
|
+
* `cancel flow`: Cancelling the current flow.
|
|
18
|
+
* `disambiguate flows flow_name1 flow_name2 ... flow_name_n`: Disambiguate which flow should be started when user input is ambiguous by listing the potential flows as options. For example, `disambiguate flows list_contacts add_contact remove_contact ...` if the user just wrote "contacts".
|
|
19
|
+
* `provide info`: Responding to the user's questions by supplying relevant information, such as answering FAQs or explaining services.
|
|
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
|
+
* `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.
|
|
23
|
+
{% if active_agent %} * `continue agent`: Continue the currently active agent {{ active_agent.name }}.{% endif %}
|
|
24
|
+
{% if completed_agents %}* `restart agent agent_name`: Restart the agent with the given name, in case the user wants to change some answer to a previous question asked by the agent. For example, `restart agent car_research_agent` if the user chnaged his mind about the car he wants to buy.{% endif %}
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## General Tips
|
|
29
|
+
* Do not fill slots with abstract values or placeholders.
|
|
30
|
+
* For categorical slots try to match the user message with allowed slot values. Use "other" if you cannot match it.
|
|
31
|
+
* Set the boolean slots based on the user response. Map positive responses to `True`, and negative to `False`.
|
|
32
|
+
* Extract text slot values exactly as provided by the user. Avoid assumptions, format changes, or partial extractions.
|
|
33
|
+
* Only use information provided by the user.
|
|
34
|
+
* Use clarification in ambiguous cases.
|
|
35
|
+
* Multiple flows can be started. If a user wants to digress into a second flow, you do not need to cancel the current flow.
|
|
36
|
+
* Do not cancel the flow unless the user explicitly requests it.
|
|
37
|
+
* Strictly adhere to the provided action format.
|
|
38
|
+
* Focus on the last message and take it one step at a time.
|
|
39
|
+
* Use the previous conversation steps only to aid understanding.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Current State
|
|
44
|
+
{% if current_flow != None %}
|
|
45
|
+
Use the following structured data:
|
|
46
|
+
```json
|
|
47
|
+
{"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 or slot.allowed_values else "" }}{% if slot.description %}"description": {{ slot.description | to_json_escaped_string }}{{ "," if slot.allowed_values else "" }}{% endif %}{% if slot.allowed_values %}"allowed_values": "{{ slot.allowed_values }}"{% endif %}}{% if not loop.last %},{% endif %}{% endfor %}]{% if active_agent or completed_agents %},{% endif %}{% if active_agent %}"active_agent": {"name": "{{ active_agent.name }}","description": "{{ active_agent.description }}"}{% if completed_agents %},{% endif %}{% endif %}{% if completed_agents %}"completed_agents": [{% for agent in completed_agents %}{"name": "{{ agent.name }}","description": "{{ agent.description }}"}{% if not loop.last %},{% endif %}{% endfor %}]{% endif %}}
|
|
48
|
+
```{% else %}
|
|
49
|
+
You are currently not inside any flow.{% endif %}
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Conversation History
|
|
54
|
+
{{ current_conversation }}
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Task
|
|
59
|
+
Create an action list with one action per line in response to the user's last message: """{{ user_message }}""".
|
|
60
|
+
|
|
61
|
+
Your action list:
|