From 9753f508d15b88d27f7b5380b042319215238ca2 Mon Sep 17 00:00:00 2001 From: milo Date: Fri, 9 May 2025 21:07:22 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=B2=20Added=20probabilistic=20schedule?= =?UTF-8?q?r=20and=20=F0=9F=93=8B=20future=20roadmap=20checklist=20for=20D?= =?UTF-8?q?elta=20AI=20bot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 79 +++++++++++------- src/scheduler/__init__.py | 33 +++++++- .../__pycache__/__init__.cpython-310.pyc | Bin 1123 -> 1836 bytes .../__pycache__/probabilistic.cpython-310.pyc | Bin 178 -> 866 bytes src/scheduler/probabilistic.py | 24 ++++++ src/settings.yml | 4 +- 6 files changed, 108 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index da21f9a..5b40508 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ A structured build plan for developing and deploying the AlphaBot Discord compan - [x] Build `!roast @user` with AI-generated replies - [x] Style roast output with selected personality - [x] Add cooldown to prevent spam (optional) -- [ ] Fix Emojis (optional) +- [x] Fix Emojis (optional) --- I think this is now fixed - Emojis from the settings.yml file are broken. Please fix --- @@ -100,14 +100,14 @@ A structured build plan for developing and deploying the AlphaBot Discord compan #### ✅ Core Features -- [ ] Replace static messages in `scheduler.py` with AI-generated ones via `get_ai_response()` +- [x] Replace static messages in `scheduler.py` with AI-generated ones via `get_ai_response()` - Use prompt like: *“Post something sassy, attention-grabbing, or chaotic to wake up the server.”* - Maintain current persona system for tone consistency -- [ ] Add `settings.yml` option to control post mode: +- [x] Add `settings.yml` option to control post mode: - `mode: preset` – static messages only - `mode: ai` – generate new message via LLM - - `mode: mixed` – random chance between the two -- [ ] Log each scheduled post and mode used for debugging + - ~~`mode: mixed` – random chance between the two~~ +- [ ] ~~Log each scheduled post and mode used for debugging~~ - Pushed back, not a critical feature right now --- @@ -115,16 +115,16 @@ A structured build plan for developing and deploying the AlphaBot Discord compan > Post when it feels "natural" – low chance at first, rising over time. -- [ ] Add `probabilistic_scheduler.py` or integrate into `scheduler.py` -- [ ] Configurable parameters: +- [x] Add `probabilistic_scheduler.py` or integrate into `scheduler.py` +- [x] Configurable parameters: - `start_chance: 0.05` (5% per hour) - `increase_per_hour: 0.05` - `decay_on_post: 0.02` -- [ ] Reset chance after post, store `last_post_time` +- [x] ~~Reset chance after post, store `last_post_time`~~ (this is using probability decay which is a bit better) --- -#### 💤 Inactivity-Aware Scheduler (Mode 3 – Stretch Goal) +~~#### 💤 Inactivity-Aware Scheduler (Mode 3 – Stretch Goal)~~ (Temporarily Passed, Probabilistic scheduler is really good for now) > Posts when the **server** or a **user** has been inactive for too long. @@ -191,25 +191,46 @@ This final step removes the need for runtime prompt injection by turning Delta i --- -### 🎨 Polish & Bonus features +### ✅ MVP Features (Core Bot Experience) +These are the must-have features to make the bot functional, fun, and engaging. -- [ ] Bot appears on the server like a "user" (ability to @delta instead of "!chat") - - helps the "sell" the idea to others that the bot is a "friend" - - All user interactions apply to the bot so other users dont need to remmember special commands -- [ ] Have the bot be content aware - - pulls the existing conversation and talks about stuff that is inline with the topics -- [ ] Give bot ability to react to mesages like users would - - adds a personal touch and helps sell the idea of it being your "friend" more - - does need some sort of content awareness -- [ ] Bot can be given some power to change the server a bit - - keeps thing fresh, makes it so that there is some change happening in servers - - the idea being it makes the bot more unique by providing more tailored experiences -- [ ] Bot is user aware - - usernames are passed to the bot along side the users prompt -- [ ] Image interpretation - - bot can read images like GPT this allows for more personalised interactions -- [ ] Web usage - - Bot can search the web like GPT or OpenWebUI - - Opens up a ton of interactivity for memes, media discussion, an be easily integrated with multiple platforms +- [ ] **Bot appears on the server like a "user"** (ability to @delta instead of `!chat`) +- [ ] **Bot is user aware** + - Usernames are passed to the bot along with prompts +- [ ] **Have the bot be content aware** + - Pulls ongoing conversations to respond in context +- [ ] **Give bot ability to react to messages like users would** +- [ ] 🗓️ **Scheduled specific times/dates** + - Daily messages, birthdays, holidays, etc. +- [ ] 💤 **Inactivity-based triggers** + - Post when the server gets too quiet to re-engage users -*Progress last updated: May 8, 2025* +--- +## 🎨 Polish & Bonus features + +### 🛠️ Phase 2 Features (Personality, Social Layer, Engagement) +These enhance immersion and build emotional or social connection. + +- [ ] **Bot can be given some power to change the server a bit** + - Occasional channel renames, topic changes, etc. +- [ ] 🧠 **Context-aware scheduling** + - Posts based on ongoing server activity +- [ ] 📊 **Rate-based adjustment** + - Increase frequency during hype, back off when people are chatting naturally +- [ ] **Web usage** + - Search memes, respond to trending topics, pull from APIs like Reddit/Twitter + +--- + +### 🧠 Advanced AI & Multimodal Features +For immersion and automation lovers. These make Delta truly feel alive. + +- [ ] **Image interpretation** + - Understands memes, screenshots, or selfies (local AI or API-driven) +- [ ] **Content-aware moderation assist** + - Alert mods or intervene when heated discussions arise +- [ ] **Integrated personality shift** + - Switch behavior based on server activity, holidays, or mood triggers + + +*Progress last updated: May 9, 2025* diff --git a/src/scheduler/__init__.py b/src/scheduler/__init__.py index 0c48895..1070cc1 100644 --- a/src/scheduler/__init__.py +++ b/src/scheduler/__init__.py @@ -1,6 +1,10 @@ +# __init__.py formaly know as scheduler.py + import os import yaml import asyncio +import random +from ai import get_ai_response from . import simple, probabilistic, inactivity def load_settings(): @@ -18,12 +22,39 @@ async def start_scheduler(bot): return mode = scheduler_settings.get("mode", "simple").lower() + print(f"🕒 Delta Scheduler started in {mode.upper()} mode.") if mode == "simple": await simple.run(bot, scheduler_settings, settings) + elif mode == "probabilistic": - await probabilistic.run(bot, scheduler_settings, settings) + # Setup and loop + probabilistic.setup(scheduler_settings["probabilistic"]) + + interval = scheduler_settings.get("interval_minutes", 5) + use_ai = scheduler_settings.get("use_ai", True) + channel = bot.get_channel(scheduler_settings["channel_id"]) + + await bot.wait_until_ready() + + while not bot.is_closed(): + if probabilistic.should_post(scheduler_settings["probabilistic"]): + if use_ai: + prompt = "Post a short chaotic or motivational message in the voice of Delta, the RGB catgirl." + message = get_ai_response(prompt) + else: + message = random.choice(scheduler_settings.get("messages", ["Hello from Delta."])) + + await channel.send(message) + print(f"📤 Scheduled message sent to #{channel.name}: {message}") + + probabilistic.on_post(scheduler_settings["probabilistic"]) + + await asyncio.sleep(interval * 60) + + elif mode == "inactivity": await inactivity.run(bot, scheduler_settings, settings) + else: print(f"❓ Unknown scheduler mode: {mode}") diff --git a/src/scheduler/__pycache__/__init__.cpython-310.pyc b/src/scheduler/__pycache__/__init__.cpython-310.pyc index f3eee1f44ffb8b7751c579fe2e32d9e97ac9532d..e235c9f9c668048f4c670c77b4871a29beff4b2c 100644 GIT binary patch literal 1836 zcmZuxPm3Hy6tAlOJF_#plg(sJP^3{08HfvlhY*5@28|#wn20zGHnm+fvz2srjaAjV z?9u~~^(vwvcnHB6P{dE*2gtXmqn`FAc=MvKdbXDw?51A*dG&tpyJC=u9e>>`61xDx2tRpR+3GYLcd+6edk~=SQ~hoTsfncTuzxL%fLxIL2@M zt9D?TxnpX-4h%wQ&!Oo@p!pgbbb=PR#!JkwKtMOC358;Sh16@>mOMiu)A{IaM+`igl;X|UXn_wB%U{T|h_Yqj%K06N3cR>HEiI#CqSmz2_ zIVDSQ- zUc_bBY%aGN%mKSFgX;uHaUCuPb-cnY7G$zrhYv159vAEQDSFoA49MFpGDha&a#;Ip zID}YQyLAkTI(8a{Ja!4P``ujn|LnofPVE6cX*nIebO&xyd%QN{CEd$8`=ELaPUx?n zo_?R)Yn2Jyibk1;GRb5)6|-II7m{)1!{#b!ES~(3+~T>RFW6~AmEp{p9fyfC*i`{+ z9uGumxH_PDT8OeTT%WpS8&+_askm>u**+~xo~MEx-@hxhNobGW$F^kRs!WoUTK<)~tQ{;d@C&%}l6#*T!cC`uM_ap64=|Dp{;| z@17;}_~-Lf*g3w2_mUWyynak>B&RnaYUQqV^$LhTo;^-JD<78fuuRUGZPLDxjCPtg zVLhm2Hkd0Qzy`TIw)u8?N@9v0(>?6rNyJ8j(XWr0mFc zgifF|yaU{!Tr;VsSDl;L$Vb1xy z$!65C9#jAuw@-Y$eV)(xvsYJ~kGMTa^|G5rZKxsC%KLIr%sRWt3vj3GAn_ppnu G7ybvYbN4X- delta 473 zcmYL_u}T9$5QcYlZ}&FwJcEgtB4`tfC>j(?2^JRGq)C@XLpGRTE|I+pA|5E{3&blW z5PK1P0UH}T`)jrF4eWIGqGn)b_Fw+pZLlV*u?%4rRWS`(% zq(%a&QX#t|BYF*!n^HRZV0$wR0ou?skJkB0Sthf@?6?)g{8V>(*t-3*me$4@Gd<}2 z+EJFQTT#5so7dU@k~6+JKWOOS&~LU|YS3+I2QU2s7J4PX0f$PkAVVe1;{ql*PxUey zN+~U|X%|auH~jNnv(t}Bf}fI;DHFfmnxd0a!k0T<-+(J-slK60A`z7XNgeS6`1V*E diff --git a/src/scheduler/__pycache__/probabilistic.cpython-310.pyc b/src/scheduler/__pycache__/probabilistic.cpython-310.pyc index 8ea524a7cb33078d9369d40ec40ac1a560a0341b..c32d283f57a62e68bb3049482d77d3c59dec603f 100644 GIT binary patch literal 866 zcmZ`%y^a$x5FXpR$>#4aNJm3~uAm?dEeN3t5+|TQ0ST^It+aC1Rnw&$LTro}#u3 zQ(2ucf3p*B2c(Zk?F|A4r?6scko*Izgkp-XIi&*%DJF5>I*BgL=CaE4kI$dHY{sLo zj+AuT<)yA$OP5vVO}$r0>(YfGXwC(dQTLkt_W6d@k=4%S)y!@HdzAdwNp?Ruu^Mes z=Ch?vo>%%9^D~_sn`~L?%GupO=@50SK;J%VvP+#~=b3FakLaKwQiMBvKfH88jLFRx%WUgrUS_MaF0m V4x8Nkl+v73JCH;%6OdqG005dg4SN6p diff --git a/src/scheduler/probabilistic.py b/src/scheduler/probabilistic.py index e69de29..ab3c535 100644 --- a/src/scheduler/probabilistic.py +++ b/src/scheduler/probabilistic.py @@ -0,0 +1,24 @@ +import random +import datetime +from ai import get_ai_response + +last_post_time = None +post_chance = None + +def setup(settings): + global last_post_time, post_chance + last_post_time = datetime.datetime.utcnow() + post_chance = settings.get("start_chance", 0.05) + +def should_post(settings): + global post_chance + if random.random() < post_chance: + return True + post_chance += settings.get("increase_per_interval", 0.05) + return False + +def on_post(settings): + global post_chance, last_post_time + post_chance -= settings.get("decay_on_post", 0.02) + post_chance = max(post_chance, 0.01) + last_post_time = datetime.datetime.utcnow() diff --git a/src/settings.yml b/src/settings.yml index 7866cca..b0e0929 100644 --- a/src/settings.yml +++ b/src/settings.yml @@ -8,8 +8,8 @@ messages: scheduler: enabled: true - mode: simple # <- this activates simple mode - interval_minutes: 0.25 # <- post every 60 minutes + mode: probabilistic # <- this activates simple mode + interval_minutes: 1 # <- post every 60 minutes use_ai: true # <- true = use LLM, false = use static messages channel_id: 1370420592360161393 # <- your Discord text channel ID