Ryan commited on
Commit
a800293
·
1 Parent(s): 14bac19
.DS_Store CHANGED
Binary files a/.DS_Store and b/.DS_Store differ
 
_archive/app copy.py DELETED
@@ -1,355 +0,0 @@
1
- import gradio as gr
2
- from ui.dataset_input import create_dataset_input, load_example_dataset
3
- from ui.analysis_screen import create_analysis_screen, process_analysis_request
4
- from visualization.bow_visualizer import process_and_visualize_analysis
5
- import nltk
6
- import os
7
- import json
8
-
9
- # Download necessary NLTK resources function remains unchanged
10
- def download_nltk_resources():
11
- """Download required NLTK resources if not already downloaded"""
12
- try:
13
- # Create nltk_data directory in the user's home directory if it doesn't exist
14
- nltk_data_path = os.path.expanduser("~/nltk_data")
15
- os.makedirs(nltk_data_path, exist_ok=True)
16
-
17
- # Add this path to NLTK's data path
18
- nltk.data.path.append(nltk_data_path)
19
-
20
- # Download required resources
21
- resources = ['punkt', 'wordnet', 'stopwords', 'punkt_tab']
22
- for resource in resources:
23
- try:
24
- # Different resources can be in different directories in NLTK
25
- locations = [
26
- f'tokenizers/{resource}',
27
- f'corpora/{resource}',
28
- f'taggers/{resource}',
29
- f'{resource}'
30
- ]
31
-
32
- found = False
33
- for location in locations:
34
- try:
35
- nltk.data.find(location)
36
- print(f"Resource {resource} already downloaded")
37
- found = True
38
- break
39
- except LookupError:
40
- continue
41
-
42
- if not found:
43
- print(f"Downloading {resource}...")
44
- nltk.download(resource, quiet=True)
45
- except Exception as e:
46
- print(f"Error with resource {resource}: {e}")
47
-
48
- print("NLTK resources check completed")
49
- except Exception as e:
50
- print(f"Error downloading NLTK resources: {e}")
51
-
52
- def create_app():
53
- """
54
- Create a streamlined Gradio app for dataset input and Bag of Words analysis.
55
-
56
- Returns:
57
- gr.Blocks: The Gradio application
58
- """
59
- with gr.Blocks(title="LLM Response Comparator") as app:
60
- # Application state to share data between tabs
61
- dataset_state = gr.State({})
62
- analysis_results_state = gr.State({})
63
-
64
- # Dataset Input Tab
65
- with gr.Tab("Dataset Input"):
66
- dataset_inputs, example_dropdown, load_example_btn, create_btn, prompt, response1, model1, response2, model2 = create_dataset_input()
67
-
68
- # Add status indicator to show when dataset is created
69
- dataset_status = gr.Markdown("*No dataset loaded*")
70
-
71
- # Load example dataset
72
- load_example_btn.click(
73
- fn=load_example_dataset,
74
- inputs=[example_dropdown],
75
- outputs=[prompt, response1, model1, response2, model2] # Update all field values
76
- )
77
-
78
- # Save dataset to state and update status
79
- def create_dataset(p, r1, m1, r2, m2):
80
- if not p or not r1 or not r2:
81
- return {}, "❌ **Error:** Please fill in at least the prompt and both responses"
82
-
83
- dataset = {
84
- "entries": [
85
- {"prompt": p, "response": r1, "model": m1 or "Model 1"},
86
- {"prompt": p, "response": r2, "model": m2 or "Model 2"}
87
- ]
88
- }
89
- return dataset, "✅ **Dataset created successfully!** You can now go to the Analysis tab"
90
-
91
- create_btn.click(
92
- fn=create_dataset,
93
- inputs=[prompt, response1, model1, response2, model2],
94
- outputs=[dataset_state, dataset_status]
95
- )
96
-
97
- # Analysis Tab
98
- with gr.Tab("Analysis"):
99
- # Use create_analysis_screen to get UI components including visualization container
100
- analysis_options, analysis_params, run_analysis_btn, analysis_output, bow_top_slider = create_analysis_screen()
101
-
102
- # Pre-create visualization components (initially hidden)
103
- visualization_area_visible = gr.Checkbox(value=False, visible=False, label="Visualization Visible")
104
- analysis_title = gr.Markdown("## Analysis Results", visible=False)
105
- prompt_title = gr.Markdown(visible=False)
106
- models_compared = gr.Markdown(visible=False)
107
-
108
- # Container for model 1 words
109
- model1_title = gr.Markdown(visible=False)
110
- model1_words = gr.Markdown(visible=False)
111
-
112
- # Container for model 2 words
113
- model2_title = gr.Markdown(visible=False)
114
- model2_words = gr.Markdown(visible=False)
115
-
116
- # Similarity metrics
117
- similarity_metrics_title = gr.Markdown("### Similarity Metrics", visible=False)
118
- similarity_metrics = gr.Markdown(visible=False)
119
-
120
- # Status or error message area
121
- status_message_visible = gr.Checkbox(value=False, visible=False, label="Status Message Visible")
122
- status_message = gr.Markdown(visible=False)
123
-
124
- # Define a helper function to extract parameter values and run the analysis
125
- def run_analysis(dataset, selected_analyses, bow_top, ngram_n, ngram_top):
126
- try:
127
- if not dataset or "entries" not in dataset or not dataset["entries"]:
128
- return (
129
- {}, # analysis_results_state
130
- False, # analysis_output visibility
131
- False, # visualization_area_visible
132
- gr.update(visible=False), # analysis_title
133
- gr.update(visible=False), # prompt_title
134
- gr.update(visible=False), # models_compared
135
- gr.update(visible=False), # model1_title
136
- gr.update(visible=False), # model1_words
137
- gr.update(visible=False), # model2_title
138
- gr.update(visible=False), # model2_words
139
- gr.update(visible=False), # similarity_metrics_title
140
- gr.update(visible=False), # similarity_metrics
141
- True, # status_message_visible
142
- gr.update(visible=True, value="❌ **Error:** No dataset loaded. Please create or load a dataset first.") # status_message
143
- )
144
-
145
- parameters = {
146
- "bow_top": bow_top,
147
- "ngram_n": ngram_n,
148
- "ngram_top": ngram_top
149
- }
150
- print("Running analysis with parameters:", parameters)
151
-
152
- # Process the analysis request
153
- analysis_results, _ = process_analysis_request(dataset, selected_analyses, parameters)
154
-
155
- # If there's an error or no results
156
- if not analysis_results or "analyses" not in analysis_results or not analysis_results["analyses"]:
157
- return (
158
- analysis_results,
159
- False,
160
- False,
161
- gr.update(visible=False),
162
- gr.update(visible=False),
163
- gr.update(visible=False),
164
- gr.update(visible=False),
165
- gr.update(visible=False),
166
- gr.update(visible=False),
167
- gr.update(visible=False),
168
- gr.update(visible=False),
169
- gr.update(visible=False),
170
- True,
171
- gr.update(visible=True, value="❌ **No results found.** Try different analysis options.")
172
- )
173
-
174
- # Extract information to display in components
175
- prompt = list(analysis_results["analyses"].keys())[0]
176
- analyses = analysis_results["analyses"][prompt]
177
-
178
- if "bag_of_words" not in analyses:
179
- return (
180
- analysis_results,
181
- False,
182
- False,
183
- gr.update(visible=False),
184
- gr.update(visible=False),
185
- gr.update(visible=False),
186
- gr.update(visible=False),
187
- gr.update(visible=False),
188
- gr.update(visible=False),
189
- gr.update(visible=False),
190
- gr.update(visible=False),
191
- gr.update(visible=False),
192
- True,
193
- gr.update(visible=True, value="❌ **No Bag of Words analysis found.** Make sure to select it in the options.")
194
- )
195
-
196
- bow_results = analyses["bag_of_words"]
197
- models = bow_results.get("models", [])
198
-
199
- if len(models) < 2:
200
- return (
201
- analysis_results,
202
- False,
203
- False,
204
- gr.update(visible=False),
205
- gr.update(visible=False),
206
- gr.update(visible=False),
207
- gr.update(visible=False),
208
- gr.update(visible=False),
209
- gr.update(visible=False),
210
- gr.update(visible=False),
211
- gr.update(visible=False),
212
- gr.update(visible=False),
213
- True,
214
- gr.update(visible=True, value="❌ **Not enough models to compare.** Please ensure you have two model responses.")
215
- )
216
-
217
- # Extract and format information for display
218
- model1_name = models[0]
219
- model2_name = models[1]
220
-
221
- # Format important words for each model
222
- important_words = bow_results.get("important_words", {})
223
- model1_words_text = "No important words found"
224
- model2_words_text = "No important words found"
225
-
226
- if model1_name in important_words:
227
- word_list = [f"**{item['word']}** ({item['count']})" for item in important_words[model1_name][:10]]
228
- model1_words_text = ", ".join(word_list)
229
-
230
- if model2_name in important_words:
231
- word_list = [f"**{item['word']}** ({item['count']})" for item in important_words[model2_name][:10]]
232
- model2_words_text = ", ".join(word_list)
233
-
234
- # Format similarity metrics
235
- similarity_text = "No similarity metrics found"
236
- comparisons = bow_results.get("comparisons", {})
237
- comparison_key = f"{model1_name} vs {model2_name}"
238
-
239
- if comparison_key in comparisons:
240
- metrics = comparisons[comparison_key]
241
- cosine = metrics.get("cosine_similarity", 0)
242
- jaccard = metrics.get("jaccard_similarity", 0)
243
- semantic = metrics.get("semantic_similarity", 0) # Add semantic similarity
244
- common_words = metrics.get("common_word_count", 0)
245
-
246
- similarity_text = f"""
247
- - **Cosine Similarity**: {cosine:.2f} (higher means more similar word frequency patterns)
248
- - **Jaccard Similarity**: {jaccard:.2f} (higher means more word overlap)
249
- - **Semantic Similarity**: {semantic:.2f} (higher means more similar meaning)
250
- - **Common Words**: {common_words} words appear in both responses
251
- """
252
-
253
- # Return all updated component values
254
- return (
255
- analysis_results, # analysis_results_state
256
- False, # analysis_output visibility
257
- True, # visualization_area_visible
258
- gr.update(visible=True), # analysis_title
259
- gr.update(visible=True, value=f"## Analysis of Prompt: \"{prompt[:100]}...\""), # prompt_title
260
- gr.update(visible=True, value=f"### Comparing responses from {model1_name} and {model2_name}"), # models_compared
261
- gr.update(visible=True, value=f"#### Top Words Used by {model1_name}"), # model1_title
262
- gr.update(visible=True, value=model1_words_text), # model1_words
263
- gr.update(visible=True, value=f"#### Top Words Used by {model2_name}"), # model2_title
264
- gr.update(visible=True, value=model2_words_text), # model2_words
265
- gr.update(visible=True), # similarity_metrics_title
266
- gr.update(visible=True, value=similarity_text), # similarity_metrics
267
- False, # status_message_visible
268
- gr.update(visible=False) # status_message
269
- )
270
-
271
- except Exception as e:
272
- import traceback
273
- error_msg = f"Error in analysis: {str(e)}\n{traceback.format_exc()}"
274
- print(error_msg)
275
-
276
- return (
277
- {"error": error_msg}, # analysis_results_state
278
- True, # analysis_output visibility (show raw JSON for debugging)
279
- False, # visualization_area_visible
280
- gr.update(visible=False),
281
- gr.update(visible=False),
282
- gr.update(visible=False),
283
- gr.update(visible=False),
284
- gr.update(visible=False),
285
- gr.update(visible=False),
286
- gr.update(visible=False),
287
- gr.update(visible=False),
288
- gr.update(visible=False),
289
- True, # status_message_visible
290
- gr.update(visible=True, value=f"❌ **Error during analysis:**\n\n```\n{str(e)}\n```") # status_message
291
- )
292
-
293
- # Function to update visibility based on checkbox state
294
- def update_visibility(viz_visible, status_visible):
295
- return [
296
- gr.update(visible=viz_visible), # analysis_title
297
- gr.update(visible=viz_visible), # prompt_title
298
- gr.update(visible=viz_visible), # models_compared
299
- gr.update(visible=viz_visible), # model1_title
300
- gr.update(visible=viz_visible), # model1_words
301
- gr.update(visible=viz_visible), # model2_title
302
- gr.update(visible=viz_visible), # model2_words
303
- gr.update(visible=viz_visible), # similarity_metrics_title
304
- gr.update(visible=viz_visible), # similarity_metrics
305
- gr.update(visible=status_visible) # status_message
306
- ]
307
-
308
- # Connect visibility checkboxes to update function
309
- visualization_area_visible.change(
310
- fn=update_visibility,
311
- inputs=[visualization_area_visible, status_message_visible],
312
- outputs=[
313
- analysis_title,
314
- prompt_title,
315
- models_compared,
316
- model1_title,
317
- model1_words,
318
- model2_title,
319
- model2_words,
320
- similarity_metrics_title,
321
- similarity_metrics,
322
- status_message
323
- ]
324
- )
325
-
326
- # Run analysis with proper parameters
327
- run_analysis_btn.click(
328
- fn=run_analysis,
329
- inputs=[dataset_state, analysis_options, bow_top_slider, ngram_n, ngram_top],
330
- outputs=[
331
- analysis_results_state,
332
- analysis_output,
333
- visualization_area_visible,
334
- analysis_title,
335
- prompt_title,
336
- models_compared,
337
- model1_title,
338
- model1_words,
339
- model2_title,
340
- model2_words,
341
- similarity_metrics_title,
342
- similarity_metrics,
343
- status_message_visible,
344
- status_message
345
- ]
346
- )
347
-
348
- return app
349
-
350
- if __name__ == "__main__":
351
- # Download required NLTK resources before launching the app
352
- download_nltk_resources()
353
-
354
- app = create_app()
355
- app.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
_archive/app.py DELETED
@@ -1,63 +0,0 @@
1
- import gradio as gr
2
- import os
3
- from ui.dataset_input import create_dataset_input, load_example_dataset
4
- from ui.analysis_screen import process_analysis_request
5
-
6
- def create_app():
7
- """
8
- Create a streamlined Gradio app for dataset input and Bag of Words analysis.
9
-
10
- Returns:
11
- gr.Blocks: The Gradio application
12
- """
13
- with gr.Blocks(title="LLM Response Comparator") as app:
14
- # Application state to share data between tabs
15
- dataset_state = gr.State({})
16
- analysis_results_state = gr.State({})
17
-
18
- # Dataset Input Tab
19
- with gr.Tab("Dataset Input"):
20
- dataset_inputs, example_dropdown, load_example_btn, create_btn, prompt, response1, model1, response2, model2 = create_dataset_input()
21
-
22
- # Load example dataset
23
- load_example_btn.click(
24
- fn=load_example_dataset,
25
- inputs=[example_dropdown],
26
- outputs=[dataset_inputs] # Ensure `load_example_dataset` returns compatible data
27
- )
28
-
29
- # Save dataset to state
30
- create_btn.click(
31
- fn=lambda p, r1, m1, r2, m2: {
32
- "entries": [
33
- {"prompt": p, "response": r1, "model": m1},
34
- {"prompt": p, "response": r2, "model": m2}
35
- ]
36
- },
37
- inputs=[prompt, response1, model1, response2, model2], # Ensure these are valid Gradio components
38
- outputs=[dataset_state] # Ensure `dataset_state` is correctly defined
39
- )
40
-
41
- # Analysis Tab
42
- with gr.Tab("Analysis"):
43
- analysis_options = gr.CheckboxGroup(
44
- choices=["Bag of Words"],
45
- value=["Bag of Words"],
46
- label="Select Analyses to Run"
47
- )
48
- run_analysis_btn = gr.Button("Run Analysis", variant="primary")
49
- analysis_output = gr.JSON(label="Analysis Results", visible=False)
50
-
51
- # Run analysis
52
- run_analysis_btn.click(
53
- fn=process_analysis_request,
54
- inputs=[dataset_state, analysis_options], # Removed None
55
- outputs=[analysis_results_state, analysis_output]
56
- )
57
-
58
- return app
59
-
60
- if __name__ == "__main__":
61
- # Create and launch the app
62
- app = create_app()
63
- app.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app.bak.py DELETED
@@ -1,7 +0,0 @@
1
- import gradio as gr
2
-
3
- def greet(name):
4
- return "Hello " + name + "!!"
5
-
6
- demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7
- demo.launch()
 
 
 
 
 
 
 
 
app.py CHANGED
@@ -97,7 +97,7 @@ def create_app():
97
  # Analysis Tab
98
  with gr.Tab("Analysis"):
99
  # Use create_analysis_screen to get UI components including visualization container
100
- analysis_options, analysis_params, run_analysis_btn, analysis_output, bow_top_slider, ngram_n, ngram_top = create_analysis_screen()
101
 
102
  # Pre-create visualization components (initially hidden)
103
  visualization_area_visible = gr.Checkbox(value=False, visible=False, label="Visualization Visible")
@@ -122,7 +122,7 @@ def create_app():
122
  status_message = gr.Markdown(visible=False)
123
 
124
  # Define a helper function to extract parameter values and run the analysis
125
- def run_analysis(dataset, selected_analyses, bow_top, ngram_n, ngram_top):
126
  try:
127
  if not dataset or "entries" not in dataset or not dataset["entries"]:
128
  return (
@@ -145,12 +145,14 @@ def create_app():
145
  parameters = {
146
  "bow_top": bow_top,
147
  "ngram_n": ngram_n,
148
- "ngram_top": ngram_top
 
149
  }
150
- print("Running analysis with parameters:", parameters)
 
151
 
152
- # Process the analysis request
153
- analysis_results, _ = process_analysis_request(dataset, selected_analyses, parameters)
154
 
155
  # If there's an error or no results
156
  if not analysis_results or "analyses" not in analysis_results or not analysis_results["analyses"]:
@@ -168,7 +170,7 @@ def create_app():
168
  gr.update(visible=False),
169
  gr.update(visible=False),
170
  True,
171
- gr.update(visible=True, value="❌ **No results found.** Try different analysis options.")
172
  )
173
 
174
  # Extract information to display in components
@@ -196,6 +198,25 @@ def create_app():
196
  similarity_metrics_visible = False
197
  similarity_metrics_value = ""
198
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  # Check for Bag of Words analysis
200
  if "bag_of_words" in analyses:
201
  visualization_area_visible = True
@@ -252,8 +273,8 @@ def create_app():
252
  - **Common Words**: {common_words} words appear in both responses
253
  """
254
 
255
- # Check for N-gram analysis (if not found, we'll fallback to BOW)
256
- if "ngram_analysis" in analyses and not visualization_area_visible:
257
  visualization_area_visible = True
258
  ngram_results = analyses["ngram_analysis"]
259
  models = ngram_results.get("models", [])
@@ -304,6 +325,78 @@ def create_app():
304
  - **Common {size_name}**: {common_count} {size_name.lower()} appear in both responses
305
  """
306
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
  # If we don't have visualization data from any analysis
308
  if not visualization_area_visible:
309
  return (
@@ -320,7 +413,7 @@ def create_app():
320
  gr.update(visible=False),
321
  gr.update(visible=False),
322
  True,
323
- gr.update(visible=True, value="❌ **No visualization data found.** Make sure to select at least one analysis type.")
324
  )
325
 
326
  # Return all updated component values
@@ -363,60 +456,59 @@ def create_app():
363
  gr.update(visible=True, value=f"❌ **Error during analysis:**\n\n```\n{str(e)}\n```") # status_message
364
  )
365
 
366
- # Function to update visibility based on checkbox state
367
- def update_visibility(viz_visible, status_visible):
368
- return [
369
- gr.update(visible=viz_visible), # analysis_title
370
- gr.update(visible=viz_visible), # prompt_title
371
- gr.update(visible=viz_visible), # models_compared
372
- gr.update(visible=viz_visible), # model1_title
373
- gr.update(visible=viz_visible), # model1_words
374
- gr.update(visible=viz_visible), # model2_title
375
- gr.update(visible=viz_visible), # model2_words
376
- gr.update(visible=viz_visible), # similarity_metrics_title
377
- gr.update(visible=viz_visible), # similarity_metrics
378
- gr.update(visible=status_visible) # status_message
379
- ]
380
 
381
- # Connect visibility checkboxes to update function
382
- visualization_area_visible.change(
383
- fn=update_visibility,
384
- inputs=[visualization_area_visible, status_message_visible],
385
- outputs=[
386
- analysis_title,
387
- prompt_title,
388
- models_compared,
389
- model1_title,
390
- model1_words,
391
- model2_title,
392
- model2_words,
393
- similarity_metrics_title,
394
- similarity_metrics,
395
- status_message
396
- ]
397
- )
398
 
399
- # Run analysis with proper parameters
400
- run_analysis_btn.click(
401
- fn=run_analysis,
402
- inputs=[dataset_state, analysis_options, bow_top_slider, ngram_n, ngram_top],
403
- outputs=[
404
- analysis_results_state,
405
- analysis_output,
406
- visualization_area_visible,
407
- analysis_title,
408
- prompt_title,
409
- models_compared,
410
- model1_title,
411
- model1_words,
412
- model2_title,
413
- model2_words,
414
- similarity_metrics_title,
415
- similarity_metrics,
416
- status_message_visible,
417
- status_message
418
- ]
419
- )
420
 
421
  return app
422
 
@@ -425,4 +517,4 @@ if __name__ == "__main__":
425
  download_nltk_resources()
426
 
427
  app = create_app()
428
- app.launch()
 
97
  # Analysis Tab
98
  with gr.Tab("Analysis"):
99
  # Use create_analysis_screen to get UI components including visualization container
100
+ analysis_options, analysis_params, run_analysis_btn, analysis_output, bow_top_slider, ngram_n, ngram_top, topic_count = create_analysis_screen()
101
 
102
  # Pre-create visualization components (initially hidden)
103
  visualization_area_visible = gr.Checkbox(value=False, visible=False, label="Visualization Visible")
 
122
  status_message = gr.Markdown(visible=False)
123
 
124
  # Define a helper function to extract parameter values and run the analysis
125
+ def run_analysis(dataset, selected_analysis, bow_top, ngram_n, ngram_top, topic_count):
126
  try:
127
  if not dataset or "entries" not in dataset or not dataset["entries"]:
128
  return (
 
145
  parameters = {
146
  "bow_top": bow_top,
147
  "ngram_n": ngram_n,
148
+ "ngram_top": ngram_top,
149
+ "topic_count": topic_count
150
  }
151
+ print(f"Running analysis with selected type: {selected_analysis}")
152
+ print("Parameters:", parameters)
153
 
154
+ # Process the analysis request - note we're now passing selected_analysis as a string, not a list
155
+ analysis_results, _ = process_analysis_request(dataset, selected_analysis, parameters)
156
 
157
  # If there's an error or no results
158
  if not analysis_results or "analyses" not in analysis_results or not analysis_results["analyses"]:
 
170
  gr.update(visible=False),
171
  gr.update(visible=False),
172
  True,
173
+ gr.update(visible=True, value="❌ **No results found.** Try a different analysis option.")
174
  )
175
 
176
  # Extract information to display in components
 
198
  similarity_metrics_visible = False
199
  similarity_metrics_value = ""
200
 
201
+ # Check for messages from placeholder analyses
202
+ if "message" in analyses:
203
+ return (
204
+ analysis_results,
205
+ False,
206
+ False,
207
+ gr.update(visible=False),
208
+ gr.update(visible=False),
209
+ gr.update(visible=False),
210
+ gr.update(visible=False),
211
+ gr.update(visible=False),
212
+ gr.update(visible=False),
213
+ gr.update(visible=False),
214
+ gr.update(visible=False),
215
+ gr.update(visible=False),
216
+ True,
217
+ gr.update(visible=True, value=f"ℹ️ **{analyses['message']}**")
218
+ )
219
+
220
  # Check for Bag of Words analysis
221
  if "bag_of_words" in analyses:
222
  visualization_area_visible = True
 
273
  - **Common Words**: {common_words} words appear in both responses
274
  """
275
 
276
+ # Check for N-gram analysis
277
+ if "ngram_analysis" in analyses:
278
  visualization_area_visible = True
279
  ngram_results = analyses["ngram_analysis"]
280
  models = ngram_results.get("models", [])
 
325
  - **Common {size_name}**: {common_count} {size_name.lower()} appear in both responses
326
  """
327
 
328
+ # Check for Topic Modeling analysis
329
+ if "topic_modeling" in analyses:
330
+ visualization_area_visible = True
331
+ topic_results = analyses["topic_modeling"]
332
+ models = topic_results.get("models", [])
333
+ method = topic_results.get("method", "lda").upper()
334
+ n_topics = topic_results.get("n_topics", 3)
335
+
336
+ if len(models) >= 2:
337
+ prompt_title_visible = True
338
+ prompt_title_value = f"## Analysis of Prompt: \"{prompt[:100]}...\""
339
+
340
+ models_compared_visible = True
341
+ models_compared_value = f"### Topic Modeling Analysis ({method}, {n_topics} topics)"
342
+
343
+ # Extract and format topic information
344
+ topics = topic_results.get("topics", [])
345
+
346
+ if topics:
347
+ # Format topic info for display
348
+ topic_info = []
349
+ for topic in topics[:3]: # Show first 3 topics
350
+ topic_id = topic.get("id", 0)
351
+ words = topic.get("words", [])[:5] # Top 5 words per topic
352
+
353
+ if words:
354
+ topic_info.append(f"**Topic {topic_id+1}**: {', '.join(words)}")
355
+
356
+ if topic_info:
357
+ model1_title_visible = True
358
+ model1_title_value = "#### Discovered Topics"
359
+ model1_words_visible = True
360
+ model1_words_value = "\n".join(topic_info)
361
+
362
+ # Get topic distributions for models
363
+ model_topics = topic_results.get("model_topics", {})
364
+
365
+ if model_topics:
366
+ model1_name = models[0]
367
+ model2_name = models[1]
368
+
369
+ # Format topic distribution info
370
+ if model1_name in model_topics and model2_name in model_topics:
371
+ model2_title_visible = True
372
+ model2_title_value = "#### Topic Distribution"
373
+ model2_words_visible = True
374
+
375
+ # Simple distribution display
376
+ dist1 = model_topics[model1_name]
377
+ dist2 = model_topics[model2_name]
378
+
379
+ model2_words_value = f"""
380
+ **{model1_name}**: {', '.join([f"Topic {i+1}: {v:.2f}" for i, v in enumerate(dist1[:3])])}
381
+
382
+ **{model2_name}**: {', '.join([f"Topic {i+1}: {v:.2f}" for i, v in enumerate(dist2[:3])])}
383
+ """
384
+
385
+ # Add similarity metrics if available
386
+ comparisons = topic_results.get("comparisons", {})
387
+ if comparisons:
388
+ comparison_key = f"{model1_name} vs {model2_name}"
389
+
390
+ if comparison_key in comparisons:
391
+ metrics = comparisons[comparison_key]
392
+ js_div = metrics.get("js_divergence", 0)
393
+
394
+ similarity_title_visible = True
395
+ similarity_metrics_visible = True
396
+ similarity_metrics_value = f"""
397
+ - **Topic Distribution Divergence**: {js_div:.4f} (lower means more similar topic distributions)
398
+ """
399
+
400
  # If we don't have visualization data from any analysis
401
  if not visualization_area_visible:
402
  return (
 
413
  gr.update(visible=False),
414
  gr.update(visible=False),
415
  True,
416
+ gr.update(visible=True, value="❌ **No visualization data found.** Make sure to select a valid analysis option.")
417
  )
418
 
419
  # Return all updated component values
 
456
  gr.update(visible=True, value=f"❌ **Error during analysis:**\n\n```\n{str(e)}\n```") # status_message
457
  )
458
 
459
+ def update_visibility(viz_visible, status_visible):
460
+ return [
461
+ gr.update(visible=viz_visible), # analysis_title
462
+ gr.update(visible=viz_visible), # prompt_title
463
+ gr.update(visible=viz_visible), # models_compared
464
+ gr.update(visible=viz_visible), # model1_title
465
+ gr.update(visible=viz_visible), # model1_words
466
+ gr.update(visible=viz_visible), # model2_title
467
+ gr.update(visible=viz_visible), # model2_words
468
+ gr.update(visible=viz_visible), # similarity_metrics_title
469
+ gr.update(visible=viz_visible), # similarity_metrics
470
+ gr.update(visible=status_visible) # status_message
471
+ ]
 
472
 
473
+ # Connect visibility checkboxes to update function
474
+ visualization_area_visible.change(
475
+ fn=update_visibility,
476
+ inputs=[visualization_area_visible, status_message_visible],
477
+ outputs=[
478
+ analysis_title,
479
+ prompt_title,
480
+ models_compared,
481
+ model1_title,
482
+ model1_words,
483
+ model2_title,
484
+ model2_words,
485
+ similarity_metrics_title,
486
+ similarity_metrics,
487
+ status_message
488
+ ]
489
+ )
490
 
491
+ # Run analysis with proper parameters - update to include topic_count
492
+ run_analysis_btn.click(
493
+ fn=run_analysis,
494
+ inputs=[dataset_state, analysis_options, bow_top_slider, ngram_n, ngram_top, topic_count],
495
+ outputs=[
496
+ analysis_results_state,
497
+ analysis_output,
498
+ visualization_area_visible,
499
+ analysis_title,
500
+ prompt_title,
501
+ models_compared,
502
+ model1_title,
503
+ model1_words,
504
+ model2_title,
505
+ model2_words,
506
+ similarity_metrics_title,
507
+ similarity_metrics,
508
+ status_message_visible,
509
+ status_message
510
+ ]
511
+ )
512
 
513
  return app
514
 
 
517
  download_nltk_resources()
518
 
519
  app = create_app()
520
+ app.launch()
ui/analysis_screen.py CHANGED
@@ -3,8 +3,7 @@ import json
3
  from visualization.bow_visualizer import process_and_visualize_analysis
4
 
5
  # Import analysis modules
6
- # Uncomment these when implemented
7
- # from processors.topic_modeling import extract_topics, compare_topics
8
  from processors.ngram_analysis import compare_ngrams
9
  # from processors.bias_detection import compare_bias
10
  from processors.bow_analysis import compare_bow
@@ -16,27 +15,25 @@ def create_analysis_screen():
16
  Create the analysis options screen
17
 
18
  Returns:
19
- tuple: (analysis_options, analysis_params, run_analysis_btn, analysis_output, bow_top_slider, ngram_n, ngram_top)
20
  """
21
  with gr.Column() as analysis_screen:
22
  gr.Markdown("## Analysis Options")
23
- gr.Markdown("Select which analyses you want to run on the LLM responses.")
24
 
25
- # Analysis selection
26
  with gr.Group():
27
- analysis_options = gr.CheckboxGroup(
28
  choices=[
29
- "Topic Modeling",
30
  "N-gram Analysis",
 
31
  "Bias Detection",
32
- "Bag of Words",
33
- "Similarity Metrics",
34
- "Difference Highlighting"
35
  ],
36
- value=[
37
- "Bag of Words",
38
- ],
39
- label="Select Analyses to Run"
40
  )
41
 
42
  # Create slider directly here for easier access
@@ -59,13 +56,19 @@ def create_analysis_screen():
59
  visible=False
60
  )
61
 
 
 
 
 
 
 
 
62
  # Parameters for each analysis type
63
  with gr.Group() as analysis_params:
64
  # Topic modeling parameters
65
  with gr.Group(visible=False) as topic_params:
66
  gr.Markdown("### Topic Modeling Parameters")
67
- topic_count = gr.Slider(minimum=2, maximum=10, value=3, step=1,
68
- label="Number of Topics")
69
 
70
  # N-gram parameters group (using external ngram_n and ngram_top)
71
  with gr.Group(visible=False) as ngram_params:
@@ -81,32 +84,45 @@ def create_analysis_screen():
81
  label="Bias Detection Methods"
82
  )
83
 
84
- # Similarity metrics parameters
85
- with gr.Group(visible=False) as similarity_params:
86
- gr.Markdown("### Similarity Metrics Parameters")
87
- similarity_metrics = gr.CheckboxGroup(
88
- choices=["Cosine Similarity", "Jaccard Similarity", "Semantic Similarity"],
89
- value=["Cosine Similarity", "Semantic Similarity"],
90
- label="Similarity Metrics to Calculate"
91
- )
 
92
 
93
- # Function to update parameter visibility based on selected analyses
94
  def update_params_visibility(selected):
95
- ngram_visible = "N-gram Analysis" in selected
96
  return {
97
- topic_params: gr.update(visible="Topic Modeling" in selected),
98
- ngram_params: gr.update(visible=ngram_visible),
99
- bias_params: gr.update(visible="Bias Detection" in selected),
100
- similarity_params: gr.update(visible="Similarity Metrics" in selected),
101
- ngram_n: gr.update(visible=ngram_visible),
102
- ngram_top: gr.update(visible=ngram_visible)
 
 
 
103
  }
104
 
105
  # Set up event handler for analysis selection
106
  analysis_options.change(
107
  fn=update_params_visibility,
108
  inputs=[analysis_options],
109
- outputs=[topic_params, ngram_params, bias_params, similarity_params, ngram_n, ngram_top]
 
 
 
 
 
 
 
 
 
 
110
  )
111
 
112
  # Run analysis button
@@ -116,15 +132,15 @@ def create_analysis_screen():
116
  analysis_output = gr.JSON(label="Analysis Results", visible=False)
117
 
118
  # Return the components needed by app.py
119
- return analysis_options, analysis_params, run_analysis_btn, analysis_output, bow_top_slider, ngram_n, ngram_top
120
 
121
  # Process analysis request function
122
- def process_analysis_request(dataset, selected_analyses, parameters):
123
  """
124
- Process the analysis request and run selected analyses
125
  """
126
  try:
127
- print(f"Processing analysis request with: {selected_analyses}")
128
  print(f"Parameters: {parameters}")
129
 
130
  if not dataset or "entries" not in dataset or not dataset["entries"]:
@@ -144,19 +160,36 @@ def process_analysis_request(dataset, selected_analyses, parameters):
144
  analysis_results["analyses"][prompt] = {}
145
 
146
  # Run Bag of Words analysis if selected
147
- if "Bag of Words" in selected_analyses:
148
  top_words = parameters.get("bow_top", 25)
149
  print(f"Running BOW analysis with top_words={top_words}")
150
  bow_results = compare_bow(response_texts, model_names, top_words)
151
  analysis_results["analyses"][prompt]["bag_of_words"] = bow_results
152
 
153
  # Run N-gram analysis if selected
154
- if "N-gram Analysis" in selected_analyses:
155
  ngram_n = int(parameters.get("ngram_n", "2"))
156
  ngram_top = parameters.get("ngram_top", 10)
157
  print(f"Running N-gram analysis with n={ngram_n}, top_n={ngram_top}")
158
  ngram_results = compare_ngrams(response_texts, model_names, ngram_n, ngram_top)
159
  analysis_results["analyses"][prompt]["ngram_analysis"] = ngram_results
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
 
161
  print("Analysis complete - results:", analysis_results)
162
 
 
3
  from visualization.bow_visualizer import process_and_visualize_analysis
4
 
5
  # Import analysis modules
6
+ from processors.topic_modeling import compare_topics # Added import
 
7
  from processors.ngram_analysis import compare_ngrams
8
  # from processors.bias_detection import compare_bias
9
  from processors.bow_analysis import compare_bow
 
15
  Create the analysis options screen
16
 
17
  Returns:
18
+ tuple: (analysis_options, analysis_params, run_analysis_btn, analysis_output, bow_top_slider, ngram_n, ngram_top, topic_count)
19
  """
20
  with gr.Column() as analysis_screen:
21
  gr.Markdown("## Analysis Options")
22
+ gr.Markdown("Select which analysis you want to run on the LLM responses.")
23
 
24
+ # Change from CheckboxGroup to Radio for analysis selection
25
  with gr.Group():
26
+ analysis_options = gr.Radio(
27
  choices=[
28
+ "Bag of Words",
29
  "N-gram Analysis",
30
+ "Topic Modeling",
31
  "Bias Detection",
32
+ "Classifier", # New option for future development
33
+ "LLM Analysis" # New option for future development
 
34
  ],
35
+ value="Bag of Words", # Default selection
36
+ label="Select Analysis Type"
 
 
37
  )
38
 
39
  # Create slider directly here for easier access
 
56
  visible=False
57
  )
58
 
59
+ # Create topic modeling parameter accessible at top level
60
+ topic_count = gr.Slider(
61
+ minimum=2, maximum=10, value=3, step=1,
62
+ label="Number of Topics",
63
+ visible=False
64
+ )
65
+
66
  # Parameters for each analysis type
67
  with gr.Group() as analysis_params:
68
  # Topic modeling parameters
69
  with gr.Group(visible=False) as topic_params:
70
  gr.Markdown("### Topic Modeling Parameters")
71
+ # We'll use the topic_count defined above
 
72
 
73
  # N-gram parameters group (using external ngram_n and ngram_top)
74
  with gr.Group(visible=False) as ngram_params:
 
84
  label="Bias Detection Methods"
85
  )
86
 
87
+ # Classifier parameters for future development
88
+ with gr.Group(visible=False) as classifier_params:
89
+ gr.Markdown("### Classifier Parameters")
90
+ gr.Markdown("*Classifier options will be available in a future update*")
91
+
92
+ # LLM Analysis parameters for future development
93
+ with gr.Group(visible=False) as llm_params:
94
+ gr.Markdown("### LLM Analysis Parameters")
95
+ gr.Markdown("*LLM Analysis options will be available in a future update*")
96
 
97
+ # Function to update parameter visibility based on selected analysis
98
  def update_params_visibility(selected):
 
99
  return {
100
+ topic_params: gr.update(visible=selected == "Topic Modeling"),
101
+ ngram_params: gr.update(visible=selected == "N-gram Analysis"),
102
+ bias_params: gr.update(visible=selected == "Bias Detection"),
103
+ classifier_params: gr.update(visible=selected == "Classifier"),
104
+ llm_params: gr.update(visible=selected == "LLM Analysis"),
105
+ ngram_n: gr.update(visible=selected == "N-gram Analysis"),
106
+ ngram_top: gr.update(visible=selected == "N-gram Analysis"),
107
+ topic_count: gr.update(visible=selected == "Topic Modeling"),
108
+ bow_top_slider: gr.update(visible=selected == "Bag of Words")
109
  }
110
 
111
  # Set up event handler for analysis selection
112
  analysis_options.change(
113
  fn=update_params_visibility,
114
  inputs=[analysis_options],
115
+ outputs=[
116
+ topic_params,
117
+ ngram_params,
118
+ bias_params,
119
+ classifier_params,
120
+ llm_params,
121
+ ngram_n,
122
+ ngram_top,
123
+ topic_count,
124
+ bow_top_slider
125
+ ]
126
  )
127
 
128
  # Run analysis button
 
132
  analysis_output = gr.JSON(label="Analysis Results", visible=False)
133
 
134
  # Return the components needed by app.py
135
+ return analysis_options, analysis_params, run_analysis_btn, analysis_output, bow_top_slider, ngram_n, ngram_top, topic_count
136
 
137
  # Process analysis request function
138
+ def process_analysis_request(dataset, selected_analysis, parameters):
139
  """
140
+ Process the analysis request and run selected analysis
141
  """
142
  try:
143
+ print(f"Processing analysis request with: {selected_analysis}")
144
  print(f"Parameters: {parameters}")
145
 
146
  if not dataset or "entries" not in dataset or not dataset["entries"]:
 
160
  analysis_results["analyses"][prompt] = {}
161
 
162
  # Run Bag of Words analysis if selected
163
+ if selected_analysis == "Bag of Words":
164
  top_words = parameters.get("bow_top", 25)
165
  print(f"Running BOW analysis with top_words={top_words}")
166
  bow_results = compare_bow(response_texts, model_names, top_words)
167
  analysis_results["analyses"][prompt]["bag_of_words"] = bow_results
168
 
169
  # Run N-gram analysis if selected
170
+ elif selected_analysis == "N-gram Analysis":
171
  ngram_n = int(parameters.get("ngram_n", "2"))
172
  ngram_top = parameters.get("ngram_top", 10)
173
  print(f"Running N-gram analysis with n={ngram_n}, top_n={ngram_top}")
174
  ngram_results = compare_ngrams(response_texts, model_names, ngram_n, ngram_top)
175
  analysis_results["analyses"][prompt]["ngram_analysis"] = ngram_results
176
+
177
+ # Run Topic Modeling analysis if selected
178
+ elif selected_analysis == "Topic Modeling":
179
+ topic_count = int(parameters.get("topic_count", 3))
180
+ print(f"Running Topic Modeling analysis with topic_count={topic_count}")
181
+ topic_results = compare_topics(response_texts, model_names, n_topics=topic_count)
182
+ analysis_results["analyses"][prompt]["topic_modeling"] = topic_results
183
+
184
+ # Add placeholder for future analysis types
185
+ elif selected_analysis == "Bias Detection":
186
+ analysis_results["analyses"][prompt]["message"] = "Bias Detection will be available in a future update"
187
+
188
+ elif selected_analysis == "Classifier":
189
+ analysis_results["analyses"][prompt]["message"] = "Classifier will be available in a future update"
190
+
191
+ elif selected_analysis == "LLM Analysis":
192
+ analysis_results["analyses"][prompt]["message"] = "LLM Analysis will be available in a future update"
193
 
194
  print("Analysis complete - results:", analysis_results)
195
 
visualization/bow_visualizer.py CHANGED
@@ -8,6 +8,7 @@ import pandas as pd
8
  from difflib import SequenceMatcher
9
 
10
  from visualization.ngram_visualizer import create_ngram_visualization
 
11
 
12
  def create_bow_visualization(analysis_results):
13
  """
@@ -203,6 +204,14 @@ def process_and_visualize_analysis(analysis_results):
203
  ngram_components = create_ngram_visualization(
204
  {"analyses": {prompt: {"ngram_analysis": analyses["ngram_analysis"]}}})
205
  components.extend(ngram_components)
 
 
 
 
 
 
 
 
206
 
207
  if not components:
208
  components.append(gr.Markdown("No visualization components could be created from the analysis results."))
 
8
  from difflib import SequenceMatcher
9
 
10
  from visualization.ngram_visualizer import create_ngram_visualization
11
+ from visualization.topic_visualizer import process_and_visualize_topic_analysis # Added import
12
 
13
  def create_bow_visualization(analysis_results):
14
  """
 
204
  ngram_components = create_ngram_visualization(
205
  {"analyses": {prompt: {"ngram_analysis": analyses["ngram_analysis"]}}})
206
  components.extend(ngram_components)
207
+
208
+ # Check for Topic Modeling analysis
209
+ if "topic_modeling" in analyses:
210
+ print("Processing Topic Modeling visualization")
211
+ # Use the dedicated topic visualization function
212
+ topic_components = process_and_visualize_topic_analysis(
213
+ {"analyses": {prompt: {"topic_modeling": analyses["topic_modeling"]}}})
214
+ components.extend(topic_components)
215
 
216
  if not components:
217
  components.append(gr.Markdown("No visualization components could be created from the analysis results."))