File size: 8,849 Bytes
2aef932
 
 
 
 
 
74d19d3
2aef932
 
74d19d3
2aef932
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74d19d3
2aef932
74d19d3
2aef932
 
 
 
 
 
74d19d3
 
 
2aef932
 
 
74d19d3
 
 
2aef932
 
74d19d3
2aef932
 
 
 
 
 
 
74d19d3
 
2aef932
 
 
 
 
 
 
 
 
 
 
7561984
 
74d19d3
7561984
 
 
 
 
 
74d19d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2aef932
74d19d3
 
 
 
 
 
2aef932
 
 
 
74d19d3
 
 
 
2aef932
74d19d3
 
2aef932
 
7561984
74d19d3
7561984
2aef932
 
 
 
 
 
 
 
 
 
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# Import the Gradio library for creating the web interface
import gradio as gr
# Import the InferenceClient from huggingface_hub to interact with the language model
from huggingface_hub import InferenceClient

# --- Configuration Constants ---
FIXED_MAX_TOKENS = 1000

# --- Initialize the InferenceClient ---
API_BASE_URL = "https://vulture-awake-probably.ngrok-free.app/v1/chat/completions"

try:
    client = InferenceClient(base_url=API_BASE_URL)
    print(f"InferenceClient initialized with base_url: {API_BASE_URL}")
except Exception as e:
    print(f"Error initializing InferenceClient with base_url '{API_BASE_URL}': {e}")
    raise RuntimeError(
        "Could not initialize InferenceClient. "
        f"Please check the API base URL ('{API_BASE_URL}') and ensure the server is accessible. "
        f"Error: {e}"
    )

# --- Core Chatbot Logic ---
def respond(message, history):
    messages = []
    for user_message, ai_message in history:
        if user_message:
            messages.append({"role": "user", "content": user_message})
        if ai_message:
            messages.append({"role": "assistant", "content": ai_message})
    messages.append({"role": "user", "content": message})

    response_text = ""
    try:
        stream = client.chat_completion(
            messages=messages,
            max_tokens=FIXED_MAX_TOKENS,
            stream=True,
        )
        for chunk in stream:
            if chunk.choices and chunk.choices[0].delta and chunk.choices[0].delta.content is not None:
                token = chunk.choices[0].delta.content
                response_text += token
                yield response_text
    except Exception as e:
        error_message = f"An error occurred during model inference: {e}"
        print(error_message)
        yield error_message

# --- Gradio Interface Definition ---

# URL for the header image
header_image_path = "https://cdn-uploads.huggingface.co/production/uploads/6540a02d1389943fef4d2640/j61iZTDaK9g0UW3aWGwWi.gif"

# Ko-fi widget script (original)
kofi_script_original = """
<script src='https://storage.ko-fi.com/cdn/scripts/overlay-widget.js'></script>
<script>
  kofiWidgetOverlay.draw('sonnydesorbo', {
    'type': 'floating-chat',
    'floating-chat.donateButton.text': 'Support me',
    'floating-chat.donateButton.background-color': '#00b9fe',
    'floating-chat.donateButton.text-color': '#fff'
  });
</script>
"""

# Ko-fi button HTML
kofi_button_html = """
<div style="text-align: center; padding: 10px 20px 20px 20px;">
    <a href='https://ko-fi.com/Z8Z51E5TIG' target='_blank'>
        <img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi5.png?v=6' border='0' alt='Buy Me a Coffee at ko-fi.com' />
    </a>
</div>
"""

# HTML, CSS, and JavaScript for Matrix Rain
matrix_rain_html_script = """
<canvas id="matrixCanvas"></canvas>
<style>
    body {
        /* overflow: hidden; */ /* Might hide Gradio scrollbars, be careful */
        /* Gradio manages its own background, so direct body changes might be tricky.
           The canvas will be fixed behind everything. */
    }
    #matrixCanvas {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        z-index: -1; /* Place it behind all Gradio content */
        display: block;
    }
    /* Ensure Gradio's main content area is above the canvas and has a transparent background
       if you want the rain to be visible *through* it, or a solid dark background
       if you want it *around* it. Gradio theming should handle the component backgrounds.
    */
    gradio-app > .main, gradio-app > .main > .wrap, gradio-app { /* Attempt to make Gradio app background transparent */
        /* background: transparent !important; */ /* This can be aggressive, use with caution */
    }
    /* You might need to adjust specific Gradio component backgrounds if they are not dark by default with the theme */
    .gradio-container {
        /* background: transparent !important; */ /* Example */
    }

</style>
<script>
    document.addEventListener('DOMContentLoaded', (event) => {
        const canvas = document.getElementById('matrixCanvas');
        if (!canvas) {
            console.error("Matrix canvas not found");
            return;
        }
        const ctx = canvas.getContext('2d');

        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;

        const katakana = 'アァカサタナハマヤャラワガザダバパイィキシチニヒミリヰギジヂビピウゥクスツヌフムユュルグズブヅプエェケセテネヘメレヱゲゼデベペオォコソトノホモヨョロヲゴゾドボポヴッン';
        const latin = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        const nums = '0123456789';
        const characters = katakana + latin + nums;

        const fontSize = 16;
        let columns = Math.floor(canvas.width / fontSize);
        let drops = [];

        function initializeDrops() {
            columns = Math.floor(canvas.width / fontSize);
            drops = [];
            for (let x = 0; x < columns; x++) {
                drops[x] = 1 + Math.floor(Math.random() * (canvas.height / fontSize));
            }
        }
        initializeDrops();

        function drawMatrix() {
            ctx.fillStyle = 'rgba(0, 0, 0, 0.04)'; // Black BG for the canvas with a little blur
            ctx.fillRect(0, 0, canvas.width, canvas.height);

            // Use a color that fits the dark theme, e.g., a neon green or the theme's primary color
            // For Gradio, you might try to pick up CSS variables if available, or hardcode.
            ctx.fillStyle = '#0F0'; // Classic green
            // Example: Try to use Gradio's primary color if possible (might require more complex JS)
            // const gradioPrimaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary-500') || '#0F0';
            // ctx.fillStyle = gradioPrimaryColor;

            ctx.font = fontSize + 'px monospace';

            for (let i = 0; i < drops.length; i++) {
                const text = characters.charAt(Math.floor(Math.random() * characters.length));
                ctx.fillText(text, i * fontSize, drops[i] * fontSize);

                if (drops[i] * fontSize > canvas.height && Math.random() > 0.975) {
                    drops[i] = 0;
                }
                drops[i]++;
            }
        }

        let matrixInterval = setInterval(drawMatrix, 45); // Adjusted speed

        window.addEventListener('resize', () => {
            const oldWidth = canvas.width;
            const oldHeight = canvas.height;
            
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;

            if (canvas.width !== oldWidth || canvas.height !== oldHeight) {
                initializeDrops();
            }
        });

        // Optional: A slight delay for Gradio to finish rendering before starting matrix
        // setTimeout(() => {
        //     if (matrixInterval) clearInterval(matrixInterval);
        //     initializeDrops();
        //     matrixInterval = setInterval(drawMatrix, 45);
        // }, 500);
    });
</script>
"""

# Combine Ko-fi script with Matrix Rain script for the 'head'
combined_head_script = kofi_script_original + matrix_rain_html_script


# Create a Gradio Blocks layout
# Use a dark theme and add the combined scripts to the head
# theme = gr.themes.Soft() # Original theme
theme = gr.themes.Base(primary_hue=gr.themes.colors.green, neutral_hue=gr.themes.colors.slate).dark() # Example dark theme

with gr.Blocks(theme=theme, head=combined_head_script) as demo:
    # Display an image at the top
    gr.Image(
        value=header_image_path,
        label="Chatbot Header",
        show_label=False,
        interactive=False,
        height=150,
        elem_id="chatbot-logo"
    )

    # Create the chat interface component
    gr.ChatInterface(
        fn=respond,
        chatbot=gr.Chatbot(
            height=650,
            # elem_id="chatbot_messages_container" # You can add an ID for more specific CSS
        ),
        # title="XORTRON AI", # You can set a title
        # description="Engage with the digital rain." # And a description
    )

    # Add the Ko-fi button at the bottom
    gr.HTML(kofi_button_html)

# --- Application Entry Point ---
if __name__ == "__main__":
    try:
        demo.launch(show_api=False, share=False)
    except NameError as ne:
        print(f"Gradio demo could not be launched. 'client' might not have been initialized: {ne}")
    except RuntimeError as re:
        print(f"Gradio demo could not be launched due to an error during client initialization: {re}")
    except Exception as e:
        print(f"An unexpected error occurred when trying to launch Gradio demo: {e}")