rasa-pro 3.14.0a14__py3-none-any.whl → 3.14.0a16__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/builder/config.py +1 -0
- rasa/builder/copilot/constants.py +3 -0
- rasa/builder/copilot/copilot.py +127 -31
- rasa/builder/copilot/models.py +34 -0
- rasa/builder/copilot/prompts/copilot_system_prompt.jinja2 +28 -84
- rasa/builder/copilot/prompts/latest_user_message_context_prompt.jinja2 +61 -0
- rasa/builder/copilot/telemetry.py +16 -6
- rasa/builder/document_retrieval/models.py +3 -3
- rasa/builder/main.py +13 -0
- rasa/builder/project_generator.py +1 -3
- rasa/builder/service.py +8 -9
- rasa/builder/template_cache.py +183 -9
- rasa/cli/project_templates/telco/data/general/human_handoff.yml +1 -1
- rasa/cli/project_templates/telco/domain/general/human_handoff.yml +3 -6
- rasa/cli/project_templates/telco/tests/e2e_test_cases/billing/understand_bill.yml +67 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/bot_challenge.yml +8 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/feedback.yml +46 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/goodbye.yml +9 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/hello.yml +8 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/human_handoff.yml +35 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/patterns.yml +23 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/network/solve_internet_issue.yml +57 -0
- rasa/core/channels/development_inspector.py +1 -21
- rasa/core/channels/hangouts.py +2 -2
- rasa/core/channels/inspector/dist/assets/{arc-c24d8d79.js → arc-460861ce.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-1b6b9f26.js → blockDiagram-38ab4fdb-16c993e0.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-da91d0f9.js → c4Diagram-3d4e48cf-488337d7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/channel-b560a3d4.js +1 -0
- rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-6067f302.js → classDiagram-70f12bd4-b08e53a8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-705d024a.js → classDiagram-v2-f2320105-b73f5a83.js} +1 -1
- rasa/core/channels/inspector/dist/assets/clone-67015557.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-3751dffe.js → createText-2e5e7dd3-0210a219.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-7b25b4af.js → edges-e0da2a9e-28df7099.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-eb7deea8.js → erDiagram-9861fffd-9fbf4a58.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-67235ff6.js → flowDb-956e92f1-fa691f62.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-34c3a16a.js → flowDiagram-66a62f08-ca907b67.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-4a070961.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-f1a93631.js → flowchart-elk-definition-4a651766-c10945f2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-a68cbad1.js → ganttDiagram-c361ad54-9d49a75a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-0b1e4a1d.js → gitGraphDiagram-72cf32ee-9aa698ac.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-f3c1d212.js → graph-3ab38d50.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3862675e-34cbca30.js → index-3862675e-6edac98f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-051c5a6e.js → index-61128091.js} +41 -40
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-e69960a1.js → infoDiagram-f8f76790-21baff85.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-8dd3296a.js → journeyDiagram-49397b02-4a6c7e98.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-e93126bc.js → layout-4beae36e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-15eb1e26.js → line-633b638e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-fec95d33.js → linear-22d77d65.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-2557813e.js → mindmap-definition-fc14e90a-f219ef43.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-40d756b1.js → pieDiagram-8a3498a8-c7e1cafb.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-a48cbdcd.js → quadrantDiagram-120e2f19-045e49b4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-dc778150.js → requirementDiagram-deff3bca-22485cb9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-10026b94.js → sankeyDiagram-04a897e0-281c3da2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-3b2ed10a.js → sequenceDiagram-704730f1-a3dd10e0.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-c5f3b3fb.js → stateDiagram-587899a1-61bd6eb2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-e503656b.js → stateDiagram-v2-d93cdb3a-deead491.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-a683ce56.js → styles-6aaf32cf-1b10e104.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-02bcdcee.js → styles-9a916d00-b1e18e58.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-8e90dbb9.js → styles-c10674c1-956c3492.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-7c23fc1e.js → svgDrawCommon-08f97a94-e13f753d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-c42faec8.js → timeline-definition-85554ec2-e568acd2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-5e3bb0ea.js → xychartDiagram-e933f94c-8b7e27fc.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +1 -1
- rasa/core/channels/inspector/src/App.tsx +0 -7
- rasa/core/channels/inspector/src/components/DialogueInformation.tsx +9 -1
- rasa/core/channels/inspector/src/components/LatencyDisplay.tsx +63 -35
- rasa/core/channels/inspector/src/types.ts +32 -7
- rasa/core/channels/studio_chat.py +14 -40
- rasa/core/constants.py +6 -0
- rasa/core/iam_credentials_providers/__init__.py +0 -0
- rasa/core/iam_credentials_providers/aws_iam_credentials_providers.py +66 -0
- rasa/core/iam_credentials_providers/credentials_provider_protocol.py +89 -0
- rasa/core/processor.py +32 -0
- rasa/core/redis_connection_factory.py +411 -0
- rasa/core/tracker_stores/redis_tracker_store.py +32 -14
- rasa/core/tracker_stores/sql_tracker_store.py +57 -1
- rasa/model_manager/socket_bridge.py +1 -2
- rasa/shared/core/constants.py +1 -0
- rasa/shared/core/events.py +2 -0
- rasa/version.py +1 -1
- {rasa_pro-3.14.0a14.dist-info → rasa_pro-3.14.0a16.dist-info}/METADATA +11 -12
- {rasa_pro-3.14.0a14.dist-info → rasa_pro-3.14.0a16.dist-info}/RECORD +90 -77
- rasa/core/channels/inspector/dist/assets/channel-d2444dfd.js +0 -1
- rasa/core/channels/inspector/dist/assets/clone-281a0990.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-aa4cca3b.js +0 -1
- /rasa/cli/project_templates/telco/domain/billing/{domain_undertand_bill.yml → understand_bill.yml} +0 -0
- /rasa/cli/project_templates/telco/domain/network/{domain_reboot_router.yml → reboot_router.yml} +0 -0
- /rasa/cli/project_templates/telco/domain/network/{domain_reset_router.yml → reset_router.yml} +0 -0
- /rasa/cli/project_templates/telco/domain/network/{domain_run_speed_test.yml → run_speed_test.yml} +0 -0
- /rasa/cli/project_templates/telco/domain/network/{domain_solve_internet_issue.yml → solve_internet_issue.yml} +0 -0
- {rasa_pro-3.14.0a14.dist-info → rasa_pro-3.14.0a16.dist-info}/NOTICE +0 -0
- {rasa_pro-3.14.0a14.dist-info → rasa_pro-3.14.0a16.dist-info}/WHEEL +0 -0
- {rasa_pro-3.14.0a14.dist-info → rasa_pro-3.14.0a16.dist-info}/entry_points.txt +0 -0
|
@@ -2,40 +2,47 @@ import {
|
|
|
2
2
|
Box,
|
|
3
3
|
Flex,
|
|
4
4
|
FlexProps,
|
|
5
|
-
Text,
|
|
6
|
-
useColorModeValue,
|
|
7
|
-
Tooltip,
|
|
8
5
|
Table,
|
|
9
6
|
Tbody,
|
|
10
|
-
Tr,
|
|
11
7
|
Td,
|
|
8
|
+
Text,
|
|
9
|
+
Tooltip,
|
|
10
|
+
Tr,
|
|
11
|
+
useColorModeValue,
|
|
12
12
|
} from '@chakra-ui/react'
|
|
13
13
|
import { useOurTheme } from '../theme'
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
isRasaLatency,
|
|
16
|
+
isVoiceLatency,
|
|
17
|
+
RasaLatency,
|
|
18
|
+
VoiceLatency,
|
|
19
|
+
} from '../types'
|
|
15
20
|
|
|
16
|
-
interface
|
|
17
|
-
latency:
|
|
21
|
+
interface MinimalDisplayProps extends FlexProps {
|
|
22
|
+
latency: RasaLatency
|
|
18
23
|
}
|
|
19
24
|
|
|
20
25
|
/**
|
|
21
26
|
* Simple latency display for text-only conversations.
|
|
22
27
|
* Shows a single response time value.
|
|
23
28
|
*/
|
|
24
|
-
const MinimalDisplay = ({ latency, sx, ...props }:
|
|
29
|
+
const MinimalDisplay = ({ latency, sx, ...props }: MinimalDisplayProps) => {
|
|
25
30
|
const containerSx = {
|
|
26
31
|
...sx,
|
|
27
32
|
display: 'flex',
|
|
28
33
|
alignItems: 'center',
|
|
29
34
|
}
|
|
30
|
-
|
|
35
|
+
|
|
31
36
|
const getLatencyColor = (latency: number) => {
|
|
32
37
|
if (latency < 1500) return 'green.500'
|
|
33
38
|
if (latency < 2500) return 'orange.500'
|
|
34
39
|
return 'red.500'
|
|
35
40
|
}
|
|
36
|
-
|
|
37
|
-
const value = Math.round(
|
|
38
|
-
|
|
41
|
+
|
|
42
|
+
const value = Math.round(
|
|
43
|
+
(latency.command_processor || 0) + (latency.prediction_loop || 0),
|
|
44
|
+
)
|
|
45
|
+
const color = getLatencyColor(value)
|
|
39
46
|
|
|
40
47
|
return (
|
|
41
48
|
<Flex sx={containerSx} {...props}>
|
|
@@ -49,11 +56,15 @@ const MinimalDisplay = ({ latency, sx, ...props }: Props) => {
|
|
|
49
56
|
)
|
|
50
57
|
}
|
|
51
58
|
|
|
59
|
+
interface WaterfallDisplayProps extends FlexProps {
|
|
60
|
+
latency: VoiceLatency
|
|
61
|
+
}
|
|
62
|
+
|
|
52
63
|
/**
|
|
53
64
|
* Detailed latency waterfall chart for voice conversations.
|
|
54
65
|
* Displays processing times for ASR, Rasa, and TTS components.
|
|
55
66
|
*/
|
|
56
|
-
const WaterfallDisplay = ({ latency, sx, ...props }:
|
|
67
|
+
const WaterfallDisplay = ({ latency, sx, ...props }: WaterfallDisplayProps) => {
|
|
57
68
|
const { rasaSpace } = useOurTheme()
|
|
58
69
|
|
|
59
70
|
const containerSx = {
|
|
@@ -61,13 +72,13 @@ const WaterfallDisplay = ({ latency, sx, ...props }: Props) => {
|
|
|
61
72
|
flexDirection: 'column',
|
|
62
73
|
gap: rasaSpace[1],
|
|
63
74
|
}
|
|
64
|
-
|
|
75
|
+
|
|
65
76
|
const headerSx = {
|
|
66
77
|
fontSize: 'sm',
|
|
67
78
|
fontWeight: 'bold',
|
|
68
79
|
color: useColorModeValue('gray.700', 'gray.300'),
|
|
69
80
|
}
|
|
70
|
-
|
|
81
|
+
|
|
71
82
|
const waterfallBarSx = {
|
|
72
83
|
height: '24px',
|
|
73
84
|
borderRadius: '4px',
|
|
@@ -75,10 +86,10 @@ const WaterfallDisplay = ({ latency, sx, ...props }: Props) => {
|
|
|
75
86
|
border: '1px solid',
|
|
76
87
|
borderColor: useColorModeValue('gray.200', 'gray.600'),
|
|
77
88
|
}
|
|
78
|
-
|
|
89
|
+
|
|
79
90
|
const legendTableSx = {
|
|
80
91
|
size: 'sm',
|
|
81
|
-
mt: rasaSpace[0.5]
|
|
92
|
+
mt: rasaSpace[0.5],
|
|
82
93
|
}
|
|
83
94
|
|
|
84
95
|
const getLatencyColor = (type: string) => {
|
|
@@ -95,8 +106,10 @@ const WaterfallDisplay = ({ latency, sx, ...props }: Props) => {
|
|
|
95
106
|
const descriptions: { [key: string]: string } = {
|
|
96
107
|
asr: 'Time from the first Partial Transcript event to the Final Transcript event from Speech Recognition. It also includes the time taken by the user to speak.',
|
|
97
108
|
rasa: 'Time taken by Rasa to process the text from the Final Transcript event from Speech Recognition until a text response is generated.',
|
|
98
|
-
tts_first:
|
|
99
|
-
|
|
109
|
+
tts_first:
|
|
110
|
+
'Time between the request sent to Text-to-Speech processing and the first byte of audio received by Rasa.',
|
|
111
|
+
tts_complete:
|
|
112
|
+
'Time taken by Text-to-Speech to complete audio generation. It depends on the length of the text and could overlap with the Bot speaking time.',
|
|
100
113
|
}
|
|
101
114
|
return descriptions[type] || ''
|
|
102
115
|
}
|
|
@@ -151,10 +164,10 @@ const WaterfallDisplay = ({ latency, sx, ...props }: Props) => {
|
|
|
151
164
|
)
|
|
152
165
|
|
|
153
166
|
// Calculate total latency for title (Rasa + TTS First Byte)
|
|
154
|
-
const totalDisplayLatency =
|
|
155
|
-
(latency.rasa_processing_latency_ms || 0) +
|
|
156
|
-
(latency.tts_first_byte_latency_ms || 0)
|
|
157
|
-
|
|
167
|
+
const totalDisplayLatency =
|
|
168
|
+
(latency.rasa_processing_latency_ms || 0) +
|
|
169
|
+
(latency.tts_first_byte_latency_ms || 0)
|
|
170
|
+
|
|
158
171
|
return (
|
|
159
172
|
<Flex sx={containerSx} {...props}>
|
|
160
173
|
<Text sx={headerSx}>
|
|
@@ -241,28 +254,43 @@ const WaterfallDisplay = ({ latency, sx, ...props }: Props) => {
|
|
|
241
254
|
)
|
|
242
255
|
}
|
|
243
256
|
|
|
257
|
+
interface LatencyDisplayProps extends FlexProps {
|
|
258
|
+
voiceLatency?: any
|
|
259
|
+
rasaLatency?: any
|
|
260
|
+
}
|
|
261
|
+
|
|
244
262
|
/**
|
|
245
263
|
* Displays processing latency information for the conversation.
|
|
246
|
-
* Shows either a detailed waterfall chart for voice conversations or
|
|
264
|
+
* Shows either a detailed waterfall chart for voice conversations or
|
|
247
265
|
* a simpler display for text-only conversations.
|
|
248
266
|
*/
|
|
249
267
|
export const LatencyDisplay = ({
|
|
250
268
|
sx,
|
|
251
|
-
|
|
269
|
+
voiceLatency,
|
|
270
|
+
rasaLatency,
|
|
252
271
|
...props
|
|
253
|
-
}:
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
return
|
|
272
|
+
}: LatencyDisplayProps) => {
|
|
273
|
+
// We give priority to voice latency as most comprehensive.
|
|
274
|
+
if (isVoiceLatency(voiceLatency)) {
|
|
275
|
+
return <WaterfallDisplay latency={voiceLatency} sx={sx} {...props} />
|
|
257
276
|
}
|
|
258
277
|
|
|
259
|
-
//
|
|
260
|
-
|
|
261
|
-
latency
|
|
278
|
+
// If voice latency is not available, we use rasa latency.
|
|
279
|
+
if (isRasaLatency(rasaLatency)) {
|
|
280
|
+
return <MinimalDisplay latency={rasaLatency} sx={sx} {...props} />
|
|
281
|
+
}
|
|
262
282
|
|
|
263
|
-
|
|
264
|
-
|
|
283
|
+
// If rasa latency is not available, we are either waiting for first data from voice stream or the conversation is not started yet.
|
|
284
|
+
if (!rasaLatency) {
|
|
285
|
+
return <Text>Rasa latency data is not available yet</Text>
|
|
265
286
|
}
|
|
266
287
|
|
|
267
|
-
|
|
288
|
+
// If rasa latency is available but did not pass type guard, we are in an unexpected state
|
|
289
|
+
// and we should log an error but gracefully fallback to showing no data.
|
|
290
|
+
console.warn(
|
|
291
|
+
`Latency data has unexpected format. Raw data of rasaLatency: ${rasaLatency},
|
|
292
|
+
raw data of voice latency: ${voiceLatency}`,
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
return <Text>Latency data is not available yet</Text>
|
|
268
296
|
}
|
|
@@ -17,7 +17,8 @@ export interface Event {
|
|
|
17
17
|
timestamp: string
|
|
18
18
|
update?: string
|
|
19
19
|
parse_data?: { commands: Command[] }
|
|
20
|
-
metadata?: { utter_action?: string }
|
|
20
|
+
metadata?: { utter_action?: string; execution_times?: RasaLatency }
|
|
21
|
+
name?: string
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
export interface Command {
|
|
@@ -42,11 +43,16 @@ export interface Stack {
|
|
|
42
43
|
ended: boolean
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
export interface
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
export interface RasaLatency {
|
|
47
|
+
command_processor: number
|
|
48
|
+
prediction_loop: number
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface VoiceLatency {
|
|
52
|
+
rasa_processing_latency_ms: number
|
|
53
|
+
asr_latency_ms: number
|
|
54
|
+
tts_first_byte_latency_ms: number
|
|
55
|
+
tts_complete_latency_ms: number
|
|
50
56
|
}
|
|
51
57
|
|
|
52
58
|
export interface Tracker {
|
|
@@ -54,7 +60,6 @@ export interface Tracker {
|
|
|
54
60
|
slots: { [key: string]: unknown }
|
|
55
61
|
events: Event[]
|
|
56
62
|
stack: Stack[]
|
|
57
|
-
latency?: LatencyData
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
export interface Flow {
|
|
@@ -96,3 +101,23 @@ interface Step {
|
|
|
96
101
|
utter: string
|
|
97
102
|
set_slots?: unknown
|
|
98
103
|
}
|
|
104
|
+
|
|
105
|
+
export function isRasaLatency(obj: any): obj is RasaLatency {
|
|
106
|
+
return (
|
|
107
|
+
obj !== null &&
|
|
108
|
+
typeof obj === 'object' &&
|
|
109
|
+
typeof obj.command_processor === 'number' &&
|
|
110
|
+
typeof obj.prediction_loop === 'number'
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function isVoiceLatency(obj: any): obj is VoiceLatency {
|
|
115
|
+
return (
|
|
116
|
+
obj !== null &&
|
|
117
|
+
typeof obj === 'object' &&
|
|
118
|
+
typeof obj.rasa_processing_latency_ms === 'number' &&
|
|
119
|
+
typeof obj.asr_latency_ms === 'number' &&
|
|
120
|
+
typeof obj.tts_first_byte_latency_ms === 'number' &&
|
|
121
|
+
typeof obj.tts_complete_latency_ms === 'number'
|
|
122
|
+
)
|
|
123
|
+
}
|
|
@@ -4,7 +4,6 @@ import asyncio
|
|
|
4
4
|
import audioop
|
|
5
5
|
import base64
|
|
6
6
|
import json
|
|
7
|
-
import time
|
|
8
7
|
import uuid
|
|
9
8
|
from functools import partial
|
|
10
9
|
from typing import (
|
|
@@ -53,9 +52,7 @@ if TYPE_CHECKING:
|
|
|
53
52
|
structlogger = structlog.get_logger()
|
|
54
53
|
|
|
55
54
|
|
|
56
|
-
def tracker_as_dump(
|
|
57
|
-
tracker: "DialogueStateTracker", latency: Optional[float] = None
|
|
58
|
-
) -> Dict[str, Any]:
|
|
55
|
+
def tracker_as_dump(tracker: "DialogueStateTracker") -> Dict[str, Any]:
|
|
59
56
|
"""Create a dump of the tracker state."""
|
|
60
57
|
from rasa.shared.core.trackers import get_trackers_for_conversation_sessions
|
|
61
58
|
|
|
@@ -66,13 +63,7 @@ def tracker_as_dump(
|
|
|
66
63
|
else:
|
|
67
64
|
last_tracker = multiple_tracker_sessions[-1]
|
|
68
65
|
|
|
69
|
-
# TODO: this is a bug: the bridge converts this back to json, but it
|
|
70
|
-
# should be json in the first place
|
|
71
66
|
state = last_tracker.current_state(EventVerbosity.AFTER_RESTART)
|
|
72
|
-
|
|
73
|
-
if latency is not None:
|
|
74
|
-
state["latency"] = {"rasa_processing_latency_ms": latency}
|
|
75
|
-
|
|
76
67
|
return state
|
|
77
68
|
|
|
78
69
|
|
|
@@ -227,32 +218,16 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
227
218
|
def _register_tracker_update_hook(self) -> None:
|
|
228
219
|
plugin_manager().register(StudioTrackerUpdatePlugin(self))
|
|
229
220
|
|
|
230
|
-
async def on_tracker_updated(
|
|
231
|
-
self, tracker: "DialogueStateTracker", latency: Optional[float] = None
|
|
232
|
-
) -> None:
|
|
221
|
+
async def on_tracker_updated(self, tracker: "DialogueStateTracker") -> None:
|
|
233
222
|
"""Triggers a tracker update notification after a change to the tracker."""
|
|
234
|
-
await self.publish_tracker_update(
|
|
235
|
-
tracker.sender_id, tracker_as_dump(tracker, latency)
|
|
236
|
-
)
|
|
223
|
+
await self.publish_tracker_update(tracker.sender_id, tracker_as_dump(tracker))
|
|
237
224
|
|
|
238
|
-
async def publish_tracker_update(
|
|
225
|
+
async def publish_tracker_update(
|
|
226
|
+
self, sender_id: str, tracker_dump: Dict[str, Any]
|
|
227
|
+
) -> None:
|
|
239
228
|
"""Publishes a tracker update notification to the websocket."""
|
|
240
229
|
await self.emit("tracker", tracker_dump, room=sender_id)
|
|
241
230
|
|
|
242
|
-
def _record_turn_start_time(self, sender_id: Text) -> None:
|
|
243
|
-
"""Records the start time of a new turn."""
|
|
244
|
-
self._turn_start_times[sender_id] = time.time()
|
|
245
|
-
|
|
246
|
-
def _get_latency(self, sender_id: Text) -> Optional[float]:
|
|
247
|
-
"""Returns the latency of the current turn in milliseconds."""
|
|
248
|
-
if sender_id not in self._turn_start_times:
|
|
249
|
-
return None
|
|
250
|
-
|
|
251
|
-
latency = (time.time() - self._turn_start_times[sender_id]) * 1000
|
|
252
|
-
# The turn is over, so we can remove the start time
|
|
253
|
-
del self._turn_start_times[sender_id]
|
|
254
|
-
return latency
|
|
255
|
-
|
|
256
231
|
async def on_message_proxy(
|
|
257
232
|
self,
|
|
258
233
|
on_new_message: Callable[[UserMessage], Awaitable[Any]],
|
|
@@ -262,7 +237,6 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
262
237
|
|
|
263
238
|
Triggers a tracker update notification after processing the message.
|
|
264
239
|
"""
|
|
265
|
-
self._record_turn_start_time(message.sender_id)
|
|
266
240
|
try:
|
|
267
241
|
await on_new_message(message)
|
|
268
242
|
except Exception as e:
|
|
@@ -288,8 +262,7 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
288
262
|
structlogger.error("studio_chat.on_message_proxy.tracker_not_found")
|
|
289
263
|
return
|
|
290
264
|
|
|
291
|
-
|
|
292
|
-
await self.on_tracker_updated(tracker, latency)
|
|
265
|
+
await self.on_tracker_updated(tracker)
|
|
293
266
|
|
|
294
267
|
async def emit_error(self, message: str, room: str, e: Exception) -> None:
|
|
295
268
|
await self.emit(
|
|
@@ -389,10 +362,10 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
389
362
|
call_state.is_bot_speaking = True
|
|
390
363
|
return ContinueConversationAction()
|
|
391
364
|
|
|
392
|
-
def
|
|
365
|
+
def create_output_channel(
|
|
393
366
|
self, voice_websocket: "Websocket", tts_engine: TTSEngine
|
|
394
367
|
) -> VoiceOutputChannel:
|
|
395
|
-
"""Create a voice output channel."""
|
|
368
|
+
"""Create a voice output channel. This is used by VoiceInputChannel."""
|
|
396
369
|
return StudioVoiceOutputChannel(
|
|
397
370
|
voice_websocket,
|
|
398
371
|
tts_engine,
|
|
@@ -469,8 +442,9 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
469
442
|
def blueprint(
|
|
470
443
|
self, on_new_message: Callable[[UserMessage], Awaitable[Any]]
|
|
471
444
|
) -> SocketBlueprint:
|
|
472
|
-
|
|
473
|
-
|
|
445
|
+
socket_blueprint = super().blueprint(
|
|
446
|
+
partial(self.on_message_proxy, on_new_message)
|
|
447
|
+
)
|
|
474
448
|
|
|
475
449
|
if not self.sio_server:
|
|
476
450
|
structlogger.error("studio_chat.blueprint.sio_not_initialized")
|
|
@@ -506,7 +480,7 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
506
480
|
|
|
507
481
|
# start a voice session if requested
|
|
508
482
|
if data and data.get("is_voice", False):
|
|
509
|
-
self._start_voice_session(data["session_id"], sid,
|
|
483
|
+
self._start_voice_session(data["session_id"], sid, on_new_message)
|
|
510
484
|
|
|
511
485
|
@self.sio_server.on(self.user_message_evt, namespace=self.namespace)
|
|
512
486
|
async def handle_message(sid: Text, data: Dict) -> None:
|
|
@@ -521,7 +495,7 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
521
495
|
|
|
522
496
|
try:
|
|
523
497
|
# Handle text messages
|
|
524
|
-
await self.handle_user_message(sid, data,
|
|
498
|
+
await self.handle_user_message(sid, data, on_new_message)
|
|
525
499
|
except Exception as e:
|
|
526
500
|
structlogger.exception(
|
|
527
501
|
"studio_chat.sio.handle_message.error",
|
rasa/core/constants.py
CHANGED
|
@@ -112,3 +112,9 @@ ACTIVE_FLOW_METADATA_KEY = "active_flow"
|
|
|
112
112
|
STEP_ID_METADATA_KEY = "step_id"
|
|
113
113
|
KEY_IS_CALM_SYSTEM = "is_calm_system"
|
|
114
114
|
KEY_IS_COEXISTENCE_ASSISTANT = "is_coexistence_assistant"
|
|
115
|
+
|
|
116
|
+
IAM_CLOUD_PROVIDER_ENV_VAR_NAME = "IAM_CLOUD_PROVIDER"
|
|
117
|
+
SQL_TRACKER_STORE_SSL_MODE_ENV_VAR_NAME = "SQL_TRACKER_STORE_SSL_MODE"
|
|
118
|
+
SQL_TRACKER_STORE_SSL_ROOT_CERTIFICATE_ENV_VAR_NAME = (
|
|
119
|
+
"SQL_TRACKER_STORE_SSL_ROOT_CERTIFICATE"
|
|
120
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
import boto3
|
|
4
|
+
import structlog
|
|
5
|
+
from botocore.exceptions import BotoCoreError
|
|
6
|
+
|
|
7
|
+
from rasa.core.iam_credentials_providers.credentials_provider_protocol import (
|
|
8
|
+
IAMCredentialsProvider,
|
|
9
|
+
IAMCredentialsProviderInput,
|
|
10
|
+
SupportedServiceType,
|
|
11
|
+
TemporaryCredentials,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
structlogger = structlog.get_logger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AWSRDSIAMCredentialsProvider(IAMCredentialsProvider):
|
|
18
|
+
"""Generates temporary credentials for AWS RDS using IAM roles."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, username: str, host: str, port: int):
|
|
21
|
+
"""Initializes the provider."""
|
|
22
|
+
self.username = username
|
|
23
|
+
self.host = host
|
|
24
|
+
self.port = port
|
|
25
|
+
|
|
26
|
+
def get_credentials(self) -> TemporaryCredentials:
|
|
27
|
+
"""Generates temporary credentials for AWS RDS."""
|
|
28
|
+
structlogger.debug(
|
|
29
|
+
"rasa.core.aws_rds_iam_credentials_provider.get_credentials",
|
|
30
|
+
event_info="IAM authentication for AWS RDS enabled. "
|
|
31
|
+
"Generating temporary auth token...",
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
client = boto3.client("rds")
|
|
36
|
+
auth_token = client.generate_db_auth_token(
|
|
37
|
+
DBHostname=self.host,
|
|
38
|
+
Port=self.port,
|
|
39
|
+
DBUsername=self.username,
|
|
40
|
+
)
|
|
41
|
+
structlogger.info(
|
|
42
|
+
"rasa.core.aws_rds_iam_credentials_provider.generated_credentials",
|
|
43
|
+
event_info="Successfully generated temporary auth token for AWS RDS.",
|
|
44
|
+
)
|
|
45
|
+
return TemporaryCredentials(auth_token=auth_token)
|
|
46
|
+
except (BotoCoreError, ValueError) as exc:
|
|
47
|
+
structlogger.error(
|
|
48
|
+
"rasa.core.aws_rds_iam_credentials_provider.error_generating_credentials",
|
|
49
|
+
event_info="Failed to generate temporary auth token for AWS RDS.",
|
|
50
|
+
error=str(exc),
|
|
51
|
+
)
|
|
52
|
+
return TemporaryCredentials(auth_token=None)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def create_aws_iam_credentials_provider(
|
|
56
|
+
provider_input: "IAMCredentialsProviderInput",
|
|
57
|
+
) -> Optional["IAMCredentialsProvider"]:
|
|
58
|
+
"""Factory function to create an AWS IAM credentials provider."""
|
|
59
|
+
if provider_input.service_name == SupportedServiceType.TRACKER_STORE:
|
|
60
|
+
return AWSRDSIAMCredentialsProvider(
|
|
61
|
+
username=provider_input.username,
|
|
62
|
+
host=provider_input.host,
|
|
63
|
+
port=provider_input.port,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
return None
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from typing import Optional, Protocol, runtime_checkable
|
|
6
|
+
|
|
7
|
+
import structlog
|
|
8
|
+
from pydantic import BaseModel
|
|
9
|
+
|
|
10
|
+
from rasa.core.constants import IAM_CLOUD_PROVIDER_ENV_VAR_NAME
|
|
11
|
+
|
|
12
|
+
structlogger = structlog.get_logger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TemporaryCredentials(BaseModel):
|
|
16
|
+
"""Dataclass storing temporary credentials."""
|
|
17
|
+
|
|
18
|
+
auth_token: Optional[str] = None
|
|
19
|
+
expiration: Optional[int] = None
|
|
20
|
+
username: Optional[str] = None
|
|
21
|
+
presigned_url: Optional[str] = None
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@runtime_checkable
|
|
25
|
+
class IAMCredentialsProvider(Protocol):
|
|
26
|
+
"""Interface for generating temporary credentials using IAM roles."""
|
|
27
|
+
|
|
28
|
+
def get_credentials(self) -> TemporaryCredentials:
|
|
29
|
+
"""Generates temporary credentials using IAM roles."""
|
|
30
|
+
...
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class IAMCredentialsProviderType(Enum):
|
|
34
|
+
"""Enum for supported IAM credentials provider types."""
|
|
35
|
+
|
|
36
|
+
AWS = "aws"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class SupportedServiceType(Enum):
|
|
40
|
+
"""Enum for supported services using IAM credentials providers."""
|
|
41
|
+
|
|
42
|
+
TRACKER_STORE = "tracker_store"
|
|
43
|
+
EVENT_BROKER = "event_broker"
|
|
44
|
+
LOCK_STORE = "lock_store"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class IAMCredentialsProviderInput(BaseModel):
|
|
48
|
+
"""Input data for creating an IAM credentials provider."""
|
|
49
|
+
|
|
50
|
+
service_name: SupportedServiceType
|
|
51
|
+
username: Optional[str] = None
|
|
52
|
+
host: Optional[str] = None
|
|
53
|
+
port: Optional[int] = None
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def create_iam_credentials_provider(
|
|
57
|
+
provider_input: IAMCredentialsProviderInput,
|
|
58
|
+
) -> Optional[IAMCredentialsProvider]:
|
|
59
|
+
"""Factory function to create an IAM credentials provider.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
provider_input: Input data for creating an IAM credentials provider.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
An instance of the specified IAM credentials provider or
|
|
66
|
+
None if the type is unsupported.
|
|
67
|
+
"""
|
|
68
|
+
iam_cloud_provider = os.getenv(IAM_CLOUD_PROVIDER_ENV_VAR_NAME)
|
|
69
|
+
|
|
70
|
+
if iam_cloud_provider is None:
|
|
71
|
+
return None
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
provider_type = IAMCredentialsProviderType(iam_cloud_provider.lower())
|
|
75
|
+
except ValueError:
|
|
76
|
+
structlogger.warning(
|
|
77
|
+
"rasa.core.iam_credentials_provider.create_iam_credentials_provider.unsupported_provider",
|
|
78
|
+
event_info=f"Unsupported IAM cloud provider: {iam_cloud_provider}",
|
|
79
|
+
)
|
|
80
|
+
return None
|
|
81
|
+
|
|
82
|
+
if provider_type == IAMCredentialsProviderType.AWS:
|
|
83
|
+
from rasa.core.iam_credentials_providers.aws_iam_credentials_providers import (
|
|
84
|
+
create_aws_iam_credentials_provider,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
return create_aws_iam_credentials_provider(provider_input)
|
|
88
|
+
|
|
89
|
+
return None
|
rasa/core/processor.py
CHANGED
|
@@ -72,6 +72,7 @@ from rasa.shared.core.constants import (
|
|
|
72
72
|
ACTION_CORRECT_FLOW_SLOT,
|
|
73
73
|
ACTION_EXTRACT_SLOTS,
|
|
74
74
|
ACTION_LISTEN_NAME,
|
|
75
|
+
ACTION_METADATA_EXECUTION_TIME,
|
|
75
76
|
ACTION_SESSION_START_NAME,
|
|
76
77
|
FOLLOWUP_ACTION,
|
|
77
78
|
SESSION_START_METADATA_SLOT,
|
|
@@ -207,6 +208,7 @@ class MessageProcessor:
|
|
|
207
208
|
) -> Optional[List[Dict[Text, Any]]]:
|
|
208
209
|
"""Handle a single message with this processor."""
|
|
209
210
|
# preprocess message if necessary
|
|
211
|
+
self.time_turn_start = time.time()
|
|
210
212
|
tracker = await self.log_message(message, should_save_tracker=False)
|
|
211
213
|
|
|
212
214
|
if self.model_metadata.training_type == TrainingType.NLU:
|
|
@@ -1154,6 +1156,7 @@ class MessageProcessor:
|
|
|
1154
1156
|
should_predict_another_action = True
|
|
1155
1157
|
|
|
1156
1158
|
tracker = await self.run_command_processor(tracker)
|
|
1159
|
+
self.time_command_processor = time.time()
|
|
1157
1160
|
|
|
1158
1161
|
# action loop. predicts actions until we hit action listen
|
|
1159
1162
|
while should_predict_another_action and self._should_handle_message(tracker):
|
|
@@ -1403,6 +1406,34 @@ class MessageProcessor:
|
|
|
1403
1406
|
plugin_manager().hook.after_action_executed(tracker=tracker)
|
|
1404
1407
|
return self.should_predict_another_action(action.name())
|
|
1405
1408
|
|
|
1409
|
+
def _add_metadata_if_action_listen(
|
|
1410
|
+
self, action: Action, prediction: PolicyPrediction
|
|
1411
|
+
) -> None:
|
|
1412
|
+
"""Adds execution times to the ActionExecuted event metadata."""
|
|
1413
|
+
if not hasattr(self, "time_turn_start"):
|
|
1414
|
+
return
|
|
1415
|
+
|
|
1416
|
+
if not hasattr(self, "time_command_processor"):
|
|
1417
|
+
return
|
|
1418
|
+
|
|
1419
|
+
if not action.name() == ACTION_LISTEN_NAME:
|
|
1420
|
+
return
|
|
1421
|
+
|
|
1422
|
+
if prediction.action_metadata is None:
|
|
1423
|
+
prediction.action_metadata = {}
|
|
1424
|
+
|
|
1425
|
+
# calculate execution times
|
|
1426
|
+
execution_time_prediction_loop = (
|
|
1427
|
+
time.time() - self.time_command_processor
|
|
1428
|
+
) * 1000
|
|
1429
|
+
execution_time_command_processor = (
|
|
1430
|
+
self.time_command_processor - self.time_turn_start
|
|
1431
|
+
) * 1000
|
|
1432
|
+
prediction.action_metadata[ACTION_METADATA_EXECUTION_TIME] = {
|
|
1433
|
+
"command_processor": execution_time_command_processor,
|
|
1434
|
+
"prediction_loop": execution_time_prediction_loop,
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1406
1437
|
def _log_action_and_events_on_tracker(
|
|
1407
1438
|
self,
|
|
1408
1439
|
tracker: DialogueStateTracker,
|
|
@@ -1448,6 +1479,7 @@ class MessageProcessor:
|
|
|
1448
1479
|
tracker.update_with_events(prediction.events)
|
|
1449
1480
|
|
|
1450
1481
|
# log the action and its produced events
|
|
1482
|
+
self._add_metadata_if_action_listen(action, prediction)
|
|
1451
1483
|
tracker.update(
|
|
1452
1484
|
action.event_for_successful_execution(
|
|
1453
1485
|
prediction, was_successful, error_message
|