From 287eee0d34fa6af574b9d5d3e54cbcee4696002b Mon Sep 17 00:00:00 2001 From: Dani Date: Sat, 19 Apr 2025 08:55:20 -0400 Subject: [PATCH] Starting a book reading module so that Ruby can read in her downtime. --- .gitignore | 3 ++- main.py | 6 ++++++ reader.py | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 reader.py diff --git a/.gitignore b/.gitignore index 821304d..ef465be 100644 --- a/.gitignore +++ b/.gitignore @@ -171,4 +171,5 @@ cython_debug/ /tokenizer_vocab.txt /logs/core_dreams.txt /logs/best_dream.txt -/.vscode/launch.json \ No newline at end of file +/.vscode/launch.json +/books \ No newline at end of file diff --git a/main.py b/main.py index 9785710..190d0ee 100644 --- a/main.py +++ b/main.py @@ -8,6 +8,7 @@ from datetime import datetime, timedelta from dashboard import start_dashboard from tokenizer import Tokenizer from trainer import RubyTrainer +from reader import BookReader import logging # Setup logging @@ -41,12 +42,17 @@ class Ruby(discord.Client): super().__init__(intents=intents) self.tokenizer = Tokenizer() self.trainer = RubyTrainer(self.tokenizer) + self.reader = BookReader(trainer=self.trainer, + book_path="books//wizard_of_oz.txt", # or whatever book you want + interval=180 # read every 3 minutes (adjust if needed) + ) self.last_message_time = datetime.utcnow() self.idle_threshold = timedelta(seconds=120) self.log_path = os.path.join("logs", "messages.log") os.makedirs("logs", exist_ok=True) async def setup_hook(self): + self.loop.create_task(self.reader.start_reading()) self.loop.create_task(self.idle_dream_loop()) async def set_activity(self, text=None): diff --git a/reader.py b/reader.py new file mode 100644 index 0000000..a5af528 --- /dev/null +++ b/reader.py @@ -0,0 +1,53 @@ +import os +import asyncio +from datetime import datetime + +class BookReader: + def __init__(self, trainer, book_path, state_path="readstate.txt", log_path="logs/read.log", interval=180): + self.trainer = trainer + self.book_path = book_path + self.state_path = state_path + self.log_path = log_path + self.interval = interval # seconds between reading cycles + self.current_line = 0 + os.makedirs(os.path.dirname(self.log_path), exist_ok=True) + + if os.path.exists(self.state_path): + try: + with open(self.state_path, "r", encoding="utf-8") as f: + self.current_line = int(f.read().strip()) + except Exception: + self.current_line = 0 + + def _save_state(self): + with open(self.state_path, "w", encoding="utf-8") as f: + f.write(str(self.current_line)) + + def _log_read(self, text: str, score: float, tag: str = "Book"): + with open(self.log_path, "a", encoding="utf-8") as f: + f.write(f"[{datetime.utcnow().isoformat()}] ({tag}) {score:.2f} | {text.strip()}\\n") + + async def start_reading(self): + if not os.path.exists(self.book_path): + print(f"[BOOK] File not found: {self.book_path}") + return + + with open(self.book_path, "r", encoding="utf-8") as f: + lines = f.readlines() + + print(f"[BOOK] Starting to read {self.book_path} from line {self.current_line}...") + + while self.current_line < len(lines): + passage = lines[self.current_line].strip() + + if len(passage.split()) >= 5: + score = self.trainer.score_sentence(passage) + if self.trainer.is_reinforceable(passage) and score >= 2.5: + self.trainer.train_on_tokens_from_text(passage) + self._log_read(passage, score) + + self.current_line += 1 + self._save_state() + await asyncio.sleep(self.interval) + + print("[BOOK] Finished reading the book.") \ No newline at end of file