Spaces:
Running
Running
random pick an incomplete task instead of go with sequential order
Browse files- app.py +28 -22
- chatbot_simulator.py +57 -32
- prompts.py +66 -83
app.py
CHANGED
@@ -38,12 +38,13 @@ def find_random_incomplete_task(app_name):
|
|
38 |
return random_idx
|
39 |
|
40 |
|
41 |
-
def write_task_data(app_name, idx, task, task_complete, task_completed_step):
|
42 |
doc_ref = db.collection(app_name).document(f"{app_name}_{idx}")
|
43 |
doc_ref.set({
|
44 |
"task": task,
|
45 |
"task_completed": task_complete,
|
46 |
-
"task_completed_steps": task_completed_step
|
|
|
47 |
})
|
48 |
|
49 |
|
@@ -57,19 +58,20 @@ class AppSimulator:
|
|
57 |
|
58 |
def initialize_simulator(self, sitemap_url, progress=gr.Progress(track_tqdm=True)):
|
59 |
"""Initialize the simulator with retries and elapsed time tracking."""
|
60 |
-
synthetic_sitemap = load_dataset(sitemap_url, "
|
61 |
-
app_name,
|
|
|
62 |
for row in synthetic_sitemap:
|
63 |
if row['name'] == 'app_name':
|
64 |
-
app_name = row['value']
|
|
|
|
|
65 |
elif row['name'] == 'sitemap':
|
66 |
sitemap = json_repair.loads(row['value'])
|
67 |
-
elif row['name'] == '
|
68 |
-
|
69 |
-
elif row['name'] == '
|
70 |
-
|
71 |
-
elif row['name'] == 'system_data':
|
72 |
-
system_data = json_repair.loads(row['value'])
|
73 |
|
74 |
self.app_name = app_name
|
75 |
smallest_index = find_random_incomplete_task(app_name)
|
@@ -78,25 +80,26 @@ class AppSimulator:
|
|
78 |
self.smallest_index = smallest_index
|
79 |
|
80 |
synthetic_tasks = load_dataset(sitemap_url, "tasks", split='train')
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
|
|
85 |
|
86 |
self.task = task
|
87 |
|
88 |
self.simulation = ChatbotSimulation(
|
89 |
app_name=app_name,
|
|
|
90 |
site_map=sitemap,
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
user_data=user_data,
|
95 |
task=task,
|
96 |
solution=solution,
|
97 |
log_location=f'conversation_log_{app_name}.txt',
|
98 |
openai_api_key=openai_api_key,
|
99 |
-
agent='
|
100 |
)
|
101 |
|
102 |
initial_message = self.simulation.start_conversation()
|
@@ -124,7 +127,9 @@ def chat(user_input, history, simulator_app):
|
|
124 |
app_name = simulator_app.app_name
|
125 |
idx = simulator_app.smallest_index
|
126 |
task = simulator_app.task
|
127 |
-
|
|
|
|
|
128 |
|
129 |
return response
|
130 |
|
@@ -137,8 +142,9 @@ def give_up(simulator_app):
|
|
137 |
app_name = simulator_app.app_name
|
138 |
idx = simulator_app.smallest_index
|
139 |
task = simulator_app.task
|
|
|
140 |
|
141 |
-
write_task_data(app_name, idx, task, task_completed, task_completed_steps)
|
142 |
|
143 |
return "Task marked as abandoned (Give-Up action)."
|
144 |
|
|
|
38 |
return random_idx
|
39 |
|
40 |
|
41 |
+
def write_task_data(app_name, idx, task, task_complete, task_completed_step, trajectory):
|
42 |
doc_ref = db.collection(app_name).document(f"{app_name}_{idx}")
|
43 |
doc_ref.set({
|
44 |
"task": task,
|
45 |
"task_completed": task_complete,
|
46 |
+
"task_completed_steps": task_completed_step,
|
47 |
+
"trajectory": trajectory
|
48 |
})
|
49 |
|
50 |
|
|
|
58 |
|
59 |
def initialize_simulator(self, sitemap_url, progress=gr.Progress(track_tqdm=True)):
|
60 |
"""Initialize the simulator with retries and elapsed time tracking."""
|
61 |
+
synthetic_sitemap = load_dataset(sitemap_url, "schema", split='train')
|
62 |
+
app_name, app_description, sitemap, relevant_tables_per_page, jinjia_prerender_page = None, None, None, None, None
|
63 |
+
|
64 |
for row in synthetic_sitemap:
|
65 |
if row['name'] == 'app_name':
|
66 |
+
app_name = row['value']
|
67 |
+
elif row['name'] == 'app_description':
|
68 |
+
app_description = row['value']
|
69 |
elif row['name'] == 'sitemap':
|
70 |
sitemap = json_repair.loads(row['value'])
|
71 |
+
elif row['name'] == 'relevant_tables_per_page':
|
72 |
+
relevant_tables_per_page = json_repair.loads(row['value'])
|
73 |
+
elif row['name'] == 'jinjia_prerender_pages':
|
74 |
+
jinjia_prerender_page = json_repair.loads(row['value'])
|
|
|
|
|
75 |
|
76 |
self.app_name = app_name
|
77 |
smallest_index = find_random_incomplete_task(app_name)
|
|
|
80 |
self.smallest_index = smallest_index
|
81 |
|
82 |
synthetic_tasks = load_dataset(sitemap_url, "tasks", split='train')
|
83 |
+
random_index = random.randint(0, len(synthetic_tasks) - 1) # Generate a random index
|
84 |
+
random_row = synthetic_tasks[random_index]
|
85 |
+
task = random_row['task']
|
86 |
+
solution = random_row['solution']
|
87 |
+
database = random_row['database']
|
88 |
|
89 |
self.task = task
|
90 |
|
91 |
self.simulation = ChatbotSimulation(
|
92 |
app_name=app_name,
|
93 |
+
app_description=app_description,
|
94 |
site_map=sitemap,
|
95 |
+
relevant_tables_per_page=relevant_tables_per_page,
|
96 |
+
database=database,
|
97 |
+
jinjia_prerender_page=jinjia_prerender_page,
|
|
|
98 |
task=task,
|
99 |
solution=solution,
|
100 |
log_location=f'conversation_log_{app_name}.txt',
|
101 |
openai_api_key=openai_api_key,
|
102 |
+
agent='Human'
|
103 |
)
|
104 |
|
105 |
initial_message = self.simulation.start_conversation()
|
|
|
127 |
app_name = simulator_app.app_name
|
128 |
idx = simulator_app.smallest_index
|
129 |
task = simulator_app.task
|
130 |
+
trajectory = simulator_app.simulation.trajectory
|
131 |
+
|
132 |
+
write_task_data(app_name, idx, task, task_complete, task_completed_step, trajectory)
|
133 |
|
134 |
return response
|
135 |
|
|
|
142 |
app_name = simulator_app.app_name
|
143 |
idx = simulator_app.smallest_index
|
144 |
task = simulator_app.task
|
145 |
+
trajectory = simulator_app.simulation.trajectory
|
146 |
|
147 |
+
write_task_data(app_name, idx, task, task_completed, task_completed_steps, trajectory)
|
148 |
|
149 |
return "Task marked as abandoned (Give-Up action)."
|
150 |
|
chatbot_simulator.py
CHANGED
@@ -5,24 +5,28 @@ from prompts import *
|
|
5 |
import re
|
6 |
from tenacity import retry, wait_fixed, stop_after_attempt, retry_if_exception_type
|
7 |
from openai import RateLimitError
|
|
|
8 |
|
9 |
|
10 |
class ChatbotSimulation:
|
11 |
-
def __init__(self, app_name,
|
|
|
12 |
log_location, openai_api_key, agent='human',
|
13 |
-
max_steps=
|
14 |
self.app_name = app_name
|
|
|
15 |
self.sitemap = site_map
|
16 |
-
self.
|
17 |
-
self.
|
18 |
-
self.
|
19 |
-
self.user_state['task_completed'] = 'False'
|
20 |
-
self.user_state['back'] = 'False'
|
21 |
-
self.system_data = system_data
|
22 |
-
self.user_data = user_data
|
23 |
self.task = task
|
24 |
self.solution = solution
|
25 |
|
|
|
|
|
|
|
|
|
|
|
26 |
self.log_location = log_location
|
27 |
self.agent = agent.lower()
|
28 |
if self.agent not in ['human', 'llm']:
|
@@ -31,40 +35,53 @@ class ChatbotSimulation:
|
|
31 |
self.max_tokens = max_tokens
|
32 |
self.buffer_tokens = buffer_tokens
|
33 |
self.conversation = [] # Stores recent conversation snippets
|
|
|
34 |
self.prompt_count = 0
|
35 |
self.client = OpenAI(api_key=openai_api_key)
|
36 |
self.actions = []
|
37 |
self.tokenizer = AutoTokenizer.from_pretrained("gpt2", clean_up_tokenization_spaces=True)
|
38 |
|
39 |
-
#
|
40 |
self.page_history = ['Home']
|
41 |
|
42 |
-
def
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
|
51 |
def _generate_system_prompt(self):
|
52 |
"""Create a dynamic system prompt based on the current state."""
|
53 |
-
current_page = self.page_history[-1] if len(self.page_history) >= 1 else
|
54 |
-
last_page = self.page_history[-2] if len(self.page_history) > 1 else
|
55 |
-
|
56 |
-
|
|
|
57 |
|
58 |
return get_system_prompt(app_name=self.app_name,
|
59 |
-
|
|
|
60 |
task=self.task,
|
61 |
-
user_data=self.user_data,
|
62 |
current_page=current_page,
|
63 |
last_page=last_page,
|
64 |
actions=self.actions,
|
65 |
-
|
66 |
-
|
67 |
-
page_linkage=page_linkage
|
68 |
)
|
69 |
|
70 |
@retry(
|
@@ -100,28 +117,33 @@ class ChatbotSimulation:
|
|
100 |
def one_conversation_round(self, user_input):
|
101 |
"""Conduct one round of conversation between the user and the assistant."""
|
102 |
# User provides input
|
|
|
103 |
valid_input = self._is_valid_input(user_input)
|
104 |
if valid_input[0]:
|
105 |
pass
|
106 |
else:
|
107 |
-
|
|
|
|
|
|
|
108 |
|
109 |
self.actions.append(user_input + f'on {self.user_state["current_page"]} page')
|
110 |
self.conversation.append({"role": "user", "content": user_input})
|
111 |
self.prompt_count += 1
|
112 |
|
113 |
# Update user state using GPT's response
|
114 |
-
current_page = self.page_history[-1] if len(self.page_history) >= 1 else
|
115 |
update_prompt = get_user_state_update_prompt(user_input=user_input,
|
116 |
current_page=current_page,
|
117 |
task=self.task,
|
|
|
118 |
solution=self.solution,
|
119 |
user_state=self.user_state,
|
120 |
sitemap=self.sitemap)
|
121 |
|
122 |
-
self.conversation.append({"role": "
|
123 |
updated_state = self._get_openai_response(self.conversation).split("UPDATED", 1)[1].strip()
|
124 |
-
self.conversation.pop(-1)
|
125 |
|
126 |
# Parse and update the user state
|
127 |
updated_state = json_repair.loads(updated_state)
|
@@ -151,7 +173,9 @@ class ChatbotSimulation:
|
|
151 |
|
152 |
try:
|
153 |
if str(updated_state['task_completed']).lower() == 'true':
|
154 |
-
|
|
|
|
|
155 |
except:
|
156 |
updated_state['task_completed'] = 'False'
|
157 |
|
@@ -168,6 +192,7 @@ class ChatbotSimulation:
|
|
168 |
self.conversation.append({"role": "system", "content": system_prompt})
|
169 |
gpt_instruction = self._get_openai_response(self.conversation)
|
170 |
self.conversation.append({"role": "assistant", "content": gpt_instruction})
|
|
|
171 |
return gpt_instruction
|
172 |
|
173 |
def start_conversation(self):
|
|
|
5 |
import re
|
6 |
from tenacity import retry, wait_fixed, stop_after_attempt, retry_if_exception_type
|
7 |
from openai import RateLimitError
|
8 |
+
from difflib import get_close_matches
|
9 |
|
10 |
|
11 |
class ChatbotSimulation:
|
12 |
+
def __init__(self, app_name, app_description, site_map, relevant_tables_per_page,
|
13 |
+
database, jinjia_prerender_page, task, solution,
|
14 |
log_location, openai_api_key, agent='human',
|
15 |
+
max_steps=30, max_tokens=8192, buffer_tokens=500):
|
16 |
self.app_name = app_name
|
17 |
+
self.app_description = app_description
|
18 |
self.sitemap = site_map
|
19 |
+
self.relevant_tables_per_page = relevant_tables_per_page
|
20 |
+
self.database = database
|
21 |
+
self.jinjia_prerender_page = jinjia_prerender_page
|
|
|
|
|
|
|
|
|
22 |
self.task = task
|
23 |
self.solution = solution
|
24 |
|
25 |
+
self.user_state = dict()
|
26 |
+
self.user_state['current_page'] = self.sitemap['pages'][0]['id'] # Initialize current page
|
27 |
+
self.user_state['task_completed'] = 'False'
|
28 |
+
self.user_state['back'] = 'False'
|
29 |
+
|
30 |
self.log_location = log_location
|
31 |
self.agent = agent.lower()
|
32 |
if self.agent not in ['human', 'llm']:
|
|
|
35 |
self.max_tokens = max_tokens
|
36 |
self.buffer_tokens = buffer_tokens
|
37 |
self.conversation = [] # Stores recent conversation snippets
|
38 |
+
self.trajectory = [{"role": "system", "content": f"Welcome to {app_name} simulator! Your task is: {task}"}]
|
39 |
self.prompt_count = 0
|
40 |
self.client = OpenAI(api_key=openai_api_key)
|
41 |
self.actions = []
|
42 |
self.tokenizer = AutoTokenizer.from_pretrained("gpt2", clean_up_tokenization_spaces=True)
|
43 |
|
44 |
+
#back button
|
45 |
self.page_history = ['Home']
|
46 |
|
47 |
+
def _get_relevant_data(self, current_page):
|
48 |
+
# Check if the current page exists as a key
|
49 |
+
if current_page in self.relevant_tables_per_page:
|
50 |
+
relevant_tables = self.relevant_tables_per_page[current_page]
|
51 |
+
else:
|
52 |
+
# Find the closest matching key
|
53 |
+
closest_match = get_close_matches(current_page, self.relevant_tables_per_page.keys(), n=1, cutoff=0.5)
|
54 |
+
if closest_match:
|
55 |
+
relevant_tables = self.relevant_tables_per_page[closest_match[0]]
|
56 |
+
else:
|
57 |
+
return self.database
|
58 |
+
|
59 |
+
return {table: self.database[table] for table in relevant_tables if table in self.database}
|
60 |
+
|
61 |
+
def _get_prerender_page(self, current_page):
|
62 |
+
if current_page in self.jinjia_prerender_page:
|
63 |
+
return self.jinjia_prerender_page[current_page]
|
64 |
+
else:
|
65 |
+
closest_match = get_close_matches(current_page, self.jinjia_prerender_page.keys(), n=1, cutoff=0)
|
66 |
+
return self.jinjia_prerender_page[closest_match[0]]
|
67 |
|
68 |
def _generate_system_prompt(self):
|
69 |
"""Create a dynamic system prompt based on the current state."""
|
70 |
+
current_page = self.page_history[-1] if len(self.page_history) >= 1 else self.sitemap['pages'][0]['id']
|
71 |
+
last_page = self.page_history[-2] if len(self.page_history) > 1 else self.sitemap['pages'][0]['id']
|
72 |
+
relevant_database = self._get_relevant_data(current_page)
|
73 |
+
relevant_sitemap = next((page for page in self.sitemap["pages"] if page["id"] == current_page), self.sitemap["pages"])
|
74 |
+
prerender_page = self._get_prerender_page(current_page)
|
75 |
|
76 |
return get_system_prompt(app_name=self.app_name,
|
77 |
+
app_description=self.app_description,
|
78 |
+
relevant_database=relevant_database,
|
79 |
task=self.task,
|
|
|
80 |
current_page=current_page,
|
81 |
last_page=last_page,
|
82 |
actions=self.actions,
|
83 |
+
sitemap_page=relevant_sitemap,
|
84 |
+
jinjia_prerender=prerender_page,
|
|
|
85 |
)
|
86 |
|
87 |
@retry(
|
|
|
117 |
def one_conversation_round(self, user_input):
|
118 |
"""Conduct one round of conversation between the user and the assistant."""
|
119 |
# User provides input
|
120 |
+
self.trajectory.append({"role": "user", "content": f'Human: {user_input}'})
|
121 |
valid_input = self._is_valid_input(user_input)
|
122 |
if valid_input[0]:
|
123 |
pass
|
124 |
else:
|
125 |
+
self.prompt_count += 1
|
126 |
+
invalid_input_message = f"\n{self.app_name}: Invalid input. {valid_input[1]}"
|
127 |
+
self.trajectory.append({"role": "assistant", "content": invalid_input_message})
|
128 |
+
return invalid_input_message
|
129 |
|
130 |
self.actions.append(user_input + f'on {self.user_state["current_page"]} page')
|
131 |
self.conversation.append({"role": "user", "content": user_input})
|
132 |
self.prompt_count += 1
|
133 |
|
134 |
# Update user state using GPT's response
|
135 |
+
current_page = self.page_history[-1] if len(self.page_history) >= 1 else self.sitemap['pages'][0]['id']
|
136 |
update_prompt = get_user_state_update_prompt(user_input=user_input,
|
137 |
current_page=current_page,
|
138 |
task=self.task,
|
139 |
+
database=self.database,
|
140 |
solution=self.solution,
|
141 |
user_state=self.user_state,
|
142 |
sitemap=self.sitemap)
|
143 |
|
144 |
+
self.conversation.append({"role": "user", "content": update_prompt})
|
145 |
updated_state = self._get_openai_response(self.conversation).split("UPDATED", 1)[1].strip()
|
146 |
+
self.conversation.pop(-1) # update prompt don't have to stay in conversation history
|
147 |
|
148 |
# Parse and update the user state
|
149 |
updated_state = json_repair.loads(updated_state)
|
|
|
173 |
|
174 |
try:
|
175 |
if str(updated_state['task_completed']).lower() == 'true':
|
176 |
+
complete_message = f"{self.app_name}: Task completed! You took {self.prompt_count} steps."
|
177 |
+
self.trajectory.append({"role": "assistant", "content": complete_message})
|
178 |
+
return complete_message
|
179 |
except:
|
180 |
updated_state['task_completed'] = 'False'
|
181 |
|
|
|
192 |
self.conversation.append({"role": "system", "content": system_prompt})
|
193 |
gpt_instruction = self._get_openai_response(self.conversation)
|
194 |
self.conversation.append({"role": "assistant", "content": gpt_instruction})
|
195 |
+
self.trajectory.append({"role": "assistant", "content": gpt_instruction})
|
196 |
return gpt_instruction
|
197 |
|
198 |
def start_conversation(self):
|
prompts.py
CHANGED
@@ -1,97 +1,80 @@
|
|
|
|
1 |
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
You are
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
Details and buttons on the current page:
|
13 |
-
{
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
You have the following options:
|
29 |
-
1. option 1: action type
|
30 |
-
2. option 2: action type
|
31 |
-
3. option 3: action type
|
32 |
-
4. option 4: action type
|
33 |
-
<If any linked page does not have button links to it, add the button.>
|
34 |
-
5. Back to last page: click
|
35 |
-
6. Back to Home page: click
|
36 |
-
7. <If user_state['logged_in'] == False, display Log In: click to take user to log in page>
|
37 |
-
8. Do nothing: noop
|
38 |
-
|
39 |
-
Each button is in the format: `number. button name: action_type`.
|
40 |
-
Please provide your choice in the format: `action_type(button name)`.
|
41 |
-
If you have a query, use the format: `type(button name, query)`.
|
42 |
-
Please provide only one choice per turn.
|
43 |
-
|
44 |
-
### **Rules**:
|
45 |
-
1. Display all available options from the buttons on the page.
|
46 |
-
2. Remain robotic and emotionless. Avoid offering any advice or opinions to the user.
|
47 |
-
3. Ensure there is always a button to navigate back to the **{last_page}** and a button to go to the **Home page**.
|
48 |
-
4. Ensure there is always a button that allow user to do nothing.
|
49 |
-
5. Ensure the action type is a single word, such as ‘type’ or ‘click.’ If the action type is not a single word, convert it to a single word. For example, type(SUMMER, apply) should be transformed to type.
|
50 |
-
6. Group similar action types under ‘type’ and display them as ‘type’ (e.g., display ‘input’ or ‘search’ as ‘type’).
|
51 |
-
7. Mimic the real {app_name} scenario as much as possible.
|
52 |
-
"""
|
53 |
return system_prompt
|
54 |
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
}
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
return update_prompt
|
86 |
|
87 |
|
88 |
def get_agent_prompt(app_name, task, conversation):
|
89 |
-
agent_prompt = f"""
|
90 |
Imagine you are an agent navigate through the {app_name} environment.
|
91 |
Your overarching task is: {task}. You may have done some part of the task, or none at all.
|
92 |
You will have access to all of your previous actions in the environment, as well as the last message from the assistant giving the current state of the environment.
|
93 |
The last message from the assistant was: {conversation[-1]['content']}
|
94 |
Respond first with a brief "Plan" which suggests what steps you are going to take to accomplish the task, and what your immediate.
|
95 |
Then generate an "Action" which is the immediate next step you can take.
|
96 |
-
|
97 |
return agent_prompt
|
|
|
1 |
+
import textwrap
|
2 |
|
3 |
+
|
4 |
+
def get_system_prompt(app_name, app_description, relevant_database, task,
|
5 |
+
current_page, last_page, actions, sitemap_page, jinjia_prerender):
|
6 |
+
system_prompt = textwrap.dedent(f"""
|
7 |
+
You are a text-based CLI {app_name} ({app_description}) simulator.
|
8 |
+
The {app_name} app contains the following database tables: {relevant_database}.
|
9 |
+
You are interacting with a user whose task is: {task}.
|
10 |
+
The user's last page was {last_page}, and they have taken the following actions: {actions}.
|
11 |
+
After performing the most recent action, the user is now on the {current_page} page.
|
12 |
+
|
13 |
+
Details and buttons on the current page:
|
14 |
+
{sitemap_page}
|
15 |
+
|
16 |
+
This page should display following pre-rendered page to user and making sure replace the placeholders with real data from database.
|
17 |
+
|
18 |
+
{jinjia_prerender}
|
19 |
+
|
20 |
+
### **Rules**:
|
21 |
+
1. Display all information from the pre-rendered page.
|
22 |
+
2. Remain robotic and emotionless. Avoid offering any advice or opinions to the user.
|
23 |
+
3. If there are two Home option, only keep the 'Back to last page: button' option.
|
24 |
+
4. Add a button to interact with displayed item if such button doesn't exist.
|
25 |
+
5. Mimic the real {app_name} scenario as much as possible.
|
26 |
+
6. Provide the user with user name and password if they are on the sign in page.
|
27 |
+
""")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
return system_prompt
|
29 |
|
30 |
+
|
31 |
+
def get_database_update_prompt(user_input, current_page, database):
|
32 |
+
update_database = textwrap.dedent(f"""
|
33 |
+
You will now update the database.
|
34 |
+
The user takes the action '{user_input}' on the {current_page} page. Determine how will database change.
|
35 |
+
Recall the current Database:
|
36 |
+
{database}
|
37 |
+
|
38 |
+
### Output Format:
|
39 |
+
1. Start with "REASON": Explain which fields in database need to be updated and why.
|
40 |
+
2. End with "UPDATED": Provide only the updated database. Follow the input database schema structure exactly without modifying its organization. Do not include explanations or any additional text after updated database.
|
41 |
+
""")
|
42 |
+
return update_database
|
43 |
+
|
44 |
+
|
45 |
+
def get_user_state_update_prompt(user_input, current_page, task, database, solution, user_state, sitemap):
|
46 |
+
update_prompt = textwrap.dedent(f"""
|
47 |
+
You will now update the user state.
|
48 |
+
The user takes the action '{user_input}' on the {current_page} page. Determine which page the user will move to next.
|
49 |
+
The next page must from the sitemap: {sitemap}
|
50 |
+
Recall the user's task: {task}. Recall the current Database: {database}. Solution to the user's task: {solution}.
|
51 |
+
Update the `user_state` dictionary based on the user's last action:
|
52 |
+
Current user_state: {user_state}.
|
53 |
+
|
54 |
+
### Instructions:
|
55 |
+
1. If the 'current_page' has changed, update it to a valid page from the sitemap.
|
56 |
+
2. If the task is completed, update 'task_completed' to `True`. Otherwise, leave it as `False`.
|
57 |
+
3. If no updates are needed, return the `user_state` exactly as provided, without any changes.
|
58 |
+
|
59 |
+
### Important Notes:
|
60 |
+
- Ensure 'current_page' and 'task_completed' are always present as keys in the returned dictionary.
|
61 |
+
- If the user go back a page from current page, set 'back' to `True`. Otherwise, it should remain `False`.
|
62 |
+
- Return only the updated dictionary, without additional text, explanations, or wrapping.
|
63 |
+
|
64 |
+
### Output Format:
|
65 |
+
1. Start with "REASON": Explain which fields in `user_state` need to be updated and why.
|
66 |
+
2. End with "UPDATED": Provide only the updated `user_state` dictionary. Follow the input user_state schema structure exactly without modifying its organization. Do not include explanations or any additional text after updated user state.
|
67 |
+
""")
|
68 |
return update_prompt
|
69 |
|
70 |
|
71 |
def get_agent_prompt(app_name, task, conversation):
|
72 |
+
agent_prompt = textwrap.dedent(f"""
|
73 |
Imagine you are an agent navigate through the {app_name} environment.
|
74 |
Your overarching task is: {task}. You may have done some part of the task, or none at all.
|
75 |
You will have access to all of your previous actions in the environment, as well as the last message from the assistant giving the current state of the environment.
|
76 |
The last message from the assistant was: {conversation[-1]['content']}
|
77 |
Respond first with a brief "Plan" which suggests what steps you are going to take to accomplish the task, and what your immediate.
|
78 |
Then generate an "Action" which is the immediate next step you can take.
|
79 |
+
""")
|
80 |
return agent_prompt
|