Spaces:
Sleeping
Sleeping
File size: 5,789 Bytes
91fe002 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
"""
Conversation Service for Multi-turn Chat
Server-side session management
"""
from typing import List, Dict, Optional
from datetime import datetime
from pymongo.collection import Collection
import uuid
class ConversationService:
"""
Manages multi-turn conversation history với server-side session
"""
def __init__(self, mongo_collection: Collection, max_history: int = 10):
"""
Args:
mongo_collection: MongoDB collection for storing conversations
max_history: Maximum số messages giữ lại (sliding window)
"""
self.collection = mongo_collection
self.max_history = max_history
# Create indexes
self._ensure_indexes()
def _ensure_indexes(self):
"""Create necessary indexes"""
try:
self.collection.create_index("session_id", unique=True)
# Auto-delete sessions sau 7 ngày không dùng
self.collection.create_index(
"updated_at",
expireAfterSeconds=604800 # 7 days
)
print("✓ Conversation indexes created")
except Exception as e:
print(f"Conversation indexes already exist or error: {e}")
def create_session(self, metadata: Optional[Dict] = None) -> str:
"""
Create new conversation session
Returns:
session_id (UUID string)
"""
session_id = str(uuid.uuid4())
self.collection.insert_one({
"session_id": session_id,
"messages": [],
"metadata": metadata or {},
"created_at": datetime.utcnow(),
"updated_at": datetime.utcnow()
})
return session_id
def add_message(
self,
session_id: str,
role: str,
content: str,
metadata: Optional[Dict] = None
):
"""
Add message to conversation history
Args:
session_id: Session identifier
role: "user" or "assistant"
content: Message text
metadata: Additional info (rag_stats, tool_calls, etc.)
"""
message = {
"role": role,
"content": content,
"timestamp": datetime.utcnow().isoformat(),
"metadata": metadata or {}
}
# Upsert: tạo session nếu chưa tồn tại
self.collection.update_one(
{"session_id": session_id},
{
"$push": {
"messages": {
"$each": [message],
"$slice": -self.max_history # Keep only last N messages
}
},
"$set": {"updated_at": datetime.utcnow()}
},
upsert=True
)
def get_conversation_history(
self,
session_id: str,
limit: Optional[int] = None,
include_metadata: bool = False
) -> List[Dict]:
"""
Get conversation messages for LLM context
Args:
session_id: Session identifier
limit: Override max_history với số lượng tùy chỉnh
include_metadata: Include metadata trong response
Returns:
List of messages in format: [{"role": "user", "content": "..."}, ...]
"""
session = self.collection.find_one({"session_id": session_id})
if not session:
return []
messages = session.get("messages", [])
# Limit to recent messages
if limit:
messages = messages[-limit:]
else:
messages = messages[-self.max_history:]
# Format for LLM
if include_metadata:
return messages
else:
return [
{
"role": msg["role"],
"content": msg["content"]
}
for msg in messages
]
def get_session_info(self, session_id: str) -> Optional[Dict]:
"""
Get session metadata
Returns:
Session info hoặc None nếu không tồn tại
"""
session = self.collection.find_one(
{"session_id": session_id},
{"_id": 0, "session_id": 1, "created_at": 1, "updated_at": 1, "metadata": 1}
)
return session
def clear_session(self, session_id: str) -> bool:
"""
Clear conversation history for session
Returns:
True nếu xóa thành công, False nếu session không tồn tại
"""
result = self.collection.delete_one({"session_id": session_id})
return result.deleted_count > 0
def session_exists(self, session_id: str) -> bool:
"""
Check if session exists
"""
return self.collection.count_documents({"session_id": session_id}) > 0
def get_last_user_message(self, session_id: str) -> Optional[str]:
"""
Get the last user message in conversation
Useful for context extraction
"""
session = self.collection.find_one({"session_id": session_id})
if not session:
return None
messages = session.get("messages", [])
# Tìm message cuối cùng từ user
for msg in reversed(messages):
if msg["role"] == "user":
return msg["content"]
return None
|