harvesthealth commited on
Commit
6299c29
·
verified ·
1 Parent(s): 842f617

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. app.py +43 -10
  2. verify_report_viewer.py +25 -0
  3. verify_tabs.py +35 -0
app.py CHANGED
@@ -65,15 +65,16 @@ def patch_tinytroupe():
65
  content = content.replace("i = 0", "parallel_retry = False\n i = 0")
66
 
67
  # Modify the model call inside the loop
68
- old_call = "response = self._raw_model_call(model, chat_api_params)"
69
- new_call = """if parallel_retry:
 
70
  logger.info("Attempting parallel call to alias-large and alias-huge.")
71
  response = self._raw_model_call_parallel(["alias-large", "alias-huge"], chat_api_params)
72
  if isinstance(response, Exception):
73
  raise response
74
  else:
75
  response = self._raw_model_call(model, chat_api_params)"""
76
- content = content.replace(old_call, new_call)
77
 
78
  # Update the 502 catch block
79
  pattern = r"if isinstance\(e, openai\.APIStatusError\) and e\.status_code == 502 and isinstance\(self, HelmholtzBlabladorClient\):.*?except Exception as fallback_e:.*?logger\.error\(f\"Fallback to OpenAI also failed: \{fallback_e\}\"\)"
@@ -266,6 +267,17 @@ def get_persona_pool():
266
  print(f"Error fetching persona pool: {e}")
267
  return []
268
 
 
 
 
 
 
 
 
 
 
 
 
269
  def upload_persona_to_pool(persona_data):
270
  if not gh:
271
  return
@@ -286,7 +298,22 @@ def upload_persona_to_pool(persona_data):
286
  except Exception as e:
287
  print(f"Error uploading persona to pool: {e}")
288
 
289
- def select_or_create_personas(theme, customer_profile, num_personas, force_method=None):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  if force_method == "DeepPersona":
291
  add_log("Forcing DeepPersona generation...")
292
  personas = []
@@ -296,7 +323,6 @@ def select_or_create_personas(theme, customer_profile, num_personas, force_metho
296
  if len(personas) >= int(num_personas): return personas[:int(num_personas)]
297
  # fallback if some failed
298
  num_personas = int(num_personas) - len(personas)
299
- final_personas_base = personas
300
  elif force_method == "TinyTroupe":
301
  add_log("Forcing TinyTroupe generation...")
302
  return generate_personas_from_tiny_factory(theme, customer_profile, num_personas)
@@ -599,13 +625,13 @@ def generate_tasks(theme, customer_profile):
599
 
600
  return [f"Task {i+1} for {theme} (Manual fallback)" for i in range(10)]
601
 
602
- def handle_generate(theme, customer_profile, num_personas, method):
603
  try:
604
  yield "Generating tasks...", None, None
605
  tasks = generate_tasks(theme, customer_profile)
606
 
607
  yield "Selecting or creating personas...", tasks, None
608
- personas = select_or_create_personas(theme, customer_profile, num_personas, force_method=method)
609
 
610
  yield "Generation complete!", tasks, personas
611
  except Exception as e:
@@ -993,9 +1019,10 @@ def generate_full_ui_call(repo, branch, session_id, selected_solutions_json):
993
  return f"Error reading template: {e}"
994
 
995
  prompt = template.replace("{{selected_solutions}}", selected_solutions_json)
996
- prompt = prompt.replace("{{url}}", "Original Target URL")
997
  prompt = prompt.replace("{{analysis_report}}", "See previous activities in this session")
998
  prompt = prompt.replace("{{report_id}}", session_id[:8])
 
999
 
1000
  headers = {
1001
  "X-Goog-Api-Key": ANALYSIS_API_KEY,
@@ -1103,10 +1130,16 @@ with gr.Blocks(title="UX Analysis Orchestrator") as demo:
1103
  theme_input = gr.Textbox(label="Theme", placeholder="e.g., Communication, Purchase decisions, Information gathering")
1104
  profile_input = gr.Textbox(label="Customer Profile Description", placeholder="Describe the target customer...")
1105
  num_personas_input = gr.Number(label="Number of Personas", value=1, precision=0)
1106
- persona_method = gr.Radio(["TinyTroupe", "DeepPersona"], label="Persona Generation Method", value="TinyTroupe")
 
1107
  url_input = gr.Textbox(label="Target URL", value="https://example.com")
1108
  generate_btn = gr.Button("Generate Personas & Tasks")
1109
 
 
 
 
 
 
1110
  with gr.Column():
1111
  status_output = gr.Textbox(label="Status", interactive=False)
1112
  task_list_display = gr.JSON(label="Tasks")
@@ -1352,7 +1385,7 @@ with gr.Blocks(title="UX Analysis Orchestrator") as demo:
1352
  # Event handlers
1353
  generate_btn.click(
1354
  fn=handle_generate,
1355
- inputs=[theme_input, profile_input, num_personas_input, persona_method],
1356
  outputs=[status_output, task_list_display, persona_display]
1357
  )
1358
 
 
65
  content = content.replace("i = 0", "parallel_retry = False\n i = 0")
66
 
67
  # Modify the model call inside the loop
68
+ if 'if parallel_retry:' not in content:
69
+ old_call = "response = self._raw_model_call(model, chat_api_params)"
70
+ new_call = """if parallel_retry:
71
  logger.info("Attempting parallel call to alias-large and alias-huge.")
72
  response = self._raw_model_call_parallel(["alias-large", "alias-huge"], chat_api_params)
73
  if isinstance(response, Exception):
74
  raise response
75
  else:
76
  response = self._raw_model_call(model, chat_api_params)"""
77
+ content = content.replace(old_call, new_call)
78
 
79
  # Update the 502 catch block
80
  pattern = r"if isinstance\(e, openai\.APIStatusError\) and e\.status_code == 502 and isinstance\(self, HelmholtzBlabladorClient\):.*?except Exception as fallback_e:.*?logger\.error\(f\"Fallback to OpenAI also failed: \{fallback_e\}\"\)"
 
267
  print(f"Error fetching persona pool: {e}")
268
  return []
269
 
270
+ def get_example_personas():
271
+ example_path = "external/TinyTroupe/examples/agents/"
272
+ if not os.path.exists(example_path):
273
+ return []
274
+ try:
275
+ files = [f for f in os.listdir(example_path) if f.endswith(".json")]
276
+ return sorted(files)
277
+ except Exception as e:
278
+ print(f"Error listing example personas: {e}")
279
+ return []
280
+
281
  def upload_persona_to_pool(persona_data):
282
  if not gh:
283
  return
 
298
  except Exception as e:
299
  print(f"Error uploading persona to pool: {e}")
300
 
301
+ def select_or_create_personas(theme, customer_profile, num_personas, force_method=None, example_file=None):
302
+ if force_method == "Example Persona" and example_file:
303
+ add_log(f"Loading example persona from {example_file}...")
304
+ try:
305
+ with open(os.path.join("external/TinyTroupe/examples/agents/", example_file), "r") as f:
306
+ data = json.load(f)
307
+ # Adapt TinyTroupe format to our internal format
308
+ persona = {
309
+ "name": data.get("name", "Unknown"),
310
+ "minibio": data.get("mental_faculties", [{}])[0].get("context", "An example persona.") if "mental_faculties" in data else "An example persona.",
311
+ "persona": data
312
+ }
313
+ return [persona] * int(num_personas)
314
+ except Exception as e:
315
+ add_log(f"Failed to load example persona: {e}")
316
+
317
  if force_method == "DeepPersona":
318
  add_log("Forcing DeepPersona generation...")
319
  personas = []
 
323
  if len(personas) >= int(num_personas): return personas[:int(num_personas)]
324
  # fallback if some failed
325
  num_personas = int(num_personas) - len(personas)
 
326
  elif force_method == "TinyTroupe":
327
  add_log("Forcing TinyTroupe generation...")
328
  return generate_personas_from_tiny_factory(theme, customer_profile, num_personas)
 
625
 
626
  return [f"Task {i+1} for {theme} (Manual fallback)" for i in range(10)]
627
 
628
+ def handle_generate(theme, customer_profile, num_personas, method, example_file):
629
  try:
630
  yield "Generating tasks...", None, None
631
  tasks = generate_tasks(theme, customer_profile)
632
 
633
  yield "Selecting or creating personas...", tasks, None
634
+ personas = select_or_create_personas(theme, customer_profile, num_personas, force_method=method, example_file=example_file)
635
 
636
  yield "Generation complete!", tasks, personas
637
  except Exception as e:
 
1019
  return f"Error reading template: {e}"
1020
 
1021
  prompt = template.replace("{{selected_solutions}}", selected_solutions_json)
1022
+ prompt = prompt.replace("{{url}}", "the analyzed website")
1023
  prompt = prompt.replace("{{analysis_report}}", "See previous activities in this session")
1024
  prompt = prompt.replace("{{report_id}}", session_id[:8])
1025
+ prompt = prompt.replace("{{screenshots_dir}}", f"user_experience_reports/screenshots/{session_id[:8]}")
1026
 
1027
  headers = {
1028
  "X-Goog-Api-Key": ANALYSIS_API_KEY,
 
1130
  theme_input = gr.Textbox(label="Theme", placeholder="e.g., Communication, Purchase decisions, Information gathering")
1131
  profile_input = gr.Textbox(label="Customer Profile Description", placeholder="Describe the target customer...")
1132
  num_personas_input = gr.Number(label="Number of Personas", value=1, precision=0)
1133
+ persona_method = gr.Radio(["Example Persona", "TinyTroupe", "DeepPersona"], label="Persona Generation Method", value="TinyTroupe")
1134
+ example_persona_select = gr.Dropdown(label="Select Example Persona", choices=get_example_personas(), visible=False)
1135
  url_input = gr.Textbox(label="Target URL", value="https://example.com")
1136
  generate_btn = gr.Button("Generate Personas & Tasks")
1137
 
1138
+ def update_method_visibility(method):
1139
+ return gr.update(visible=(method == "Example Persona"))
1140
+
1141
+ persona_method.change(fn=update_method_visibility, inputs=[persona_method], outputs=[example_persona_select])
1142
+
1143
  with gr.Column():
1144
  status_output = gr.Textbox(label="Status", interactive=False)
1145
  task_list_display = gr.JSON(label="Tasks")
 
1385
  # Event handlers
1386
  generate_btn.click(
1387
  fn=handle_generate,
1388
+ inputs=[theme_input, profile_input, num_personas_input, persona_method, example_persona_select],
1389
  outputs=[status_output, task_list_display, persona_display]
1390
  )
1391
 
verify_report_viewer.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ from playwright.async_api import async_playwright
3
+
4
+ async def run():
5
+ async with async_playwright() as p:
6
+ browser = await p.chromium.launch()
7
+ page = await browser.new_page()
8
+ await page.goto("http://localhost:7860")
9
+
10
+ # Wait for Gradio to load
11
+ await page.wait_for_selector("button:has-text('Report Viewer')", state='visible')
12
+
13
+ # Click Report Viewer
14
+ await page.evaluate("""
15
+ Array.from(document.querySelectorAll('button')).find(el => el.textContent === 'Report Viewer').click()
16
+ """)
17
+ await asyncio.sleep(2)
18
+
19
+ # The Report Viewer might be empty if no reports exist.
20
+ # I'll check if there's any content or at least the dropdown.
21
+ await page.screenshot(path="/home/jules/verification/report_viewer_tab.png")
22
+
23
+ await browser.close()
24
+
25
+ asyncio.run(run())
verify_tabs.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ from playwright.async_api import async_playwright
3
+
4
+ async def run():
5
+ async with async_playwright() as p:
6
+ browser = await p.chromium.launch()
7
+ page = await browser.new_page()
8
+ await page.goto("http://localhost:7860")
9
+
10
+ # Wait for Gradio to load
11
+ await page.wait_for_selector("button:has-text('Average User Journey Heatmaps')", state='visible')
12
+
13
+ async def click_tab(name):
14
+ print(f"Clicking {name}...")
15
+ await page.evaluate(f"""
16
+ const btns = Array.from(document.querySelectorAll('button')).filter(el => el.textContent.includes('{name}'));
17
+ btns.forEach(btn => btn.click());
18
+ """)
19
+ await asyncio.sleep(2)
20
+
21
+ # Screenshot Heatmaps tab
22
+ await click_tab('Average User Journey Heatmaps')
23
+ await page.screenshot(path="/home/jules/verification/heatmaps_tab.png")
24
+
25
+ # Screenshot Agents.txt tab
26
+ await click_tab('Agents.txt')
27
+ await page.screenshot(path="/home/jules/verification/agents_tab.png")
28
+
29
+ # Screenshot Full New UI tab
30
+ await click_tab('Full New UI')
31
+ await page.screenshot(path="/home/jules/verification/full_ui_tab.png")
32
+
33
+ await browser.close()
34
+
35
+ asyncio.run(run())