Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from chatbot_simulator import ChatbotSimulation | |
| from datasets import load_dataset | |
| import json_repair | |
| import random | |
| import os | |
| import re | |
| import firebase_admin | |
| from firebase_admin import credentials, firestore | |
| import json | |
| os.environ["TOKENIZERS_PARALLELISM"] = "false" | |
| cred = credentials.Certificate(json.loads(os.getenv("Firebase_JSON"))) | |
| firebase_admin.initialize_app(cred) | |
| db = firestore.client() | |
| openai_api_key = os.getenv("OPENAI_API_KEY") | |
| def find_random_incomplete_task(app_name): | |
| collection_ref = db.collection(app_name) | |
| incomplete_indices = [] | |
| for doc in collection_ref.stream(): | |
| task_data = doc.to_dict() | |
| if task_data['task_completed'] is None and task_data['task_completed_steps'] is None: | |
| _, idx = doc.id.split('_') | |
| idx = int(idx) | |
| incomplete_indices.append(idx) | |
| # Check if any incomplete tasks found | |
| if not incomplete_indices: | |
| return None | |
| # Pick a random incomplete index from the list | |
| random_idx = random.choice(incomplete_indices) | |
| return random_idx | |
| def write_task_data(app_name, idx, task, task_complete, task_completed_step, trajectory): | |
| doc_ref = db.collection(app_name).document(f"{app_name}_{idx}") | |
| doc_ref.set({ | |
| "task": task, | |
| "task_completed": task_complete, | |
| "task_completed_steps": task_completed_step, | |
| "trajectory": trajectory | |
| }) | |
| class AppSimulator: | |
| def __init__(self, openai_api_key): | |
| self.simulation = None | |
| self.openai_api_key = openai_api_key | |
| self.app_name = None | |
| self.smallest_index = None | |
| self.task = None | |
| def initialize_simulator(self, sitemap_url, progress=gr.Progress(track_tqdm=True)): | |
| """Initialize the simulator with retries and elapsed time tracking.""" | |
| synthetic_sitemap = load_dataset(sitemap_url, "schema", split='train') | |
| app_name, app_description, sitemap, relevant_tables_per_page, jinjia_prerender_page = None, None, None, None, None | |
| for row in synthetic_sitemap: | |
| if row['name'] == 'app_name': | |
| app_name = row['value'] | |
| elif row['name'] == 'app_description': | |
| app_description = row['value'] | |
| elif row['name'] == 'sitemap': | |
| sitemap = json_repair.loads(row['value']) | |
| elif row['name'] == 'relevant_tables_per_page': | |
| relevant_tables_per_page = json_repair.loads(row['value']) | |
| elif row['name'] == 'jinjia_prerender_pages': | |
| jinjia_prerender_page = json_repair.loads(row['value']) | |
| self.app_name = app_name | |
| smallest_index = find_random_incomplete_task(app_name) | |
| if smallest_index is None: | |
| return "All tasks in this app have been completed!" | |
| self.smallest_index = smallest_index | |
| synthetic_tasks = load_dataset(sitemap_url, "tasks", split='train') | |
| random_index = random.randint(0, len(synthetic_tasks) - 1) # Generate a random index | |
| random_row = synthetic_tasks[random_index] | |
| task = random_row['task'] | |
| solution = random_row['solution'] | |
| database = random_row['database'] | |
| self.task = task | |
| self.simulation = ChatbotSimulation( | |
| app_name=app_name, | |
| app_description=app_description, | |
| site_map=sitemap, | |
| relevant_tables_per_page=relevant_tables_per_page, | |
| database=database, | |
| jinjia_prerender_page=jinjia_prerender_page, | |
| task=task, | |
| solution=solution, | |
| log_location=f'conversation_log_{app_name}.txt', | |
| openai_api_key=openai_api_key, | |
| agent='Human' | |
| ) | |
| initial_message = self.simulation.start_conversation() | |
| progress.update("Initialization Successful") | |
| return initial_message # Return the initial assistant message for chat | |
| def chat_interaction(self, user_input, history): | |
| """Handle one round of conversation.""" | |
| return self.simulation.one_conversation_round(user_input) | |
| def chat(user_input, history, simulator_app): | |
| """Chat handler that validates input and interacts with the simulator.""" | |
| response = simulator_app.chat_interaction(user_input, history) | |
| # Initialize variables for task completion and steps | |
| # Define the pattern for matching the response | |
| pattern = r"Task completed! You took (\d+) steps\." | |
| match = re.match(pattern, response) | |
| if match: | |
| task_complete = 1 | |
| task_completed_step = int(match.group(1)) | |
| app_name = simulator_app.app_name | |
| idx = simulator_app.smallest_index | |
| task = simulator_app.task | |
| trajectory = simulator_app.simulation.trajectory | |
| write_task_data(app_name, idx, task, task_complete, task_completed_step, trajectory) | |
| return response | |
| def give_up(simulator_app): | |
| """Handle the Give-Up action by marking the first incomplete task as abandoned.""" | |
| task_completed = 0 | |
| task_completed_steps = 0 | |
| app_name = simulator_app.app_name | |
| idx = simulator_app.smallest_index | |
| task = simulator_app.task | |
| trajectory = simulator_app.simulation.trajectory | |
| write_task_data(app_name, idx, task, task_completed, task_completed_steps, trajectory) | |
| return "Task marked as abandoned (Give-Up action)." | |
| # Gradio Interface using ChatInterface | |
| with gr.Blocks(fill_height=True) as demo: | |
| # Simulator instance stored in gr.State for each session | |
| simulator_state = gr.State(AppSimulator(openai_api_key=openai_api_key)) | |
| gr.Markdown("## Simulator Setup") | |
| # Input fields for initialization | |
| sitemap_input = gr.Textbox(label="Sitemap", placeholder="Enter the Hugging Face link to sitemap... (eg.jjz5463/AppStore_synthetic_sitemap)") | |
| initialize_button = gr.Button("Initialize Simulator") | |
| # Status block to display initialization progress with elapsed time | |
| status = gr.Textbox(label="Status", interactive=False) | |
| # Chat interface to handle user interactions | |
| chat_interface = gr.ChatInterface( | |
| fn=chat, | |
| type="messages", | |
| additional_inputs=[simulator_state] | |
| ) | |
| give_up_button = gr.Button("Give Up") | |
| # Define the callback function to initialize the simulator and update status | |
| def initialize_and_start_chat(sitemap, simulator_app): | |
| return simulator_app.initialize_simulator(sitemap) # Use progress tracking | |
| # Set up the button click to initialize simulator and update status only | |
| initialize_button.click( | |
| fn=initialize_and_start_chat, | |
| inputs=[sitemap_input, simulator_state], | |
| outputs=status # Update only the status block | |
| ) | |
| # Set up the Give-Up button click to update the dataset | |
| give_up_button.click( | |
| fn=give_up, | |
| inputs=[simulator_state], | |
| outputs=status # Update the status with the give-up message | |
| ) | |
| # Launch the app | |
| demo.launch() | |