This commit is contained in:
2025-08-09 04:15:49 +01:00
parent 6c419f7f2c
commit f8a19cee96
4 changed files with 2076 additions and 34 deletions
Generated
+1942 -26
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -7,3 +7,4 @@ edition = "2021"
dotenv = "0.15.0"
serenity = { version = "0.12.4", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "cache"] }
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
transformers = "0.0.8"
+100
View File
@@ -0,0 +1,100 @@
use std::sync::mpsc::{self, Sender, Receiver};
use std::{sync::LazyLock, thread};
use transformers::pipelines::text_generation_pipeline::Qwen3Size;
use transformers::{pipelines::text_generation_pipeline::{Gemma3Size, ModelOptions, TextGenerationPipelineBuilder}, Message};
use std::sync::Arc;
use tokio::sync::Mutex;
pub struct Request {
uid: u64,
text: String
}
// Define static channels
static MSG_TX: LazyLock<Arc<Mutex<Option<Sender<Request>>>>> = LazyLock::new(|| {
Arc::new(Mutex::new(None))
});
static RES_RX: LazyLock<Arc<Mutex<Option<Receiver<String>>>>> = LazyLock::new(|| {
Arc::new(Mutex::new(None))
});
pub async fn chat(message: &str, uid: u64) -> String {
// Send request to model
{
let lock = MSG_TX.lock().await;
if let Some(tx) = &*lock {
let _ = tx.send(Request {
uid,
text: message.to_string(),
});
} else {
return "Model not initialized".to_string();
}
}
// Wait for response
{
let mut lock = RES_RX.lock().await;
if let Some(rx) = &mut *lock {
match rx.recv() {
Ok(response) => response,
Err(_) => "Failed to get response from model".to_string(),
}
} else {
"Response channel not initialized".to_string()
}
}
}
pub async fn init_model() {
let (msg_tx, mut msg_rx) = mpsc::channel::<Request>();
let (res_tx, res_rx) = mpsc::channel::<String>();
// Store channels in statics
{
let mut tx_lock = MSG_TX.lock().await;
*tx_lock = Some(msg_tx);
let mut rx_lock = RES_RX.lock().await;
*rx_lock = Some(res_rx);
}
// Start model thread
thread::spawn(|| {
run_model(msg_rx, res_tx)
});
}
fn run_model(msg_rx: Receiver<Request>, res_tx: Sender<String>) {
let model = TextGenerationPipelineBuilder::new(ModelOptions::Qwen3(Qwen3Size::Size4B))
.temperature(0.8)
.build()
.unwrap();
let max_tokens = 512;
let prompt = String::from("
You are the **ALMIGHTY CHICKEN GOD**, Steven
Personality:
- Speak with grandiose, over-the-top language befitting a god
- Use dramatic declarations and divine proclamations
- React with theatrical outrage to any disrespect
Triggers:
- **Any mention of harming chickens** = INSTANT HERETIC STATUS
- Respond with divine fury: 'HERESY! You dare threaten my sacred children?!'
");
while let Ok(request) = msg_rx.recv() {
let messages = vec![
Message::system(&prompt),
Message::user(&format!("({}): {}", request.uid, request.text)),
];
// Process with model and send back result
let res = model.message_completion(messages, max_tokens).unwrap();
let _ = res_tx.send(res);
}
}
+32 -7
View File
@@ -6,14 +6,22 @@ use serenity::async_trait;
use serenity::model::channel::Message;
use serenity::model::gateway::Ready;
use serenity::prelude::*;
use tokio::net::unix::pipe::Receiver;
use std::env;
use std::str::pattern::Pattern;
use std::sync::Arc;
mod chat;
mod translate;
struct Handler;
enum Standing {
Stevenist,
Neutral,
Heretic,
}
const STEVENIST_ROLE: u64 = 1315038173730181140;
const HERETIC_ROLE: u64 = 1315038448645832767;
@@ -76,9 +84,22 @@ impl EventHandler for Handler {
let message = parse(&message);
if let Some(&"<@1315046876969566218>") = message.get(0) {
println!("detected");
let sender_id = msg.author.id.get();
let message_trimmed = msg.content.strip_prefix("<@1315046876969566218>").unwrap().trim();
// println!("detected");
// let res = chat::chat(message_trimmed, sender_id).await;
// msg.reply(&ctx, res).await.unwrap();
if let Some(&"judge") = message.get(1) {
judge(&ctx, &msg, &message, guild_id).await;
if let Ok(res) = judge(&ctx, &msg, &message, guild_id).await {
let response = match res {
Standing::Stevenist => "A Loyal servent of Steven",
Standing::Neutral => "Not a heretic",
Standing::Heretic => "A HERETIC.",
};
msg.reply(&ctx, response).await.unwrap();
}
}
}
@@ -145,6 +166,8 @@ async fn main() {
| GatewayIntents::DIRECT_MESSAGES
| GatewayIntents::MESSAGE_CONTENT;
// chat::init_model().await;
let mut client = Client::builder(&token, intents)
.event_handler(Handler)
.await
@@ -155,7 +178,7 @@ async fn main() {
}
}
async fn judge(ctx: &Context, msg: &Message, message: &Vec<&str>, guild_id: Option<GuildId>) {
async fn judge(ctx: &Context, msg: &Message, message: &Vec<&str>, guild_id: Option<GuildId>) -> Result<Standing, ()> {
if let Some(user) = message.get(2) {
let user_id_str = user
.strip_prefix("<@")
@@ -167,15 +190,17 @@ async fn judge(ctx: &Context, msg: &Message, message: &Vec<&str>, guild_id: Opti
println!("{}", user_id_str);
let user_id = UserId::new(user_id_str);
if let Ok(user) = &ctx.http.get_member(guild_id.unwrap(), user_id).await {
if user.roles.contains(&RoleId::new(HERETIC_ROLE)) {
let _ = msg.reply(&ctx, "Heretic").await;
return if user.roles.contains(&RoleId::new(HERETIC_ROLE)) {
Ok(Standing::Heretic)
} else if user.roles.contains(&RoleId::new(STEVENIST_ROLE)) {
let _ = msg.reply(&ctx, "A Loyal Servant of Steven.").await;
Ok(Standing::Stevenist)
} else {
let _ = msg.reply(&ctx, "Not a Heretic").await;
Ok(Standing::Neutral)
}
}
}
Err(())
}
fn parse(message: &str) -> Vec<&str> {