AI Agent commited on
Commit ·
130f6cd
1
Parent(s): 87e6e59
Fix multiuser concurrency bottleneck and update HF deployment docs
Browse files- NITDAA_HF_DEPLOYMENT_GUIDE.md +5 -2
- app.py +5 -18
- pipeline/graph_store.py +31 -21
NITDAA_HF_DEPLOYMENT_GUIDE.md
CHANGED
|
@@ -10,10 +10,13 @@ This document outlines the specific steps and constraints required to deploy the
|
|
| 10 |
- Hardware allocation: Free Tier (2 vCPU, 16GB Disk, 12GB RAM).
|
| 11 |
|
| 12 |
## 2. HuggingFace Secrets Configuration
|
| 13 |
-
To enable dynamic Dataset Synchronization, you must configure the following variable
|
| 14 |
-
- `HF_TOKEN`: A HuggingFace access token with "Read" and "Write" permissions to the `Sam-max1/he-data` and `Sam-max1/mat_data` datasets.
|
| 15 |
- `ADMIN_MODE`: Set to `0` to completely lock down the UI for public usage.
|
| 16 |
|
|
|
|
|
|
|
|
|
|
| 17 |
## 3. Deployment Steps
|
| 18 |
1. Clone the `nitdaa` folder locally.
|
| 19 |
2. Initialize a git repository pointing to your HF Space remote.
|
|
|
|
| 10 |
- Hardware allocation: Free Tier (2 vCPU, 16GB Disk, 12GB RAM).
|
| 11 |
|
| 12 |
## 2. HuggingFace Secrets Configuration
|
| 13 |
+
To enable dynamic Dataset Synchronization, you must configure the following variable:
|
| 14 |
+
- `HF_TOKEN`: A HuggingFace access token with "Read" and "Write" permissions to the `Sam-max1/he-data` and `Sam-max1/mat_data` datasets. This token is available via the system keyring or environment variables.
|
| 15 |
- `ADMIN_MODE`: Set to `0` to completely lock down the UI for public usage.
|
| 16 |
|
| 17 |
+
## 2.1 Minimalist Deployment Rule
|
| 18 |
+
Nitdaa must always contain **only the bare minimum files required** to run the application in HF and the bare minimum files to be pushed to HF. Exclude all extraneous assets, development scripts, or unnecessary documentation from the Hugging Face repository.
|
| 19 |
+
|
| 20 |
## 3. Deployment Steps
|
| 21 |
1. Clone the `nitdaa` folder locally.
|
| 22 |
2. Initialize a git repository pointing to your HF Space remote.
|
app.py
CHANGED
|
@@ -131,23 +131,9 @@ _jobs: dict[str, dict] = {}
|
|
| 131 |
_active_graph_tasks = 0
|
| 132 |
_session_uploads: dict[str, int] = {}
|
| 133 |
|
| 134 |
-
# Global
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
def _query_worker():
|
| 139 |
-
while True:
|
| 140 |
-
task = _llm_query_queue.get()
|
| 141 |
-
if task is None: break
|
| 142 |
-
func, args = task
|
| 143 |
-
try:
|
| 144 |
-
func(*args)
|
| 145 |
-
except Exception as e:
|
| 146 |
-
log.exception("Query worker error")
|
| 147 |
-
finally:
|
| 148 |
-
_llm_query_queue.task_done()
|
| 149 |
-
|
| 150 |
-
threading.Thread(target=_query_worker, daemon=True).start()
|
| 151 |
|
| 152 |
# Auto-ingest background progress tracker
|
| 153 |
_auto_ingest_status: dict = {
|
|
@@ -879,7 +865,8 @@ def query_start():
|
|
| 879 |
_query_jobs[job_id]["done"] = True
|
| 880 |
log_query_summary(token, remote_addr, q, top_k or 10, 0, False, str(e))
|
| 881 |
|
| 882 |
-
|
|
|
|
| 883 |
return jsonify({"job_id": job_id})
|
| 884 |
|
| 885 |
@app.route("/api/query/stream/<job_id>")
|
|
|
|
| 131 |
_active_graph_tasks = 0
|
| 132 |
_session_uploads: dict[str, int] = {}
|
| 133 |
|
| 134 |
+
# Global thread pool to allow concurrent RAG execution
|
| 135 |
+
from concurrent.futures import ThreadPoolExecutor
|
| 136 |
+
_query_executor = ThreadPoolExecutor(max_workers=8)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
|
| 138 |
# Auto-ingest background progress tracker
|
| 139 |
_auto_ingest_status: dict = {
|
|
|
|
| 865 |
_query_jobs[job_id]["done"] = True
|
| 866 |
log_query_summary(token, remote_addr, q, top_k or 10, 0, False, str(e))
|
| 867 |
|
| 868 |
+
_query_executor.submit(_run)
|
| 869 |
+
|
| 870 |
return jsonify({"job_id": job_id})
|
| 871 |
|
| 872 |
@app.route("/api/query/stream/<job_id>")
|
pipeline/graph_store.py
CHANGED
|
@@ -9,38 +9,48 @@ sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
|
|
| 9 |
import config
|
| 10 |
|
| 11 |
_db = None
|
| 12 |
-
_conn = None
|
| 13 |
_db_lock = threading.Lock()
|
| 14 |
_schema_initialized = False
|
| 15 |
-
|
| 16 |
|
| 17 |
def _get_conn():
|
| 18 |
-
global _db,
|
| 19 |
if not getattr(config, 'GRAPH_AVAILABLE', True):
|
| 20 |
return None
|
|
|
|
|
|
|
|
|
|
| 21 |
|
| 22 |
with _db_lock:
|
| 23 |
-
if
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
return _conn
|
| 39 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
|
| 41 |
-
|
|
|
|
| 42 |
"""Create node and relationship tables for Kuzu."""
|
| 43 |
-
|
|
|
|
| 44 |
if not conn:
|
| 45 |
return
|
| 46 |
|
|
|
|
| 9 |
import config
|
| 10 |
|
| 11 |
_db = None
|
|
|
|
| 12 |
_db_lock = threading.Lock()
|
| 13 |
_schema_initialized = False
|
| 14 |
+
_local = threading.local()
|
| 15 |
|
| 16 |
def _get_conn():
|
| 17 |
+
global _db, _schema_initialized
|
| 18 |
if not getattr(config, 'GRAPH_AVAILABLE', True):
|
| 19 |
return None
|
| 20 |
+
|
| 21 |
+
if hasattr(_local, 'conn') and _local.conn is not None:
|
| 22 |
+
return _local.conn
|
| 23 |
|
| 24 |
with _db_lock:
|
| 25 |
+
if _db is None:
|
| 26 |
+
try:
|
| 27 |
+
import kuzu
|
| 28 |
+
os.makedirs(os.path.dirname(config.KUZU_DB_PATH), exist_ok=True)
|
| 29 |
+
_db = kuzu.Database(config.KUZU_DB_PATH)
|
| 30 |
+
print(f"[GraphStore] Connected to Kuzu at {config.KUZU_DB_PATH}")
|
| 31 |
+
|
| 32 |
+
# Use a temporary connection to initialize schema
|
| 33 |
+
tmp_conn = kuzu.Connection(_db)
|
| 34 |
+
if not _schema_initialized:
|
| 35 |
+
_init_schema(tmp_conn)
|
| 36 |
+
_schema_initialized = True
|
| 37 |
+
except Exception as e:
|
| 38 |
+
print(f"[GraphStore] Kuzu initialization failed. ({e})")
|
| 39 |
+
return None
|
|
|
|
| 40 |
|
| 41 |
+
try:
|
| 42 |
+
import kuzu
|
| 43 |
+
_local.conn = kuzu.Connection(_db)
|
| 44 |
+
return _local.conn
|
| 45 |
+
except Exception as e:
|
| 46 |
+
print(f"[GraphStore] Failed to create thread-local Kuzu connection. ({e})")
|
| 47 |
+
return None
|
| 48 |
|
| 49 |
+
|
| 50 |
+
def _init_schema(conn=None):
|
| 51 |
"""Create node and relationship tables for Kuzu."""
|
| 52 |
+
if not conn:
|
| 53 |
+
conn = _get_conn()
|
| 54 |
if not conn:
|
| 55 |
return
|
| 56 |
|