File size: 5,174 Bytes
eb4b18c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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 <!DOCTYPE html> and includes all necessary elements.



Data Details:

- Columns: {columns}

- Data Types: {dtypes}

- Summary Stats: {summary_stats}



Required HTML Structure:

<!DOCTYPE html>

<html>

<head>

    <!-- Include Plotly CDN -->

    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>

    <style>

        /* Add your CSS styling here */

    </style>

</head>

<body>

    <!-- Report content goes here -->

</body>

</html>



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 "<!DOCTYPE html>" not in response_text:
        # Fallback if response isn't proper HTML
        return f"""

        <!DOCTYPE html>

        <html>

        <head>

            <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>

        </head>

        <body>

            <h1>Analysis Report</h1>

            {response_text}

        </body>

        </html>

        """
    
    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()