Some checks failed
social-bot integration tests / Lint (flake8 + pep257) (pull_request) Failing after 29s
social-bot integration tests / Core integration tests (mock sensors, no GPU) (pull_request) Has been skipped
social-bot integration tests / Latency profiling (GPU, Orin) (pull_request) Has been cancelled
- SQLite database at /home/seb/saltybot-data/social_memory.db - Tables: persons (name, embeddings, relationship_tier, notes), encounters (person_id, timestamp, transcript, mood) - ROS2 services: /saltybot/social_memory/lookup, /update, /encounter, /stats - Automatic tier promotion by encounter count (5→regular, 20→favorite) - Quality-based promotion: 80%+ positive interactions required - Custom greetings per relationship tier (stranger/regular/favorite) - Encounter tracking: transcript, mood, engagement_score, positive_interaction flag - Face embedding storage support for face recognition integration - Relationship score computation from interaction history - Thread-safe concurrent service calls - Periodic stats publishing on /saltybot/social_memory/stats_update - Backup/restore functionality with gzip compression - Full database statistics: person counts by tier, total encounters, database size - Configurable via social_memory.yaml: thresholds, backup dir, publish interval Two packages: - saltybot_social_memory: Service definitions (CMake, ROS2 services) - saltybot_social_memory_node: Python service server with SQLite backend Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
SaltyBot Social Memory Database (Issue #443)
Persistent SQLite-backed social knowledge system for maintaining person profiles, relationship history, and interaction statistics.
Features
1. Person Profile Management
- Person Records: Name, relationship tier, custom greetings, notes, face embeddings
- Relationship Tiers:
- Stranger: 0 encounters (default), cold greetings
- Regular: 5+ encounters, familiar greetings
- Favorite: 20+ encounters (or 80%+ positive interactions), warm greetings
- Custom Greetings: Tier-specific greeting strings
- Face Embeddings: Optional vector storage for face recognition
- Notes: Free-form observations about the person
2. Encounter Tracking
- Encounter Recording:
- Timestamp, transcript of conversation, detected mood
- Engagement score (0.0–1.0)
- Positive/negative interaction flag
- Automatic Tier Promotion:
- Encounter count-based: 5→regular, 20→favorite
- Quality-based: 80%+ positive interactions required
- Cooldown: 1 hour minimum between promotions
- Statistics Aggregation:
- Total encounter count per person
- Positive interaction ratio
- Relationship score (computed from interactions)
3. ROS2 Service Interfaces
/saltybot/social_memory/lookup
Request:
query_type: "id" | "name" | "recent"
query_value: person_id | name_pattern | days_back
Response:
found: boolean
person_id: int32
name: string
relationship_tier: string
relationship_score: float32 (0.0–1.0)
interaction_count: int32
custom_greetings: string[3] # [stranger, regular, favorite]
notes: string
last_seen: Time
/saltybot/social_memory/update
Request:
person_id: int32
name: string
relationship_tier: string
custom_greetings: string[3]
notes: string
embedding: float32[]
Response:
success: boolean
message: string
updated_person_id: int32
/saltybot/social_memory/encounter
Request:
person_id: int32
transcript: string
mood: string
engagement_score: float32
positive_interaction: boolean
Response:
success: boolean
message: string
encounter_id: int32
tier_changed_to: string (or empty if no change)
/saltybot/social_memory/stats
Request:
(empty)
Response:
total_persons: int32
total_encounters: int32
favorites_count: int32
regulars_count: int32
strangers_count: int32
database_size_mb: float32
last_backup: Time
database_path: string
4. Statistics Publishing
- Topic:
/saltybot/social_memory/stats_update(std_msgs/String, JSON) - Frequency: Configurable (default 60s)
- Content: Database statistics snapshot
5. Backup & Restore
- Automatic Backups: Gzipped snapshots stored in backup directory
- Backup Tracking: Recorded in database with timestamp and size
- Manual Restore: Restore from any backup file
Database Schema
persons Table
| Column | Type | Notes |
|---|---|---|
| person_id | INTEGER PRIMARY KEY | Auto-increment |
| name | TEXT UNIQUE | Person's name |
| embedding | BLOB | JSON-encoded face embedding |
| relationship_tier | TEXT | stranger/regular/favorite |
| relationship_score | REAL | 0.0–1.0 computed from encounters |
| interaction_count | INTEGER | Total encounters |
| positive_interactions | INTEGER | Count of positive encounters |
| greeting_stranger | TEXT | Greeting for strangers |
| greeting_regular | TEXT | Greeting for regular contacts |
| greeting_favorite | TEXT | Greeting for favorites |
| notes | TEXT | Custom observations |
| created_at | TIMESTAMP | When person was first recorded |
| last_seen | TIMESTAMP | Last encounter timestamp |
| last_tier_promotion | TIMESTAMP | Cooldown tracking |
encounters Table
| Column | Type | Notes |
|---|---|---|
| encounter_id | INTEGER PRIMARY KEY | Auto-increment |
| person_id | INTEGER | Foreign key to persons |
| transcript | TEXT | Conversation text/summary |
| detected_mood | TEXT | Emotion detected during encounter |
| engagement_score | REAL | 0.0–1.0 |
| positive_interaction | BOOLEAN | Was interaction positive? |
| encounter_timestamp | TIMESTAMP | When encounter occurred |
backups Table
| Column | Type | Notes |
|---|---|---|
| backup_id | INTEGER PRIMARY KEY | Auto-increment |
| backup_path | TEXT UNIQUE | Full path to backup file |
| backup_timestamp | TIMESTAMP | When backup was created |
| file_size_mb | REAL | Compressed size in MB |
Configuration
Edit config/social_memory.yaml:
database_path: "/home/seb/saltybot-data/social_memory.db"
backup_dir: "/home/seb/saltybot-data/backups"
publish_stats: true
stats_publish_interval: 60.0 # seconds
tier_promotion:
regular_threshold: 5 # Encounters for regular tier
favorite_threshold: 20 # Encounters for favorite tier
positive_ratio_min: 0.8 # 80% positive required
cooldown_hours: 1 # Minimum between promotions
Running
Launch the service node
ros2 launch saltybot_social_memory_node social_memory.launch.py
Direct execution
ros2 run saltybot_social_memory_node social_memory
Usage Examples
Add a new person
ros2 service call /saltybot/social_memory/update saltybot_social_memory/PersonUpdate \
"{name: 'Alice', relationship_tier: 'stranger', \
custom_greetings: ['Hello there!', 'Nice to see you!', 'Great to see you again!']}"
Record an encounter
ros2 service call /saltybot/social_memory/encounter saltybot_social_memory/EncounterRecord \
"{person_id: 1, transcript: 'Alice: Hi! How are you?', \
mood: 'happy', engagement_score: 0.85, positive_interaction: true}"
Lookup a person
ros2 service call /saltybot/social_memory/lookup saltybot_social_memory/PersonLookup \
"{query_type: 'name', query_value: 'Alice'}"
Get database statistics
ros2 service call /saltybot/social_memory/stats saltybot_social_memory/DatabaseStats
Monitor statistics stream
ros2 topic echo /saltybot/social_memory/stats_update
Integration Points
-
Emotion Engine (
saltybot_emotion_engine)- Queries person familiarity for warmth modifier
- Records encounters to build relationship history
-
Person Tracker (
sl-perception)- Provides person_id from face recognition
- Supplies engagement_score and detected_mood
-
Voice Recognition (
sl-jetson)- Provides transcript of conversations
- Records as encounter transcript
-
Greeting System
- Queries custom_greetings based on tier
- Personalizes robot responses
Tier Promotion Logic
When encounter recorded:
1. Increment interaction_count
2. Update positive_interactions if positive_interaction=true
3. Compute positive_ratio = positive_interactions / interaction_count
4. Check promotion eligibility:
- current_tier == "stranger" && interaction_count >= 5 && positive_ratio >= 0.8
→ Promote to "regular"
- current_tier == "regular" && interaction_count >= 20 && positive_ratio >= 0.8
→ Promote to "favorite"
5. If promoted and cooldown_hours passed since last promotion:
- Update relationship_tier
- Set last_tier_promotion = now()
- Return tier_changed_to in response
Backup Strategy
- Manual backups via
backup_database()method - Automatic tracking in backups table with timestamp
- Restore from any backup:
restore_database(backup_path) - Format: gzip-compressed SQLite database (.db.gz)
Thread Safety
- All database operations protected by
threading.Lock() - Safe for concurrent ROS2 service calls
- Sequential writes to ensure data integrity
Performance Characteristics
- Lookup: O(1) indexed by person_id, O(n) by name pattern
- Encounter recording: O(1) insertion + O(1) stats update
- Database size: ~1KB per person + ~0.5KB per encounter
Future Enhancements
- Persistent memory integration with LLM (e.g., "Alice loves plants")
- Group relationships (track person groups/families)
- Preference learning (dietary restrictions, favorite topics)
- Sentiment analysis over time
- Web UI for person management
- Integration with voice recognition confidence
- Automated cleanup of old encounters (>1 year)
- Graph-based relationship networks