Spaces:
Sleeping
Sleeping
| # app.py | |
| import os | |
| import gradio as gr | |
| # Import your modules | |
| from parsers import parse_pcap | |
| from analysis import analyze_calls | |
| from call_flow import create_call_flow_diagram | |
| # We'll adapt llm_utils to load flan-t5-base locally | |
| from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM | |
| def create_local_pipeline(model_id="google/flan-t5-base"): | |
| """ | |
| Create a local pipeline for Flan-T5, which is a seq2seq model. | |
| This should run within ~16GB RAM for 'flan-t5-base'. | |
| """ | |
| tokenizer = AutoTokenizer.from_pretrained(model_id) | |
| model = AutoModelForSeq2SeqLM.from_pretrained(model_id, device_map="auto") | |
| # Use text2text-generation for T5-based models | |
| return pipeline("text2text-generation", model=model, tokenizer=tokenizer) | |
| # Initialize model pipeline once | |
| MODEL_ID = "google/flan-t5-base" | |
| generator = create_local_pipeline(MODEL_ID) | |
| def get_llm_opinion(prompt, generator): | |
| """ | |
| Generate text from the local Flan-T5 pipeline. | |
| We use text2text-generation to handle the seq2seq nature of T5. | |
| """ | |
| outputs = generator(prompt, max_length=256, do_sample=True, temperature=0.5) | |
| return outputs[0]["generated_text"] | |
| def process_file(pcap_file): | |
| """ | |
| This function is called when user clicks the 'Analyze File' button. | |
| - pcap_file: A dictionary returned by Gradio's File component. | |
| Returns: | |
| - a textual summary (analysis + call flow) | |
| - the dictionary of calls_by_id (saved in Gradio state so we can pass them to the LLM) | |
| """ | |
| print("DEBUG pcap_file =", pcap_file, type(pcap_file)) # <--- debug line | |
| if not pcap_file: | |
| return "No file uploaded.", {} | |
| # pcap_file is a string path to the temp file, e.g. "/tmp/gradio/xyz/somefile.pcap" | |
| temp_filename = pcap_file | |
| # 1) Parse the PCAP | |
| calls_by_id = parse_pcap(temp_filename) | |
| # 2) Analyze the calls | |
| analysis_result = analyze_calls(calls_by_id) | |
| # 3) Create a call flow diagram (textual) | |
| call_flow_text = create_call_flow_diagram(calls_by_id) | |
| # Combine them into one display string | |
| result_text = ( | |
| f"=== VoIP Analysis ===\n" | |
| f"{analysis_result}\n\n" | |
| f"=== Call Flow Diagram(s) ===\n" | |
| f"{call_flow_text}" | |
| ) | |
| # Delete the temp file if desired | |
| os.remove(temp_filename) | |
| return result_text, calls_by_id | |
| def ask_llm_opinion(calls_data, question): | |
| """ | |
| This function passes the call analysis info + user question to the LLM (local pipeline). | |
| - calls_data: The dictionary of calls returned from parse_pcap() [Gradio state] | |
| - question: The user’s question in text form | |
| """ | |
| if not calls_data: | |
| return "No call data available. Please upload and analyze a PCAP first." | |
| if not question.strip(): | |
| return "Please enter a question." | |
| # Summarize the calls for context | |
| calls_context = "Below is a brief description of the calls found in the PCAP:\n" | |
| for call_id, call_obj in calls_data.items(): | |
| calls_context += f"- Call-ID: {call_id}, from_tag: {call_obj.from_tag}, to_tag: {call_obj.to_tag}\n" | |
| # Build a prompt for T5 | |
| prompt = ( | |
| f"{calls_context}\n" | |
| f"User's question: {question}\n\n" | |
| "Please provide your expert VoIP analysis or advice." | |
| ) | |
| # Query the local pipeline | |
| llm_response = get_llm_opinion(prompt, generator=generator) | |
| return llm_response | |
| def main(): | |
| """ | |
| Build the Gradio interface with two tabs: | |
| 1) PCAP Analysis | |
| 2) LLM Consultation | |
| """ | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# VoIP Analyzer\nUpload a PCAP/PCAPNG file for SIP/RTP analysis. Then consult Flan-T5 for further insights.") | |
| # We keep the calls data in a Gradio State so we can pass it between tabs | |
| calls_state = gr.State({}) | |
| with gr.Tab("PCAP Analysis"): | |
| file_input = gr.File(label="Upload a PCAP or PCAPNG file") | |
| analyze_button = gr.Button("Analyze File") | |
| analysis_output = gr.Textbox(label="Analysis & Call Flow", lines=20) | |
| analyze_button.click( | |
| fn=process_file, | |
| inputs=file_input, | |
| outputs=[analysis_output, calls_state] | |
| ) | |
| with gr.Tab("LLM Consultation"): | |
| question_input = gr.Textbox(label="Ask a question about the call(s)") | |
| ask_button = gr.Button("Ask LLM") | |
| llm_output = gr.Textbox(label="LLM Response", lines=10) | |
| ask_button.click( | |
| fn=ask_llm_opinion, | |
| inputs=[calls_state, question_input], | |
| outputs=[llm_output] | |
| ) | |
| demo.launch(server_name="0.0.0.0", server_port=7860, share=True) | |
| if __name__ == "__main__": | |
| main() | |