17
17
import logging
18
18
import re
19
19
from ast import literal_eval
20
- from typing import Any , List , Optional
20
+ from typing import Any , List , Optional , Tuple
21
21
22
22
from langchain .llms import BaseLLM
23
23
@@ -140,30 +140,9 @@ async def _init_flows_index(self) -> None:
140
140
if self .instruction_flows_index is None :
141
141
self .instruction_flows_index = self .flows_index
142
142
143
- @action (name = "GetLastUserMessageAction" , is_system_action = True )
144
- async def get_last_user_message (
145
- self , events : List [dict ], llm : Optional [BaseLLM ] = None
146
- ) -> str :
147
- event = get_last_user_utterance_event_v2_x (events )
148
- assert event and event ["type" ] == "UtteranceUserActionFinished"
149
- return event ["final_transcript" ]
150
-
151
- @action (name = "GenerateUserIntentAction" , is_system_action = True , execute_async = True )
152
- async def generate_user_intent (
153
- self ,
154
- state : State ,
155
- events : List [dict ],
156
- user_action : str ,
157
- max_example_flows : int = 5 ,
158
- llm : Optional [BaseLLM ] = None ,
159
- ) -> str :
160
- """Generate the canonical form for what the user said i.e. user intent."""
161
-
162
- # Use action specific llm if registered else fallback to main llm
163
- llm = llm or self .llm
164
-
165
- log .info ("Phase 1 :: Generating user intent" )
166
-
143
+ async def _collect_user_intent_and_examples (
144
+ self , state : State , user_action : str , max_example_flows : int
145
+ ) -> Tuple [List [str ], str ]:
167
146
# We search for the most relevant similar user intents
168
147
examples = ""
169
148
potential_user_intents = []
@@ -182,25 +161,68 @@ async def generate_user_intent(
182
161
heads = find_all_active_event_matchers (state )
183
162
for head in heads :
184
163
element = get_element_from_head (state , head )
185
- event = get_event_from_element (
186
- state , state .flow_states [head .flow_state_uid ], element
187
- )
164
+ flow_state = state .flow_states [head .flow_state_uid ]
165
+ event = get_event_from_element (state , flow_state , element )
188
166
if (
189
167
event .name == InternalEvents .FLOW_FINISHED
190
168
and "flow_id" in event .arguments
191
169
):
192
170
flow_id = event .arguments ["flow_id" ]
171
+ if not isinstance (flow_id , str ):
172
+ continue
173
+
193
174
flow_config = state .flow_configs .get (flow_id , None )
194
- if isinstance (flow_id , str ) and (
195
- flow_config is None
175
+ element_flow_state_instance = state .flow_id_states [flow_id ]
176
+ if flow_config is not None and (
177
+ flow_config .has_meta_tag ("user_intent" )
196
178
or (
197
- flow_config . has_meta_tag ( "user_intent" )
198
- and flow_id not in potential_user_intents
179
+ element_flow_state_instance
180
+ and "_user_intent" in element_flow_state_instance [ 0 ]. context
199
181
)
200
182
):
201
- examples += f"user intent: { flow_id } \n \n "
202
- potential_user_intents .append (flow_id )
183
+ if flow_config .elements [1 ]["_type" ] == "doc_string_stmt" :
184
+ examples += "user action: <" + (
185
+ flow_config .elements [1 ]["elements" ][0 ]["elements" ][0 ][
186
+ "elements"
187
+ ][0 ][3 :- 3 ]
188
+ + ">\n "
189
+ )
190
+ examples += f"user intent: { flow_id } \n \n "
191
+ elif flow_id not in potential_user_intents :
192
+ examples += f"user intent: { flow_id } \n \n "
193
+ potential_user_intents .append (flow_id )
203
194
examples = examples .strip ("\n " )
195
+ return (potential_user_intents , examples )
196
+
197
+ @action (name = "GetLastUserMessageAction" , is_system_action = True )
198
+ async def get_last_user_message (
199
+ self , events : List [dict ], llm : Optional [BaseLLM ] = None
200
+ ) -> str :
201
+ event = get_last_user_utterance_event_v2_x (events )
202
+ assert event and event ["type" ] == "UtteranceUserActionFinished"
203
+ return event ["final_transcript" ]
204
+
205
+ @action (name = "GenerateUserIntentAction" , is_system_action = True , execute_async = True )
206
+ async def generate_user_intent (
207
+ self ,
208
+ state : State ,
209
+ events : List [dict ],
210
+ user_action : str ,
211
+ max_example_flows : int = 5 ,
212
+ llm : Optional [BaseLLM ] = None ,
213
+ ) -> str :
214
+ """Generate the canonical form for what the user said i.e. user intent."""
215
+
216
+ # Use action specific llm if registered else fallback to main llm
217
+ llm = llm or self .llm
218
+
219
+ log .info ("Phase 1 :: Generating user intent" )
220
+ (
221
+ potential_user_intents ,
222
+ examples ,
223
+ ) = await self ._collect_user_intent_and_examples (
224
+ state , user_action , max_example_flows
225
+ )
204
226
205
227
prompt = self .llm_task_manager .render_task_prompt (
206
228
task = Task .GENERATE_USER_INTENT_FROM_USER_ACTION ,
@@ -257,43 +279,12 @@ async def generate_user_intent_and_bot_action(
257
279
258
280
log .info ("Phase 1 :: Generating user intent and bot action" )
259
281
260
- # We search for the most relevant similar user intents
261
- examples = ""
262
- potential_user_intents = []
263
-
264
- if self .user_message_index :
265
- results = await self .user_message_index .search (
266
- text = user_action , max_results = max_example_flows
267
- )
268
-
269
- # We add these in reverse order so the most relevant is towards the end.
270
- for result in reversed (results ):
271
- examples += f"user action: user said \" { result .text } \" \n user intent: { result .meta ['intent' ]} \n \n "
272
- potential_user_intents .append (result .meta ["intent" ])
273
-
274
- # We add all currently active user intents (heads on match statements)
275
- heads = find_all_active_event_matchers (state )
276
- for head in heads :
277
- element = get_element_from_head (state , head )
278
- event = get_event_from_element (
279
- state , state .flow_states [head .flow_state_uid ], element
280
- )
281
- if (
282
- event .name == InternalEvents .FLOW_FINISHED
283
- and "flow_id" in event .arguments
284
- ):
285
- flow_id = event .arguments ["flow_id" ]
286
- flow_config = state .flow_configs .get (flow_id , None )
287
- if isinstance (flow_id , str ) and (
288
- flow_config is None
289
- or (
290
- flow_config .has_meta_tag ("user_intent" )
291
- and flow_id not in potential_user_intents
292
- )
293
- ):
294
- examples += f"user intent: { flow_id } \n \n "
295
- potential_user_intents .append (flow_id )
296
- examples = examples .strip ("\n " )
282
+ (
283
+ potential_user_intents ,
284
+ examples ,
285
+ ) = await self ._collect_user_intent_and_examples (
286
+ state , user_action , max_example_flows
287
+ )
297
288
298
289
prompt = self .llm_task_manager .render_task_prompt (
299
290
task = Task .GENERATE_USER_INTENT_FROM_USER_ACTION ,
0 commit comments