import gradio as gr import os import pandas as pd from openai import OpenAI import logging # Set up logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler('app.log'), logging.StreamHandler() ] ) logger = logging.getLogger(__name__) def upload_file(xsl_file): if xsl_file is None: return "Please upload a file first" try: df = pd.read_excel(xsl_file.name) return df except Exception as e: return f"Error reading file: {str(e)}" def process_query(xsl_file, query): # Process the file and generate responses logger.info("Starting query processing") api_key = os.getenv('OPENAI_API_KEY') client = OpenAI() model = "gpt-4o" responses = {} # Convert DataFrame to JSON if xsl_file is not None: logger.info(f"Reading Excel file: {xsl_file.name}") try: df = pd.read_excel(xsl_file.name) json_data = df.to_json(orient='records') responses['data'] = json_data logger.info("Successfully converted Excel to JSON") except Exception as e: logger.error(f"Error converting Excel to JSON: {str(e)}") raise try: logger.info("Sending request to OpenAI API") response = client.chat.completions.create( model=model, messages=[ {"role": "system", "content": os.getenv('system_prompt')}, {"role": "user", "content": f"Examples: {os.getenv('context_prompt')}\n\n Data: {json_data}\n\n Query: {query} \n\n INSTRUCTIONS: You must absolutely return the sql between and the XML between . If the user query is incorrect, add the disclaimer between the SQL/XML tags as well. \n\n Output:"} ] ) responses['query'] = query responses['response'] = response.choices[0].message.content logger.info(f"Raw response content: {response.choices[0].message.content}") # Add validation before splitting if '' not in response.choices[0].message.content or '' not in response.choices[0].message.content: logger.error("Response missing SQL or XML tags") raise ValueError("Response format invalid - missing SQL or XML tags") try: responses['SQL'] = response.choices[0].message.content.split('')[1].split('')[0] logger.info("Successfully extracted SQL query") except IndexError as e: logger.error(f"Error extracting SQL query: {str(e)}") responses['SQL'] = "Error extracting SQL query" try: responses['XML'] = response.choices[0].message.content.split('')[1].split('')[0] logger.info("Successfully extracted XML query") except IndexError as e: logger.error(f"Error extracting XML query: {str(e)}") responses['XML'] = "Error extracting XML query" logger.info("Successfully processed OpenAI response") except Exception as e: print(f"Error occurred: {e}") responses['error'] = str(e) try: df = pd.read_excel(xsl_file.name) return responses['SQL'], responses['XML'], responses except Exception as e: return f"Error reading file: {str(e)}", None, None # Create the Gradio interface with gr.Blocks() as demo: gr.Markdown("# WEF Hackathon Demo") # Top section - XLS file upload with gr.Row(): xsl_upload = gr.File( label="Upload XLS File", file_types=[".xls"] ) # Display section for uploaded data data_display = gr.Dataframe( label="Uploaded Data Preview", interactive=False, wrap=True ) # Bottom section - 3 columns with gr.Row(): # First column - Natural language input with gr.Column(): query_input = gr.Textbox( label="Natural Language Query", placeholder="Enter your query here...", lines=5 ) # Second column - SQL output with gr.Column(): sql_output = gr.Textbox( label="LLM SQL Response", interactive=False ) # Third column - XML output with gr.Column(): xml_output = gr.Textbox( label="LLM XML Response", interactive=False ) # Submit button submit_btn = gr.Button("Process Query") cached_examples = os.getenv('examples') examples = gr.Examples( examples=[ '''Join LFA1 (general vendor data) with LFB1 (company code data) by matching LIFNR. Filter on a specific vendor (e.g., LIFNR = "100000"), then retrieve the vendor’s number, name, company code, payment block, and payment terms.''', '''Match LFA1’s address number (ADRNR) to ADR6’s address reference (ADDRNUMBER) to get e-mail data. For a given vendor (e.g., LIFNR = "100000"), select the vendor’s number, name, e-mail address, and validity dates.''', '''Join LFM1 and LFM2 on both vendor number (LIFNR) and purchasing organization (EKORG). Retrieve data like the vendor’s credit group and blocking status for a given vendor (LIFNR) and purchasing org (EKORG).''' '''Link LFBK (vendor’s bank details) to BNKA (bank master) by matching bank key and account (e.g., LFBK.BANKL = BNKA.BANKL and LFBK.BANKN = BNKA.BANKN). For a vendor (LIFNR = "100000"), return their bank account plus the bank’s name and country.''', '''Join BSIK (open vendor items) with LFA1 (vendor data) using LIFNR. Filter on a specific vendor and list open items (document number, amount) alongside the vendor’s name.''', '''Combine CDHDR/CDPOS (change documents) with LFA1 (vendors). Match CDHDR.OBJECTID = LFA1.LIFNR (and ensure CDHDR.OBJECTCLAS = "LFA1"), then join CDHDR.CHANGENR = CDPOS.CHANGENR to display what fields changed, along with old/new values, for a specific vendor.''' ], inputs=query_input ) xsl_upload.change(fn=upload_file, inputs=[xsl_upload], outputs=data_display) # Handle submission submit_btn.click( fn=process_query, inputs=[xsl_upload, query_input], outputs=[sql_output, xml_output] ) if __name__ == "__main__": demo.launch()