File size: 6,198 Bytes
5f02ff5
 
1c41e23
7a43222
7246ac3
b8f89e6
 
7a43222
b8f89e6
5f02ff5
 
 
 
 
 
 
 
 
1c41e23
 
5f02ff5
1c41e23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b8f89e6
2cd9f16
5f02ff5
1c41e23
449048d
b8f89e6
 
449048d
 
5f02ff5
 
 
1c41e23
5f02ff5
 
1c41e23
5f02ff5
1c41e23
 
 
 
449048d
1c41e23
 
5f02ff5
 
 
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
import os
import gc
from flask import Flask, request, jsonify, render_template_string
from flask_cors import CORS
from brain import MairaBrain

app = Flask(__name__)
CORS(app)

# --- Configuration for the 5 Neural Cores ---
MODELS = {
    "small": {"repo": "CyberCoder225/maira-model", "file": "SmolLM2-360M-Instruct.Q4_K_M.gguf"},
    "medium": {"repo": "bartowski/Llama-3.2-1B-Instruct-GGUF", "file": "Llama-3.2-1B-Instruct-Q4_K_M.gguf"},
    "qwen": {"repo": "Qwen/Qwen2.5-1.5B-Instruct-GGUF", "file": "qwen2.5-1.5b-instruct-q4_k_m.gguf"},
    "danube": {"repo": "h2oai/h2o-danube3-500m-chat-GGUF", "file": "h2o-danube3-500m-chat-Q4_K_M.gguf"},
    "granite": {"repo": "bartowski/granite-3.0-2b-instruct-GGUF", "file": "granite-3.0-2b-instruct-Q4_K_M.gguf"}
}

# --- Initialize Neural Core Registry ---
print("🌌 Loading Neural Core Registry...")
cores = {name: MairaBrain(cfg["repo"], cfg["file"]) for name, cfg in MODELS.items()}

# --- EMBEDDED HTML (No more templates folder needed!) ---
HTML_UI = """
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Maira Quintessence</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <style>
        .glass { background: rgba(15, 23, 42, 0.9); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.1); }
        .chat-scroll::-webkit-scrollbar { width: 4px; }
        .chat-scroll::-webkit-scrollbar-thumb { background: #6366f1; border-radius: 10px; }
    </style>
</head>
<body class="bg-[#020617] text-slate-300 min-h-screen flex items-center justify-center p-4 font-sans">
    <div class="w-full max-w-2xl h-[90vh] glass rounded-3xl flex flex-col overflow-hidden shadow-2xl">
        <div class="p-5 border-b border-white/10 flex justify-between items-center">
            <div>
                <h1 class="text-xl font-bold text-indigo-400">Maira Quintessence</h1>
                <p class="text-[10px] uppercase tracking-widest text-slate-500">Owner: CyberCoder225</p>
            </div>
            <select id="model-select" class="bg-slate-800 border border-white/10 rounded-lg px-3 py-2 text-xs text-white outline-none focus:ring-1 focus:ring-indigo-500">
                <option value="small">Maira Lite (Fast)</option>
                <option value="medium">Maira Prime (Llama)</option>
                <option value="qwen">Maira Logic (Qwen)</option>
                <option value="danube">Maira Chat (H2O)</option>
                <option value="granite">Maira Art (Granite)</option>
            </select>
        </div>
        <div id="chat-window" class="flex-grow p-6 overflow-y-auto chat-scroll space-y-4">
            <div class="bg-indigo-500/10 border border-indigo-500/20 p-4 rounded-2xl rounded-tl-none max-w-[85%] text-sm">
                Awaiting your command, Boss. All cores are on standby.
            </div>
        </div>
        <form id="chat-form" class="p-4 bg-black/20 border-t border-white/10 flex gap-2">
            <input type="text" id="user-input" placeholder="Enter message..." required
                class="flex-grow bg-slate-800/50 border border-white/10 rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500">
            <button type="submit" id="send-btn" class="bg-indigo-600 hover:bg-indigo-500 px-5 py-3 rounded-xl text-sm font-bold transition-all disabled:opacity-50">
                SEND
            </button>
        </form>
    </div>
    <script>
        const chatWindow = document.getElementById('chat-window');
        const chatForm = document.getElementById('chat-form');
        const userInput = document.getElementById('user-input');
        const modelSelect = document.getElementById('model-select');
        const sendBtn = document.getElementById('send-btn');

        function addMessage(role, text) {
            const div = document.createElement('div');
            div.className = role === 'user' 
                ? 'bg-slate-800 ml-auto p-4 rounded-2xl rounded-tr-none max-w-[85%] text-sm text-white' 
                : 'bg-indigo-500/10 border border-indigo-500/20 p-4 rounded-2xl rounded-tl-none max-w-[85%] text-sm';
            div.innerText = text;
            chatWindow.appendChild(div);
            chatWindow.scrollTop = chatWindow.scrollHeight;
        }

        chatForm.onsubmit = async (e) => {
            e.preventDefault();
            const message = userInput.value.trim();
            const model = modelSelect.value;
            if (!message) return;

            addMessage('user', message);
            userInput.value = '';
            sendBtn.disabled = true;
            sendBtn.innerText = 'CORE BUSY...';

            try {
                const response = await fetch('/chat', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ message, model_type: model })
                });
                const data = await response.json();
                addMessage('maira', data.maira || "ERROR: " + data.error);
            } catch (err) {
                addMessage('maira', "CONNECTION LOST: Check if Space is still building.");
            } finally {
                sendBtn.disabled = false;
                sendBtn.innerText = 'SEND';
            }
        };
    </script>
</body>
</html>
"""

@app.route('/')
def home():
    return render_template_string(HTML_UI)

@app.route('/chat', methods=['POST'])
def chat():
    try:
        data = request.json
        user_input = data.get("message", "")
        model_type = data.get("model_type", "small")

        # Memory Cleanup: Unload all EXCEPT active model
        for name, core in cores.items():
            if name != model_type:
                core.unload()

        active_core = cores.get(model_type, cores["small"])
        answer = active_core.get_response("CyberCoder225", user_input)
        
        return jsonify({"maira": answer})
    except Exception as e:
        print(f"❌ ERROR: {e}")
        return jsonify({"error": str(e)}), 500

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=7860, debug=False)