jjz5463 commited on
Commit
15af633
1 Parent(s): 258c0f5

update gui

Browse files
Files changed (3) hide show
  1. app.py +66 -80
  2. chatbot_simulator.py +29 -30
  3. task_specific_data_population.py +5 -11
app.py CHANGED
@@ -1,27 +1,27 @@
1
  import gradio as gr
2
  from chatbot_simulator import ChatbotSimulation
3
  from task_specific_data_population import DataPopulation
 
4
  import os
5
 
6
  openai_api_key = os.getenv("OPENAI_API_KEY")
7
 
8
-
9
  class AppSimulator:
10
  def __init__(self, openai_api_key):
11
  self.simulation = None
12
- self.conversation = [] # Stores full conversation for logging
13
- self.display_conversation = [] # Stores last 2 messages for display
14
  self.openai_api_key = openai_api_key
15
 
16
- def initialize_simulator(self, task, app_name, sitemap):
17
- """Initialize the simulator with retries in case of failure."""
18
- success = False
19
  retry_count = 0
20
  max_retries = 50
21
 
22
- while not success and retry_count < max_retries:
23
  try:
24
- # Process data
 
 
 
25
  data_population = DataPopulation(api_key=self.openai_api_key)
26
  sitemap_data, page_details, user_state = data_population.process_data(task, sitemap)
27
 
@@ -36,93 +36,79 @@ class AppSimulator:
36
  agent='human'
37
  )
38
 
39
- # Start the conversation and update the logs and display
40
- text = self.simulation.start_conversation()
41
- self._log_message("assistant", text)
42
- self.display_conversation = [('Start Simulator', text)]
43
-
44
- return self.display_conversation
45
  except Exception as e:
46
  retry_count += 1
47
- print(f"Attempt {retry_count}/{max_retries}: An error occurred: {e}. Retrying...")
48
 
49
- def chatbot_interaction(self, user_input):
 
 
 
 
50
  """Handle one round of conversation."""
51
- if self.simulation is None:
52
- return [("system", "Simulation is not initialized. Please start the simulator.")]
53
-
54
- try:
55
- # Get the response from the simulator
56
- response = self.simulation.one_conversation_round(user_input)
57
-
58
- # Log both user input and assistant's response
59
- self._log_message("user", user_input)
60
- self._log_message("assistant", response)
61
-
62
- # Update display conversation (keep last 2 entries)
63
- self.display_conversation.extend([(user_input, response)])
64
- while len(self.display_conversation) > 2:
65
- self.display_conversation.pop(0)
66
- print(len(self.display_conversation))
67
- return self.display_conversation
68
- except Exception as e:
69
- return [("system", f"An error occurred: {e}")]
70
-
71
- def _log_message(self, role, content):
72
- """Log conversation messages to both memory and file."""
73
- self.conversation.append({"role": role, "content": content})
74
- self._write_log_to_file(content)
75
-
76
- def _write_log_to_file(self, content):
77
- """Append conversation to a log file."""
78
- log_location = self.simulation.log_location if self.simulation else "conversation_log.txt"
79
- try:
80
- with open(log_location, 'a') as f:
81
- for message in self.conversation:
82
- f.write(f"{message['role']}: {message['content']}\n\n")
83
- except Exception as e:
84
- print(f"Error logging conversation: {e}")
85
-
86
-
87
- # JavaScript function to refresh theme to dark mode
88
- js_func = """
89
- function refresh() {
90
- const url = new URL(window.location);
91
- if (url.searchParams.get('__theme') !== 'dark') {
92
- url.searchParams.set('__theme', 'dark');
93
- window.location.href = url.href;
94
- }
95
- }
96
- """
97
 
 
98
  simulator_app = AppSimulator(openai_api_key=openai_api_key)
99
 
100
- # Gradio Interface
101
- with gr.Blocks(js=js_func) as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  gr.Markdown("## Simulator Setup")
103
 
 
104
  task_input = gr.Textbox(label="Task", placeholder="Describe your task...")
105
  app_name_input = gr.Textbox(label="App Name", placeholder="Enter the app name...")
106
  sitemap_input = gr.Textbox(label="Sitemap", placeholder="Enter the Hugging Face link to sitemap...")
107
-
108
  initialize_button = gr.Button("Initialize Simulator")
109
- chatbot = gr.Chatbot(label="Simulator Chat", height=800)
110
- user_message = gr.Textbox(label="Enter your message", placeholder="Type your message here...")
111
- submit_button = gr.Button("Send")
112
 
113
- # Initialize simulator and display the welcome message
 
 
 
 
 
 
 
 
 
 
114
  initialize_button.click(
115
- simulator_app.initialize_simulator,
116
  inputs=[task_input, app_name_input, sitemap_input],
117
- outputs=chatbot
118
- )
119
-
120
- # Handle conversation interaction
121
- submit_button.click(
122
- simulator_app.chatbot_interaction,
123
- inputs=user_message,
124
- outputs=chatbot
125
  )
126
 
127
- # Launch the Gradio app
128
- demo.launch()
 
1
  import gradio as gr
2
  from chatbot_simulator import ChatbotSimulation
3
  from task_specific_data_population import DataPopulation
4
+ import re
5
  import os
6
 
7
  openai_api_key = os.getenv("OPENAI_API_KEY")
8
 
 
9
  class AppSimulator:
10
  def __init__(self, openai_api_key):
11
  self.simulation = None
 
 
12
  self.openai_api_key = openai_api_key
13
 
14
+ def initialize_simulator(self, task, app_name, sitemap, progress=gr.Progress(track_tqdm=True)):
15
+ """Initialize the simulator with retries and elapsed time tracking."""
 
16
  retry_count = 0
17
  max_retries = 50
18
 
19
+ while retry_count < max_retries:
20
  try:
21
+ # Display current attempt with progress bar
22
+ progress.update(f"Initializing... Attempt {retry_count + 1}/{max_retries}")
23
+
24
+ # Process data and initialize the simulation
25
  data_population = DataPopulation(api_key=self.openai_api_key)
26
  sitemap_data, page_details, user_state = data_population.process_data(task, sitemap)
27
 
 
36
  agent='human'
37
  )
38
 
39
+ # Successful initialization
40
+ initial_message = self.simulation.start_conversation()
41
+ progress.update("Initialization Successful")
42
+ return initial_message # Return the initial assistant message for chat
 
 
43
  except Exception as e:
44
  retry_count += 1
45
+ print(f"Attempt {retry_count}/{max_retries} failed: {e}")
46
 
47
+ # If all retries failed
48
+ progress.update("Failed to initialize simulator after multiple retries.")
49
+ return "Initialization failed." # Error message for chat
50
+
51
+ def chat_interaction(self, user_input, history):
52
  """Handle one round of conversation."""
53
+ return self.simulation.one_conversation_round(user_input)
54
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
+ # Initialize the simulator
57
  simulator_app = AppSimulator(openai_api_key=openai_api_key)
58
 
59
+ def is_valid_input(user_input):
60
+ """Validate user input format."""
61
+ pattern = r"^\d+\.\s+.*"
62
+ return bool(re.match(pattern, user_input))
63
+
64
+ def chat(user_input, history):
65
+ """Chat handler that validates input and interacts with the simulator."""
66
+ if is_valid_input(user_input):
67
+ valid_response = simulator_app.chat_interaction(user_input, history)
68
+ return valid_response
69
+ else:
70
+ invalid_response = "Invalid input. Please use the format: '<Number>. <Description>: query'"
71
+ return invalid_response
72
+
73
+ css = """
74
+ body {
75
+ background-color: black !important;
76
+ color: white;
77
+ }
78
+ .gradio-container {
79
+ background-color: black !important;
80
+ }
81
+ .chatbox-message, input {
82
+ color: white !important;
83
+ }
84
+ """
85
+
86
+ # Gradio Interface using ChatInterface
87
+ with gr.Blocks(fill_height=True, css=css) as demo:
88
  gr.Markdown("## Simulator Setup")
89
 
90
+ # Input fields for initialization
91
  task_input = gr.Textbox(label="Task", placeholder="Describe your task...")
92
  app_name_input = gr.Textbox(label="App Name", placeholder="Enter the app name...")
93
  sitemap_input = gr.Textbox(label="Sitemap", placeholder="Enter the Hugging Face link to sitemap...")
 
94
  initialize_button = gr.Button("Initialize Simulator")
 
 
 
95
 
96
+ # Status block to display initialization progress with elapsed time
97
+ status = gr.Textbox(label="Status", interactive=False)
98
+
99
+ # Chat interface to handle user interactions
100
+ chat_interface = gr.ChatInterface(fn=chat)
101
+
102
+ # Define the callback function to initialize the simulator and update status
103
+ def initialize_and_start_chat(task, app_name, sitemap):
104
+ return simulator_app.initialize_simulator(task, app_name, sitemap) # Use progress tracking
105
+
106
+ # Set up the button click to initialize simulator and update status only
107
  initialize_button.click(
108
+ fn=initialize_and_start_chat,
109
  inputs=[task_input, app_name_input, sitemap_input],
110
+ outputs=status # Update only the status block
 
 
 
 
 
 
 
111
  )
112
 
113
+ # Launch the app
114
+ demo.launch()
chatbot_simulator.py CHANGED
@@ -59,12 +59,11 @@ You are at the {current_page} page. You have the following options:
59
  3. Feature 3
60
  4. Feature 4
61
 
62
- Please enter your choice as the corresponding number. If you have a query, enter as number: query
63
 
64
  Rules:
65
  - Be sure to display all options that is available in features.
66
  - Be robotic and emotionless. Avoid offering any advice to the user.
67
- - If a feature requires `input_text`, request input as: "Enter query as: [number]: query"
68
  """
69
 
70
  def _get_openai_response(self, prompt):
@@ -74,7 +73,7 @@ Rules:
74
  model="gpt-4",
75
  messages=prompt,
76
  max_tokens=self.buffer_tokens, # Adjusted max_tokens if needed
77
- temperature=1.0,
78
  )
79
  return response.choices[0].message.content
80
 
@@ -84,8 +83,8 @@ Rules:
84
 
85
  def _trim_conversation(self):
86
  """Trim the conversation to keep it within the token limit."""
87
- while self._calculate_token_count(self.conversation) > self.max_tokens - self.buffer_tokens:
88
- self.conversation.pop(0) #
89
 
90
  def one_conversation_round(self, user_input):
91
  """Conduct one round of conversation between the user and the assistant."""
@@ -95,26 +94,22 @@ Rules:
95
 
96
  # Update user state using GPT's response
97
  update_prompt = f"""
98
- Update the user state based on user input: '{user_input}' and task: {self.task}
99
-
100
- Current user state (JSON format): {self.user_state}
101
-
102
  Sitemap: {self.sitemap}
103
 
104
  Instructions:
105
  1. If the 'current_page' has changed, update it to a page from the sitemap.
106
- 2. If the task is finished, update 'task_completed' to 1. Otherwise, leave it unchanged.
107
  3. If no updates are needed, return the user state exactly as provided, without modification.
108
- 4. Preserve the **exact JSON structure** and **format** of the provided user state.
109
- 5. The output **must be a single JSON dictionary** representing the updated user state—do not wrap it in a list.
110
- 6. Do not change any other fields unless explicitly required by the instructions.
111
 
112
  Important:
113
  - Ensure 'current_page' and 'task_completed' are keys in the returned dictionary.
114
- - Return **only the JSON object** without additional output or wrapping.
115
- - **AVOID OUTPUT A LIST**, must be JSON!
116
 
117
- Example Format:
118
  {{
119
  'current_page': 'Home',
120
  'task_completed': 0,
@@ -127,20 +122,24 @@ Example Format:
127
  # Parse and update the user state
128
  updated_state = json_repair.loads(updated_state)
129
 
130
- if isinstance(updated_state, list):
131
- reformat_prompt = f'''
132
- Given the {updated_state}, reformat it into a proper JSON.
133
- Make sure follow the format:
134
- {{
135
- 'current_page': 'Home',
136
- 'task_completed': 0,
137
- }}
138
- '''
139
- reformat_state = self._get_openai_response([{"role": "assistant", "content": reformat_prompt}])
140
- updated_state = json_repair.loads(reformat_state)
141
-
142
- if updated_state['task_completed']:
143
- return f"Task completed! You took {self.prompt_count} steps."
 
 
 
 
144
 
145
  self.user_state = updated_state
146
 
 
59
  3. Feature 3
60
  4. Feature 4
61
 
62
+ Please enter your choice as 'Number. Description'. If you have a query, enter as 'Number. Description: query'
63
 
64
  Rules:
65
  - Be sure to display all options that is available in features.
66
  - Be robotic and emotionless. Avoid offering any advice to the user.
 
67
  """
68
 
69
  def _get_openai_response(self, prompt):
 
73
  model="gpt-4",
74
  messages=prompt,
75
  max_tokens=self.buffer_tokens, # Adjusted max_tokens if needed
76
+ temperature=0,
77
  )
78
  return response.choices[0].message.content
79
 
 
83
 
84
  def _trim_conversation(self):
85
  """Trim the conversation to keep it within the token limit."""
86
+ while self._calculate_token_count(self.conversation) >= (self.max_tokens - self.buffer_tokens * 4):
87
+ self.conversation.pop(0)
88
 
89
  def one_conversation_round(self, user_input):
90
  """Conduct one round of conversation between the user and the assistant."""
 
94
 
95
  # Update user state using GPT's response
96
  update_prompt = f"""
97
+ If user takes action '{user_input}' on {self.user_state['current_page']} page, which page will they move it?
98
+ Recall user's task: {self.task}
99
+ Update the user_state dictionary based on user's last action:
100
+ Current user_state: {self.user_state}
101
  Sitemap: {self.sitemap}
102
 
103
  Instructions:
104
  1. If the 'current_page' has changed, update it to a page from the sitemap.
105
+ 2. If the task is finished, update 'task_completed' to 1. Otherwise, leave it as 0.
106
  3. If no updates are needed, return the user state exactly as provided, without modification.
 
 
 
107
 
108
  Important:
109
  - Ensure 'current_page' and 'task_completed' are keys in the returned dictionary.
110
+ - Return only the dictionary without additional output or wrapping.
 
111
 
112
+ Example Output Format:
113
  {{
114
  'current_page': 'Home',
115
  'task_completed': 0,
 
122
  # Parse and update the user state
123
  updated_state = json_repair.loads(updated_state)
124
 
125
+ # if isinstance(updated_state, list):
126
+ # reformat_prompt = f'''
127
+ # Given the {updated_state}, reformat it into a proper JSON.
128
+ # Make sure follow the format:
129
+ # {{
130
+ # 'current_page': 'Home',
131
+ # 'task_completed': 0,
132
+ # }}
133
+ # '''
134
+ # self.conversation.append({"role": "assistant", "content": reformat_prompt})
135
+ # reformat_state = self._get_openai_response(self.conversation)
136
+ # updated_state = json_repair.loads(reformat_state)
137
+
138
+ try:
139
+ if updated_state['task_completed']:
140
+ return f"Task completed! You took {self.prompt_count} steps."
141
+ except:
142
+ updated_state['task_completed'] = 0
143
 
144
  self.user_state = updated_state
145
 
task_specific_data_population.py CHANGED
@@ -17,15 +17,6 @@ class DataPopulation:
17
  )
18
  }
19
  ]
20
- self.feature_update_conversation = [
21
- {
22
- "role": "system",
23
- "content": (
24
- "You are an intelligent assistant specialized in web page management tasks. "
25
- "Your responsibilities is to identify which type of actions (select vs text_input) does each feature represents."
26
- )
27
- }
28
- ]
29
 
30
  def fetch_huggingface_dataset(self, dataset_name):
31
  """Fetch the dataset from Hugging Face."""
@@ -37,7 +28,7 @@ class DataPopulation:
37
  model="gpt-4",
38
  messages=conversation,
39
  max_tokens=1000, # Adjusted max_tokens if needed
40
- temperature=1.0,
41
  )
42
  return response.choices[0].message.content.strip()
43
 
@@ -122,7 +113,10 @@ class DataPopulation:
122
  self.conversation.append({"role": "assistant", "content": updated_user_data})
123
  updated_user_data = json_repair.loads(updated_user_data)
124
  for uid, page_data in updated_user_data.items():
125
- page_details[uid]['user_data'] = page_data['user_data']
 
 
 
126
 
127
  # Step 5: Update user state
128
  updated_user_state = self.ask_to_update_user_state(task, user_state)
 
17
  )
18
  }
19
  ]
 
 
 
 
 
 
 
 
 
20
 
21
  def fetch_huggingface_dataset(self, dataset_name):
22
  """Fetch the dataset from Hugging Face."""
 
28
  model="gpt-4",
29
  messages=conversation,
30
  max_tokens=1000, # Adjusted max_tokens if needed
31
+ temperature=0,
32
  )
33
  return response.choices[0].message.content.strip()
34
 
 
113
  self.conversation.append({"role": "assistant", "content": updated_user_data})
114
  updated_user_data = json_repair.loads(updated_user_data)
115
  for uid, page_data in updated_user_data.items():
116
+ try:
117
+ page_details[uid]['user_data'] = page_data['user_data']
118
+ except:
119
+ continue
120
 
121
  # Step 5: Update user state
122
  updated_user_state = self.ask_to_update_user_state(task, user_state)