feat: Implement Living AI system
Complete implementation of the Living AI features: Phase 1 - Foundation: - MoodService: Valence-arousal mood model with time decay - RelationshipService: Stranger→Close Friend progression - Enhanced system prompt with personality modifiers Phase 2 - Autonomous Learning: - FactExtractionService: AI-powered fact extraction from conversations - Rate-limited extraction (configurable, default 30%) - Deduplication and importance scoring Phase 3 - Personalization: - CommunicationStyleService: Learn user preferences - OpinionService: Bot opinion formation on topics - SelfAwarenessService: Bot statistics and self-reflection Phase 4 - Proactive Features: - ProactiveService: Scheduled events (birthdays, follow-ups) - Event detection from conversations - Recurring event support Phase 5 - Social Features: - AssociationService: Cross-user memory connections - Shared interest discovery - Connection suggestions New database tables: - bot_states, bot_opinions, user_relationships - user_communication_styles, scheduled_events - fact_associations, mood_history Configuration: - Living AI feature toggles - Individual command enable/disable - All features work naturally through conversation when commands disabled
This commit is contained in:
141
schema.sql
141
schema.sql
@@ -117,3 +117,144 @@ CREATE TABLE IF NOT EXISTS messages (
|
||||
CREATE INDEX IF NOT EXISTS ix_messages_conversation_id ON messages(conversation_id);
|
||||
CREATE INDEX IF NOT EXISTS ix_messages_user_id ON messages(user_id);
|
||||
CREATE INDEX IF NOT EXISTS ix_messages_created_at ON messages(created_at);
|
||||
|
||||
-- =====================================================
|
||||
-- LIVING AI TABLES
|
||||
-- =====================================================
|
||||
|
||||
-- Bot state table (mood, statistics, preferences per guild)
|
||||
CREATE TABLE IF NOT EXISTS bot_states (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
guild_id BIGINT UNIQUE, -- NULL = global state
|
||||
mood_valence FLOAT DEFAULT 0.0, -- -1.0 (sad) to 1.0 (happy)
|
||||
mood_arousal FLOAT DEFAULT 0.0, -- -1.0 (calm) to 1.0 (excited)
|
||||
mood_updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
total_messages_sent INTEGER DEFAULT 0,
|
||||
total_facts_learned INTEGER DEFAULT 0,
|
||||
total_users_known INTEGER DEFAULT 0,
|
||||
first_activated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
preferences JSONB DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_bot_states_guild_id ON bot_states(guild_id);
|
||||
|
||||
-- Bot opinions table (topic preferences)
|
||||
CREATE TABLE IF NOT EXISTS bot_opinions (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
guild_id BIGINT, -- NULL = global opinion
|
||||
topic VARCHAR(255) NOT NULL,
|
||||
sentiment FLOAT DEFAULT 0.0, -- -1.0 to 1.0
|
||||
interest_level FLOAT DEFAULT 0.5, -- 0.0 to 1.0
|
||||
discussion_count INTEGER DEFAULT 0,
|
||||
reasoning TEXT,
|
||||
formed_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
last_reinforced_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(guild_id, topic)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_bot_opinions_guild_id ON bot_opinions(guild_id);
|
||||
CREATE INDEX IF NOT EXISTS ix_bot_opinions_topic ON bot_opinions(topic);
|
||||
|
||||
-- User relationships table (relationship depth tracking)
|
||||
CREATE TABLE IF NOT EXISTS user_relationships (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
guild_id BIGINT, -- NULL = global relationship
|
||||
relationship_score FLOAT DEFAULT 10.0, -- 0-100 scale
|
||||
total_interactions INTEGER DEFAULT 0,
|
||||
positive_interactions INTEGER DEFAULT 0,
|
||||
negative_interactions INTEGER DEFAULT 0,
|
||||
avg_message_length FLOAT DEFAULT 0.0,
|
||||
conversation_depth_avg FLOAT DEFAULT 0.0,
|
||||
shared_references JSONB DEFAULT '{}',
|
||||
first_interaction_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
last_interaction_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(user_id, guild_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_user_relationships_user_id ON user_relationships(user_id);
|
||||
CREATE INDEX IF NOT EXISTS ix_user_relationships_guild_id ON user_relationships(guild_id);
|
||||
|
||||
-- User communication styles table (learned preferences)
|
||||
CREATE TABLE IF NOT EXISTS user_communication_styles (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE UNIQUE,
|
||||
preferred_length VARCHAR(20) DEFAULT 'medium', -- short/medium/long
|
||||
preferred_formality FLOAT DEFAULT 0.5, -- 0=casual, 1=formal
|
||||
emoji_affinity FLOAT DEFAULT 0.5, -- 0=none, 1=lots
|
||||
humor_affinity FLOAT DEFAULT 0.5, -- 0=serious, 1=playful
|
||||
detail_preference FLOAT DEFAULT 0.5, -- 0=concise, 1=detailed
|
||||
engagement_signals JSONB DEFAULT '{}',
|
||||
samples_collected INTEGER DEFAULT 0,
|
||||
confidence FLOAT DEFAULT 0.0,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_user_communication_styles_user_id ON user_communication_styles(user_id);
|
||||
|
||||
-- Scheduled events table (proactive behavior)
|
||||
CREATE TABLE IF NOT EXISTS scheduled_events (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id BIGINT REFERENCES users(id) ON DELETE CASCADE,
|
||||
guild_id BIGINT,
|
||||
channel_id BIGINT,
|
||||
event_type VARCHAR(50) NOT NULL, -- birthday, follow_up, reminder, etc.
|
||||
trigger_at TIMESTAMPTZ NOT NULL,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
context JSONB DEFAULT '{}',
|
||||
is_recurring BOOLEAN DEFAULT FALSE,
|
||||
recurrence_rule VARCHAR(100), -- yearly, monthly, etc.
|
||||
status VARCHAR(20) DEFAULT 'pending', -- pending, triggered, cancelled
|
||||
triggered_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_scheduled_events_user_id ON scheduled_events(user_id);
|
||||
CREATE INDEX IF NOT EXISTS ix_scheduled_events_trigger_at ON scheduled_events(trigger_at);
|
||||
CREATE INDEX IF NOT EXISTS ix_scheduled_events_status ON scheduled_events(status);
|
||||
|
||||
-- Fact associations table (cross-user memory links)
|
||||
CREATE TABLE IF NOT EXISTS fact_associations (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
fact_id_1 BIGINT NOT NULL REFERENCES user_facts(id) ON DELETE CASCADE,
|
||||
fact_id_2 BIGINT NOT NULL REFERENCES user_facts(id) ON DELETE CASCADE,
|
||||
association_type VARCHAR(50) NOT NULL, -- shared_interest, same_location, etc.
|
||||
strength FLOAT DEFAULT 0.5,
|
||||
discovered_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(fact_id_1, fact_id_2)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_fact_associations_fact_id_1 ON fact_associations(fact_id_1);
|
||||
CREATE INDEX IF NOT EXISTS ix_fact_associations_fact_id_2 ON fact_associations(fact_id_2);
|
||||
|
||||
-- Mood history table (track mood changes over time)
|
||||
CREATE TABLE IF NOT EXISTS mood_history (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
guild_id BIGINT,
|
||||
valence FLOAT NOT NULL,
|
||||
arousal FLOAT NOT NULL,
|
||||
trigger_type VARCHAR(50) NOT NULL, -- conversation, time_decay, event
|
||||
trigger_user_id BIGINT REFERENCES users(id) ON DELETE SET NULL,
|
||||
trigger_description TEXT,
|
||||
recorded_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_mood_history_guild_id ON mood_history(guild_id);
|
||||
CREATE INDEX IF NOT EXISTS ix_mood_history_recorded_at ON mood_history(recorded_at);
|
||||
|
||||
-- Add new columns to user_facts for enhanced memory
|
||||
ALTER TABLE user_facts ADD COLUMN IF NOT EXISTS category VARCHAR(50);
|
||||
ALTER TABLE user_facts ADD COLUMN IF NOT EXISTS importance FLOAT DEFAULT 0.5;
|
||||
ALTER TABLE user_facts ADD COLUMN IF NOT EXISTS temporal_relevance VARCHAR(20);
|
||||
ALTER TABLE user_facts ADD COLUMN IF NOT EXISTS expiry_date TIMESTAMPTZ;
|
||||
ALTER TABLE user_facts ADD COLUMN IF NOT EXISTS extracted_from_message_id BIGINT;
|
||||
ALTER TABLE user_facts ADD COLUMN IF NOT EXISTS extraction_context TEXT;
|
||||
|
||||
Reference in New Issue
Block a user