Spaces:
Sleeping
Sleeping
Implement Admin db clean up
Browse files- app/admin/admin_functions.py +35 -0
- app/admin/templates/data_management.html +66 -0
- app/admin/templates/user_registration.html +4 -0
- app/main.py +25 -3
- app/utils/chat_rag.py +1 -1
- requirements.txt +1 -1
app/admin/admin_functions.py
CHANGED
@@ -3,6 +3,14 @@ from typing import Optional
|
|
3 |
import bcrypt
|
4 |
import os
|
5 |
import shutil
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
from ..utils import get_user_cropped_image_from_photo
|
7 |
|
8 |
|
@@ -68,6 +76,7 @@ def verify_admin_password(submitted_user: str, submitted_password: str) -> bool:
|
|
68 |
|
69 |
return False
|
70 |
|
|
|
71 |
def get_disk_usage(path="/home/user/data"):
|
72 |
total, used, free = shutil.disk_usage(path)
|
73 |
# Convert bytes to MB by dividing by 2^20
|
@@ -83,3 +92,29 @@ def get_disk_usage(path="/home/user/data"):
|
|
83 |
# - Moderating chat messages or viewing chat history.
|
84 |
# - Managing system settings or configurations.
|
85 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
import bcrypt
|
4 |
import os
|
5 |
import shutil
|
6 |
+
|
7 |
+
# Import vector store for database operations
|
8 |
+
from langchain.vectorstores import Chroma
|
9 |
+
# Import embeddings module from langchain for vector representations of text
|
10 |
+
from langchain.embeddings import HuggingFaceEmbeddings
|
11 |
+
from app.main import CHROMADB_LOC
|
12 |
+
|
13 |
+
from app.utils.chat_rag import sanitize_collection_name
|
14 |
from ..utils import get_user_cropped_image_from_photo
|
15 |
|
16 |
|
|
|
76 |
|
77 |
return False
|
78 |
|
79 |
+
# Get disk usage
|
80 |
def get_disk_usage(path="/home/user/data"):
|
81 |
total, used, free = shutil.disk_usage(path)
|
82 |
# Convert bytes to MB by dividing by 2^20
|
|
|
92 |
# - Moderating chat messages or viewing chat history.
|
93 |
# - Managing system settings or configurations.
|
94 |
|
95 |
+
# Display all faces in collection
|
96 |
+
def faces_count(client, db):
|
97 |
+
return {
|
98 |
+
"face_count" : db.count(),
|
99 |
+
"all_faces" : db.get(),
|
100 |
+
"all_collections" : client.list_collections() # List all collections at this location
|
101 |
+
}
|
102 |
+
|
103 |
+
# Delete all faces in collection
|
104 |
+
def remove_all_faces(client, user_faces_collection="user_faces_db"):
|
105 |
+
# Fetch all user IDs from the user_faces_db collection
|
106 |
+
all_user_ids = client.get_all_ids(collection_name=user_faces_collection)
|
107 |
+
|
108 |
+
# Loop through all user IDs and delete associated collections
|
109 |
+
for user_id in all_user_ids:
|
110 |
+
sanitized_collection_name = sanitize_collection_name(user_id)
|
111 |
+
vectordb = Chroma(
|
112 |
+
collection_name=sanitized_collection_name,
|
113 |
+
embedding_function=HuggingFaceEmbeddings(model_name='sentence-transformers/all-MiniLM-L6-v2'),
|
114 |
+
persist_directory=f"{CHROMADB_LOC}/{sanitized_collection_name}", # Optional: Separate directory for each user's data
|
115 |
+
)
|
116 |
+
all_ids = vectordb._collection.get()
|
117 |
+
vectordb._collection.delete(ids=all_ids)
|
118 |
+
# Finally, delete the user_faces_db collection itself
|
119 |
+
client.delete_collection(user_faces_collection)
|
120 |
+
print(f"All user collections and {user_faces_collection} have been removed.")
|
app/admin/templates/data_management.html
ADDED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html>
|
3 |
+
<head>
|
4 |
+
<title>Econnect Data Management</title>
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<link href="static/css/mvp.css" rel="stylesheet" media="screen">
|
7 |
+
<!-- Bootstrap CSS -->
|
8 |
+
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
|
9 |
+
</head>
|
10 |
+
<body>
|
11 |
+
<h1>Face DB</h1>
|
12 |
+
<div>
|
13 |
+
<p>Total Faces: {{ faces.face_count }}</p>
|
14 |
+
<h2>Registered faces:</h2>
|
15 |
+
<p>{{ faces.all_faces }}</p>
|
16 |
+
<hr>
|
17 |
+
<h2>All collections:</h2>
|
18 |
+
<p>{{ faces.all_collections }}</p>
|
19 |
+
</div>
|
20 |
+
<hr>
|
21 |
+
<div class="container">
|
22 |
+
<h2>User Registration</h2>
|
23 |
+
<form id="deleteForm" action="/admin/delete_faces" method="post" enctype="multipart/form-data">
|
24 |
+
<h2>Delete and clean vectordb:</h2>
|
25 |
+
<!-- Updated button to only trigger the modal -->
|
26 |
+
<button type="button" class="btn btn-default" data-toggle="modal" data-target="#confirmationModal">Delete ALL</button>
|
27 |
+
</form>
|
28 |
+
{% if error %}
|
29 |
+
<p class="error"><strong>Error:</strong> {{ error }}</p>
|
30 |
+
{% endif %}
|
31 |
+
</div>
|
32 |
+
|
33 |
+
<!-- Modal -->
|
34 |
+
<div class="modal fade" id="confirmationModal" tabindex="-1" role="dialog" aria-labelledby="confirmationModalLabel" aria-hidden="true">
|
35 |
+
<div class="modal-dialog" role="document">
|
36 |
+
<div class="modal-content">
|
37 |
+
<div class="modal-header">
|
38 |
+
<h5 class="modal-title" id="confirmationModalLabel">Confirm Deletion</h5>
|
39 |
+
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
40 |
+
<span aria-hidden="true">×</span>
|
41 |
+
</button>
|
42 |
+
</div>
|
43 |
+
<div class="modal-body">
|
44 |
+
Are you sure you want to delete ALL faces?
|
45 |
+
</div>
|
46 |
+
<div class="modal-footer">
|
47 |
+
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
48 |
+
<button type="button" class="btn btn-danger" id="confirmDelete">Delete All</button>
|
49 |
+
</div>
|
50 |
+
</div>
|
51 |
+
</div>
|
52 |
+
</div>
|
53 |
+
|
54 |
+
<!-- Bootstrap and jQuery scripts -->
|
55 |
+
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
|
56 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
|
57 |
+
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
|
58 |
+
<script>
|
59 |
+
document.addEventListener('DOMContentLoaded', (event) => {
|
60 |
+
document.getElementById('confirmDelete').addEventListener('click', function() {
|
61 |
+
document.getElementById('deleteForm').submit();
|
62 |
+
});
|
63 |
+
});
|
64 |
+
</script>
|
65 |
+
</body>
|
66 |
+
</html>
|
app/admin/templates/user_registration.html
CHANGED
@@ -30,5 +30,9 @@
|
|
30 |
<p class="error"><strong>Error:</strong> {{ error }}
|
31 |
{% endif %}
|
32 |
</div>
|
|
|
|
|
|
|
|
|
33 |
</body>
|
34 |
</html>
|
|
|
30 |
<p class="error"><strong>Error:</strong> {{ error }}
|
31 |
{% endif %}
|
32 |
</div>
|
33 |
+
<hr>
|
34 |
+
<div>
|
35 |
+
<a href="/admin/data_management">Data Management</a>
|
36 |
+
</div>
|
37 |
</body>
|
38 |
</html>
|
app/main.py
CHANGED
@@ -1,16 +1,16 @@
|
|
1 |
import os
|
2 |
import chromadb
|
3 |
|
4 |
-
from fastapi import FastAPI, Request, Form, File, UploadFile
|
5 |
from fastapi.middleware.cors import CORSMiddleware
|
6 |
from fastapi.staticfiles import StaticFiles
|
7 |
-
from fastapi.responses import
|
8 |
from fastapi.templating import Jinja2Templates
|
9 |
|
10 |
from .admin import admin_functions as admin
|
11 |
from .utils.db import UserFaceEmbeddingFunction,ChromaDBFaceHelper
|
12 |
from .api import userlogin, userlogout, userchat, userupload
|
13 |
-
from .utils.db import
|
14 |
|
15 |
CHROMADB_LOC = "/home/user/data/chromadb"
|
16 |
|
@@ -28,6 +28,7 @@ app.add_middleware(
|
|
28 |
|
29 |
# Persitent storage for chromadb setup in /data volume
|
30 |
ec_client = chromadb.PersistentClient(CHROMADB_LOC)
|
|
|
31 |
# The following collection reference is needed for admin function to register face
|
32 |
user_faces_db = ec_client.get_or_create_collection(name="user_faces_db", embedding_function=UserFaceEmbeddingFunction())
|
33 |
|
@@ -85,6 +86,27 @@ async def handle_user_registration(request: Request, email: str = Form(...), nam
|
|
85 |
# Reload registration page with error message
|
86 |
return templates.TemplateResponse("user_registration.html", {"request": request, "error": "Registration failed"})
|
87 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
app.include_router(userlogin.router)
|
89 |
app.include_router(userlogout.router)
|
90 |
app.include_router(userchat.router)
|
|
|
1 |
import os
|
2 |
import chromadb
|
3 |
|
4 |
+
from fastapi import FastAPI, Request, Form, File, UploadFile
|
5 |
from fastapi.middleware.cors import CORSMiddleware
|
6 |
from fastapi.staticfiles import StaticFiles
|
7 |
+
from fastapi.responses import HTMLResponse, RedirectResponse
|
8 |
from fastapi.templating import Jinja2Templates
|
9 |
|
10 |
from .admin import admin_functions as admin
|
11 |
from .utils.db import UserFaceEmbeddingFunction,ChromaDBFaceHelper
|
12 |
from .api import userlogin, userlogout, userchat, userupload
|
13 |
+
from .utils.db import ChromaDBFaceHelper
|
14 |
|
15 |
CHROMADB_LOC = "/home/user/data/chromadb"
|
16 |
|
|
|
28 |
|
29 |
# Persitent storage for chromadb setup in /data volume
|
30 |
ec_client = chromadb.PersistentClient(CHROMADB_LOC)
|
31 |
+
|
32 |
# The following collection reference is needed for admin function to register face
|
33 |
user_faces_db = ec_client.get_or_create_collection(name="user_faces_db", embedding_function=UserFaceEmbeddingFunction())
|
34 |
|
|
|
86 |
# Reload registration page with error message
|
87 |
return templates.TemplateResponse("user_registration.html", {"request": request, "error": "Registration failed"})
|
88 |
|
89 |
+
# To display admin utilities
|
90 |
+
@app.get("/admin/data_management", response_class=HTMLResponse)
|
91 |
+
async def get_db_details(request: Request):
|
92 |
+
# Render the Chroma DB details
|
93 |
+
faces = admin.faces_count(user_faces_db)
|
94 |
+
return templates.TemplateResponse("data_management.html", {
|
95 |
+
"request": request,
|
96 |
+
"faces" : faces
|
97 |
+
})
|
98 |
+
|
99 |
+
@app.post("/admin/delete_faces")
|
100 |
+
async def delete_faces(request: Request):
|
101 |
+
try:
|
102 |
+
# Call your function to remove all faces
|
103 |
+
admin.remove_all_faces(ec_client)
|
104 |
+
request.session['flash'] = "All user data successfully deleted."
|
105 |
+
except Exception as e:
|
106 |
+
request.session['flash'] = f"Failed to delete user data: {str(e)}"
|
107 |
+
|
108 |
+
return RedirectResponse(url="/admin/data_management", status_code=303)
|
109 |
+
|
110 |
app.include_router(userlogin.router)
|
111 |
app.include_router(userlogout.router)
|
112 |
app.include_router(userchat.router)
|
app/utils/chat_rag.py
CHANGED
@@ -51,7 +51,7 @@ def get_vectordb_for_user(user_collection_name):
|
|
51 |
vectordb = Chroma(
|
52 |
collection_name=user_collection_name,
|
53 |
embedding_function=HuggingFaceEmbeddings(model_name='sentence-transformers/all-MiniLM-L6-v2'),
|
54 |
-
persist_directory=f"{CHROMADB_LOC}
|
55 |
)
|
56 |
return vectordb
|
57 |
|
|
|
51 |
vectordb = Chroma(
|
52 |
collection_name=user_collection_name,
|
53 |
embedding_function=HuggingFaceEmbeddings(model_name='sentence-transformers/all-MiniLM-L6-v2'),
|
54 |
+
persist_directory=f"{CHROMADB_LOC}" # Optional: Separate directory for each user's data
|
55 |
)
|
56 |
return vectordb
|
57 |
|
requirements.txt
CHANGED
@@ -18,4 +18,4 @@ tinydb # The in memory database for storing JWT tokens
|
|
18 |
langchain # Langgchain for RAG
|
19 |
llama-cpp-python # To load the model
|
20 |
sentence-transformers # For text embeddings
|
21 |
-
pypdf # Handling PDF files
|
|
|
18 |
langchain # Langgchain for RAG
|
19 |
llama-cpp-python # To load the model
|
20 |
sentence-transformers # For text embeddings
|
21 |
+
pypdf # Handling PDF files
|