Update app.py
Browse files
app.py
CHANGED
@@ -814,22 +814,14 @@ def create_ui() -> gr.Blocks:
|
|
814 |
with gr.Row():
|
815 |
extract_analyze_btn = gr.Button("π― Extract Keywords & Analyze Now", variant="secondary", size="lg")
|
816 |
|
817 |
-
# Status
|
818 |
with gr.Row():
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
)
|
826 |
-
with gr.Column():
|
827 |
-
extracted_keywords_output = gr.Textbox(
|
828 |
-
label="π·οΈ Auto-Extracted Keywords",
|
829 |
-
interactive=False,
|
830 |
-
show_copy_button=True,
|
831 |
-
info="Keywords automatically extracted and used for search"
|
832 |
-
)
|
833 |
|
834 |
# --- Smart Search Tab (moved to second) ---
|
835 |
with gr.TabItem("π Smart Search", id="input_tab"):
|
@@ -887,9 +879,9 @@ def create_ui() -> gr.Blocks:
|
|
887 |
wrap=True,
|
888 |
interactive=False
|
889 |
)
|
890 |
-
|
891 |
# Quick links for top repositories
|
892 |
-
|
893 |
top_repo_links = gr.HTML(
|
894 |
value="",
|
895 |
label="π Quick Links",
|
@@ -920,7 +912,7 @@ def create_ui() -> gr.Blocks:
|
|
920 |
wrap=True,
|
921 |
interactive=False
|
922 |
)
|
923 |
-
|
924 |
# Quick links section for all repositories
|
925 |
with gr.Row():
|
926 |
all_repo_links = gr.HTML(
|
@@ -999,10 +991,10 @@ def create_ui() -> gr.Blocks:
|
|
999 |
history.append({"role": "user", "content": user_message})
|
1000 |
return history, ""
|
1001 |
|
1002 |
-
def handle_bot_response(history: List[Dict[str, str]]) -> Tuple[List[Dict[str, str]], str, str,
|
1003 |
"""Generates bot response and automatically extracts keywords if conversation is ready."""
|
1004 |
if not history or history[-1]["role"] != "user":
|
1005 |
-
return history, "", "",
|
1006 |
|
1007 |
user_message = history[-1]["content"]
|
1008 |
# Convert all messages *before* the last user message into tuples for the API
|
@@ -1036,11 +1028,11 @@ def create_ui() -> gr.Blocks:
|
|
1036 |
write_repos_to_csv(unique_repo_ids)
|
1037 |
df = format_dataframe_for_display(read_csv_to_dataframe())
|
1038 |
|
1039 |
-
chat_status = f"
|
1040 |
|
1041 |
-
return history, chat_status,
|
1042 |
|
1043 |
-
return history, "π¬ Conversation continuing...", "",
|
1044 |
|
1045 |
def handle_dataframe_select(evt: gr.SelectData, df_data) -> Tuple[str, Any, str]:
|
1046 |
"""Handle dataframe row selection - show modal for repo ID (column 0) clicks."""
|
@@ -1133,15 +1125,15 @@ def create_ui() -> gr.Blocks:
|
|
1133 |
return f'<div style="margin: 10px 0; padding: 15px; background: rgba(255, 255, 255, 0.1); border-radius: 12px; backdrop-filter: blur(10px);">{"".join(html_links)}</div>'
|
1134 |
return ""
|
1135 |
|
1136 |
-
def handle_extract_and_analyze(history: List[Dict[str, str]]) -> Tuple[str, str,
|
1137 |
"""Extract keywords from chat, search repositories, and immediately start analysis."""
|
1138 |
if not history:
|
1139 |
-
return "β No conversation to extract from.", "",
|
1140 |
|
1141 |
# Convert the full, valid history for the extraction logic
|
1142 |
tuple_history = convert_messages_to_tuples(history)
|
1143 |
if not tuple_history:
|
1144 |
-
return "β No completed conversations to analyze.", "",
|
1145 |
|
1146 |
# Get raw keywords string from the LLM
|
1147 |
raw_keywords_str = extract_keywords_from_conversation(tuple_history)
|
@@ -1151,7 +1143,7 @@ def create_ui() -> gr.Blocks:
|
|
1151 |
cleaned_keywords = [kw.strip() for kw in cleaned_keywords if kw.strip()]
|
1152 |
|
1153 |
if not cleaned_keywords:
|
1154 |
-
return f"β Could not extract valid keywords. Raw output: '{raw_keywords_str}'", "",
|
1155 |
|
1156 |
# Join them into a clean, comma-separated string
|
1157 |
final_keywords_str = ", ".join(cleaned_keywords)
|
@@ -1167,7 +1159,7 @@ def create_ui() -> gr.Blocks:
|
|
1167 |
unique_repo_ids = list(dict.fromkeys(repo_ids))
|
1168 |
|
1169 |
if not unique_repo_ids:
|
1170 |
-
return f"β No repositories found for keywords: {final_keywords_str}",
|
1171 |
|
1172 |
write_repos_to_csv(unique_repo_ids)
|
1173 |
df = format_dataframe_for_display(read_csv_to_dataframe())
|
@@ -1178,12 +1170,12 @@ def create_ui() -> gr.Blocks:
|
|
1178 |
|
1179 |
chat_status = f"π Extracted keywords β Found {len(unique_repo_ids)} repositories β Analysis complete!"
|
1180 |
|
1181 |
-
return chat_status,
|
1182 |
|
1183 |
except Exception as e:
|
1184 |
logger.error(f"Error during extract and analyze: {e}")
|
1185 |
error_status = f"β
Found {len(unique_repo_ids)} repositories, but analysis failed: {e}"
|
1186 |
-
return error_status,
|
1187 |
|
1188 |
def extract_user_requirements_from_chat(history: List[Dict[str, str]]) -> str:
|
1189 |
"""Extract user requirements from chatbot conversation."""
|
@@ -1326,7 +1318,7 @@ def create_ui() -> gr.Blocks:
|
|
1326 |
error_status = f"β Batch analysis failed: {e}"
|
1327 |
return format_dataframe_for_display(read_csv_to_dataframe()), error_status, pd.DataFrame(), gr.update(visible=False), "", ""
|
1328 |
|
1329 |
-
def handle_reset_everything() -> Tuple[List[str], int, str, pd.DataFrame, pd.DataFrame, Any, List[Dict[str, str]], str, str
|
1330 |
"""Reset everything to initial state - clear all data, CSV, and UI components."""
|
1331 |
try:
|
1332 |
# Clear the CSV file
|
@@ -1347,7 +1339,6 @@ def create_ui() -> gr.Blocks:
|
|
1347 |
|
1348 |
# Reset UI components
|
1349 |
current_requirements_reset = "No requirements extracted yet."
|
1350 |
-
extracted_keywords_reset = ""
|
1351 |
|
1352 |
# Reset chatbot to initial message
|
1353 |
chatbot_reset = [{"role": "assistant", "content": CHATBOT_INITIAL_MESSAGE}]
|
@@ -1363,8 +1354,7 @@ def create_ui() -> gr.Blocks:
|
|
1363 |
gr.update(visible=False), # top_repos_section
|
1364 |
chatbot_reset, # chatbot
|
1365 |
status_reset, # status_box_input
|
1366 |
-
current_requirements_reset
|
1367 |
-
extracted_keywords_reset # extracted_keywords_output
|
1368 |
)
|
1369 |
|
1370 |
except Exception as e:
|
@@ -1379,8 +1369,7 @@ def create_ui() -> gr.Blocks:
|
|
1379 |
gr.update(visible=False), # top_repos_section
|
1380 |
[{"role": "assistant", "content": CHATBOT_INITIAL_MESSAGE}], # chatbot
|
1381 |
error_status, # status_box_input
|
1382 |
-
"No requirements extracted yet."
|
1383 |
-
"" # extracted_keywords_output
|
1384 |
)
|
1385 |
|
1386 |
# --- Component Event Wiring ---
|
@@ -1437,7 +1426,7 @@ def create_ui() -> gr.Blocks:
|
|
1437 |
).then(
|
1438 |
fn=handle_bot_response,
|
1439 |
inputs=[chatbot],
|
1440 |
-
outputs=[chatbot, chat_status,
|
1441 |
).then(
|
1442 |
# Update requirements display when they change
|
1443 |
fn=lambda req: req if req.strip() else "No specific requirements extracted from conversation.",
|
@@ -1457,7 +1446,7 @@ def create_ui() -> gr.Blocks:
|
|
1457 |
).then(
|
1458 |
fn=handle_bot_response,
|
1459 |
inputs=[chatbot],
|
1460 |
-
outputs=[chatbot, chat_status,
|
1461 |
).then(
|
1462 |
# Update requirements display when they change
|
1463 |
fn=lambda req: req if req.strip() else "No specific requirements extracted from conversation.",
|
@@ -1474,7 +1463,7 @@ def create_ui() -> gr.Blocks:
|
|
1474 |
extract_analyze_btn.click(
|
1475 |
fn=handle_extract_and_analyze,
|
1476 |
inputs=[chatbot],
|
1477 |
-
outputs=[chat_status,
|
1478 |
).then(
|
1479 |
# Update requirements display when they change
|
1480 |
fn=lambda req: req if req.strip() else "No specific requirements extracted from conversation.",
|
@@ -1543,7 +1532,7 @@ def create_ui() -> gr.Blocks:
|
|
1543 |
# Reset button event
|
1544 |
reset_all_btn.click(
|
1545 |
fn=handle_reset_everything,
|
1546 |
-
outputs=[repo_ids_state, current_repo_idx_state, user_requirements_state, df_output, top_repos_df, top_repos_section, chatbot, status_box_input, current_requirements_display
|
1547 |
)
|
1548 |
|
1549 |
# Help modal events
|
|
|
814 |
with gr.Row():
|
815 |
extract_analyze_btn = gr.Button("π― Extract Keywords & Analyze Now", variant="secondary", size="lg")
|
816 |
|
817 |
+
# Status info (auto-updated, no manual buttons needed)
|
818 |
with gr.Row():
|
819 |
+
chat_status = gr.Textbox(
|
820 |
+
label="π― Chat Status",
|
821 |
+
interactive=False,
|
822 |
+
lines=2,
|
823 |
+
info="Conversation progress and auto-actions"
|
824 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
825 |
|
826 |
# --- Smart Search Tab (moved to second) ---
|
827 |
with gr.TabItem("π Smart Search", id="input_tab"):
|
|
|
879 |
wrap=True,
|
880 |
interactive=False
|
881 |
)
|
882 |
+
|
883 |
# Quick links for top repositories
|
884 |
+
with gr.Row():
|
885 |
top_repo_links = gr.HTML(
|
886 |
value="",
|
887 |
label="π Quick Links",
|
|
|
912 |
wrap=True,
|
913 |
interactive=False
|
914 |
)
|
915 |
+
|
916 |
# Quick links section for all repositories
|
917 |
with gr.Row():
|
918 |
all_repo_links = gr.HTML(
|
|
|
991 |
history.append({"role": "user", "content": user_message})
|
992 |
return history, ""
|
993 |
|
994 |
+
def handle_bot_response(history: List[Dict[str, str]]) -> Tuple[List[Dict[str, str]], str, str, List[str], int, pd.DataFrame, Any]:
|
995 |
"""Generates bot response and automatically extracts keywords if conversation is ready."""
|
996 |
if not history or history[-1]["role"] != "user":
|
997 |
+
return history, "", "", [], 0, pd.DataFrame(), gr.update()
|
998 |
|
999 |
user_message = history[-1]["content"]
|
1000 |
# Convert all messages *before* the last user message into tuples for the API
|
|
|
1028 |
write_repos_to_csv(unique_repo_ids)
|
1029 |
df = format_dataframe_for_display(read_csv_to_dataframe())
|
1030 |
|
1031 |
+
chat_status = f"π Extracted keywords β Found {len(unique_repo_ids)} repositories β Analysis complete!"
|
1032 |
|
1033 |
+
return history, chat_status, user_requirements, unique_repo_ids, 0, df, gr.update(selected="analysis_tab")
|
1034 |
|
1035 |
+
return history, "π¬ Conversation continuing...", "", [], 0, pd.DataFrame(), gr.update()
|
1036 |
|
1037 |
def handle_dataframe_select(evt: gr.SelectData, df_data) -> Tuple[str, Any, str]:
|
1038 |
"""Handle dataframe row selection - show modal for repo ID (column 0) clicks."""
|
|
|
1125 |
return f'<div style="margin: 10px 0; padding: 15px; background: rgba(255, 255, 255, 0.1); border-radius: 12px; backdrop-filter: blur(10px);">{"".join(html_links)}</div>'
|
1126 |
return ""
|
1127 |
|
1128 |
+
def handle_extract_and_analyze(history: List[Dict[str, str]]) -> Tuple[str, str, List[str], int, pd.DataFrame, Any, pd.DataFrame, str, Any, str, str]:
|
1129 |
"""Extract keywords from chat, search repositories, and immediately start analysis."""
|
1130 |
if not history:
|
1131 |
+
return "β No conversation to extract from.", "", [], 0, pd.DataFrame(), gr.update(), pd.DataFrame(), "", gr.update(visible=False), "", ""
|
1132 |
|
1133 |
# Convert the full, valid history for the extraction logic
|
1134 |
tuple_history = convert_messages_to_tuples(history)
|
1135 |
if not tuple_history:
|
1136 |
+
return "β No completed conversations to analyze.", "", [], 0, pd.DataFrame(), gr.update(), pd.DataFrame(), "", gr.update(visible=False), "", ""
|
1137 |
|
1138 |
# Get raw keywords string from the LLM
|
1139 |
raw_keywords_str = extract_keywords_from_conversation(tuple_history)
|
|
|
1143 |
cleaned_keywords = [kw.strip() for kw in cleaned_keywords if kw.strip()]
|
1144 |
|
1145 |
if not cleaned_keywords:
|
1146 |
+
return f"β Could not extract valid keywords. Raw output: '{raw_keywords_str}'", "", [], 0, pd.DataFrame(), gr.update(), pd.DataFrame(), "", gr.update(visible=False), "", ""
|
1147 |
|
1148 |
# Join them into a clean, comma-separated string
|
1149 |
final_keywords_str = ", ".join(cleaned_keywords)
|
|
|
1159 |
unique_repo_ids = list(dict.fromkeys(repo_ids))
|
1160 |
|
1161 |
if not unique_repo_ids:
|
1162 |
+
return f"β No repositories found for keywords: {final_keywords_str}", user_requirements, [], 0, pd.DataFrame(), gr.update(), pd.DataFrame(), "", gr.update(visible=False), "", ""
|
1163 |
|
1164 |
write_repos_to_csv(unique_repo_ids)
|
1165 |
df = format_dataframe_for_display(read_csv_to_dataframe())
|
|
|
1170 |
|
1171 |
chat_status = f"π Extracted keywords β Found {len(unique_repo_ids)} repositories β Analysis complete!"
|
1172 |
|
1173 |
+
return chat_status, user_requirements, unique_repo_ids, 0, analyzed_df, gr.update(selected="analysis_tab"), top_repos, analysis_status, top_section_update, all_links, top_links
|
1174 |
|
1175 |
except Exception as e:
|
1176 |
logger.error(f"Error during extract and analyze: {e}")
|
1177 |
error_status = f"β
Found {len(unique_repo_ids)} repositories, but analysis failed: {e}"
|
1178 |
+
return error_status, user_requirements, unique_repo_ids, 0, df, gr.update(selected="analysis_tab"), pd.DataFrame(), "", gr.update(visible=False), "", ""
|
1179 |
|
1180 |
def extract_user_requirements_from_chat(history: List[Dict[str, str]]) -> str:
|
1181 |
"""Extract user requirements from chatbot conversation."""
|
|
|
1318 |
error_status = f"β Batch analysis failed: {e}"
|
1319 |
return format_dataframe_for_display(read_csv_to_dataframe()), error_status, pd.DataFrame(), gr.update(visible=False), "", ""
|
1320 |
|
1321 |
+
def handle_reset_everything() -> Tuple[List[str], int, str, pd.DataFrame, pd.DataFrame, Any, List[Dict[str, str]], str, str]:
|
1322 |
"""Reset everything to initial state - clear all data, CSV, and UI components."""
|
1323 |
try:
|
1324 |
# Clear the CSV file
|
|
|
1339 |
|
1340 |
# Reset UI components
|
1341 |
current_requirements_reset = "No requirements extracted yet."
|
|
|
1342 |
|
1343 |
# Reset chatbot to initial message
|
1344 |
chatbot_reset = [{"role": "assistant", "content": CHATBOT_INITIAL_MESSAGE}]
|
|
|
1354 |
gr.update(visible=False), # top_repos_section
|
1355 |
chatbot_reset, # chatbot
|
1356 |
status_reset, # status_box_input
|
1357 |
+
current_requirements_reset # current_requirements_display
|
|
|
1358 |
)
|
1359 |
|
1360 |
except Exception as e:
|
|
|
1369 |
gr.update(visible=False), # top_repos_section
|
1370 |
[{"role": "assistant", "content": CHATBOT_INITIAL_MESSAGE}], # chatbot
|
1371 |
error_status, # status_box_input
|
1372 |
+
"No requirements extracted yet." # current_requirements_display
|
|
|
1373 |
)
|
1374 |
|
1375 |
# --- Component Event Wiring ---
|
|
|
1426 |
).then(
|
1427 |
fn=handle_bot_response,
|
1428 |
inputs=[chatbot],
|
1429 |
+
outputs=[chatbot, chat_status, user_requirements_state, repo_ids_state, current_repo_idx_state, df_output, tabs]
|
1430 |
).then(
|
1431 |
# Update requirements display when they change
|
1432 |
fn=lambda req: req if req.strip() else "No specific requirements extracted from conversation.",
|
|
|
1446 |
).then(
|
1447 |
fn=handle_bot_response,
|
1448 |
inputs=[chatbot],
|
1449 |
+
outputs=[chatbot, chat_status, user_requirements_state, repo_ids_state, current_repo_idx_state, df_output, tabs]
|
1450 |
).then(
|
1451 |
# Update requirements display when they change
|
1452 |
fn=lambda req: req if req.strip() else "No specific requirements extracted from conversation.",
|
|
|
1463 |
extract_analyze_btn.click(
|
1464 |
fn=handle_extract_and_analyze,
|
1465 |
inputs=[chatbot],
|
1466 |
+
outputs=[chat_status, user_requirements_state, repo_ids_state, current_repo_idx_state, df_output, tabs, top_repos_df, status_box_analysis, top_repos_section, all_repo_links, top_repo_links]
|
1467 |
).then(
|
1468 |
# Update requirements display when they change
|
1469 |
fn=lambda req: req if req.strip() else "No specific requirements extracted from conversation.",
|
|
|
1532 |
# Reset button event
|
1533 |
reset_all_btn.click(
|
1534 |
fn=handle_reset_everything,
|
1535 |
+
outputs=[repo_ids_state, current_repo_idx_state, user_requirements_state, df_output, top_repos_df, top_repos_section, chatbot, status_box_input, current_requirements_display]
|
1536 |
)
|
1537 |
|
1538 |
# Help modal events
|