broadfield-dev commited on
Commit
8f054c4
·
verified ·
1 Parent(s): c0877f8

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +91 -0
  2. templates/index.html +243 -0
app.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import base64
2
+ from flask import Flask, render_template, request, jsonify, Response, stream_with_context
3
+ from visumem_core import SectorMemory
4
+ import ai_engine
5
+ import json
6
+
7
+ app = Flask(__name__)
8
+
9
+ mem_history = SectorMemory("history")
10
+
11
+
12
+ @app.route('/')
13
+ def index():
14
+ return render_template('index.html')
15
+
16
+ @app.route('/visualize/<mem_type>')
17
+ def visualize(mem_type):
18
+ target = mem_history
19
+
20
+ # 1. Generate Image
21
+ img_bytes = target.to_image_bytes()
22
+ b64 = base64.b64encode(img_bytes).decode('utf-8')
23
+
24
+ # 2. Get Stats (Updated for RGB Core Compatibility)
25
+ # The RGB core uses .count for items and .cursor_green for text size
26
+ # It does not use .slot_cursor or .heap_cursor anymore.
27
+ active_count = target.count
28
+ text_usage = target.cursor_green
29
+
30
+ return jsonify({
31
+ "image": f"data:image/png;base64,{b64}",
32
+ "stats": f"{active_count} Active Entries",
33
+ "usage": f"{text_usage} Bytes Text"
34
+ })
35
+
36
+ @app.route('/inspect/<mem_type>')
37
+ def inspect(mem_type):
38
+ content = mem_history.dump_heap_content()
39
+ return jsonify({"content": content})
40
+
41
+ @app.route('/chat', methods=['POST'])
42
+ def chat():
43
+ user_msg = request.json.get('message')
44
+ if not user_msg: return jsonify({"error": "Empty"}), 400
45
+
46
+ def generate():
47
+ # 1. VECTORIZE USER INPUT
48
+ q_vec = ai_engine.get_embedding(user_msg)
49
+
50
+ # B. Relevant Past History
51
+ hist_hits = mem_history.search(q_vec, top_k=2)
52
+ long_term_txt = "\n".join([f"[Memory]: {h['text']}" for h in hist_hits if h['score'] > 0.4])
53
+
54
+ # C. Recent Conversation
55
+ recent_msgs = mem_history.get_recent_entries(n=4)
56
+ recent_txt = "\n".join(recent_msgs)
57
+
58
+ # 3. BUILD PROMPT
59
+ system_prompt = f"""You are a helpful AI Assistant with an evolving rule system and knowledge base.
60
+
61
+ ### RELEVANT MEMORIES (Context from past):
62
+ {long_term_txt}
63
+
64
+ ### CURRENT CONVERSATION:
65
+ {recent_txt}
66
+ """
67
+
68
+ messages = [
69
+ {"role": "system", "content": system_prompt},
70
+ {"role": "user", "content": user_msg}
71
+ ]
72
+
73
+ # 4. STREAM GENERATION
74
+ full_response = ""
75
+ for chunk in ai_engine.chat_stream(messages):
76
+ full_response += chunk
77
+ yield chunk
78
+
79
+ # 5. BACKGROUND: WRITE & REFLECT
80
+ log_entry = f"User: {user_msg}\nAI: {full_response}"
81
+ mem_history.write_entry(log_entry, q_vec)
82
+
83
+ return Response(stream_with_context(generate()), mimetype='text/plain')
84
+
85
+ @app.route('/wipe', methods=['POST'])
86
+ def wipe():
87
+ mem_history.wipe()
88
+ return jsonify({"success":True})
89
+
90
+ if __name__ == '__main__':
91
+ app.run(debug=True, port=5000)
templates/index.html ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>VisuMem AI // Recursive Visual Memory</title>
6
+ <script src="https://cdn.tailwindcss.com"></script>
7
+
8
+ <!-- Markdown & Syntax Highlighting -->
9
+ <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/atom-one-dark.min.css">
11
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
12
+
13
+ <style>
14
+ @import url('https://fonts.googleapis.com/css2?family=Space+Mono:ital,wght@0,400;0,700;1,400&display=swap');
15
+ body { background-color: #050505; color: #a29bfe; font-family: 'Space Mono', monospace; }
16
+
17
+ .pixelated {
18
+ image-rendering: pixelated;
19
+ width: 100%;
20
+ border: 1px solid #6c5ce7;
21
+ box-shadow: 0 0 15px rgba(108, 92, 231, 0.2);
22
+ background: #000;
23
+ }
24
+
25
+ .panel { background: #111; border: 1px solid #333; padding: 15px; border-radius: 4px; }
26
+ .btn { background: #1a1a1a; border: 1px solid #6c5ce7; color: #6c5ce7; padding: 6px 12px; font-size: 10px; transition: 0.2s; text-transform: uppercase; }
27
+ .btn:hover { background: #6c5ce7; color: #000; cursor: pointer; }
28
+
29
+ /* Chat Styling */
30
+ .chat-bubble { padding: 10px; margin-bottom: 12px; font-size: 12px; border-left: 2px solid #6c5ce7; background: #0a0a0a; overflow-wrap: break-word;}
31
+ .system-msg { color: #fab1a0; font-style: italic; display: block; margin-top: 5px; border-top: 1px dashed #333; padding-top: 5px; }
32
+
33
+ /* Markdown Overrides */
34
+ .prose p { margin-bottom: 0.5em; }
35
+ .prose pre {
36
+ background: #1e1e1e !important;
37
+ padding: 10px;
38
+ border-radius: 4px;
39
+ overflow-x: auto;
40
+ border: 1px solid #333;
41
+ margin: 10px 0;
42
+ }
43
+ .prose code {
44
+ font-family: 'Courier New', monospace;
45
+ font-size: 11px;
46
+ color: #e0e0e0;
47
+ }
48
+ .prose ul { list-style-type: disc; margin-left: 20px; }
49
+ .prose ol { list-style-type: decimal; margin-left: 20px; }
50
+ .prose strong { color: #fff; }
51
+ .prose a { color: #6c5ce7; text-decoration: underline; }
52
+
53
+ /* Modal for Inspection */
54
+ #inspector { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 80%; height: 80%; background: #000; border: 2px solid #6c5ce7; z-index: 50; display: none; padding: 20px; overflow: auto; }
55
+ .close-btn { position: absolute; top: 10px; right: 10px; color: red; cursor: pointer; }
56
+ </style>
57
+ </head>
58
+ <body class="p-4 md:p-8 max-w-7xl mx-auto">
59
+
60
+ <!-- Header -->
61
+ <div class="flex justify-between items-end mb-6 border-b border-[#333] pb-4">
62
+ <div>
63
+ <h1 class="text-2xl font-bold text-white tracking-widest">VISUMEM_AI <span class="text-xs text-[#6c5ce7]">v2.2</span></h1>
64
+ <p class="text-gray-500 text-[10px]">RECURSIVE VISUAL STORAGE // MARKDOWN ENABLED</p>
65
+ </div>
66
+ <div class="text-right">
67
+ <div class="text-[10px] text-green-500">ENGINE: ACTIVE</div>
68
+ </div>
69
+ </div>
70
+
71
+ <div class="grid grid-cols-1 lg:grid-cols-12 gap-6">
72
+
73
+ <!-- VISUALIZERS -->
74
+ <div class="lg:col-span-4 flex flex-col gap-6">
75
+
76
+ <!-- History -->
77
+ <div class="panel">
78
+ <div class="flex justify-between items-center mb-2">
79
+ <h2 class="text-xs font-bold text-white">EPISODIC LOG</h2>
80
+ <button onclick="inspect('history')" class="btn">DECODE</button>
81
+ </div>
82
+ <div class="relative w-full aspect-square mb-2">
83
+ <img id="img-history" src="" class="pixelated">
84
+ </div>
85
+ <div class="text-[10px] text-gray-500 flex justify-between">
86
+ <span id="stat-history">--</span>
87
+ <span id="usage-history">--</span>
88
+ </div>
89
+ </div>
90
+
91
+ <button onclick="wipe()" class="btn border-red-900 text-red-500 hover:bg-red-900 hover:text-white">
92
+ HARD RESET (WIPE ALL)
93
+ </button>
94
+ </div>
95
+
96
+ <!-- CHAT -->
97
+ <div class="lg:col-span-8 flex flex-col h-[85vh]">
98
+ <div id="chat-log" class="panel flex-1 overflow-y-auto mb-4 font-mono text-gray-300">
99
+ <div class="text-center text-gray-700 text-xs mt-20">
100
+ // SYSTEM READY. WAITING FOR INPUT.
101
+ </div>
102
+ </div>
103
+
104
+ <form id="chat-form" class="flex gap-2">
105
+ <input type="text" id="user-input" class="bg-[#111] border border-[#333] text-white p-3 flex-1 outline-none focus:border-[#6c5ce7]" placeholder="Type your message..." autocomplete="off">
106
+ <button type="submit" class="btn px-6 font-bold text-white bg-[#6c5ce7] text-black hover:bg-white">SEND</button>
107
+ </form>
108
+ </div>
109
+ </div>
110
+
111
+ <!-- Inspector Modal -->
112
+ <div id="inspector">
113
+ <div class="close-btn" onclick="closeInspect()">[X] CLOSE</div>
114
+ <h2 class="text-xl font-bold mb-4 text-white" id="inspect-title">MEMORY DUMP</h2>
115
+ <div id="inspect-content" class="font-mono text-xs text-green-400 whitespace-pre-wrap"></div>
116
+ </div>
117
+
118
+ <script>
119
+ const chatLog = document.getElementById('chat-log');
120
+ const userInput = document.getElementById('user-input');
121
+
122
+ // Configure Marked.js with Highlight.js
123
+ marked.setOptions({
124
+ highlight: function(code, lang) {
125
+ const language = hljs.getLanguage(lang) ? lang : 'plaintext';
126
+ return hljs.highlight(code, { language }).value;
127
+ },
128
+ langPrefix: 'hljs language-',
129
+ breaks: true,
130
+ gfm: true
131
+ });
132
+
133
+ setInterval(refreshVisuals, 2000);
134
+
135
+ async function refreshVisuals() {
136
+ try {
137
+
138
+ const r2 = await fetch('/visualize/history');
139
+ const d2 = await r2.json();
140
+ document.getElementById('img-history').src = d2.image;
141
+ document.getElementById('stat-history').textContent = d2.stats;
142
+ document.getElementById('usage-history').textContent = d2.usage;
143
+ } catch(e) {}
144
+ }
145
+
146
+ async function inspect(type) {
147
+ document.getElementById('inspector').style.display = 'block';
148
+ document.getElementById('inspect-title').innerText = `DECODING ${type.toUpperCase()} SECTOR...`;
149
+ document.getElementById('inspect-content').innerText = "Reading bytes...";
150
+
151
+ const res = await fetch(`/inspect/${type}`);
152
+ const data = await res.json();
153
+
154
+ document.getElementById('inspect-content').innerText = data.content.join('\n\n');
155
+ }
156
+
157
+ function closeInspect() {
158
+ document.getElementById('inspector').style.display = 'none';
159
+ }
160
+
161
+ document.getElementById('chat-form').addEventListener('submit', async (e) => {
162
+ e.preventDefault();
163
+ const text = userInput.value.trim();
164
+ if(!text) return;
165
+
166
+ // Add User Message (No MD for user to keep it raw/clean)
167
+ addMsg("USER", text);
168
+ userInput.value = "";
169
+
170
+ // Create AI Message Container
171
+ const aiDiv = addMsg("AI", "...");
172
+ const aiContentDiv = document.createElement("div");
173
+ aiContentDiv.className = "prose"; // Tailwind typography class hook
174
+ aiDiv.innerHTML = "<strong>AI:</strong> ";
175
+ aiDiv.appendChild(aiContentDiv);
176
+
177
+ const res = await fetch('/chat', {
178
+ method: 'POST',
179
+ headers: {'Content-Type': 'application/json'},
180
+ body: JSON.stringify({message: text})
181
+ });
182
+
183
+ const reader = res.body.getReader();
184
+ const decoder = new TextDecoder();
185
+
186
+ let rawBuffer = "";
187
+
188
+ while(true) {
189
+ const { done, value } = await reader.read();
190
+ if (done) break;
191
+ const chunk = decoder.decode(value);
192
+ rawBuffer += chunk;
193
+
194
+ // 1. Separate actual content from [SYSTEM: ...] logs
195
+ // We use Regex to isolate the system logs so Markdown doesn't mess them up
196
+ // and so we can style them differently.
197
+
198
+ // Temporary placeholder for rendering
199
+ let renderText = rawBuffer;
200
+
201
+ // Regex to find system messages
202
+ const sysRegex = /\[SYSTEM:.*?\]/g;
203
+
204
+ // We let marked parse everything, but we pre-format the system tags slightly
205
+ // to ensure they survive properly or post-process.
206
+ // Simpler approach: Render Markdown, then replace the text matching system logs with styled HTML.
207
+
208
+ let html = marked.parse(renderText);
209
+
210
+ // Highlight System Logs after markdown conversion
211
+ html = html.replace(sysRegex, (match) => {
212
+ return `<span class="system-msg">${match}</span>`;
213
+ });
214
+
215
+ aiContentDiv.innerHTML = html;
216
+ chatLog.scrollTop = chatLog.scrollHeight;
217
+ }
218
+ refreshVisuals();
219
+ });
220
+
221
+ function addMsg(role, text) {
222
+ const div = document.createElement('div');
223
+ div.className = "chat-bubble";
224
+ if(role === "USER") {
225
+ div.innerHTML = `<strong>${role}:</strong> ${text}`;
226
+ } else {
227
+ div.innerHTML = `<strong>${role}:</strong> ${text}`;
228
+ }
229
+ chatLog.appendChild(div);
230
+ chatLog.scrollTop = chatLog.scrollHeight;
231
+ return div;
232
+ }
233
+
234
+ async function wipe() {
235
+ if(confirm("Really wipe memory?")) {
236
+ await fetch('/wipe', {method:'POST'});
237
+ refreshVisuals();
238
+ }
239
+ }
240
+ refreshVisuals();
241
+ </script>
242
+ </body>
243
+ </html>