Files
miku-discord/readmes/CONVERSATION_HISTORY_V2.md

274 lines
8.7 KiB
Markdown

# Conversation History System V2
## Overview
The new conversation history system provides centralized, intelligent management of conversation context across all bot interactions.
## Key Improvements
### 1. **Per-Channel History** (Was: Per-User Globally)
- **Servers**: History tracked per `guild_id` - all users in a server share conversation context
- **DMs**: History tracked per `user_id` - each DM has its own conversation thread
- **Benefit**: Miku can follow multi-user conversations in servers and remember context across users
### 2. **Rich Message Metadata**
Each message stores:
- `author_name`: Display name of the speaker
- `content`: Message text
- `timestamp`: When the message was sent
- `is_bot`: Whether it's from Miku or a user
### 3. **Intelligent Formatting**
The system formats messages differently based on context:
- **Multi-user servers**: `"Alice: Hello!"` format to distinguish speakers
- **DMs**: Simple content without author prefix
- **LLM output**: OpenAI-compatible `{"role": "user"|"assistant", "content": "..."}` format
### 4. **Automatic Filtering**
- Empty messages automatically skipped
- Messages truncated to 500 characters to prevent context overflow
- Vision analysis context preserved inline
### 5. **Backward Compatibility**
- Still writes to `globals.conversation_history` for legacy code
- Uses same `user_id` parameter in `query_llama()`
- Autonomous functions work without modification
## Architecture
### Core Class: `ConversationHistory`
Located in: `bot/utils/conversation_history.py`
```python
from utils.conversation_history import conversation_history
# Add a message
conversation_history.add_message(
channel_id="123456789", # guild_id or user_id
author_name="Alice", # Display name
content="Hello Miku!", # Message text
is_bot=False # True if from Miku
)
# Get recent messages
messages = conversation_history.get_recent_messages("123456789", max_messages=8)
# Returns: [(author, content, is_bot), ...]
# Format for LLM
llm_messages = conversation_history.format_for_llm("123456789", max_messages=8)
# Returns: [{"role": "user", "content": "Alice: Hello!"}, ...]
# Get statistics
stats = conversation_history.get_channel_stats("123456789")
# Returns: {"total_messages": 10, "bot_messages": 5, "user_messages": 5}
```
## Usage in `query_llama()`
### Updated Signature
```python
async def query_llama(
user_prompt,
user_id, # For DMs: actual user ID; For servers: can be anything
guild_id=None, # Server ID (None for DMs)
response_type="dm_response",
model=None,
author_name=None # NEW: Display name for multi-user context
):
```
### Channel ID Logic
```python
channel_id = str(guild_id) if guild_id else str(user_id)
```
- **Server messages**: `channel_id = guild_id` → All server users share history
- **DM messages**: `channel_id = user_id` → Each DM has separate history
### Example Calls
**Server message:**
```python
response = await query_llama(
prompt="What's the weather?",
user_id=str(message.author.id),
guild_id=message.guild.id, # Server context
response_type="server_response",
author_name=message.author.display_name # "Alice"
)
# History saved to channel_id=guild_id
```
**DM message:**
```python
response = await query_llama(
prompt="Tell me a joke",
user_id=str(message.author.id),
guild_id=None, # No server
response_type="dm_response",
author_name=message.author.display_name
)
# History saved to channel_id=user_id
```
**Autonomous message:**
```python
message = await query_llama(
prompt="Say something fun!",
user_id=f"miku-autonomous-{guild_id}", # Consistent ID
guild_id=guild_id, # Server context
response_type="autonomous_general"
)
# History saved to channel_id=guild_id
```
## Image/Video Analysis
### Updated `rephrase_as_miku()`
```python
async def rephrase_as_miku(
vision_output,
user_prompt,
guild_id=None,
user_id=None, # NEW: Actual user ID
author_name=None # NEW: Display name
):
```
### How It Works
1. **Vision analysis injected into history**:
```python
conversation_history.add_message(
channel_id=channel_id,
author_name="Vision System",
content=f"[Image/Video Analysis: {vision_output}]",
is_bot=False
)
```
2. **Follow-up questions remember the image**:
- User sends image → Vision analysis added to history
- User asks "What color is the car?" → Miku sees the vision analysis in history
- User asks "Who made this meme?" → Still has vision context
### Example Flow
```
[USER] Bob: *sends meme.gif*
[Vision System]: [Image/Video Analysis: A cat wearing sunglasses with text "deal with it"]
[BOT] Miku: Haha, that's a classic meme! The cat looks so cool! 😎
[USER] Bob: Who made this meme?
[BOT] Miku: The "Deal With It" meme originated from...
```
## Migration from Old System
### What Changed
| **Old System** | **New System** |
|----------------|----------------|
| `globals.conversation_history[user_id]` | `conversation_history.add_message(channel_id, ...)` |
| Per-user globally | Per-server or per-DM |
| `[(user_msg, bot_msg), ...]` tuples | Rich metadata with author, timestamp, role |
| Manual filtering in `llm.py` | Automatic filtering in `ConversationHistory` |
| Image analysis used `user_id="image_analysis"` | Uses actual user's channel_id |
| Reply feature added `("", message)` tuples | No manual reply handling needed |
### Backward Compatibility
The new system still writes to `globals.conversation_history` for any code that might depend on it:
```python
# In llm.py after getting LLM response
globals.conversation_history[user_id].append((user_prompt, reply))
```
This ensures existing code doesn't break during migration.
## Testing
Run the test suite:
```bash
cd /home/koko210Serve/docker/ollama-discord/bot
python test_conversation_history.py
```
Tests cover:
- ✅ Adding messages to server channels
- ✅ Adding messages to DM channels
- ✅ Formatting for LLM (OpenAI messages)
- ✅ Empty message filtering
- ✅ Message truncation (500 char limit)
- ✅ Channel statistics
## Benefits
### 1. **Context Preservation**
- Multi-user conversations tracked properly
- Image/video descriptions persist across follow-up questions
- No more lost context when using Discord reply feature
### 2. **Token Efficiency**
- Automatic truncation prevents context overflow
- Empty messages filtered out
- Configurable message limits (default: 8 messages)
### 3. **Better Multi-User Support**
- Server conversations include author names: `"Alice: Hello!"`
- Miku understands who said what
- Enables natural group chat dynamics
### 4. **Debugging & Analytics**
- Rich metadata for each message
- Channel statistics (total, bot, user message counts)
- Timestamp tracking for future features
### 5. **Maintainability**
- Single source of truth for conversation history
- Clean API: `add_message()`, `get_recent_messages()`, `format_for_llm()`
- Centralized filtering and formatting logic
## Future Enhancements
Possible improvements:
- [ ] Persistent storage (save history to disk/database)
- [ ] Conversation summarization for very long threads
- [ ] Per-user preferences (some users want more/less context)
- [ ] Automatic context pruning based on relevance
- [ ] Export conversation history for analysis
- [ ] Integration with dm_interaction_analyzer
## Code Locations
| **File** | **Changes** |
|----------|-------------|
| `bot/utils/conversation_history.py` | **NEW** - Core history management class |
| `bot/utils/llm.py` | Updated to use new system, added `author_name` parameter |
| `bot/bot.py` | Pass `author_name` to `query_llama()`, removed reply pollution |
| `bot/utils/image_handling.py` | `rephrase_as_miku()` accepts `user_id` and `author_name` |
| `bot/utils/autonomous_v1_legacy.py` | No changes needed (already guild-based) |
| `bot/test_conversation_history.py` | **NEW** - Test suite |
## Summary
The new conversation history system provides:
-**Per-channel tracking** (server-wide or DM-specific)
-**Rich metadata** (author, timestamp, role)
-**Intelligent formatting** (with author names in servers)
-**Automatic filtering** (empty messages, truncation)
-**Image/video context** (vision analysis persists)
-**Backward compatibility** (legacy code still works)
-**Clean API** (simple, testable functions)
This solves the original problems:
1.~~Video descriptions lost~~ → ✅ Now preserved in channel history
2.~~Reply feature polluted history~~ → ✅ No manual reply handling
3.~~Image analysis separate user_id~~ → ✅ Uses actual channel_id
4.~~Autonomous actions broke history~~ → ✅ Guild-based IDs work naturally