import os import gradio as gr import pandas as pd from geolocation_apis import addresses_to_coordinates, coordinates_to_route from pdf_parser import process_pdf_hebrew_rtl from llm_api import llm_parser from map_visualize import generate_route_map def summarize_items(items): """ Returns a preview list for the dataset component. """ return [ [ f"{i + 1}. [{item['source']}] " + ( os.path.basename(item['file'].name) if item['source'] == 'PDF' else item['content'][:40] ) + "..." ] for i, item in enumerate(items) ] def add_files(files, items): """ Adds uploaded PDF file objects to the state. """ new_items = [{"source": "PDF", "file": f} for f in files] items += new_items return items, gr.update(samples=summarize_items(items)) def add_text(text, items): """ Adds pasted text content to the state. """ if text.strip(): items.append({"source": "Paste", "content": text.strip()}) return items, gr.update(samples=summarize_items(items)) def delete_item(evt: gr.SelectData, items): """ Deletes an item when selected in the dataset component. """ del items[evt.index] return items, gr.update(samples=summarize_items(items)) def run_pipeline(items): """ Processes PDFs and pasted text through the LLM pipeline, geocodes addresses, computes an optimized route, and writes two HTML outputs (data table and map). """ # Separate file-based and pasted inputs pdf_paths = [item['file'].name for item in items if item['source'] == 'PDF'] # Parse PDFs to text text_docs = [process_pdf_hebrew_rtl(path) for path in pdf_paths] # Include any pasted text directly pasted_texts = [item['content'] for item in items if item['source'] == 'Paste'] # Combine for LLM parsing docs = text_docs + pasted_texts results, llm_parsed = llm_parser(docs=docs) # Geolocation and routing locations = addresses_to_coordinates([r.business_address for r in results]) points = [loc.coords for loc in locations] route = coordinates_to_route(points) # Build data table df = pd.DataFrame([loc.to_dict() for loc in locations]) llm_parsed = llm_parsed.rename(columns={'business_address': 'Address'}) df = df.join(llm_parsed.set_index('Address'), on='Address') # Write HTML outputs data_output_path = './data_output.html' with open(data_output_path, mode='w', encoding='utf-8') as html: html.write(df.to_html(index=False, escape=False)) map_output_path = './map_output.html' generate_route_map(route, map_output_path) return data_output_path, map_output_path # Build Gradio interface with gr.Blocks() as demo: state = gr.State([]) with gr.Row(): file_input = gr.Files(file_types=['.pdf'], label="Upload PDFs") file_btn = gr.Button("Add PDFs") with gr.Row(): paste_box = gr.Textbox(lines=3, placeholder="Paste text content...", label="Paste Text") paste_btn = gr.Button("Add Text") gr.Markdown("### πŸ“ Inputs:") item_list = gr.Dataset( components=[gr.Textbox(visible=False)], # hide the textbox samples=[], headers=["Items"] ) # Register callbacks for managing inputs file_btn.click(add_files, inputs=[file_input, state], outputs=[state, item_list]) paste_btn.click(add_text, inputs=[paste_box, state], outputs=[state, item_list]) item_list.select(delete_item, inputs=state, outputs=[state, item_list]) # Processing and output process_btn = gr.Button("Process & Download HTML") data_out = gr.File(label="πŸ“Š Business Data HTML") map_out = gr.File(label="πŸ—ΊοΈ Route Map HTML") process_btn.click(run_pipeline, inputs=state, outputs=[data_out, map_out]) # Launch the app if __name__ == '__main__': demo.launch()