BuddAI/core/buddai_personality.py
JamesTheGiblet f9fd27d228 Implement core skills: Code validation, model fine-tuning, and system diagnostics
- Added `ModelFineTuner` class for preparing training data and fine-tuning models based on user corrections.
- Introduced `CodeValidator` class to validate generated code against various hardware and style rules, including safety checks and function naming conventions.
- Developed skills for calculator operations, system information retrieval, weather fetching, and timer functionality.
- Implemented a self-diagnostic skill to run unit tests and report results.
- Created a dynamic skill loading mechanism to discover and register skills from the current directory.
- Added unit tests for skills to ensure functionality and reliability.
2026-01-06 22:04:37 +00:00

126 lines
No EOL
5.9 KiB
Python

import json
from pathlib import Path
from typing import Dict, Any, Union, List
from datetime import datetime
class PersonalityManager:
"""Manages AI personality, prompts, and user schedules"""
def __init__(self):
self.personality = self.load_personality()
self.validate_personality_schema()
def load_personality(self) -> Dict:
"""Loads personality from a JSON file."""
personality_path = Path(__file__).parent.parent / "personality.json"
if personality_path.exists():
print("🧠 Loading custom personality...")
with open(personality_path, 'r', encoding='utf-8') as f:
return json.load(f)
else:
# Default personality if file doesn't exist
print("🧠 Using default 'James' personality.")
return {
"user_name": "James",
"ai_name": "BuddAI",
"welcome_message": "BuddAI Executive v4.0 - Decoupled & Personality Sync",
"schedule_check_triggers": ["what should i be doing", "my schedule", "schedule check"],
"schedule": {
"weekdays": {"0-4": {"5.5-6.5": "Early Morning Build Session 🌅 (5:30-6:30 AM)", "6.5-17.0": "Work Hours (Facilities Caretaker) 🏢", "17.0-21.0": "Evening Build Session 🌙 (5:00-9:00 PM)", "default": "Rest Time 💤"}},
"saturday": { "5": { "default": "Weekend Freedom 🎨 (Creative Mode)" } },
"sunday": { "6": { "0-21.0": "Weekend Freedom 🎨 (Until 9 PM)", "default": "Rest Time 💤" } }
},
"style_scan_prompt": "Analyze this code sample from {user_name}'s repositories.\nExtract 3 distinct coding preferences or patterns.",
"style_reference_prompt": "\n[REFERENCE STYLE FROM {user_name}'S PAST PROJECTS]\n",
"integration_task_prompt": "INTEGRATION TASK: Combine modules into a cohesive GilBot system.\n\n[MODULES]\n{modules_summary}\n\n[FORGE PARAMETERS]\nSet k = {k_val} for all applyForge() calls.\n\n[REQUIREMENTS]\n1. Implement applyForge() math helper.\n2. Use k={k_val} to smooth motor and servo transitions.\n3. Ensure naming matches {user_name}'s style: activateFlipper(), setMotors()."
}
def validate_personality_schema(self) -> bool:
"""Validate the loaded personality against required schema."""
if not self.personality:
return False
required_structure = {
"meta": ["version"],
"identity": ["user_name", "ai_name"],
"communication": ["welcome_message"],
"work_cycles": ["schedule"],
"forge_theory": ["enabled", "constants"],
"prompts": ["style_scan", "integration_task"]
}
missing = []
version = self.get_value("meta.version")
if version and version != "4.0":
print(f"⚠️ Warning: Personality version mismatch. Loaded: {version}, Expected: 4.0")
for section, keys in required_structure.items():
if section not in self.personality:
missing.append(f"Missing section: {section}")
continue
for key in keys:
if key not in self.personality[section]:
missing.append(f"Missing key: {section}.{key}")
if missing:
print("⚠️ Personality Schema Validation Failed:")
for m in missing:
print(f" - {m}")
return False
return True
def get_value(self, path: Union[str, List[str]], default: Any = None) -> Any:
"""Access nested personality keys using dot notation or list of keys."""
if isinstance(path, str):
keys = path.split('.')
else:
keys = path
val = self.personality
for key in keys:
if isinstance(val, dict):
val = val.get(key)
else:
return default
return val if val is not None else default
def get_user_status(self) -> str:
"""Determine user's context based on defined schedule from personality file."""
schedule = self.get_value("work_cycles.schedule")
if not schedule:
# Fallback for simple personality files
schedule = self.personality.get("schedule")
if not schedule:
return "Schedule not defined."
now = datetime.now()
day = now.weekday() # 0=Mon, 6=Sun
t = now.hour + (now.minute / 60.0)
# Check all schedule groups (e.g., 'weekdays', 'weekends')
for group, day_ranges in schedule.items():
for day_range, time_slots in day_ranges.items():
try:
# Parse day range (e.g., "0-4" or "5")
if '-' in day_range:
start_day, end_day = map(int, day_range.split('-'))
if not (start_day <= day <= end_day):
continue
elif int(day_range) != day:
continue
# We found the right day group, now check time slots
for time_range, status in time_slots.items():
if time_range == "default": continue
start_time, end_time = map(float, time_range.split('-'))
if start_time <= t < end_time:
return status.get("description", status) if isinstance(status, dict) else status
default_status = time_slots.get("default", "No status for this time.")
return default_status.get("description", default_status) if isinstance(default_status, dict) else default_status
except (ValueError, TypeError): continue
return "No schedule match for today."