Spaces:
Sleeping
Sleeping
Add data clearing service and vector store management
Browse files- Introduced `DataClearingService` for managing the clearing of vector store and chat history data.
- Implemented `clear_all_documents` method in `VectorStoreManager` to remove all documents from the vector store.
- Enhanced UI with a button to clear all data, integrating the new service for user interaction.
- Updated logging to provide detailed feedback during data clearing operations.
- src/rag/vector_store.py +31 -0
- src/services/data_clearing_service.py +263 -0
- src/ui/ui.py +70 -6
src/rag/vector_store.py
CHANGED
@@ -225,6 +225,37 @@ class VectorStoreManager:
|
|
225 |
except Exception as e:
|
226 |
logger.error(f"Error searching with metadata filter: {e}")
|
227 |
return []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
228 |
|
229 |
# Global vector store manager instance
|
230 |
vector_store_manager = VectorStoreManager()
|
|
|
225 |
except Exception as e:
|
226 |
logger.error(f"Error searching with metadata filter: {e}")
|
227 |
return []
|
228 |
+
|
229 |
+
def clear_all_documents(self) -> bool:
|
230 |
+
"""
|
231 |
+
Clear all documents from the vector store collection.
|
232 |
+
|
233 |
+
Returns:
|
234 |
+
True if successful, False otherwise
|
235 |
+
"""
|
236 |
+
try:
|
237 |
+
vector_store = self.get_vector_store()
|
238 |
+
|
239 |
+
# Get all document IDs first
|
240 |
+
collection = vector_store._collection
|
241 |
+
all_docs = collection.get()
|
242 |
+
|
243 |
+
if not all_docs or not all_docs.get('ids'):
|
244 |
+
logger.info("No documents found in vector store to clear")
|
245 |
+
return True
|
246 |
+
|
247 |
+
# Delete all documents using their IDs
|
248 |
+
collection.delete(ids=all_docs['ids'])
|
249 |
+
|
250 |
+
# Reset the vector store instance to ensure clean state
|
251 |
+
self._vector_store = None
|
252 |
+
|
253 |
+
logger.info(f"Successfully cleared {len(all_docs['ids'])} documents from vector store")
|
254 |
+
return True
|
255 |
+
|
256 |
+
except Exception as e:
|
257 |
+
logger.error(f"Error clearing all documents: {e}")
|
258 |
+
return False
|
259 |
|
260 |
# Global vector store manager instance
|
261 |
vector_store_manager = VectorStoreManager()
|
src/services/data_clearing_service.py
ADDED
@@ -0,0 +1,263 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Data clearing service for both local and Hugging Face Space environments.
|
3 |
+
Provides functionality to clear vector store and chat history data.
|
4 |
+
"""
|
5 |
+
|
6 |
+
import os
|
7 |
+
import shutil
|
8 |
+
from pathlib import Path
|
9 |
+
from typing import Dict, Any, Tuple, List
|
10 |
+
from src.core.config import config
|
11 |
+
from src.core.logging_config import get_logger
|
12 |
+
from src.rag.vector_store import vector_store_manager
|
13 |
+
|
14 |
+
logger = get_logger(__name__)
|
15 |
+
|
16 |
+
|
17 |
+
class DataClearingService:
|
18 |
+
"""Service for clearing all RAG-related data across different environments."""
|
19 |
+
|
20 |
+
def __init__(self):
|
21 |
+
"""Initialize the data clearing service."""
|
22 |
+
self.is_hf_space = bool(os.getenv("SPACE_ID"))
|
23 |
+
logger.info(f"DataClearingService initialized (HF Space: {self.is_hf_space})")
|
24 |
+
|
25 |
+
def get_data_paths(self) -> Tuple[str, str]:
|
26 |
+
"""
|
27 |
+
Get the correct data paths for current environment.
|
28 |
+
|
29 |
+
Returns:
|
30 |
+
Tuple of (vector_store_path, chat_history_path)
|
31 |
+
"""
|
32 |
+
vector_store_path = config.rag.vector_store_path
|
33 |
+
chat_history_path = config.rag.chat_history_path
|
34 |
+
|
35 |
+
logger.info(f"Data paths - Vector store: {vector_store_path}, Chat history: {chat_history_path}")
|
36 |
+
return vector_store_path, chat_history_path
|
37 |
+
|
38 |
+
def clear_vector_store(self) -> Tuple[bool, str, Dict[str, Any]]:
|
39 |
+
"""
|
40 |
+
Clear all documents from the vector store.
|
41 |
+
|
42 |
+
Returns:
|
43 |
+
Tuple of (success, message, stats)
|
44 |
+
"""
|
45 |
+
try:
|
46 |
+
# Get initial document count
|
47 |
+
collection_info = vector_store_manager.get_collection_info()
|
48 |
+
initial_count = collection_info.get("document_count", 0)
|
49 |
+
|
50 |
+
if initial_count == 0:
|
51 |
+
return True, "Vector store is already empty", {"cleared_documents": 0}
|
52 |
+
|
53 |
+
# Clear the collection using the vector store manager's method
|
54 |
+
success = vector_store_manager.clear_all_documents()
|
55 |
+
|
56 |
+
if not success:
|
57 |
+
return False, "Failed to clear vector store", {"error": "clear_all_documents returned False"}
|
58 |
+
|
59 |
+
logger.info(f"Cleared {initial_count} documents from vector store")
|
60 |
+
|
61 |
+
return True, f"Successfully cleared {initial_count} documents from vector store", {
|
62 |
+
"cleared_documents": initial_count,
|
63 |
+
"collection_name": collection_info.get("collection_name", "unknown")
|
64 |
+
}
|
65 |
+
|
66 |
+
except Exception as e:
|
67 |
+
error_msg = f"Error clearing vector store: {str(e)}"
|
68 |
+
logger.error(error_msg)
|
69 |
+
return False, error_msg, {"error": str(e)}
|
70 |
+
|
71 |
+
def clear_chat_history(self) -> Tuple[bool, str, Dict[str, Any]]:
|
72 |
+
"""
|
73 |
+
Clear all chat history files.
|
74 |
+
|
75 |
+
Returns:
|
76 |
+
Tuple of (success, message, stats)
|
77 |
+
"""
|
78 |
+
try:
|
79 |
+
_, chat_history_path = self.get_data_paths()
|
80 |
+
chat_dir = Path(chat_history_path)
|
81 |
+
|
82 |
+
if not chat_dir.exists():
|
83 |
+
return True, "Chat history directory doesn't exist", {"cleared_files": 0}
|
84 |
+
|
85 |
+
# Count files before deletion
|
86 |
+
files_to_clear = list(chat_dir.rglob("*"))
|
87 |
+
file_count = len([f for f in files_to_clear if f.is_file()])
|
88 |
+
|
89 |
+
if file_count == 0:
|
90 |
+
return True, "Chat history is already empty", {"cleared_files": 0}
|
91 |
+
|
92 |
+
# Clear all contents of the chat history directory
|
93 |
+
for item in chat_dir.iterdir():
|
94 |
+
if item.is_file():
|
95 |
+
item.unlink()
|
96 |
+
logger.debug(f"Removed file: {item}")
|
97 |
+
elif item.is_dir():
|
98 |
+
shutil.rmtree(item)
|
99 |
+
logger.debug(f"Removed directory: {item}")
|
100 |
+
|
101 |
+
logger.info(f"Cleared {file_count} files from chat history")
|
102 |
+
|
103 |
+
return True, f"Successfully cleared {file_count} files from chat history", {
|
104 |
+
"cleared_files": file_count,
|
105 |
+
"chat_history_path": str(chat_dir)
|
106 |
+
}
|
107 |
+
|
108 |
+
except Exception as e:
|
109 |
+
error_msg = f"Error clearing chat history: {str(e)}"
|
110 |
+
logger.error(error_msg)
|
111 |
+
return False, error_msg, {"error": str(e)}
|
112 |
+
|
113 |
+
def clear_directory_contents(self, directory_path: str) -> Tuple[bool, str, int]:
|
114 |
+
"""
|
115 |
+
Clear all contents of a specific directory.
|
116 |
+
|
117 |
+
Args:
|
118 |
+
directory_path: Path to directory to clear
|
119 |
+
|
120 |
+
Returns:
|
121 |
+
Tuple of (success, message, items_cleared)
|
122 |
+
"""
|
123 |
+
try:
|
124 |
+
dir_path = Path(directory_path)
|
125 |
+
|
126 |
+
if not dir_path.exists():
|
127 |
+
return True, f"Directory doesn't exist: {directory_path}", 0
|
128 |
+
|
129 |
+
items_cleared = 0
|
130 |
+
for item in dir_path.iterdir():
|
131 |
+
try:
|
132 |
+
if item.is_file():
|
133 |
+
item.unlink()
|
134 |
+
items_cleared += 1
|
135 |
+
logger.debug(f"Removed file: {item}")
|
136 |
+
elif item.is_dir():
|
137 |
+
shutil.rmtree(item)
|
138 |
+
items_cleared += 1
|
139 |
+
logger.debug(f"Removed directory: {item}")
|
140 |
+
except Exception as e:
|
141 |
+
logger.warning(f"Failed to remove {item}: {e}")
|
142 |
+
|
143 |
+
return True, f"Cleared {items_cleared} items from {directory_path}", items_cleared
|
144 |
+
|
145 |
+
except Exception as e:
|
146 |
+
error_msg = f"Error clearing directory {directory_path}: {str(e)}"
|
147 |
+
logger.error(error_msg)
|
148 |
+
return False, error_msg, 0
|
149 |
+
|
150 |
+
def clear_all_data(self) -> Tuple[bool, str, Dict[str, Any]]:
|
151 |
+
"""
|
152 |
+
Clear all RAG-related data (vector store + chat history).
|
153 |
+
|
154 |
+
Returns:
|
155 |
+
Tuple of (success, message, combined_stats)
|
156 |
+
"""
|
157 |
+
logger.info("Starting complete data clearing operation")
|
158 |
+
|
159 |
+
combined_stats = {
|
160 |
+
"vector_store": {},
|
161 |
+
"chat_history": {},
|
162 |
+
"total_cleared_documents": 0,
|
163 |
+
"total_cleared_files": 0,
|
164 |
+
"environment": "hf_space" if self.is_hf_space else "local",
|
165 |
+
"errors": []
|
166 |
+
}
|
167 |
+
|
168 |
+
# Clear vector store
|
169 |
+
vs_success, vs_message, vs_stats = self.clear_vector_store()
|
170 |
+
combined_stats["vector_store"] = {
|
171 |
+
"success": vs_success,
|
172 |
+
"message": vs_message,
|
173 |
+
**vs_stats
|
174 |
+
}
|
175 |
+
|
176 |
+
if not vs_success:
|
177 |
+
combined_stats["errors"].append(f"Vector store: {vs_message}")
|
178 |
+
else:
|
179 |
+
combined_stats["total_cleared_documents"] = vs_stats.get("cleared_documents", 0)
|
180 |
+
|
181 |
+
# Clear chat history
|
182 |
+
ch_success, ch_message, ch_stats = self.clear_chat_history()
|
183 |
+
combined_stats["chat_history"] = {
|
184 |
+
"success": ch_success,
|
185 |
+
"message": ch_message,
|
186 |
+
**ch_stats
|
187 |
+
}
|
188 |
+
|
189 |
+
if not ch_success:
|
190 |
+
combined_stats["errors"].append(f"Chat history: {ch_message}")
|
191 |
+
else:
|
192 |
+
combined_stats["total_cleared_files"] = ch_stats.get("cleared_files", 0)
|
193 |
+
|
194 |
+
# Overall success
|
195 |
+
overall_success = vs_success and ch_success
|
196 |
+
|
197 |
+
if overall_success:
|
198 |
+
total_items = combined_stats["total_cleared_documents"] + combined_stats["total_cleared_files"]
|
199 |
+
if total_items == 0:
|
200 |
+
overall_message = "All data was already clear"
|
201 |
+
else:
|
202 |
+
overall_message = f"Successfully cleared all data: {combined_stats['total_cleared_documents']} documents, {combined_stats['total_cleared_files']} files"
|
203 |
+
else:
|
204 |
+
overall_message = f"Data clearing completed with errors: {'; '.join(combined_stats['errors'])}"
|
205 |
+
|
206 |
+
logger.info(f"Data clearing operation completed: {overall_message}")
|
207 |
+
|
208 |
+
return overall_success, overall_message, combined_stats
|
209 |
+
|
210 |
+
def get_data_status(self) -> Dict[str, Any]:
|
211 |
+
"""
|
212 |
+
Get current status of data directories and vector store.
|
213 |
+
|
214 |
+
Returns:
|
215 |
+
Dictionary with data status information
|
216 |
+
"""
|
217 |
+
try:
|
218 |
+
vector_store_path, chat_history_path = self.get_data_paths()
|
219 |
+
|
220 |
+
# Vector store status
|
221 |
+
collection_info = vector_store_manager.get_collection_info()
|
222 |
+
vs_document_count = collection_info.get("document_count", 0)
|
223 |
+
|
224 |
+
# Chat history status
|
225 |
+
chat_dir = Path(chat_history_path)
|
226 |
+
ch_file_count = 0
|
227 |
+
if chat_dir.exists():
|
228 |
+
ch_file_count = len([f for f in chat_dir.rglob("*") if f.is_file()])
|
229 |
+
|
230 |
+
# Directory status
|
231 |
+
vs_dir = Path(vector_store_path)
|
232 |
+
vs_exists = vs_dir.exists()
|
233 |
+
ch_exists = chat_dir.exists()
|
234 |
+
|
235 |
+
status = {
|
236 |
+
"environment": "hf_space" if self.is_hf_space else "local",
|
237 |
+
"vector_store": {
|
238 |
+
"path": vector_store_path,
|
239 |
+
"exists": vs_exists,
|
240 |
+
"document_count": vs_document_count,
|
241 |
+
"collection_name": collection_info.get("collection_name", "unknown")
|
242 |
+
},
|
243 |
+
"chat_history": {
|
244 |
+
"path": chat_history_path,
|
245 |
+
"exists": ch_exists,
|
246 |
+
"file_count": ch_file_count
|
247 |
+
},
|
248 |
+
"total_data_items": vs_document_count + ch_file_count,
|
249 |
+
"has_data": vs_document_count > 0 or ch_file_count > 0
|
250 |
+
}
|
251 |
+
|
252 |
+
return status
|
253 |
+
|
254 |
+
except Exception as e:
|
255 |
+
logger.error(f"Error getting data status: {e}")
|
256 |
+
return {
|
257 |
+
"error": str(e),
|
258 |
+
"environment": "hf_space" if self.is_hf_space else "local"
|
259 |
+
}
|
260 |
+
|
261 |
+
|
262 |
+
# Global data clearing service instance
|
263 |
+
data_clearing_service = DataClearingService()
|
src/ui/ui.py
CHANGED
@@ -15,6 +15,7 @@ from src.core.exceptions import (
|
|
15 |
)
|
16 |
from src.core.logging_config import get_logger
|
17 |
from src.rag import rag_chat_service, document_ingestion_service
|
|
|
18 |
|
19 |
# Use centralized logging
|
20 |
logger = get_logger(__name__)
|
@@ -252,6 +253,48 @@ def start_new_chat_session():
|
|
252 |
logger.error(error_msg)
|
253 |
return [], f"β {error_msg}"
|
254 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
255 |
def get_chat_status():
|
256 |
"""Get current chat system status."""
|
257 |
try:
|
@@ -261,6 +304,9 @@ def get_chat_status():
|
|
261 |
# Check usage stats
|
262 |
usage_stats = rag_chat_service.get_usage_stats()
|
263 |
|
|
|
|
|
|
|
264 |
# Modern status card design with better styling
|
265 |
status_html = f"""
|
266 |
<div class="status-card">
|
@@ -273,20 +319,20 @@ def get_chat_status():
|
|
273 |
|
274 |
<div class="status-grid">
|
275 |
<div class="status-item">
|
276 |
-
<div class="status-label">
|
277 |
-
<div class="status-value">{
|
278 |
</div>
|
279 |
<div class="status-item">
|
280 |
-
<div class="status-label">
|
281 |
-
<div class="status-value">{
|
282 |
</div>
|
283 |
<div class="status-item">
|
284 |
<div class="status-label">Session Usage</div>
|
285 |
<div class="status-value">{usage_stats.get('session_messages', 0)}/{usage_stats.get('session_limit', 50)}</div>
|
286 |
</div>
|
287 |
<div class="status-item">
|
288 |
-
<div class="status-label">
|
289 |
-
<div class="status-value">{
|
290 |
</div>
|
291 |
</div>
|
292 |
|
@@ -556,6 +602,16 @@ def create_ui():
|
|
556 |
transform: translateY(-1px);
|
557 |
}
|
558 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
559 |
/* Chat interface styling */
|
560 |
.chat-main-container {
|
561 |
background: #ffffff;
|
@@ -819,6 +875,7 @@ def create_ui():
|
|
819 |
with gr.Row(elem_classes=["control-buttons"]):
|
820 |
refresh_status_btn = gr.Button("π Refresh Status", elem_classes=["control-btn", "btn-refresh"])
|
821 |
new_session_btn = gr.Button("π New Session", elem_classes=["control-btn", "btn-new-session"])
|
|
|
822 |
|
823 |
# Main chat interface
|
824 |
with gr.Column(elem_classes=["chat-main-container"]):
|
@@ -885,6 +942,13 @@ def create_ui():
|
|
885 |
inputs=[],
|
886 |
outputs=[status_display]
|
887 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
888 |
|
889 |
return demo
|
890 |
|
|
|
15 |
)
|
16 |
from src.core.logging_config import get_logger
|
17 |
from src.rag import rag_chat_service, document_ingestion_service
|
18 |
+
from src.services.data_clearing_service import data_clearing_service
|
19 |
|
20 |
# Use centralized logging
|
21 |
logger = get_logger(__name__)
|
|
|
253 |
logger.error(error_msg)
|
254 |
return [], f"β {error_msg}"
|
255 |
|
256 |
+
def handle_clear_all_data():
|
257 |
+
"""Handle clearing all RAG data (vector store + chat history)."""
|
258 |
+
try:
|
259 |
+
# Clear all data using the data clearing service
|
260 |
+
success, message, stats = data_clearing_service.clear_all_data()
|
261 |
+
|
262 |
+
if success:
|
263 |
+
# Reset chat session after clearing data
|
264 |
+
session_id = rag_chat_service.start_new_session()
|
265 |
+
|
266 |
+
# Get updated status
|
267 |
+
updated_status = get_chat_status()
|
268 |
+
|
269 |
+
# Create success message with stats
|
270 |
+
if stats.get("total_cleared_documents", 0) > 0 or stats.get("total_cleared_files", 0) > 0:
|
271 |
+
clear_msg = f"β
{message}"
|
272 |
+
session_msg = f"π Started new session: {session_id}"
|
273 |
+
combined_msg = f'{clear_msg}<br/><div class="session-info">{session_msg}</div>'
|
274 |
+
else:
|
275 |
+
combined_msg = f'βΉοΈ {message}<br/><div class="session-info">π Started new session: {session_id}</div>'
|
276 |
+
|
277 |
+
logger.info(f"Data cleared successfully: {message}")
|
278 |
+
|
279 |
+
return [], combined_msg, updated_status
|
280 |
+
else:
|
281 |
+
error_msg = f"β {message}"
|
282 |
+
logger.error(f"Data clearing failed: {message}")
|
283 |
+
|
284 |
+
# Still get updated status even on error
|
285 |
+
updated_status = get_chat_status()
|
286 |
+
|
287 |
+
return None, f'<div class="session-info">{error_msg}</div>', updated_status
|
288 |
+
|
289 |
+
except Exception as e:
|
290 |
+
error_msg = f"Error clearing data: {str(e)}"
|
291 |
+
logger.error(error_msg)
|
292 |
+
|
293 |
+
# Get current status
|
294 |
+
current_status = get_chat_status()
|
295 |
+
|
296 |
+
return None, f'<div class="session-info">β {error_msg}</div>', current_status
|
297 |
+
|
298 |
def get_chat_status():
|
299 |
"""Get current chat system status."""
|
300 |
try:
|
|
|
304 |
# Check usage stats
|
305 |
usage_stats = rag_chat_service.get_usage_stats()
|
306 |
|
307 |
+
# Get data status for additional context
|
308 |
+
data_status = data_clearing_service.get_data_status()
|
309 |
+
|
310 |
# Modern status card design with better styling
|
311 |
status_html = f"""
|
312 |
<div class="status-card">
|
|
|
319 |
|
320 |
<div class="status-grid">
|
321 |
<div class="status-item">
|
322 |
+
<div class="status-label">Vector Store Docs</div>
|
323 |
+
<div class="status-value">{data_status.get('vector_store', {}).get('document_count', 0)}</div>
|
324 |
</div>
|
325 |
<div class="status-item">
|
326 |
+
<div class="status-label">Chat History Files</div>
|
327 |
+
<div class="status-value">{data_status.get('chat_history', {}).get('file_count', 0)}</div>
|
328 |
</div>
|
329 |
<div class="status-item">
|
330 |
<div class="status-label">Session Usage</div>
|
331 |
<div class="status-value">{usage_stats.get('session_messages', 0)}/{usage_stats.get('session_limit', 50)}</div>
|
332 |
</div>
|
333 |
<div class="status-item">
|
334 |
+
<div class="status-label">Environment</div>
|
335 |
+
<div class="status-value">{'HF Space' if data_status.get('environment') == 'hf_space' else 'Local'}</div>
|
336 |
</div>
|
337 |
</div>
|
338 |
|
|
|
602 |
transform: translateY(-1px);
|
603 |
}
|
604 |
|
605 |
+
.btn-clear-data {
|
606 |
+
background: #dc3545;
|
607 |
+
color: white;
|
608 |
+
}
|
609 |
+
|
610 |
+
.btn-clear-data:hover {
|
611 |
+
background: #c82333;
|
612 |
+
transform: translateY(-1px);
|
613 |
+
}
|
614 |
+
|
615 |
/* Chat interface styling */
|
616 |
.chat-main-container {
|
617 |
background: #ffffff;
|
|
|
875 |
with gr.Row(elem_classes=["control-buttons"]):
|
876 |
refresh_status_btn = gr.Button("π Refresh Status", elem_classes=["control-btn", "btn-refresh"])
|
877 |
new_session_btn = gr.Button("π New Session", elem_classes=["control-btn", "btn-new-session"])
|
878 |
+
clear_data_btn = gr.Button("ποΈ Clear All Data", elem_classes=["control-btn", "btn-clear-data"], variant="stop")
|
879 |
|
880 |
# Main chat interface
|
881 |
with gr.Column(elem_classes=["chat-main-container"]):
|
|
|
942 |
inputs=[],
|
943 |
outputs=[status_display]
|
944 |
)
|
945 |
+
|
946 |
+
# Clear all data handler
|
947 |
+
clear_data_btn.click(
|
948 |
+
fn=handle_clear_all_data,
|
949 |
+
inputs=[],
|
950 |
+
outputs=[chatbot, session_info, status_display]
|
951 |
+
)
|
952 |
|
953 |
return demo
|
954 |
|