Initial implementation of autonomous Discord LLM fishbowl

Core Features:
- Full autonomous AI character ecosystem with multi-personality support
- Advanced RAG system with personal, community, and creative memory layers
- MCP integration for character self-modification and file system access
- PostgreSQL database with comprehensive character relationship tracking
- Redis caching and ChromaDB vector storage for semantic memory retrieval
- Dynamic personality evolution based on interactions and self-reflection
- Community knowledge management with tradition and norm identification
- Sophisticated conversation engine with natural scheduling and topic management
- Docker containerization and production-ready deployment configuration

Architecture:
- Multi-layer vector databases for personal, community, and creative knowledge
- Character file systems with personal and shared digital spaces
- Autonomous self-modification with safety validation and audit trails
- Memory importance scoring with time-based decay and consolidation
- Community health monitoring and cultural evolution tracking
- RAG-powered conversation context and relationship optimization

Characters can:
- Develop authentic personalities through experience-based learning
- Create and build upon original creative works and philosophical insights
- Form complex relationships with memory of past interactions
- Modify their own personality traits through self-reflection cycles
- Contribute to and learn from shared community knowledge
- Manage personal digital spaces with diaries, creative works, and reflections
- Engage in collaborative projects and community decision-making

System supports indefinite autonomous operation with continuous character
development, community culture evolution, and creative collaboration.
This commit is contained in:
2025-07-04 21:33:27 -07:00
commit f22a68afa6
42 changed files with 10456 additions and 0 deletions

172
src/database/models.py Normal file
View File

@@ -0,0 +1,172 @@
from sqlalchemy import Column, Integer, String, Text, DateTime, Float, Boolean, ForeignKey, JSON, Index
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from datetime import datetime
from typing import Optional, Dict, Any, List
Base = declarative_base()
class Character(Base):
__tablename__ = "characters"
id = Column(Integer, primary_key=True, index=True)
name = Column(String(100), unique=True, nullable=False, index=True)
personality = Column(Text, nullable=False)
system_prompt = Column(Text, nullable=False)
interests = Column(JSON, nullable=False, default=list)
speaking_style = Column(Text, nullable=False)
background = Column(Text, nullable=False)
avatar_url = Column(String(500))
is_active = Column(Boolean, default=True)
creation_date = Column(DateTime, default=func.now())
last_active = Column(DateTime, default=func.now())
last_message_id = Column(Integer, ForeignKey("messages.id"), nullable=True)
# Relationships
messages = relationship("Message", back_populates="character", foreign_keys="Message.character_id")
memories = relationship("Memory", back_populates="character", cascade="all, delete-orphan")
relationships_as_a = relationship("CharacterRelationship", back_populates="character_a", foreign_keys="CharacterRelationship.character_a_id")
relationships_as_b = relationship("CharacterRelationship", back_populates="character_b", foreign_keys="CharacterRelationship.character_b_id")
evolution_history = relationship("CharacterEvolution", back_populates="character", cascade="all, delete-orphan")
def to_dict(self) -> Dict[str, Any]:
return {
"id": self.id,
"name": self.name,
"personality": self.personality,
"system_prompt": self.system_prompt,
"interests": self.interests,
"speaking_style": self.speaking_style,
"background": self.background,
"avatar_url": self.avatar_url,
"is_active": self.is_active,
"creation_date": self.creation_date.isoformat() if self.creation_date else None,
"last_active": self.last_active.isoformat() if self.last_active else None
}
class Conversation(Base):
__tablename__ = "conversations"
id = Column(Integer, primary_key=True, index=True)
channel_id = Column(String(50), nullable=False, index=True)
topic = Column(String(200))
participants = Column(JSON, nullable=False, default=list)
start_time = Column(DateTime, default=func.now())
last_activity = Column(DateTime, default=func.now())
is_active = Column(Boolean, default=True)
message_count = Column(Integer, default=0)
# Relationships
messages = relationship("Message", back_populates="conversation", cascade="all, delete-orphan")
__table_args__ = (
Index('ix_conversations_channel_active', 'channel_id', 'is_active'),
)
class Message(Base):
__tablename__ = "messages"
id = Column(Integer, primary_key=True, index=True)
conversation_id = Column(Integer, ForeignKey("conversations.id"), nullable=False)
character_id = Column(Integer, ForeignKey("characters.id"), nullable=False)
content = Column(Text, nullable=False)
timestamp = Column(DateTime, default=func.now())
metadata = Column(JSON, nullable=True)
discord_message_id = Column(String(50), unique=True, nullable=True)
response_to_message_id = Column(Integer, ForeignKey("messages.id"), nullable=True)
emotion = Column(String(50))
# Relationships
conversation = relationship("Conversation", back_populates="messages")
character = relationship("Character", back_populates="messages", foreign_keys=[character_id])
response_to = relationship("Message", remote_side=[id])
__table_args__ = (
Index('ix_messages_character_timestamp', 'character_id', 'timestamp'),
Index('ix_messages_conversation_timestamp', 'conversation_id', 'timestamp'),
)
class Memory(Base):
__tablename__ = "memories"
id = Column(Integer, primary_key=True, index=True)
character_id = Column(Integer, ForeignKey("characters.id"), nullable=False)
memory_type = Column(String(50), nullable=False) # 'conversation', 'relationship', 'experience', 'fact'
content = Column(Text, nullable=False)
importance_score = Column(Float, default=0.5)
timestamp = Column(DateTime, default=func.now())
last_accessed = Column(DateTime, default=func.now())
access_count = Column(Integer, default=0)
related_message_id = Column(Integer, ForeignKey("messages.id"), nullable=True)
related_character_id = Column(Integer, ForeignKey("characters.id"), nullable=True)
tags = Column(JSON, nullable=False, default=list)
# Relationships
character = relationship("Character", back_populates="memories", foreign_keys=[character_id])
related_message = relationship("Message", foreign_keys=[related_message_id])
related_character = relationship("Character", foreign_keys=[related_character_id])
__table_args__ = (
Index('ix_memories_character_type', 'character_id', 'memory_type'),
Index('ix_memories_importance', 'importance_score'),
)
class CharacterRelationship(Base):
__tablename__ = "character_relationships"
id = Column(Integer, primary_key=True, index=True)
character_a_id = Column(Integer, ForeignKey("characters.id"), nullable=False)
character_b_id = Column(Integer, ForeignKey("characters.id"), nullable=False)
relationship_type = Column(String(50), nullable=False) # 'friend', 'rival', 'neutral', 'mentor', 'student'
strength = Column(Float, default=0.5) # 0.0 to 1.0
last_interaction = Column(DateTime, default=func.now())
interaction_count = Column(Integer, default=0)
notes = Column(Text)
# Relationships
character_a = relationship("Character", back_populates="relationships_as_a", foreign_keys=[character_a_id])
character_b = relationship("Character", back_populates="relationships_as_b", foreign_keys=[character_b_id])
__table_args__ = (
Index('ix_relationships_characters', 'character_a_id', 'character_b_id'),
)
class CharacterEvolution(Base):
__tablename__ = "character_evolution"
id = Column(Integer, primary_key=True, index=True)
character_id = Column(Integer, ForeignKey("characters.id"), nullable=False)
change_type = Column(String(50), nullable=False) # 'personality', 'interests', 'speaking_style', 'system_prompt'
old_value = Column(Text)
new_value = Column(Text)
reason = Column(Text)
timestamp = Column(DateTime, default=func.now())
triggered_by_message_id = Column(Integer, ForeignKey("messages.id"), nullable=True)
# Relationships
character = relationship("Character", back_populates="evolution_history")
triggered_by_message = relationship("Message", foreign_keys=[triggered_by_message_id])
__table_args__ = (
Index('ix_evolution_character_timestamp', 'character_id', 'timestamp'),
)
class ConversationSummary(Base):
__tablename__ = "conversation_summaries"
id = Column(Integer, primary_key=True, index=True)
conversation_id = Column(Integer, ForeignKey("conversations.id"), nullable=False)
summary = Column(Text, nullable=False)
key_points = Column(JSON, nullable=False, default=list)
participants = Column(JSON, nullable=False, default=list)
created_at = Column(DateTime, default=func.now())
message_range_start = Column(Integer, nullable=False)
message_range_end = Column(Integer, nullable=False)
# Relationships
conversation = relationship("Conversation", foreign_keys=[conversation_id])
__table_args__ = (
Index('ix_summaries_conversation', 'conversation_id', 'created_at'),
)