From c76a319467714d98b15a2449bad0a72bbea3fbc8 Mon Sep 17 00:00:00 2001 From: Thomas Werkmeister Date: Sat, 17 Jun 2023 11:21:18 +0200 Subject: [PATCH] refined classifier and prompt --- .../classifiers/flow_prompt_template.jinja2 | 20 +++++++++++++------ rasa/nlu/classifiers/llm_flow_classifier.py | 12 +++++++++-- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/rasa/nlu/classifiers/flow_prompt_template.jinja2 b/rasa/nlu/classifiers/flow_prompt_template.jinja2 index ee07f2c5c0f2..df3b484c6f49 100644 --- a/rasa/nlu/classifiers/flow_prompt_template.jinja2 +++ b/rasa/nlu/classifiers/flow_prompt_template.jinja2 @@ -5,12 +5,12 @@ These are the flows that can be started, with their description and slots: - {{ flow.name }}: {{ flow.description }} (slots: {{ flow.slots }}) {%- endfor %} -Here is the current conversation: +Here is what happened previously in the conversation: {{ current_conversation }} {% if current_flow != None %} -You are currently in the flow {{ current_flow }}. -You have just asked the user for {{ question }}. +You are currently in the flow "{{ current_flow }}". +You have just asked the user for the slot "{{ question }}". {% if flow_slots|length > 0 %} Here are the slots of the currently active flow with their names and values: @@ -23,9 +23,17 @@ You are currently not in any flow and so there are no active slots. {% endif %} If you start a flow, you can already fill that flow's slots with information the user provided for starting the flow. -The user replied """{{ user_message }}""". +The user just said """{{ user_message }}""". -Based on this information generate a list of actions you want to take. Your job is to start flows and to fill slots where appropriate. Any logic of what happens next afterwards is handled by the underlying flow. These are your available actions: +Based on this information generate a list of actions you want to take. Your job is to start flows and to fill slots where appropriate. Any logic of what happens afterwards is handled by the flow engine. These are your available actions: * Slot setting, described by "SetSlot(slot_name, slot_value)". An example would be "SetSlot(recipient, Freddy)" * Starting another flow, described by "StartFlow(flow_name)". An example would be "StartFlow(transfer_money)" -Write out the actions you want to take with respect to the last user message, one per line. Strictly adhere to the provided action types above for starting flows and setting slots: +* Cancelling the current flow, describe by "CancelFlow()" + +Write out the actions you want to take for the last user message, one per line. +Do not prematurely fill slots with abstract values. +Only use information provided by the user. +Strictly adhere to the provided action types above for starting flows and setting slots. +Focus on the last message and take it one step at a time. +Use the previous conversation steps only to aid understanding. +The action list: diff --git a/rasa/nlu/classifiers/llm_flow_classifier.py b/rasa/nlu/classifiers/llm_flow_classifier.py index acad98125850..9aecc06237aa 100644 --- a/rasa/nlu/classifiers/llm_flow_classifier.py +++ b/rasa/nlu/classifiers/llm_flow_classifier.py @@ -143,8 +143,10 @@ def parse_action_list( """Parse the actions returned by the llm into intent and entities.""" start_flow_actions = [] slot_sets = [] - slot_set_re = re.compile(r"SetSlot\(([a-zA-Z_][a-zA-Z0-9_-]*?),([^)]*)\)") + cancel_flow = False + slot_set_re = re.compile(r"""SetSlot\(([a-zA-Z_][a-zA-Z0-9_-]*?), ?\"?([^)]*?)\"?\)""") start_flow_re = re.compile(r"StartFlow\(([a-zA-Z_][a-zA-Z0-9_-]*?)\)") + cancel_flow_re = re.compile(r"CancelFlow") for action in actions.strip().splitlines(): if m := slot_set_re.search(action): slot_name = m.group(1).strip() @@ -160,6 +162,8 @@ def parse_action_list( slot_sets.append((slot_name, slot_value)) elif m := start_flow_re.search(action): start_flow_actions.append(m.group(1).strip()) + elif cancel_flow_re.search(action): + cancel_flow = True # case 1 # "I want to send some money" @@ -198,8 +202,10 @@ def parse_action_list( other_slots = slot_sets if len(start_flow_actions) == 0: - if len(slot_sets) == 0: + if len(slot_sets) == 0 and not cancel_flow: return "comment", [] + elif len(slot_sets) == 0 and cancel_flow: + return "cancel_flow", [] elif ( len(slot_sets) == 1 and isinstance(top_flow_step, QuestionFlowStep) @@ -223,6 +229,8 @@ def parse_action_list( elif len(slot_sets) > 1: return "too_complex", [] elif len(start_flow_actions) == 1: + if cancel_flow: + return "too_complex", [] new_flow_id = start_flow_actions[0] potential_new_flow = flows.flow_by_id(new_flow_id) if potential_new_flow is not None: