this is my main app, im getting an x1 compute error after retrieval of all emb codes from the emb model, (all the connectivity with the plot is done in main.py and with the llm in llm.py, i suspect the issue is in main.py, please locate fix and output only code)

# main.py
import os
from flask import Flask, request, jsonify, render_template_string
from llm import get_related_phrases, get_embedding, generate_axis_names, analyze_data, chat_response
import json
import numpy as np
from sklearn.decomposition import PCA

app = Flask(__name__)

@app.route('/')
def index():
    """
    Serve the HTML page for the application.
    """
    html = """
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Interactive 3D Vector Visualizer</title>
        <style>
            body {
                font-family: Arial, sans-serif;
                background-color: #000000; /* Black background */
                color: #ffffff; /* White text for contrast */
                margin: 0;
                padding: 0;
                display: flex;
                height: 100vh;
                overflow: hidden;
            }
            /* Container for resizable panels */
            .container {
                display: flex;
                width: 100%;
                height: 100%;
            }
            /* Sidebar on the Left */
            .sidebar {
                width: 300px;
                background-color: #1a1a1a;
                padding: 20px;
                box-sizing: border-box;
                overflow-y: auto;
                resize: horizontal;
                min-width: 200px;
            }
            /* Resizer between sidebar and main-content */
            .resizer1 {
                width: 5px;
                background-color: #444;
                cursor: ew-resize;
            }
            /* Main Content */
            .main-content {
                flex-grow: 1;
                display: flex;
                flex-direction: column;
                align-items: center;
                justify-content: center;
                position: relative;
                background-color: #000000;
            }
            /* Top Bar with Action Buttons */
            .top-bar {
                width: 100%;
                background-color: #1a1a1a;
                padding: 10px;
                box-sizing: border-box;
                display: flex;
                justify-content: center;
                gap: 10px;
                position: absolute;
                top: 0;
                left: 0;
            }
            .top-bar button {
                padding: 8px 12px;
                background-color: #333333;
                border: none;
                border-radius: 4px;
                cursor: pointer;
                color: #ffffff;
                font-size: 1em;
                transition: background-color 0.3s;
                display: flex;
                align-items: center;
                justify-content: center;
            }
            .top-bar button:hover {
                background-color: #555555;
            }
            /* Plot Area */
            #result {
                width: 80%;
                height: 80%;
                margin-top: 60px; /* To prevent overlap with top bar */
            }
            /* Resizer between main-content and right-panel */
            .resizer2 {
                width: 5px;
                background-color: #444;
                cursor: ew-resize;
            }
            /* Right Panel with Legend and Chat */
            .right-panel {
                width: 300px;
                background-color: #1a1a1a;
                padding: 20px;
                box-sizing: border-box;
                overflow-y: auto;
                resize: horizontal;
                min-width: 200px;
                display: flex;
                flex-direction: column;
                gap: 20px;
            }
            /* Tabs */
            .tabs {
                display: flex;
                border-bottom: 1px solid #555555;
            }
            .tab {
                flex: 1;
                padding: 10px 0;
                cursor: pointer;
                background-color: #1a1a1a;
                border: none;
                outline: none;
                transition: background-color 0.3s;
                color: #ffffff;
                font-size: 1em;
                text-align: center;
            }
            .tab:hover, .tab.active {
                background-color: #333333;
            }
            .tab-content {
                display: none;
                flex-grow: 1;
                overflow-y: auto;
            }
            .tab-content.active {
                display: block;
            }
            /* Legend Styling */
            #legend {
                width: 100%;
                background-color: #1a1a1a;
                padding: 10px;
                box-sizing: border-box;
                overflow-y: auto;
                border-radius: 8px;
            }
            /* Dark scrollbar */
            #legend::-webkit-scrollbar {
                width: 8px;
            }
            #legend::-webkit-scrollbar-track {
                background: #1a1a1a; 
                border-radius: 4px;
            }
            #legend::-webkit-scrollbar-thumb {
                background: #555555; 
                border-radius: 4px;
            }
            #legend::-webkit-scrollbar-thumb:hover {
                background: #777777; 
            }
            #legend-list {
                list-style: none; /* Remove bullets */
                padding: 0;
                margin: 0;
            }
            #legend-list li {
                margin-bottom: 5px;
                cursor: pointer;
                padding: 5px;
                border-radius: 4px;
                transition: background-color 0.3s;
                color: #ffffff;
            }
            #legend-list li:hover {
                background-color: #333333;
            }
            .collapsible {
                background-color: #1a1a1a;
                color: #ffffff;
                cursor: pointer;
                padding: 10px;
                width: 100%;
                border: none;
                text-align: left;
                outline: none;
                font-size: 16px;
                border-radius: 4px;
                transition: background-color 0.3s;
            }
            .active, .collapsible:hover {
                background-color: #333333;
            }
            .content {
                padding-left: 15px;
                display: none;
                overflow: hidden;
                background-color: #242424;
                border-radius: 4px;
            }
            .content li {
                padding: 5px;
                margin: 3px 0;
                border-radius: 4px;
                transition: background-color 0.3s;
                color: #dddddd;
                font-size: 14px;
            }
            .content li:hover {
                background-color: #555555;
                color: #ffffff;
            }
            /* Chat Styles */
            .chat-container {
                display: flex;
                flex-direction: column;
                height: 100%;
            }
            .chat-messages {
                flex-grow: 1;
                background-color: #242424;
                padding: 10px;
                border-radius: 4px;
                overflow-y: auto;
            }
            .chat-input {
                display: flex;
                margin-top: 10px;
                width: 100%;
            }
            .chat-input input {
                flex-grow: 1;
                padding: 8px;
                border: none;
                border-radius: 4px 0 0 4px;
                font-size: 1em;
            }
            .chat-input button {
                padding: 8px;
                background-color: #8B4513; /* SaddleBrown */
                border: none;
                border-radius: 0 4px 4px 0;
                cursor: pointer;
                color: white;
                display: flex;
                align-items: center;
                justify-content: center;
                margin-left: -5px; /* Small overlap */
            }
            .chat-input button:hover {
                background-color: #A0522D; /* Sienna */
            }
            /* Resizable Panels */
            .resizer1, .resizer2 {
                width: 5px;
                background-color: #444;
                cursor: ew-resize;
            }
            /* No horizontal scrollbar */
            .chat-messages, .log-area {
                max-height: 200px;
                overflow-x: hidden;
            }
            /* Ensure Legend and I/O Panel are resizable */
            .right-panel {
                resize: horizontal;
                min-width: 200px;
            }
        </style>
        <!-- Include Plotly.js -->
        <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
        <!-- Include FontAwesome for icons -->
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    </head>
    <body>
    <div class="container">
        <!-- Sidebar on the Left -->
        <div class="sidebar">
            <h1>3D Vector Inputs</h1>
            <div class="inputs">
                <div class="input-box">
                    <label for="string1">Input String 1:</label>
                    <input type="text" id="string1" name="string1" placeholder="e.g., financial river bank institute">
                </div>
                <div class="input-box">
                    <label for="string2">Input String 2:</label>
                    <input type="text" id="string2" name="string2" placeholder="e.g., river bank place by the river">
                </div>
                <div class="input-box">
                    <label for="string3">Input String 3:</label>
                    <input type="text" id="string3" name="string3" placeholder="e.g., sustainability initiatives">
                </div>
                <div class="input-box">
                    <label for="string4">Input String 4:</label>
                    <input type="text" id="string4" name="string4" placeholder="e.g., community outreach programs">
                </div>
                <div class="num-points">
                    <button onclick="decrementPoints()" title="Decrease number of data points">-</button>
                    <input type="number" id="numPoints" name="numPoints" value="10" min="10" max="1000" step="50" title="Number of data points">
                    <button onclick="incrementPoints()" title="Increase number of data points">+</button>
                    <label for="numPoints">Data Points</label>
                </div>
                <div class="plot-options">
                    <label for="plotType">Plot Type:</label>
                    <select id="plotType">
                        <option value="markers">Markers</option>
                        <option value="lines">Lines</option>
                        <option value="markers+lines">Markers + Lines</option>
                    </select>
                </div>
                <button class="submit-button" onclick="submitStrings()" title="Generate and visualize data points">Submit</button>
                <button class="fullscreen-button" onclick="openModal()" title="View plot in full screen">View Full Screen</button>
            </div>
            <div class="log-area" id="logArea">
                <h2>Logs</h2>
                <div id="logs"></div>
            </div>
        </div>
        
        <div class="resizer1"></div>
        
        <!-- Main Content in the Center -->
        <div class="main-content">
            <div class="top-bar">
                <button onclick="rotateLeft()" title="Rotate left"><i class="fas fa-rotate-left"></i></button>
                <button onclick="rotateRight()" title="Rotate right"><i class="fas fa-rotate-right"></i></button>
                <button onclick="zoomIn()" title="Zoom in"><i class="fas fa-search-plus"></i></button>
                <button onclick="zoomOut()" title="Zoom out"><i class="fas fa-search-minus"></i></button>
                <button onclick="panUp()" title="Pan up"><i class="fas fa-arrow-up"></i></button>
                <button onclick="panDown()" title="Pan down"><i class="fas fa-arrow-down"></i></button>
                <button onclick="changeView()" title="Change view perspective"><i class="fas fa-sync-alt"></i></button>
            </div>
            <div id="result"></div>
        </div>
        
        <div class="resizer2"></div>
        
        <!-- Right Panel with Legend and Chat -->
        <div class="right-panel">
            <div class="tabs">
                <button class="tab active" onclick="openTab(event, 'Legend')">Legend</button>
                <button class="tab" onclick="openTab(event, 'I/O')">I/O</button>
            </div>
            <div id="Legend" class="tab-content active">
                <div id="legend">
                    <ul id="legend-list"></ul>
                </div>
            </div>
            <div id="I/O" class="tab-content">
                <div class="chat-container">
                    <div class="chat-messages" id="chatMessages">
                        <!-- Chat messages will appear here -->
                    </div>
                    <div class="chat-input">
                        <input type="text" id="chatInput" placeholder="Type your question here...">
                        <button onclick="sendChat()" title="Send"><i class="fas fa-envelope"></i></button>
                    </div>
                </div>
            </div>
        </div>
    </div>
    
    <!-- Modal Overlay for Full Screen View -->
    <div id="myModal" class="modal">
        <span class="close-button" onclick="closeModal()">&times;</span>
        <div class="modal-content">
            <div id="fullResult"></div>
        </div>
    </div>
    
    <script>
        let originalData = null;
        let currentView = 0; // 0: Original, 1: Swap X and Y, 2: Swap X and Z

        function showSpinner() {
            document.getElementById('loadingSpinner').style.display = 'block';
        }

        function hideSpinner() {
            document.getElementById('loadingSpinner').style.display = 'none';
        }

        function appendLog(message) {
            const logDiv = document.getElementById('logs');
            const p = document.createElement('p');
            p.textContent = message;
            logDiv.appendChild(p);
            logDiv.scrollTop = logDiv.scrollHeight;
        }

        function appendLogs(logs) {
            logs.forEach(log => appendLog(log));
        }

        function clearLogs() {
            document.getElementById('logs').innerHTML = '';
        }

        function decrementPoints() {
            const numPointsInput = document.getElementById('numPoints');
            let currentValue = parseInt(numPointsInput.value);
            if (currentValue > 10) { // Allow min 10
                numPointsInput.value = currentValue - 50;
                if (numPointsInput.value < 10) {
                    numPointsInput.value = 10;
                }
            }
        }

        function incrementPoints() {
            const numPointsInput = document.getElementById('numPoints');
            let currentValue = parseInt(numPointsInput.value);
            if (currentValue < 950) { // Step set to 50
                numPointsInput.value = currentValue + 50;
                if (numPointsInput.value > 1000) {
                    numPointsInput.value = 1000;
                }
            }
        }

        async function submitStrings() {
            const string1 = document.getElementById('string1').value.trim();
            const string2 = document.getElementById('string2').value.trim();
            const string3 = document.getElementById('string3').value.trim();
            const string4 = document.getElementById('string4').value.trim();
            const numPoints = parseInt(document.getElementById('numPoints').value);
            const plotType = document.getElementById('plotType').value;

            if (!string1 || !string2 || !string3 || !string4) {
                alert('Please provide all four input strings.');
                return;
            }

            if (isNaN(numPoints) || numPoints < 10 || numPoints > 1000) {
                alert('Please enter a valid number of data points between 10 and 1000.');
                return;
            }

            showSpinner();
            clearLogs();
            const analysisContent = document.getElementById('analysisContent');
            if (analysisContent) {
                analysisContent.innerHTML = '';
            }

            try {
                const response = await fetch('/compute', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ 
                        string1, 
                        string2, 
                        string3, 
                        string4, 
                        num_points: numPoints 
                    })
                });

                if (!response.ok) {
                    const errorData = await response.json();
                    appendLog(`Error: ${errorData.error}`);
                    hideSpinner();
                    return;
                }

                const result = await response.json();
                originalData = result.data; // Deep copy not needed as we don't modify it
                appendLogs(result.logs);
                renderPlot(result.data, 'result', plotType); // Render in main view
                renderPlot(result.data, 'fullResult', plotType); // Also render in full screen
                hideSpinner();
            } catch (error) {
                console.error('Error:', error);
                appendLog('An error occurred while processing your request.');
                hideSpinner();
            }
        }

        function renderPlot(data, elementId, plotType) {
            // Define plot modes
            let mode;
            if (plotType === 'markers') {
                mode = 'markers';
            } else if (plotType === 'lines') {
                mode = 'lines';
            } else {
                mode = 'markers+lines';
            }

            const trace1 = {
                x: data.x1,
                y: data.y1,
                z: data.z1,
                mode: mode,
                type: 'scatter3d',
                marker: {
                    size: 6,
                    color: 'cyan',
                    line: {
                        color: 'white',
                        width: 0.5
                    }
                },
                line: {
                    color: 'magenta',
                    width: 1
                },
                hoverinfo: 'text',
                text: data.hover_text1,
                name: 'Set 1'
            };

            const trace2 = {
                x: data.x2,
                y: data.y2,
                z: data.z2,
                mode: mode,
                type: 'scatter3d',
                marker: {
                    size: 6,
                    color: 'orange',
                    line: {
                        color: 'white',
                        width: 0.5
                    }
                },
                line: {
                    color: 'blue',
                    width: 1
                },
                hoverinfo: 'text',
                text: data.hover_text2,
                name: 'Set 2'
            };

            const plotData = [trace1, trace2];

            const layout = {
                paper_bgcolor: 'black',
                plot_bgcolor: 'black',
                scene: {
                    xaxis: { color: 'white', title: data.axis_names.x_axis },
                    yaxis: { color: 'white', title: data.axis_names.y_axis },
                    zaxis: { color: 'white', title: data.axis_names.z_axis },
                },
                margin: { l: 0, r: 20, b: 0, t: 0 },
                camera: {
                    eye: data.camera_eye || {x: 1.75, y: 1.75, z: 1.75}
                }
            };

            Plotly.newPlot(elementId, plotData, layout, {responsive: true, displayModeBar: false});
        }

        function populateLegend(data, legendListId) {
            const legendList = document.getElementById(legendListId);
            legendList.innerHTML = '';

            // Create legend for Set 1
            const set1Title = document.createElement('li');
            set1Title.textContent = data.legend[0];
            set1Title.classList.add('collapsible');
            set1Title.dataset.setIndex = 0;

            const set1Phrases = document.createElement('ul');
            set1Phrases.classList.add('content');

            data.labels1.forEach((phrase, i) => {
                if (i >= 100) return; // Limit to 100 phrases
                const phraseItem = document.createElement('li');
                phraseItem.textContent = phrase;
                phraseItem.dataset.setIndex = 0;
                phraseItem.dataset.phraseIndex = i;
                phraseItem.addEventListener('mouseover', () => highlightTrace(0, i));
                phraseItem.addEventListener('mouseout', () => resetTraces());
                set1Phrases.appendChild(phraseItem);
            });

            set1Title.appendChild(set1Phrases);
            legendList.appendChild(set1Title);

            // Create legend for Set 2
            const set2Title = document.createElement('li');
            set2Title.textContent = data.legend[1];
            set2Title.classList.add('collapsible');
            set2Title.dataset.setIndex = 1;

            const set2Phrases = document.createElement('ul');
            set2Phrases.classList.add('content');

            data.labels2.forEach((phrase, i) => {
                if (i >= 100) return; // Limit to 100 phrases
                const phraseItem = document.createElement('li');
                phraseItem.textContent = phrase;
                phraseItem.dataset.setIndex = 1;
                phraseItem.dataset.phraseIndex = i;
                phraseItem.addEventListener('mouseover', () => highlightTrace(1, i));
                phraseItem.addEventListener('mouseout', () => resetTraces());
                set2Phrases.appendChild(phraseItem);
            });

            set2Title.appendChild(set2Phrases);
            legendList.appendChild(set2Title);

            // Add event listeners to toggle collapse
            const collapsibles = document.getElementsByClassName("collapsible");
            for (let i = 0; i < collapsibles.length; i++) {
                collapsibles[i].addEventListener("click", function(event) {
                    // Prevent toggling when clicking on child elements
                    if (event.target !== this) return;
                    this.classList.toggle("active");
                    const content = this.querySelector(".content");
                    if (content.style.display === "block") {
                        content.style.display = "none";
                    } else {
                        content.style.display = "block";
                    }
                });
            }
        }

        function highlightTrace(setIndex, phraseIndex) {
            if (!originalData) return;
            let traceNumber = setIndex; // Set 0 for Set 1, Set 1 for Set 2

            // Define unique colors and sizes
            const baseColor = setIndex === 0 ? 'cyan' : 'orange';
            const highlightColor = 'red';
            const baseSize = 6;
            const highlightSize = 12;

            // Reset all points to base color and size for the selected trace
            Plotly.restyle('result', {
                'marker.color': [baseColor],
                'marker.size': [baseSize]
            }, [traceNumber]);

            // Highlight the specific point
            let updatedColors = [];
            let updatedSizes = [];

            if (setIndex === 0) {
                updatedColors = originalData.x1.map((_, i) => i === phraseIndex ? highlightColor : baseColor);
                updatedSizes = originalData.x1.map((_, i) => i === phraseIndex ? highlightSize : baseSize);
            } else {
                updatedColors = originalData.x2.map((_, i) => i === phraseIndex ? highlightColor : baseColor);
                updatedSizes = originalData.x2.map((_, i) => i === phraseIndex ? highlightSize : baseSize);
            }

            Plotly.restyle('result', {
                'marker.color': [updatedColors],
                'marker.size': [updatedSizes]
            }, [traceNumber]);
        }

        function resetTraces() {
            if (!originalData) return;
            Plotly.restyle('result', {
                'marker.color': [['cyan'], ['orange']],
                'marker.size': [[6], [6]],
                'line.color': [['magenta'], ['blue']]
            }, [0,1]);
        }

        function openTab(evt, tabName) {
            var i, tabcontent, tablinks;
            tabcontent = document.getElementsByClassName("tab-content");
            for (i = 0; i < tabcontent.length; i++) {
                tabcontent[i].style.display = "none";
            }
            tablinks = document.getElementsByClassName("tab");
            for (i = 0; i < tablinks.length; i++) {
                tablinks[i].classList.remove("active");
            }
            document.getElementById(tabName).style.display = "block";
            evt.currentTarget.classList.add("active");
        }

        // Chat Functionality
        async function sendChat() {
            const userInput = document.getElementById('chatInput').value.trim();
            if (!userInput) return;

            appendChatMessage('You', userInput);
            document.getElementById('chatInput').value = '';

            try {
                const response = await fetch('/chat', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ 
                        message: userInput, 
                        context: originalData 
                    })
                });

                if (!response.ok) {
                    const errorData = await response.json();
                    appendChatMessage('Error', errorData.error);
                    return;
                }

                const result = await response.json();
                appendChatMessage('Assistant', result.reply);
            } catch (error) {
                console.error('Chat Error:', error);
                appendChatMessage('Error', 'An error occurred while processing your request.');
            }
        }

        function appendChatMessage(sender, message) {
            const chatMessages = document.getElementById('chatMessages');
            const msgDiv = document.createElement('div');
            msgDiv.innerHTML = `<strong>${sender}:</strong> ${message}`;
            chatMessages.appendChild(msgDiv);
            chatMessages.scrollTop = chatMessages.scrollHeight;
        }

        // Modal Functions
        function openModal() {
            document.getElementById('myModal').style.display = 'block';
        }

        function closeModal() {
            document.getElementById('myModal').style.display = 'none';
        }
    </script>
    </body>
    </html>
    """
    return render_template_string(html)

@app.route('/compute', methods=['POST'])
def compute_route():
    """
    Handle computation and return the processed data for plotting.
    Expecting four input strings and the number of data points.
    """
    data = request.json
    string1 = data.get('string1', '').strip()
    string2 = data.get('string2', '').strip()
    string3 = data.get('string3', '').strip()
    string4 = data.get('string4', '').strip()
    num_points = data.get('num_points', 10)  # Changed min to 10

    # Initialize logs
    logs = []

    # Ensure all four strings are provided
    if not string1 or not string2 or not string3 or not string4:
        return jsonify({'error': 'All four input strings must be provided.', 'logs': logs}), 400

    if not isinstance(num_points, int) or num_points < 10 or num_points > 1000:
        return jsonify({'error': 'num_points must be an integer between 10 and 1000.', 'logs': logs}), 400

    try:
        # Prepare datasets
        datasets = []
        colors = ['cyan', 'orange']  # Colors for the two datasets
        labels_group = ['Set 1', 'Set 2']

        # Set 1: string1 and string2
        related_phrases1 = get_related_phrases((string1, string2), num_related=num_points, logs=logs)
        if not related_phrases1:
            return jsonify({'error': 'Failed to generate related phrases for Set 1.', 'logs': logs}), 500
        if len(related_phrases1) > 100:
            related_phrases1 = related_phrases1[:100]
            logs.append('Limited Set 1 phrases to 100 to optimize performance.')
        embeddings1 = [get_embedding(phrase, logs=logs) for phrase in related_phrases1]
        labels1 = related_phrases1

        datasets.append({
            'x1': [emb[0] for emb in embeddings1],
            'y1': [emb[1] for emb in embeddings1],
            'z1': [emb[2] for emb in embeddings1],
            'hover_text1': [f"Content: {phrase}" for phrase in labels1],
            'labels1': labels1
        })

        # Set 2: string3 and string4
        related_phrases2 = get_related_phrases((string3, string4), num_related=num_points, logs=logs)
        if not related_phrases2:
            return jsonify({'error': 'Failed to generate related phrases for Set 2.', 'logs': logs}), 500
        if len(related_phrases2) > 100:
            related_phrases2 = related_phrases2[:100]
            logs.append('Limited Set 2 phrases to 100 to optimize performance.')
        embeddings2 = [get_embedding(phrase, logs=logs) for phrase in related_phrases2]
        labels2 = related_phrases2

        datasets.append({
            'x2': [emb[0] for emb in embeddings2],
            'y2': [emb[1] for emb in embeddings2],
            'z2': [emb[2] for emb in embeddings2],
            'hover_text2': [f"Content: {phrase}" for phrase in labels2],
            'labels2': labels2
        })

        # Combine all data for PCA
        if len(datasets) < 2 or not all(['x1' in ds and 'x2' in ds for ds in datasets]):
            raise KeyError("'x1' or 'x2' missing in datasets.")

        all_embeddings = np.hstack([
            np.vstack([ds['x1'], ds['y1'], ds['z1']]).T for ds in datasets
        ] + [
            np.vstack([ds['x2'], ds['y2'], ds['z2']]).T for ds in datasets
        ])

        # Perform PCA
        pca = PCA(n_components=3)
        reduced_embeddings = pca.fit_transform(all_embeddings)
        logs.append("Performed PCA on combined embeddings.")

        # Generate axis names using LLM
        axis_names = generate_axis_names(
            strings=(string1, string2, string3, string4),
            pca_components=pca.components_,
            logs=logs
        )

        # Assign the reduced embeddings back to datasets
        start = 0
        for dataset in datasets:
            end = start + len(dataset['x1'])
            dataset['x1'] = reduced_embeddings[start:end, 0].tolist()
            dataset['y1'] = reduced_embeddings[start:end, 1].tolist()
            dataset['z1'] = reduced_embeddings[start:end, 2].tolist()
            start = end
        for dataset in datasets:
            end = start + len(dataset['x2'])
            dataset['x2'] = reduced_embeddings[start:end, 0].tolist()
            dataset['y2'] = reduced_embeddings[start:end, 1].tolist()
            dataset['z2'] = reduced_embeddings[start:end, 2].tolist()
            start = end

        # Prepare response data
        response_data = {
            'axis_names': axis_names,
            'x1': datasets[0]['x1'],
            'y1': datasets[0]['y1'],
            'z1': datasets[0]['z1'],
            'hover_text1': datasets[0]['hover_text1'],
            'x2': datasets[1]['x2'],
            'y2': datasets[1]['y2'],
            'z2': datasets[1]['z2'],
            'hover_text2': datasets[1]['hover_text2'],
            'legend': labels_group,
            'labels1': datasets[0]['labels1'],
            'labels2': datasets[1]['labels2'],
            'camera_eye': {  # Store camera position for zoom and rotate
                'x': 1.75,
                'y': 1.75,
                'z': 1.75
            }
        }

        return jsonify({'data': response_data, 'logs': logs})
    except KeyError as e:
        logs.append(f"Error during computation: {e}")
        print(f"Error during computation: {e}")  # Debug statement
        return jsonify({'error': f"Error during computation: {e}", 'logs': logs}), 500
    except Exception as e:
        logs.append(f"Error during computation: {e}")
        print(f"Error during computation: {e}")  # Debug statement
        return jsonify({'error': 'An internal error occurred. Please try again later.', 'logs': logs}), 500

@app.route('/analyze', methods=['POST'])
def analyze_route():
    """
    Analyze the PCA components and return conclusions.
    """
    data = request.json
    prompt = data.get('prompt', '').strip()
    logs = []

    if not prompt:
        return jsonify({'error': 'No prompt provided.'}), 400

    try:
        analysis = analyze_data(prompt, logs)
        return jsonify({'conclusions': analysis, 'logs': logs})
    except Exception as e:
        logs.append(f"Error generating analysis: {e}")
        print(f"Error generating analysis: {e}")
        return jsonify({'error': 'Failed to generate analysis.', 'logs': logs}), 500

@app.route('/chat', methods=['POST'])
def chat():
    """
    Handle chat messages and return responses from the LLM.
    """
    data = request.json
    user_message = data.get('message', '').strip()
    context = data.get('context', {})
    logs = []

    if not user_message:
        return jsonify({'error': 'No message provided.'}), 400

    try:
        reply = chat_response(user_message, context, logs)
        return jsonify({'reply': reply, 'logs': logs})
    except Exception as e:
        logs.append(f"Error in chat: {e}")
        print(f"Error in chat: {e}")
        return jsonify({'error': 'Failed to generate chat response.', 'logs': logs}), 500

if __name__ == '__main__':
    # Run the Flask app
    app.run(port=5005, debug=True)