Fixing CUDA errors
This commit is contained in:
parent
f21e9b433e
commit
5f74b2c64c
3
.gitignore
vendored
3
.gitignore
vendored
@ -174,4 +174,5 @@ cython_debug/
|
|||||||
/data/memory/context.json
|
/data/memory/context.json
|
||||||
/data/memory/dreams.json
|
/data/memory/dreams.json
|
||||||
data/memory/brainmap.json
|
data/memory/brainmap.json
|
||||||
/data/memory/vocab.json
|
/data/memory/vocab.json
|
||||||
|
data/memory/book_progress.json
|
||||||
|
@ -5,6 +5,7 @@ from model.memory import load_dreams
|
|||||||
from model.tokenizer import Tokenizer
|
from model.tokenizer import Tokenizer
|
||||||
from model.abstraction import cluster_vocab
|
from model.abstraction import cluster_vocab
|
||||||
from model.memory import load_dreams
|
from model.memory import load_dreams
|
||||||
|
from model.scheduler import get_time_until_next_action, get_next_action_label
|
||||||
from context.context import load_context
|
from context.context import load_context
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
@ -37,13 +38,16 @@ def index():
|
|||||||
top_dreams = dreams[:5]
|
top_dreams = dreams[:5]
|
||||||
memory_size = len(load_context())
|
memory_size = len(load_context())
|
||||||
loss_data = load_loss_data()
|
loss_data = load_loss_data()
|
||||||
remaining = max(0, int(next_cycle_time - time.time()))
|
next_cycle = get_time_until_next_action()
|
||||||
|
next_action_label = get_next_action_label()
|
||||||
|
|
||||||
return render_template("index.html",
|
return render_template("index.html",
|
||||||
vocab_size=len(tokenizer.vocab),
|
vocab_size=len(tokenizer.vocab),
|
||||||
top_dreams=top_dreams,
|
top_dreams=top_dreams,
|
||||||
memory_size=memory_size,
|
memory_size=memory_size,
|
||||||
loss_data=loss_data,
|
loss_data=loss_data,
|
||||||
next_cycle=remaining)
|
next_cycle=next_cycle,
|
||||||
|
next_action_label=next_action_label)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/growth")
|
@app.route("/growth")
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="refresh" content="60">
|
||||||
<title>Ruby's Brain Map</title>
|
<title>Ruby's Brain Map</title>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/force-graph"></script>
|
<script src="https://cdn.jsdelivr.net/npm/force-graph"></script>
|
||||||
<style>
|
<style>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="refresh" content="30">
|
||||||
<title>Ruby's Dashboard</title>
|
<title>Ruby's Dashboard</title>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
@ -27,24 +28,38 @@
|
|||||||
border-top: 1px solid #333;
|
border-top: 1px solid #333;
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
|
.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;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<body>
|
<div class="nav">
|
||||||
|
<a href="/">🏠 Home</a>
|
||||||
|
<a href="/journal">📓 Journal</a>
|
||||||
|
<a href="/concepts">🧠 Concepts</a>
|
||||||
|
<a href="/brainmap">🕸️ Brain Map</a>
|
||||||
|
<a href="/growth">📈 Growth</a>
|
||||||
|
<a href="/dreams">💬 Dreams</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="nav">
|
|
||||||
<a href="/">🏠 Home</a>
|
|
||||||
<a href="/journal">📓 Journal</a>
|
|
||||||
<a href="/concepts">🧠 Concepts</a>
|
|
||||||
<a href="/brainmap">🕸️ Brain Map</a>
|
|
||||||
<a href="/growth">📈 Growth</a>
|
|
||||||
<a href="/dreams">💬 Dreams</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h1>Ruby is Running 🧠</h1>
|
<h1>Ruby is Running 🧠</h1>
|
||||||
|
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2>⏳ Next Cycle Countdown</h2>
|
<h2>⏳ Next Cycle</h2>
|
||||||
|
<p><strong>Next:</strong> {{ next_action_label }}</p>
|
||||||
<p id="countdown">{{ next_cycle }} seconds</p>
|
<p id="countdown">{{ next_cycle }} seconds</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
25
main.py
25
main.py
@ -8,8 +8,10 @@ from model.brain import generate_response
|
|||||||
from model.cleanup import full_cleanup
|
from model.cleanup import full_cleanup
|
||||||
from model.dream_replay import replay_dreams
|
from model.dream_replay import replay_dreams
|
||||||
from model.rehearsal import simulate_conversation
|
from model.rehearsal import simulate_conversation
|
||||||
|
from model.scheduler import set_next_action
|
||||||
from reader.reader import read_books_forever
|
from reader.reader import read_books_forever
|
||||||
from dashboard.dashboard import run_dashboard
|
from dashboard.dashboard import run_dashboard
|
||||||
|
import threading
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
TOKEN = os.getenv("DISCORD_TOKEN")
|
TOKEN = os.getenv("DISCORD_TOKEN")
|
||||||
@ -43,27 +45,38 @@ threading.Thread(target=run_dashboard, daemon=True).start()
|
|||||||
async def background_cleanup_loop():
|
async def background_cleanup_loop():
|
||||||
while True:
|
while True:
|
||||||
full_cleanup()
|
full_cleanup()
|
||||||
|
set_next_action(300, "Cleaning up")
|
||||||
await asyncio.sleep(300) # 5 minutes
|
await asyncio.sleep(300) # 5 minutes
|
||||||
|
|
||||||
|
|
||||||
async def dream_replay_loop():
|
async def dream_replay_loop():
|
||||||
while True:
|
while True:
|
||||||
replay_dreams()
|
replay_dreams()
|
||||||
|
set_next_action(900, "Dreaming new dreams")
|
||||||
await asyncio.sleep(900) # Replay every 15 minutes
|
await asyncio.sleep(900) # Replay every 15 minutes
|
||||||
|
|
||||||
|
|
||||||
async def rehearsal_loop():
|
async def rehearsal_loop():
|
||||||
while True:
|
while True:
|
||||||
simulate_conversation()
|
simulate_conversation()
|
||||||
|
set_next_action(1200, "Practicing Conversations")
|
||||||
await asyncio.sleep(1200) # Every 20 minutes
|
await asyncio.sleep(1200) # Every 20 minutes
|
||||||
|
|
||||||
|
|
||||||
# Launch background tasks
|
# Start Ruby's Brain Loops in a separate thread
|
||||||
loop = asyncio.get_event_loop()
|
def start_brain_loops():
|
||||||
loop.create_task(read_books_forever()) # Book reader task
|
loop = asyncio.new_event_loop()
|
||||||
loop.create_task(background_cleanup_loop())
|
asyncio.set_event_loop(loop)
|
||||||
loop.create_task(dream_replay_loop())
|
|
||||||
loop.create_task(rehearsal_loop())
|
loop.create_task(read_books_forever())
|
||||||
|
loop.create_task(dream_replay_loop())
|
||||||
|
loop.create_task(background_cleanup_loop())
|
||||||
|
loop.create_task(rehearsal_loop())
|
||||||
|
|
||||||
|
loop.run_forever()
|
||||||
|
|
||||||
|
|
||||||
|
threading.Thread(target=start_brain_loops, daemon=True).start()
|
||||||
|
|
||||||
# Launch Discord bot (blocking)
|
# Launch Discord bot (blocking)
|
||||||
client.run(TOKEN)
|
client.run(TOKEN)
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import random
|
import random
|
||||||
from model.memory import load_dreams
|
from model.memory import load_dreams
|
||||||
from model.trainer import train_on_message
|
from model.trainer import train_on_message
|
||||||
|
from model.dynamic_expand import expand_model_if_needed
|
||||||
|
|
||||||
|
|
||||||
def replay_dreams():
|
def replay_dreams():
|
||||||
|
expand_model_if_needed()
|
||||||
|
|
||||||
dreams = load_dreams()
|
dreams = load_dreams()
|
||||||
if not dreams:
|
if not dreams:
|
||||||
return
|
return
|
||||||
|
@ -6,18 +6,17 @@ optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
|
|||||||
|
|
||||||
|
|
||||||
def get_optimizer():
|
def get_optimizer():
|
||||||
global optimizer
|
|
||||||
return optimizer
|
return optimizer
|
||||||
|
|
||||||
|
|
||||||
def expand_model_if_needed():
|
def expand_model_if_needed():
|
||||||
global model, optimizer
|
global model, optimizer
|
||||||
|
|
||||||
current_vocab_size = len(tokenizer.vocab) + 10 # Buffer
|
current_vocab_size = len(tokenizer.vocab) + 10
|
||||||
old_vocab_size = model.head.out_features
|
old_vocab_size = model.head.out_features
|
||||||
|
|
||||||
if current_vocab_size <= old_vocab_size:
|
if current_vocab_size <= old_vocab_size:
|
||||||
return
|
return # No expansion needed
|
||||||
|
|
||||||
print(f"Expanding model from {old_vocab_size} -> {current_vocab_size}")
|
print(f"Expanding model from {old_vocab_size} -> {current_vocab_size}")
|
||||||
|
|
||||||
@ -31,6 +30,6 @@ def expand_model_if_needed():
|
|||||||
param.copy_(old_state[name])
|
param.copy_(old_state[name])
|
||||||
|
|
||||||
model = new_model
|
model = new_model
|
||||||
opt = get_optimizer()
|
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
|
||||||
|
|
||||||
print("Model expanded and optimizer rebuilt.")
|
print("Expansion complete.")
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
import torch
|
import torch
|
||||||
from model.brain import model, tokenizer, DEVICE
|
from model.brain import model, tokenizer, DEVICE
|
||||||
from model.trainer import train_on_message
|
from model.trainer import train_on_message
|
||||||
|
from model.dynamic_expand import expand_model_if_needed
|
||||||
|
|
||||||
|
|
||||||
def simulate_conversation():
|
def simulate_conversation():
|
||||||
seed = torch.randint(0, tokenizer.next_id, (1, 5), device=DEVICE)
|
expand_model_if_needed()
|
||||||
output = model(seed)
|
|
||||||
preds = torch.argmax(output, dim=-1).squeeze().tolist()
|
|
||||||
|
|
||||||
|
model.eval()
|
||||||
|
seed = torch.randint(0, tokenizer.next_id, (1, 5), device=DEVICE)
|
||||||
|
seed = seed[:, -128:] # Safety clamp
|
||||||
|
output = model(seed)
|
||||||
|
|
||||||
|
preds = torch.argmax(output, dim=-1).squeeze().tolist()
|
||||||
if isinstance(preds, int):
|
if isinstance(preds, int):
|
||||||
preds = [preds]
|
preds = [preds]
|
||||||
|
|
||||||
|
19
model/scheduler.py
Normal file
19
model/scheduler.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
_next_action_time = time.time() + 60 # default 1 minute from now
|
||||||
|
_next_action_label = "Waiting"
|
||||||
|
|
||||||
|
|
||||||
|
def set_next_action(seconds_from_now: int, label: str = "Thinking"):
|
||||||
|
global _next_action_time, _next_action_label
|
||||||
|
_next_action_time = time.time() + seconds_from_now
|
||||||
|
_next_action_label = label
|
||||||
|
|
||||||
|
|
||||||
|
def get_time_until_next_action() -> int:
|
||||||
|
remaining = int(_next_action_time - time.time())
|
||||||
|
return max(0, remaining)
|
||||||
|
|
||||||
|
|
||||||
|
def get_next_action_label() -> str:
|
||||||
|
return _next_action_label
|
@ -1,9 +1,8 @@
|
|||||||
import torch
|
import torch
|
||||||
import time
|
import time
|
||||||
from model.brain_state import model, tokenizer, DEVICE,loss_fn
|
|
||||||
from context.context import add_to_context, get_recent_context
|
|
||||||
from model.dynamic_expand import expand_model_if_needed, get_optimizer
|
from model.dynamic_expand import expand_model_if_needed, get_optimizer
|
||||||
from model.brainmap import update_brainmap
|
from model.brain_state import model, tokenizer, DEVICE, loss_fn
|
||||||
|
from context.context import add_to_context, get_recent_context
|
||||||
|
|
||||||
LOSS_FILE = "data/logs/loss.log"
|
LOSS_FILE = "data/logs/loss.log"
|
||||||
|
|
||||||
@ -15,6 +14,7 @@ def log_loss(value: float):
|
|||||||
|
|
||||||
def train_on_message(text: str):
|
def train_on_message(text: str):
|
||||||
expand_model_if_needed()
|
expand_model_if_needed()
|
||||||
|
|
||||||
model.train()
|
model.train()
|
||||||
context_texts = get_recent_context(3)
|
context_texts = get_recent_context(3)
|
||||||
augmented_text = " ".join(context_texts + [text])
|
augmented_text = " ".join(context_texts + [text])
|
||||||
@ -23,16 +23,23 @@ def train_on_message(text: str):
|
|||||||
if len(tokens) < 2:
|
if len(tokens) < 2:
|
||||||
return
|
return
|
||||||
|
|
||||||
tokens = tokens[:128]
|
# ✋ Clamp to model's known vocab
|
||||||
words = tokenizer.detokenize(tokens).split()
|
max_token_id = model.head.out_features - 1
|
||||||
update_brainmap(words)
|
tokens = [t for t in tokens if t <= max_token_id]
|
||||||
|
|
||||||
|
if len(tokens) < 2:
|
||||||
|
return # after filtering, too short to train
|
||||||
|
|
||||||
|
tokens = tokens[:128] # safety clamp
|
||||||
input_tensor = torch.tensor(tokens[:-1], dtype=torch.long, device=DEVICE).unsqueeze(0)
|
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)
|
target_tensor = torch.tensor(tokens[1:], dtype=torch.long, device=DEVICE).unsqueeze(0)
|
||||||
|
|
||||||
|
opt = get_optimizer()
|
||||||
|
|
||||||
output = model(input_tensor)
|
output = model(input_tensor)
|
||||||
|
|
||||||
loss = loss_fn(output.view(-1, output.size(-1)), target_tensor.view(-1))
|
loss = loss_fn(output.view(-1, output.size(-1)), target_tensor.view(-1))
|
||||||
|
|
||||||
opt = get_optimizer()
|
|
||||||
opt.zero_grad()
|
opt.zero_grad()
|
||||||
loss.backward()
|
loss.backward()
|
||||||
opt.step()
|
opt.step()
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import os
|
import os
|
||||||
import asyncio
|
import asyncio
|
||||||
from model.trainer import train_on_message
|
from model.trainer import train_on_message
|
||||||
|
from model.scheduler import set_next_action
|
||||||
from reader.filter import is_valid_line
|
from reader.filter import is_valid_line
|
||||||
|
import json
|
||||||
|
|
||||||
BOOK_DIR = "data/books"
|
BOOK_DIR = "data/books"
|
||||||
PROGRESS_FILE = "data/memory/book_progress.json"
|
PROGRESS_FILE = "data/memory/book_progress.json"
|
||||||
@ -45,4 +47,5 @@ async def read_books_forever():
|
|||||||
|
|
||||||
if is_valid_line(line):
|
if is_valid_line(line):
|
||||||
train_on_message(line)
|
train_on_message(line)
|
||||||
|
set_next_action(READ_DELAY, "Reading")
|
||||||
await asyncio.sleep(READ_DELAY)
|
await asyncio.sleep(READ_DELAY)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user