import streamlit as st import pandas as pd import anthropic import base64 import plotly.express as px from datetime import datetime import json from pathlib import Path from utils import EmbeddingManager def send_to_llm(user_query, data, df): """Send data chunks to the LLM and get a response.""" columns = df.columns.tolist() dtypes = df.dtypes.to_dict() summary_stats = df.describe().to_json() client = anthropic.AnthropicBedrock() prompt = """You are a data analysis expert. Your task is to generate a complete, standalone HTML report. You MUST return ONLY valid HTML code that starts with and includes all necessary elements. Data Details: - Columns: {columns} - Data Types: {dtypes} - Summary Stats: {summary_stats} Required HTML Structure: Requirements: 1. Create visualizations using Plotly.js 2. Include executive summary, insights, and analysis 3. Add proper styling and make it visually appealing 4. Ensure all Plotly charts have proper div containers 5. Include the current date DO NOT include any explanatory text outside the HTML code. Return ONLY the complete HTML document.""" message = client.messages.create( model="anthropic.claude-3-5-sonnet-20240620-v1:0", max_tokens=4096, # Increased token limit for full HTML response system=prompt, messages=[{ "role": "user", "content": f"Generate a complete HTML report analyzing this data: {str(data)} \nUser query: {user_query}" }] ) # Extract only the HTML content response_text = message.content[0].text if "" not in response_text: # Fallback if response isn't proper HTML return f"""

Analysis Report

{response_text} """ return response_text def create_chunks_and_send(data_dict: dict, filename): """Process each sheet separately and combine their chunks""" all_chunks = [] for sheet_name, df in data_dict.items(): # Reset index for each DataFrame df = df.reset_index(drop=True) output_dir = Path('./output') embeddings_dir = output_dir / 'embeddings' / filename / sheet_name if embeddings_dir.exists(): chunks_file = embeddings_dir / "chunks.json" if chunks_file.is_file(): with open(chunks_file, "r", encoding="utf-8") as f: sheet_chunks = json.load(f) all_chunks.extend(sheet_chunks) else: embeddings_dir.mkdir(parents=True, exist_ok=True) embedding_manager = EmbeddingManager(output_dir=Path('./output')) # Convert DataFrame to JSON with orient='records' text = df.to_json(orient='records') sheet_chunks, _ = embedding_manager.process_script(data=str(text), filename=f"{filename}_{sheet_name}") all_chunks.extend(sheet_chunks) return all_chunks def main(): st.title("Excel Chatbot") query = st.text_input("Enter the query") # File upload uploaded_file = st.file_uploader("Upload Excel File", type=['xlsx', 'xls']) if uploaded_file and query: try: # Read Excel without concatenating sheets df_dict = pd.read_excel(uploaded_file, sheet_name=None) st.success("File uploaded successfully!") # Show preview of each sheet for sheet_name, df in df_dict.items(): st.subheader(f"Data Preview - {sheet_name}") st.dataframe(df) with st.spinner("Generating response with Claude..."): # Process all sheets and get combined chunks data = create_chunks_and_send(df_dict, uploaded_file.name) # Get complete HTML report from Claude response = send_to_llm(user_query=query, data=data, df=pd.concat(df_dict.values())) # Get the HTML content (ensure it's a string) html_report = ''.join(str(message.text) for message in response.content) st.components.v1.html(html_report, height=800, scrolling=True) st.success("Report generated successfully! Click the link above to download.") except Exception as e: st.error(f"An error occurred: {str(e)}") #st.error("Please check your API key and file format, then try again.") if __name__ == "__main__": main()