import streamlit as st import subprocess import pandas as pd import re import asyncio import logging # Set up logging to a file logging.basicConfig(filename='subprocess_output.log', level=logging.INFO, format='%(asctime)s - %(message)s', force=True) # Set the page title st.set_page_config(page_title="Multi Agent SQL Chat") st.title('Multi Agent SQL Chat') # Sidebar: Model provider dropdown and corresponding API key input option = st.sidebar.selectbox( 'Select the model provider:', #('OpenAI', 'Google', 'Openrouter', 'Ollama-local') ('Google') ) api_key = st.sidebar.text_input(f'{option} API key') # Sidebar: Multi-select for table(s) multi_select = st.sidebar.multiselect( 'Select the table/s:', #['TCGA_clinical', 'BRCA_Clinical'] ['TCGA_clinical'] ) # Determine if all required fields are provided submit_disabled = not (api_key and multi_select) # Function to remove ANSI escape sequences def remove_ansi_codes(text): ansi_escape = re.compile(r'\x1B[@-_][0-?]*[ -/]*[@-~]') return ansi_escape.sub('', text) # Function to read errors from subprocess_output.log def read_log_errors(log_file='subprocess_output.log'): errors = [] try: with open(log_file, 'r') as f: for line in f: if 'ERROR' in line: # Filter lines containing error messages errors.append(line.strip()) return errors except FileNotFoundError: return ["Log file not found."] except Exception as e: return [f"Error reading log file: {e}"] # Asynchronous function to stream subprocess output async def stream_subprocess(command, output_placeholder, buffer_limit=1024*128): try: process = await asyncio.create_subprocess_exec( *command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, limit=buffer_limit # Set the buffer limit ) output = "" while True: try: line = await process.stdout.readline() if not line: break clean_line = remove_ansi_codes(line.decode().strip()) output += clean_line + "\n" output_placeholder.text_area("Execution Output", output, height=300) logging.info(clean_line) except asyncio.LimitOverrunError as e: logging.error(f"Line exceeded buffer limit: {e}") continue await process.wait() error_output = await process.stderr.read() return_code = process.returncode if error_output: clean_error = remove_ansi_codes(error_output.decode().strip()) logging.error(clean_error) return return_code, clean_error return return_code, None except Exception as e: logging.exception("An unexpected error occurred in stream_subprocess: %s", e) return None, f"An unexpected error occurred: {e}" # Main form with a text area with st.form('my_form'): text = st.text_area('Enter text:', 'How many male patients have overall survival more than 6 months?') submitted = st.form_submit_button('Submit', disabled=submit_disabled) if submitted: # Dump the selections into a local file selections = { "Text": [text], "Selected Model Provider": [option], "API Key / Server IP": [api_key], "Selected Tables": [", ".join(multi_select)] # Join list as a string } print(selections) df = pd.DataFrame(selections) df.to_csv("selections.csv", index=False) # Placeholder for output box output_placeholder = st.empty() command = ["python", "-u", "SQL-Chat-cB-v3.py"] # Run the subprocess and check for completion try: return_code, error_message = asyncio.run(stream_subprocess(command, output_placeholder)) if return_code is None or return_code != 0: # Subprocess failed or threw an exception st.error("Subprocess failed to complete successfully.") if error_message: st.code(f"Error details: {error_message}") # Display any additional errors from the log errors = read_log_errors() if errors: st.error("Additional errors found in log:") st.code("\n".join(errors)) else: # Subprocess completed successfully # Display errors from the log file (if any) errors = read_log_errors() if errors: st.error("Errors occurred during execution:") st.code("\n".join(errors)) # Display final output try: with open("Data/write_report_output.txt", "r") as f: st.success("Final Output: " + f.read()) except FileNotFoundError: st.error("Final output file not found: Data/write_report_output.txt") except Exception as e: st.error("Failed to run subprocess.") st.code(f"Reason: {e}") # Display any errors from the log errors = read_log_errors() if errors: st.error("Additional errors found in log:") st.code("\n".join(errors)) # Author section at the bottom of the page footer = """ """ st.markdown(footer, unsafe_allow_html=True)