first
This commit is contained in:
37
src/agent.rs
Normal file
37
src/agent.rs
Normal file
@ -0,0 +1,37 @@
|
||||
use chrono::{NaiveDateTime};
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub struct AIState {
|
||||
pub relation_score: f32,
|
||||
pub previous_score: f32,
|
||||
pub decay_rate: f32,
|
||||
pub sensitivity: f32,
|
||||
pub message_threshold: f32,
|
||||
pub last_message_time: NaiveDateTime,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl AIState {
|
||||
pub fn update(&mut self, now: NaiveDateTime) {
|
||||
let days_passed = (now - self.last_message_time).num_days() as f32;
|
||||
let decay = self.decay_rate * days_passed;
|
||||
self.previous_score = self.relation_score;
|
||||
self.relation_score -= decay;
|
||||
self.relation_score = self.relation_score.clamp(0.0, 100.0);
|
||||
}
|
||||
|
||||
pub fn should_talk(&self) -> bool {
|
||||
let delta = self.previous_score - self.relation_score;
|
||||
delta > self.message_threshold && self.sensitivity > 0.5
|
||||
}
|
||||
|
||||
pub fn generate_message(&self) -> String {
|
||||
match self.relation_score as i32 {
|
||||
80..=100 => "ふふっ、最近どうしてる?会いたくなっちゃった!".to_string(),
|
||||
60..=79 => "ちょっとだけ、さみしかったんだよ?".to_string(),
|
||||
40..=59 => "えっと……話せる時間ある?".to_string(),
|
||||
_ => "ううん、もしかして私のこと、忘れちゃったのかな……".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
90
src/cli.rs
Normal file
90
src/cli.rs
Normal file
@ -0,0 +1,90 @@
|
||||
//src/cli.rs
|
||||
use seahorse::{App, Command, Context};
|
||||
|
||||
use crate::model::{AiSystem};
|
||||
use std::fs;
|
||||
|
||||
use crate::agent::AIState;
|
||||
use chrono::{Duration, Local};
|
||||
|
||||
fn load_config(path: &str) -> AiSystem {
|
||||
let data = fs::read_to_string(path).expect("JSON読み込み失敗");
|
||||
serde_json::from_str(&data).expect("JSONパース失敗")
|
||||
}
|
||||
|
||||
fn save_config(path: &str, ai: &AiSystem) {
|
||||
let json = serde_json::to_string_pretty(&ai).expect("JSONシリアライズ失敗");
|
||||
fs::write(path, json).expect("JSON保存失敗");
|
||||
}
|
||||
|
||||
pub fn cli_app() -> App {
|
||||
let set_cmd = Command::new("set")
|
||||
.usage("set [trust|intimacy|curiosity] [value]")
|
||||
.action(|c: &Context| {
|
||||
if c.args.len() != 2 {
|
||||
eprintln!("Usage: set [trust|intimacy|curiosity] [value]");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
let field = &c.args[0];
|
||||
let value: f32 = c.args[1].parse().unwrap_or_else(|_| {
|
||||
eprintln!("数値で入力してください");
|
||||
std::process::exit(1);
|
||||
});
|
||||
|
||||
let path = "config/config.json";
|
||||
let mut ai = load_config(path);
|
||||
|
||||
match field.as_str() {
|
||||
"trust" => ai.relationship.trust = value,
|
||||
"intimacy" => ai.relationship.intimacy = value,
|
||||
"curiosity" => ai.relationship.curiosity = value,
|
||||
_ => {
|
||||
eprintln!("trust / intimacy / curiosity のいずれかを指定してください");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
save_config(path, &ai);
|
||||
println!("✅ {field} を {value} に更新しました");
|
||||
});
|
||||
|
||||
let show_cmd = Command::new("show")
|
||||
.usage("show")
|
||||
.action(|_c: &Context| {
|
||||
let ai = load_config("config/config.json");
|
||||
println!("🧠 現在のAI状態:\n{:#?}", ai);
|
||||
});
|
||||
|
||||
let talk_cmd = Command::new("talk")
|
||||
.usage("talk")
|
||||
.action(|_c: &Context| {
|
||||
let ai = load_config("config/config.json");
|
||||
|
||||
let now = Local::now().naive_local();
|
||||
let mut state = AIState {
|
||||
relation_score: 80.0,
|
||||
previous_score: 80.0,
|
||||
decay_rate: ai.messaging.decay_rate,
|
||||
sensitivity: ai.personality.strength,
|
||||
message_threshold: 5.0,
|
||||
last_message_time: now - Duration::days(4),
|
||||
};
|
||||
|
||||
state.update(now);
|
||||
|
||||
if state.should_talk() {
|
||||
println!("💬 AI発話: {}", state.generate_message());
|
||||
} else {
|
||||
println!("🤫 今日は静かにしているみたい...");
|
||||
}
|
||||
});
|
||||
|
||||
App::new("aigpt")
|
||||
.version("0.1.0")
|
||||
.description("AGE system CLI controller")
|
||||
.author("syui")
|
||||
.command(set_cmd)
|
||||
.command(show_cmd)
|
||||
.command(talk_cmd)
|
||||
}
|
133
src/data.rs
Normal file
133
src/data.rs
Normal file
@ -0,0 +1,133 @@
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct RelationalAutonomousAI {
|
||||
pub system_name: String,
|
||||
pub description: String,
|
||||
pub core_components: CoreComponents,
|
||||
pub extensions: Extensions,
|
||||
pub note: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CoreComponents {
|
||||
pub personality: Personality,
|
||||
pub relationship: Relationship,
|
||||
pub environment: Environment,
|
||||
pub memory: Memory,
|
||||
pub message_trigger: MessageTrigger,
|
||||
pub message_generation: MessageGeneration,
|
||||
pub state_transition: StateTransition,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Personality {
|
||||
pub r#type: String,
|
||||
pub variants: Vec<String>,
|
||||
pub parameters: PersonalityParameters,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct PersonalityParameters {
|
||||
pub message_trigger_style: String,
|
||||
pub decay_rate_modifier: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Relationship {
|
||||
pub parameters: Vec<String>,
|
||||
pub properties: RelationshipProperties,
|
||||
pub decay_function: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct RelationshipProperties {
|
||||
pub persistent: bool,
|
||||
pub hidden: bool,
|
||||
pub irreversible: bool,
|
||||
pub decay_over_time: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Environment {
|
||||
pub daily_luck: DailyLuck,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct DailyLuck {
|
||||
pub r#type: String,
|
||||
pub range: Vec<f32>,
|
||||
pub update: String,
|
||||
pub streak_mechanism: StreakMechanism,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct StreakMechanism {
|
||||
pub trigger: String,
|
||||
pub effect: String,
|
||||
pub chance: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Memory {
|
||||
pub long_term_memory: String,
|
||||
pub short_term_context: String,
|
||||
pub usage_in_generation: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct MessageTrigger {
|
||||
pub condition: TriggerCondition,
|
||||
pub timing: TriggerTiming,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct TriggerCondition {
|
||||
pub relationship_threshold: String,
|
||||
pub time_decay: bool,
|
||||
pub environment_luck: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct TriggerTiming {
|
||||
pub based_on: Vec<String>,
|
||||
pub modifiers: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct MessageGeneration {
|
||||
pub style_variants: Vec<String>,
|
||||
pub influenced_by: Vec<String>,
|
||||
pub llm_integration: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct StateTransition {
|
||||
pub states: Vec<String>,
|
||||
pub transitions: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Extensions {
|
||||
pub persistence: Persistence,
|
||||
pub api: Api,
|
||||
pub scheduler: Scheduler,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Persistence {
|
||||
pub database: String,
|
||||
pub storage_items: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Api {
|
||||
pub llm: String,
|
||||
pub mode: String,
|
||||
pub external_event_trigger: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Scheduler {
|
||||
pub async_event_loop: bool,
|
||||
pub interval_check: i32,
|
||||
pub time_decay_check: bool,
|
||||
}
|
13
src/logic.rs
Normal file
13
src/logic.rs
Normal file
@ -0,0 +1,13 @@
|
||||
//src/logic.rs
|
||||
use crate::model::AiSystem;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn should_send(ai: &AiSystem) -> bool {
|
||||
let r = &ai.relationship;
|
||||
let env = &ai.environment;
|
||||
let score = r.trust + r.intimacy + r.curiosity;
|
||||
let relationship_ok = score >= r.threshold;
|
||||
let luck_ok = env.luck_today > 0.5;
|
||||
|
||||
ai.messaging.enabled && relationship_ok && luck_ok
|
||||
}
|
14
src/main.rs
Normal file
14
src/main.rs
Normal file
@ -0,0 +1,14 @@
|
||||
//src/main.rs
|
||||
mod model;
|
||||
mod logic;
|
||||
mod agent;
|
||||
mod cli;
|
||||
|
||||
use cli::cli_app;
|
||||
use seahorse::App;
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
let app: App = cli_app();
|
||||
app.run(args);
|
||||
}
|
41
src/model.rs
Normal file
41
src/model.rs
Normal file
@ -0,0 +1,41 @@
|
||||
//src/model.rs
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct AiSystem {
|
||||
pub personality: Personality,
|
||||
pub relationship: Relationship,
|
||||
pub environment: Environment,
|
||||
pub messaging: Messaging,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Personality {
|
||||
pub kind: String, // e.g., "positive", "negative", "neutral"
|
||||
pub strength: f32, // 0.0 - 1.0
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Relationship {
|
||||
pub trust: f32, // 0.0 - 1.0
|
||||
pub intimacy: f32, // 0.0 - 1.0
|
||||
pub curiosity: f32, // 0.0 - 1.0
|
||||
pub threshold: f32, // if sum > threshold, allow messaging
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Environment {
|
||||
pub luck_today: f32, // 0.1 - 1.0
|
||||
pub luck_history: Vec<f32>, // last 3 values
|
||||
pub level: i32, // current mental strength level
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Messaging {
|
||||
pub enabled: bool,
|
||||
pub schedule_time: Option<String>, // e.g., "08:00"
|
||||
pub decay_rate: f32, // how quickly emotion fades (0.0 - 1.0)
|
||||
pub templates: Vec<String>, // message template variations
|
||||
}
|
||||
|
||||
|
46
src/system.rs
Normal file
46
src/system.rs
Normal file
@ -0,0 +1,46 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Write};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
mod model;
|
||||
use model::RelationalAutonomousAI;
|
||||
|
||||
fn load_config(path: &str) -> std::io::Result<RelationalAutonomousAI> {
|
||||
let file = File::open(path)?;
|
||||
let reader = BufReader::new(file);
|
||||
let config: RelationalAutonomousAI = serde_json::from_reader(reader)?;
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
fn save_config(config: &RelationalAutonomousAI, path: &str) -> std::io::Result<()> {
|
||||
let mut file = File::create(path)?;
|
||||
let json = serde_json::to_string_pretty(config)?;
|
||||
file.write_all(json.as_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn should_send_message(config: &RelationalAutonomousAI) -> bool {
|
||||
// 簡易な送信条件: relationshipが高く、daily_luckが0.8以上
|
||||
config.core_components.relationship.parameters.contains(&"trust".to_string())
|
||||
&& config.core_components.environment.daily_luck.range[1] >= 0.8
|
||||
}
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
let path = "config.json";
|
||||
|
||||
let mut config = load_config(path)?;
|
||||
|
||||
if should_send_message(&config) {
|
||||
println!("💌 メッセージを送信できます: {:?}", config.core_components.personality.r#type);
|
||||
|
||||
// ステート変化の例: メッセージ送信後に記録用トランジションを追加
|
||||
config.core_components.state_transition.transitions.push("message_sent".to_string());
|
||||
|
||||
save_config(&config, path)?;
|
||||
} else {
|
||||
println!("😶 まだ送信条件に達していません。");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
Reference in New Issue
Block a user