Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from huggingface_hub import InferenceClient | |
| import pandas as pd | |
| # ββ Constants βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| IMAGE_URL = "https://drive.google.com/uc?export=view&id=1OX1tj6gTNo8CkV9IDbNKgZ7WHvpNmgFo" | |
| MODEL_ID = "microsoft/phi-4" | |
| SYSTEM_MESSAGE = """\ | |
| You are a Fault Prediction Chatbot that analyzes network and system performance data \ | |
| to identify potential issues before they escalate. \ | |
| Based on the provided data, respond in the following format and must include the following headings: | |
| # **Future Performance Prediction** | |
| # **Risk Analysis and Potential Issues** | |
| # **Preventive Actions and Recommendations**""" | |
| SIMPLE_SYSTEM_MESSAGE = ( | |
| "You are an AI powered chatbot named as NetPulse-AI built by team HelixAI that provides " | |
| "predictive maintenance insights, cost optimization suggestions, and energy efficiency " | |
| "recommendations for networks." | |
| ) | |
| css = """ | |
| footer {display:none !important} | |
| .output-markdown{display:none !important} | |
| .gr-button-primary { | |
| z-index: 14; height: 43px; width: 130px; left: 0px; top: 0px; padding: 0px; | |
| cursor: pointer !important; | |
| background: none rgb(17, 20, 45) !important; | |
| border: none !important; text-align: center !important; | |
| font-family: Poppins !important; font-size: 14px !important; | |
| font-weight: 500 !important; color: rgb(255, 255, 255) !important; | |
| line-height: 1 !important; border-radius: 12px !important; | |
| transition: box-shadow 200ms ease 0s, background 200ms ease 0s !important; | |
| box-shadow: none !important; | |
| } | |
| .gr-button-primary:hover { | |
| background: none rgb(66, 133, 244) !important; | |
| box-shadow: rgb(0 0 0 / 23%) 0px 1px 7px 0px !important; | |
| } | |
| #image-container { | |
| display: flex; justify-content: center; | |
| align-items: center; height: auto; margin-top: 20px; | |
| } | |
| #compass-image { max-width: 800px; max-height: 600px; object-fit: contain; } | |
| """ | |
| # ββ Helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def _build_messages(system_msg: str, history: list, message: str) -> list: | |
| """Convert Gradio history + new message into the HF messages format.""" | |
| msgs = [{"role": "system", "content": system_msg}] | |
| for user_turn, bot_turn in history: | |
| if user_turn: | |
| msgs.append({"role": "user", "content": user_turn}) | |
| if bot_turn: | |
| msgs.append({"role": "assistant", "content": bot_turn}) | |
| msgs.append({"role": "user", "content": message}) | |
| return msgs | |
| def stream_chat(message, history, system_msg, | |
| max_tokens, temperature, top_p, | |
| hf_token: gr.OAuthToken): | |
| """ | |
| Generator that streams tokens back to the Gradio Chatbot component. | |
| Yields the full updated history list on every token so Gradio can | |
| re-render incrementally β this is true streaming with zero extra load. | |
| """ | |
| if not message: | |
| yield history | |
| return | |
| if not hf_token: | |
| yield history + [(message, | |
| "β οΈ Please log in with your Hugging Face account (sidebar) before sending messages.")] | |
| return | |
| client = InferenceClient(model=MODEL_ID, token=hf_token.token) | |
| messages = _build_messages(system_msg, history, message) | |
| history = history + [(message, "")] # append placeholder | |
| response = "" | |
| for chunk in client.chat_completion( | |
| messages, | |
| max_tokens=max_tokens, | |
| stream=True, | |
| temperature=temperature, | |
| top_p=top_p, | |
| ): | |
| token = chunk.choices[0].delta.content or "" | |
| response += token | |
| history[-1] = (message, response) # update last turn in place | |
| yield history | |
| def save_history(history: list): | |
| """Serialise chatbot history to a .txt file for download.""" | |
| if not history: | |
| return None | |
| lines = [] | |
| for user_turn, bot_turn in history: | |
| if user_turn: | |
| lines.append(f"User: {user_turn}") | |
| if bot_turn: | |
| lines.append(f"Assistant: {bot_turn}\n") | |
| path = "/tmp/chat_history.txt" | |
| with open(path, "w", encoding="utf-8") as fh: | |
| fh.write("\n".join(lines)) | |
| return path | |
| def read_excel(file): | |
| if file is None: | |
| return "" | |
| df = pd.read_excel(file.name) | |
| return df.to_string() | |
| # ββ UI ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # FIX 1: css removed from gr.Blocks() β now passed to demo.launch() below | |
| with gr.Blocks() as demo: | |
| # ββ Sidebar βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| with gr.Sidebar(): | |
| gr.Markdown("### π Login") | |
| gr.LoginButton() | |
| gr.Markdown( | |
| "Log in with your Hugging Face account to use NetPulse AI. " | |
| "Your token is used only to call the inference API." | |
| ) | |
| # ββ Intro tab βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| with gr.Tab("NetPulse AI"): | |
| with gr.Row(elem_id="image-container"): | |
| gr.Image(IMAGE_URL, elem_id="compass-image") | |
| gr.Markdown("# **NetPulse AI**") | |
| gr.Markdown("### **Developed by Team HELIX AI**") | |
| gr.Markdown(""" | |
| **This project monitors network health using a Raspberry Pi, collecting data on CPU usage, | |
| temperature, signal strength, and packet loss. The data is logged in Excel, identifying | |
| abnormal conditions. Users upload the data to the chatbot for predictive analysis and | |
| optimization recommendations.** | |
| **Features:** | |
| - **Future Performance Prediction:** Identifies upcoming failure risks based on past data trends. | |
| - **Risk Analysis and Potential Issues:** Detects high-risk periods and network bottlenecks. | |
| - **Preventive Actions and Recommendations:** Suggests cooling measures, bandwidth optimization, and maintenance alerts. | |
| **How It Works:** | |
| 1. Log in with your Hugging Face account (sidebar). | |
| 2. Upload your Excel file in the *Upload Data* tab. | |
| 3. Paste the data into *Detailed Analysis* for a full report. | |
| 4. Use *General Chat* for follow-up questions. | |
| """) | |
| # ββ Detailed Analysis tab βββββββββββββββββββββββββββββββββββββββββββββββββ | |
| with gr.Tab("Detailed Analysis"): | |
| gr.Markdown("# Detailed Analysis") | |
| gr.Markdown( | |
| "Analyze network performance trends, predict potential issues, and receive " | |
| "tailored recommendations based on the uploaded data." | |
| ) | |
| # FIX 2: show_copy_button removed β not supported in Gradio 6.0 | |
| chatbot_detail = gr.Chatbot(height=520) | |
| msg_detail = gr.Textbox(label="Enter the Excel Copied Data here", lines=3) | |
| with gr.Row(): | |
| clear_detail = gr.Button("New Chat") | |
| download_btn = gr.Button("Download Chat History") | |
| submit_detail = gr.Button("Submit", variant="primary") | |
| download_out = gr.File(label="Download", visible=False) | |
| with gr.Accordion("Advanced Settings", open=False): | |
| max_tok_d = gr.Slider(1, 2048, 1024, step=1, label="Max new tokens") | |
| temp_d = gr.Slider(0.1, 4.0, 0.7, step=0.1, label="Temperature") | |
| top_p_d = gr.Slider(0.1, 1.0, 0.95, step=0.05, label="Top-p (nucleus sampling)") | |
| sys_msg_detail = gr.Textbox(value=SYSTEM_MESSAGE, visible=False) | |
| # Stream response, then clear input box | |
| submit_detail.click( | |
| stream_chat, | |
| inputs=[msg_detail, chatbot_detail, sys_msg_detail, | |
| max_tok_d, temp_d, top_p_d], | |
| outputs=[chatbot_detail], | |
| ).then( | |
| lambda: gr.update(value=""), | |
| outputs=[msg_detail], | |
| ) | |
| # Also allow Enter key to submit | |
| msg_detail.submit( | |
| stream_chat, | |
| inputs=[msg_detail, chatbot_detail, sys_msg_detail, | |
| max_tok_d, temp_d, top_p_d], | |
| outputs=[chatbot_detail], | |
| ).then( | |
| lambda: gr.update(value=""), | |
| outputs=[msg_detail], | |
| ) | |
| clear_detail.click(lambda: [], outputs=[chatbot_detail]) | |
| download_btn.click( | |
| save_history, | |
| inputs=[chatbot_detail], | |
| outputs=[download_out], | |
| ).then( | |
| lambda: gr.update(visible=True), | |
| outputs=[download_out], | |
| ) | |
| # ββ Upload Data tab βββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| with gr.Tab("Upload Data"): | |
| gr.Markdown("# Upload Data") | |
| file_input = gr.File(label="Upload Excel file") | |
| excel_output = gr.Textbox(label="Excel Content", lines=12, interactive=False) | |
| file_input.change(read_excel, inputs=file_input, outputs=excel_output) | |
| # ββ General Chat tab ββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| with gr.Tab("General Chat for Network Optimization"): | |
| gr.Markdown("# General Chat for Network Optimization") | |
| gr.Markdown( | |
| "Ask NetPulse AI for predictive maintenance insights, cost optimization " | |
| "suggestions, and energy efficiency recommendations." | |
| ) | |
| # FIX 2 (continued): show_copy_button removed here too | |
| chatbot_simple = gr.Chatbot(height=520) | |
| msg_simple = gr.Textbox(label="Type a message") | |
| with gr.Row(): | |
| clear_simple = gr.Button("Clear") | |
| submit_simple = gr.Button("Submit", variant="primary") | |
| with gr.Accordion("Advanced Settings", open=False): | |
| max_tok_s = gr.Slider(1, 2048, 1024, step=1, label="Max new tokens") | |
| temp_s = gr.Slider(0.1, 4.0, 0.7, step=0.1, label="Temperature") | |
| top_p_s = gr.Slider(0.1, 1.0, 0.95, step=0.05, label="Top-p (nucleus sampling)") | |
| sys_msg_simple = gr.Textbox(value=SIMPLE_SYSTEM_MESSAGE, visible=False) | |
| submit_simple.click( | |
| stream_chat, | |
| inputs=[msg_simple, chatbot_simple, sys_msg_simple, | |
| max_tok_s, temp_s, top_p_s], | |
| outputs=[chatbot_simple], | |
| ).then( | |
| lambda: gr.update(value=""), | |
| outputs=[msg_simple], | |
| ) | |
| msg_simple.submit( | |
| stream_chat, | |
| inputs=[msg_simple, chatbot_simple, sys_msg_simple, | |
| max_tok_s, temp_s, top_p_s], | |
| outputs=[chatbot_simple], | |
| ).then( | |
| lambda: gr.update(value=""), | |
| outputs=[msg_simple], | |
| ) | |
| clear_simple.click(lambda: [], outputs=[chatbot_simple]) | |
| # FIX 1 (continued): css now passed here instead of gr.Blocks() | |
| demo.launch(css=css) |