From 52cbba027ec2604e3002d1eeb5564ee917b123fb Mon Sep 17 00:00:00 2001 From: Dani Date: Fri, 25 Apr 2025 23:09:04 -0400 Subject: [PATCH] Fixed dashboard added brainmap --- .gitignore | 4 +- dashboard/dashboard.py | 21 +++++++++++ dashboard/templates/brainmap.html | 61 +++++++++++++++++++++++++++++++ dashboard/templates/concepts.html | 22 +++++++++++ dashboard/templates/index.html | 6 +++ dashboard/templates/journal.html | 28 ++++++++++++-- data/memory/vocab.json | 8 +++- model/abstraction.py | 7 ++-- model/brainmap.py | 39 ++++++++++++++++++++ model/trainer.py | 3 ++ 10 files changed, 189 insertions(+), 10 deletions(-) create mode 100644 dashboard/templates/brainmap.html create mode 100644 model/brainmap.py diff --git a/.gitignore b/.gitignore index 03d13f6..7d115c6 100644 --- a/.gitignore +++ b/.gitignore @@ -173,4 +173,6 @@ cython_debug/ /data/books/wizard_of_oz.txt /data/memory/context.json /data/memory/dreams.json -/data/memory/vocab.json \ No newline at end of file +/data/memory/vocab.json +data/memory/vocab.json +data/memory/brainmap.json diff --git a/dashboard/dashboard.py b/dashboard/dashboard.py index 6d73288..c233b87 100644 --- a/dashboard/dashboard.py +++ b/dashboard/dashboard.py @@ -1,9 +1,11 @@ from flask import Flask, render_template +from model.brainmap import get_brainmap from model.journal import read_journal_entries from model.memory import load_dreams from model.tokenizer import Tokenizer from model.abstraction import cluster_vocab from context.context import load_context +import json import os import time @@ -43,6 +45,25 @@ def index(): next_cycle=remaining) +@app.route("/brainmap") +def brainmap(): + map_data = get_brainmap() + + nodes = [] + links = [] + + for word, connections in map_data.items(): + nodes.append({"id": word}) + for linked_word, weight in connections.items(): + links.append({ + "source": word, + "target": linked_word, + "value": weight + }) + + return render_template("brainmap.html", nodes=json.dumps(nodes), links=json.dumps(links)) + + @app.route("/journal") def journal(): entries = read_journal_entries() diff --git a/dashboard/templates/brainmap.html b/dashboard/templates/brainmap.html new file mode 100644 index 0000000..0e201e1 --- /dev/null +++ b/dashboard/templates/brainmap.html @@ -0,0 +1,61 @@ + + + + + Ruby's Brain Map + + + + + + + +
+ + + + + diff --git a/dashboard/templates/concepts.html b/dashboard/templates/concepts.html index 81154fc..419a9a4 100644 --- a/dashboard/templates/concepts.html +++ b/dashboard/templates/concepts.html @@ -23,9 +23,31 @@ list-style-type: square; padding-left: 20px; } + .entry { + margin-bottom: 15px; + padding-bottom: 10px; + border-bottom: 1px solid #333; + } + .nav { + background-color: #1e1e1e; + padding: 10px; + margin-bottom: 20px; + } + .nav a { + color: #e0e0e0; + margin-right: 20px; + text-decoration: none; + } + +

🧠 Ruby's Concept Clusters

{% for cluster_id, words in clusters.items() %} diff --git a/dashboard/templates/index.html b/dashboard/templates/index.html index e78c99c..f35a875 100644 --- a/dashboard/templates/index.html +++ b/dashboard/templates/index.html @@ -30,6 +30,12 @@ +
+ 🏠 Home + πŸ““ Journal + 🧠 Concepts + πŸ•ΈοΈ Brain Map +

Ruby is Running 🧠

diff --git a/dashboard/templates/journal.html b/dashboard/templates/journal.html index ef6c8ac..edf9e53 100644 --- a/dashboard/templates/journal.html +++ b/dashboard/templates/journal.html @@ -9,6 +9,7 @@ color: #e0e0e0; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; padding: 20px; + margin: 0; } h1 { color: #ffffff; @@ -18,13 +19,32 @@ padding-bottom: 10px; border-bottom: 1px solid #333; } + .nav { + background-color: #1e1e1e; + padding: 10px; + margin-bottom: 20px; + } + .nav a { + color: #e0e0e0; + margin-right: 20px; + text-decoration: none; + } -

πŸ““ Ruby's Journal

- {% for entry in entries %} -
{{ entry }}
- {% endfor %} + + +

πŸ““ Ruby's Journal

+ +{% for entry in entries %} +
{{ entry }}
+{% endfor %} + diff --git a/data/memory/vocab.json b/data/memory/vocab.json index 5c40c60..aee3562 100644 --- a/data/memory/vocab.json +++ b/data/memory/vocab.json @@ -4,5 +4,11 @@ "how": 3, "are": 4, "you": 5, - "today": 6 + "today": 6, + "the": 7, + "cat": 8, + "ran": 9, + "across": 10, + "sunny": 11, + "street": 12 } \ No newline at end of file diff --git a/model/abstraction.py b/model/abstraction.py index fb91787..be8c2f0 100644 --- a/model/abstraction.py +++ b/model/abstraction.py @@ -9,11 +9,10 @@ def cluster_vocab(n_clusters=10): vocab_items = list(tokenizer.vocab.items()) words, ids = zip(*vocab_items) - embeds = torch.nn.Embedding(len(ids), 256) # Same as model size - with torch.no_grad(): - vectors = embeds(torch.tensor(list(ids))) + # Instead of embeddings, let's make random small vectors manually + vectors = torch.randn(len(ids), 64) # 64d random vectors for clustering - kmeans = KMeans(n_clusters=n_clusters) + kmeans = KMeans(n_clusters=min(n_clusters, len(ids))) labels = kmeans.fit_predict(vectors.cpu().numpy()) clusters = {} diff --git a/model/brainmap.py b/model/brainmap.py new file mode 100644 index 0000000..739820a --- /dev/null +++ b/model/brainmap.py @@ -0,0 +1,39 @@ +import os +import json +from collections import defaultdict + +BRAINMAP_FILE = "data/memory/brainmap.json" + + +def load_brainmap(): + if os.path.exists(BRAINMAP_FILE): + with open(BRAINMAP_FILE, "r", encoding="utf-8") as f: + return json.load(f) + return {} + + +def save_brainmap(map_data): + with open(BRAINMAP_FILE, "w", encoding="utf-8") as f: + json.dump(map_data, f, indent=2) + + +brain_map = load_brainmap() + + +def update_brainmap(words): + for i, word in enumerate(words): + for j in range(i+1, len(words)): + w1 = word + w2 = words[j] + if w1 == w2: + continue + if w1 not in brain_map: + brain_map[w1] = {} + if w2 not in brain_map[w1]: + brain_map[w1][w2] = 0 + brain_map[w1][w2] += 1 + save_brainmap(brain_map) + + +def get_brainmap(): + return brain_map diff --git a/model/trainer.py b/model/trainer.py index 702bf37..79c67f9 100644 --- a/model/trainer.py +++ b/model/trainer.py @@ -3,6 +3,7 @@ import time from model.brain_state import model, tokenizer, DEVICE, optimizer, loss_fn from context.context import add_to_context, get_recent_context from model.dynamic_expand import expand_model_if_needed +from model.brainmap import update_brainmap LOSS_FILE = "data/logs/loss.log" @@ -22,6 +23,8 @@ def train_on_message(text: str): if len(tokens) < 2: return + words = tokenizer.detokenize(tokens).split() + update_brainmap(words) input_tensor = torch.tensor(tokens[:-1], dtype=torch.long, device=DEVICE).unsqueeze(0) target_tensor = torch.tensor(tokens[1:], dtype=torch.long, device=DEVICE).unsqueeze(0)