Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -632,6 +632,7 @@ def create_ui() -> gr.Blocks:
|
|
| 632 |
value=True,
|
| 633 |
info="Automatically start analysis when repositories are found"
|
| 634 |
)
|
|
|
|
| 635 |
|
| 636 |
status_box_input = gr.Textbox(label="π Status", interactive=False, lines=2)
|
| 637 |
|
|
@@ -704,6 +705,9 @@ def create_ui() -> gr.Blocks:
|
|
| 704 |
)
|
| 705 |
send_btn = gr.Button("π€", variant="primary", scale=1)
|
| 706 |
|
|
|
|
|
|
|
|
|
|
| 707 |
# Status and extracted info (auto-updated, no manual buttons needed)
|
| 708 |
with gr.Row():
|
| 709 |
with gr.Column():
|
|
@@ -857,6 +861,58 @@ def create_ui() -> gr.Blocks:
|
|
| 857 |
|
| 858 |
return ""
|
| 859 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 860 |
def extract_user_requirements_from_chat(history: List[Dict[str, str]]) -> str:
|
| 861 |
"""Extract user requirements from chatbot conversation."""
|
| 862 |
if not history:
|
|
@@ -1071,6 +1127,18 @@ def create_ui() -> gr.Blocks:
|
|
| 1071 |
outputs=[df_output, status_box_input, top_repos_df, top_repos_section]
|
| 1072 |
)
|
| 1073 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1074 |
# Auto-analyze checkbox toggle
|
| 1075 |
auto_analyze_checkbox.change(
|
| 1076 |
fn=handle_auto_analyze_toggle,
|
|
@@ -1126,6 +1194,18 @@ def create_ui() -> gr.Blocks:
|
|
| 1126 |
outputs=[df_output, chat_status, top_repos_df, top_repos_section]
|
| 1127 |
)
|
| 1128 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1129 |
# Repo Explorer Tab
|
| 1130 |
setup_repo_explorer_events(repo_components, repo_states)
|
| 1131 |
|
|
|
|
| 632 |
value=True,
|
| 633 |
info="Automatically start analysis when repositories are found"
|
| 634 |
)
|
| 635 |
+
smart_submit_btn = gr.Button("π Find & Process Repositories", variant="primary", size="lg", scale=1)
|
| 636 |
|
| 637 |
status_box_input = gr.Textbox(label="π Status", interactive=False, lines=2)
|
| 638 |
|
|
|
|
| 705 |
)
|
| 706 |
send_btn = gr.Button("π€", variant="primary", scale=1)
|
| 707 |
|
| 708 |
+
with gr.Row():
|
| 709 |
+
extract_analyze_btn = gr.Button("π― Extract Keywords & Analyze Now", variant="secondary", size="lg")
|
| 710 |
+
|
| 711 |
# Status and extracted info (auto-updated, no manual buttons needed)
|
| 712 |
with gr.Row():
|
| 713 |
with gr.Column():
|
|
|
|
| 861 |
|
| 862 |
return ""
|
| 863 |
|
| 864 |
+
def handle_extract_and_analyze(history: List[Dict[str, str]]) -> Tuple[str, str, str, List[str], int, pd.DataFrame, Any, pd.DataFrame, str, Any]:
|
| 865 |
+
"""Extract keywords from chat, search repositories, and immediately start analysis."""
|
| 866 |
+
if not history:
|
| 867 |
+
return "β No conversation to extract from.", "", "", [], 0, pd.DataFrame(), gr.update(), pd.DataFrame(), "", gr.update(visible=False)
|
| 868 |
+
|
| 869 |
+
# Convert the full, valid history for the extraction logic
|
| 870 |
+
tuple_history = convert_messages_to_tuples(history)
|
| 871 |
+
if not tuple_history:
|
| 872 |
+
return "β No completed conversations to analyze.", "", "", [], 0, pd.DataFrame(), gr.update(), pd.DataFrame(), "", gr.update(visible=False)
|
| 873 |
+
|
| 874 |
+
# Get raw keywords string from the LLM
|
| 875 |
+
raw_keywords_str = extract_keywords_from_conversation(tuple_history)
|
| 876 |
+
|
| 877 |
+
# Sanitize the LLM output to extract only keyword-like parts
|
| 878 |
+
cleaned_keywords = re.findall(r'[\w\s-]+', raw_keywords_str)
|
| 879 |
+
cleaned_keywords = [kw.strip() for kw in cleaned_keywords if kw.strip()]
|
| 880 |
+
|
| 881 |
+
if not cleaned_keywords:
|
| 882 |
+
return f"β Could not extract valid keywords. Raw output: '{raw_keywords_str}'", "", "", [], 0, pd.DataFrame(), gr.update(), pd.DataFrame(), "", gr.update(visible=False)
|
| 883 |
+
|
| 884 |
+
# Join them into a clean, comma-separated string
|
| 885 |
+
final_keywords_str = ", ".join(cleaned_keywords)
|
| 886 |
+
|
| 887 |
+
# Extract user requirements for analysis
|
| 888 |
+
user_requirements = extract_user_requirements_from_chat(history)
|
| 889 |
+
|
| 890 |
+
# Auto-search repositories
|
| 891 |
+
repo_ids = []
|
| 892 |
+
for kw in cleaned_keywords[:3]: # Use top 3 keywords to avoid too many results
|
| 893 |
+
repo_ids.extend(search_top_spaces(kw, limit=5))
|
| 894 |
+
|
| 895 |
+
unique_repo_ids = list(dict.fromkeys(repo_ids))
|
| 896 |
+
|
| 897 |
+
if not unique_repo_ids:
|
| 898 |
+
return f"β No repositories found for keywords: {final_keywords_str}", final_keywords_str, user_requirements, [], 0, pd.DataFrame(), gr.update(), pd.DataFrame(), "", gr.update(visible=False)
|
| 899 |
+
|
| 900 |
+
write_repos_to_csv(unique_repo_ids)
|
| 901 |
+
df = format_dataframe_for_display(read_csv_to_dataframe())
|
| 902 |
+
|
| 903 |
+
# Immediately start analysis
|
| 904 |
+
try:
|
| 905 |
+
analyzed_df, analysis_status, top_repos, top_section_update = handle_analyze_all_repos(unique_repo_ids, user_requirements)
|
| 906 |
+
|
| 907 |
+
chat_status = f"π Extracted keywords β Found {len(unique_repo_ids)} repositories β Analysis complete!"
|
| 908 |
+
|
| 909 |
+
return chat_status, final_keywords_str, user_requirements, unique_repo_ids, 0, analyzed_df, gr.update(selected="analysis_tab"), top_repos, analysis_status, top_section_update
|
| 910 |
+
|
| 911 |
+
except Exception as e:
|
| 912 |
+
logger.error(f"Error during extract and analyze: {e}")
|
| 913 |
+
error_status = f"β
Found {len(unique_repo_ids)} repositories, but analysis failed: {e}"
|
| 914 |
+
return error_status, final_keywords_str, user_requirements, unique_repo_ids, 0, df, gr.update(selected="analysis_tab"), pd.DataFrame(), "", gr.update(visible=False)
|
| 915 |
+
|
| 916 |
def extract_user_requirements_from_chat(history: List[Dict[str, str]]) -> str:
|
| 917 |
"""Extract user requirements from chatbot conversation."""
|
| 918 |
if not history:
|
|
|
|
| 1127 |
outputs=[df_output, status_box_input, top_repos_df, top_repos_section]
|
| 1128 |
)
|
| 1129 |
|
| 1130 |
+
# Smart Submit Button (same behavior as enter)
|
| 1131 |
+
smart_submit_btn.click(
|
| 1132 |
+
fn=handle_smart_input,
|
| 1133 |
+
inputs=[smart_input, auto_analyze_checkbox],
|
| 1134 |
+
outputs=[repo_ids_state, current_repo_idx_state, df_output, status_box_input, tabs, status_box_input]
|
| 1135 |
+
).then(
|
| 1136 |
+
# If auto_analyze is enabled and we got repos, start analysis automatically
|
| 1137 |
+
fn=lambda repo_ids, user_reqs, trigger: handle_analyze_all_repos(repo_ids, user_reqs) if trigger == "auto_analyze" and repo_ids else (pd.DataFrame(), "Ready for analysis.", pd.DataFrame(), gr.update(visible=False)),
|
| 1138 |
+
inputs=[repo_ids_state, user_requirements_state, status_box_input],
|
| 1139 |
+
outputs=[df_output, status_box_input, top_repos_df, top_repos_section]
|
| 1140 |
+
)
|
| 1141 |
+
|
| 1142 |
# Auto-analyze checkbox toggle
|
| 1143 |
auto_analyze_checkbox.change(
|
| 1144 |
fn=handle_auto_analyze_toggle,
|
|
|
|
| 1194 |
outputs=[df_output, chat_status, top_repos_df, top_repos_section]
|
| 1195 |
)
|
| 1196 |
|
| 1197 |
+
# Extract and Analyze Button (one-click solution for chatbot)
|
| 1198 |
+
extract_analyze_btn.click(
|
| 1199 |
+
fn=handle_extract_and_analyze,
|
| 1200 |
+
inputs=[chatbot],
|
| 1201 |
+
outputs=[chat_status, extracted_keywords_output, user_requirements_state, repo_ids_state, current_repo_idx_state, df_output, tabs, top_repos_df, status_box_analysis, top_repos_section]
|
| 1202 |
+
).then(
|
| 1203 |
+
# Update requirements display when they change
|
| 1204 |
+
fn=lambda req: req if req.strip() else "No specific requirements extracted from conversation.",
|
| 1205 |
+
inputs=[user_requirements_state],
|
| 1206 |
+
outputs=[current_requirements_display]
|
| 1207 |
+
)
|
| 1208 |
+
|
| 1209 |
# Repo Explorer Tab
|
| 1210 |
setup_repo_explorer_events(repo_components, repo_states)
|
| 1211 |
|