rishik1111 commited on
Commit
bf340fa
·
1 Parent(s): ff97980

fix: Add safe response handling and error alerts for text and voice queries in web UI

Browse files
.agents/skills/huggingface-nexus/SKILL.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- name: huggingface-nexus
3
  description: "Hugging Face Hub CLI (`hf`) for downloading, uploading, and managing models, datasets, spaces, buckets, repos, papers, jobs, and more on the Hugging Face Hub. Use when: handling authentication; managing local cache; managing Hugging Face Buckets; running or scheduling jobs on Hugging Face infrastructure; managing Hugging Face repos; discussions and pull requests; browsing models, datasets and spaces; reading, searching, or browsing academic papers; managing collections; querying datasets; configuring spaces; setting up webhooks; or deploying and managing HF Inference Endpoints. Make sure to use this skill whenever the user mentions 'hf', 'huggingface', 'Hugging Face', 'huggingface-cli', or 'hugging face cli', or wants to do anything related to the Hugging Face ecosystem and to AI and ML in general. Also use for cloud storage needs like training checkpoints, data pipelines, or agent traces. Use even if the user doesn't explicitly ask for a CLI command. Replaces the deprecated `huggingface-cli`."
4
  ---
5
 
 
1
  ---
2
+ name: hf-cli
3
  description: "Hugging Face Hub CLI (`hf`) for downloading, uploading, and managing models, datasets, spaces, buckets, repos, papers, jobs, and more on the Hugging Face Hub. Use when: handling authentication; managing local cache; managing Hugging Face Buckets; running or scheduling jobs on Hugging Face infrastructure; managing Hugging Face repos; discussions and pull requests; browsing models, datasets and spaces; reading, searching, or browsing academic papers; managing collections; querying datasets; configuring spaces; setting up webhooks; or deploying and managing HF Inference Endpoints. Make sure to use this skill whenever the user mentions 'hf', 'huggingface', 'Hugging Face', 'huggingface-cli', or 'hugging face cli', or wants to do anything related to the Hugging Face ecosystem and to AI and ML in general. Also use for cloud storage needs like training checkpoints, data pipelines, or agent traces. Use even if the user doesn't explicitly ask for a CLI command. Replaces the deprecated `huggingface-cli`."
4
  ---
5
 
Dockerfile CHANGED
@@ -1,3 +1,4 @@
 
1
  FROM python:3.11-slim
2
 
3
  # Set environment variables
@@ -5,16 +6,10 @@ ENV PYTHONUNBUFFERED=1 \
5
  PYTHONDONTWRITEBYTECODE=1 \
6
  PORT=7860 \
7
  HOST=0.0.0.0 \
8
- OMP_NUM_THREADS=1 \
9
- MKL_NUM_THREADS=1 \
10
- OPENBLAS_NUM_THREADS=1 \
11
- VECLIB_MAXIMUM_THREADS=1 \
12
- NUMEXPR_NUM_THREADS=1 \
13
- TOKENIZERS_PARALLELISM=false \
14
  DATA_DIR=/app/knowledge_base \
15
  INDEX_DIR=/app/knowledge_base/indexes \
16
  PROCESSED_DIR=/app/knowledge_base/processed \
17
- HF_HOME=/tmp/.cache/huggingface
18
 
19
  WORKDIR /app
20
 
@@ -32,11 +27,30 @@ COPY requirements.txt .
32
  RUN pip install --no-cache-dir --upgrade pip && \
33
  pip install --no-cache-dir -r requirements.txt
34
 
35
- # Copy application source code
36
- COPY . .
37
 
38
- # Expose default port
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  EXPOSE 7860
40
 
41
  # Launch FastAPI server
42
- CMD ["sh", "-c", "python main.py"]
 
1
+ # Hugging Face Spaces Docker SDK Image
2
  FROM python:3.11-slim
3
 
4
  # Set environment variables
 
6
  PYTHONDONTWRITEBYTECODE=1 \
7
  PORT=7860 \
8
  HOST=0.0.0.0 \
 
 
 
 
 
 
9
  DATA_DIR=/app/knowledge_base \
10
  INDEX_DIR=/app/knowledge_base/indexes \
11
  PROCESSED_DIR=/app/knowledge_base/processed \
12
+ HF_HOME=/app/.cache/huggingface
13
 
14
  WORKDIR /app
15
 
 
27
  RUN pip install --no-cache-dir --upgrade pip && \
28
  pip install --no-cache-dir -r requirements.txt
29
 
30
+ # Pre-cache embedding model weights into Docker image at build time
31
+ RUN python -c "from transformers import AutoTokenizer, AutoModel; AutoTokenizer.from_pretrained('intfloat/multilingual-e5-small'); AutoModel.from_pretrained('intfloat/multilingual-e5-small')"
32
 
33
+ # Copy application source code and pre-built index/processed artifacts
34
+ COPY config.py .
35
+ COPY main.py .
36
+ COPY knowledge_base/ ./knowledge_base/
37
+ COPY doc_chunking/ ./doc_chunking/
38
+ COPY vector_search/ ./vector_search/
39
+ COPY voice_stt/ ./voice_stt/
40
+ COPY safety_guardrails/ ./safety_guardrails/
41
+ COPY llm_synthesis/ ./llm_synthesis/
42
+ COPY rag_pipeline/ ./rag_pipeline/
43
+ COPY api_endpoints/ ./api_endpoints/
44
+ COPY latency_benchmarks/ ./latency_benchmarks/
45
+ COPY web_ui/ ./web_ui/
46
+
47
+ # Create user for Hugging Face Spaces security
48
+ RUN useradd -m -u 1000 user && \
49
+ chown -R user:user /app
50
+ USER user
51
+
52
+ # Expose default Hugging Face Spaces port
53
  EXPOSE 7860
54
 
55
  # Launch FastAPI server
56
+ CMD ["python", "main.py"]
README.md CHANGED
@@ -1,15 +1,3 @@
1
- ---
2
- title: VisionQuest Voice Indic RAG
3
- emoji: ⚡
4
- colorFrom: blue
5
- colorTo: indigo
6
- sdk: gradio
7
- sdk_version: 5.20.0
8
- app_file: app.py
9
- pinned: false
10
- license: mit
11
- ---
12
-
13
  # ⚡ VECTOR: Voice-Enabled Multilingual Indic RAG Engine
14
 
15
  <div align="center">
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # ⚡ VECTOR: Voice-Enabled Multilingual Indic RAG Engine
2
 
3
  <div align="center">
app.py DELETED
@@ -1,8 +0,0 @@
1
- import main
2
-
3
- # Expose main.app for Hugging Face Spaces Gradio / FastAPI launcher
4
- app = main.app
5
-
6
- if __name__ == "__main__":
7
- import uvicorn
8
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
 
 
 
 
 
 
 
 
config.py CHANGED
@@ -12,13 +12,10 @@ import os
12
  from pathlib import Path
13
  from dotenv import load_dotenv
14
 
15
- # Limit background thread creation & RAM consumption for cloud containers
16
  os.environ["TOKENIZERS_PARALLELISM"] = "false"
17
- os.environ["OMP_NUM_THREADS"] = "1"
18
- os.environ["MKL_NUM_THREADS"] = "1"
19
- os.environ["OPENBLAS_NUM_THREADS"] = "1"
20
- os.environ["VECLIB_MAXIMUM_THREADS"] = "1"
21
- os.environ["NUMEXPR_NUM_THREADS"] = "1"
22
 
23
  # Load environment variables
24
  load_dotenv()
 
12
  from pathlib import Path
13
  from dotenv import load_dotenv
14
 
15
+ # Limit background thread creation to preserve Windows system resources
16
  os.environ["TOKENIZERS_PARALLELISM"] = "false"
17
+ os.environ["OMP_NUM_THREADS"] = "2"
18
+ os.environ["MKL_NUM_THREADS"] = "2"
 
 
 
19
 
20
  # Load environment variables
21
  load_dotenv()
main.py CHANGED
@@ -88,7 +88,13 @@ app.add_middleware(
88
  # Preload models and perform full pipeline warmup asynchronously at startup
89
  @app.on_event("startup")
90
  async def startup_event():
91
- print("[Space Startup] Server process started cleanly. Listening for connections...")
 
 
 
 
 
 
92
 
93
 
94
  @app.get("/", response_class=HTMLResponse)
@@ -128,15 +134,6 @@ async def serve_cap() -> FileResponse:
128
  raise HTTPException(status_code=404, detail="Captain America image missing")
129
 
130
 
131
- @app.get("/spider_gwen.png")
132
- async def serve_spider_gwen() -> FileResponse:
133
- """Serve Spider-Gwen sprite image."""
134
- img_path = config.BASE_DIR / "web_ui" / "spider_gwen.png"
135
- if img_path.exists():
136
- return FileResponse(img_path)
137
- raise HTTPException(status_code=404, detail="Spider-Gwen image missing")
138
-
139
-
140
  @app.get("/health", response_class=JSONResponse)
141
  async def health_check() -> Dict[str, Any]:
142
  """Health check reporting system and index readiness."""
@@ -243,12 +240,7 @@ app = gr.mount_gradio_app(app, demo, path="/gradio")
243
 
244
 
245
  if __name__ == "__main__":
246
- import sys
247
  port = int(os.getenv("PORT", "7860"))
248
  host = os.getenv("HOST", "0.0.0.0")
249
- share = "--share" in sys.argv or os.getenv("SHARE", "false").lower() == "true"
250
- print(f"[Space Startup] Starting VECTOR Command Center UI on http://{host}:{port} (share={share})")
251
- if share:
252
- demo.launch(server_name=host, server_port=port, share=True)
253
- else:
254
- uvicorn.run(app, host=host, port=port)
 
88
  # Preload models and perform full pipeline warmup asynchronously at startup
89
  @app.on_event("startup")
90
  async def startup_event():
91
+ async def run_warmup():
92
+ print("[Space Startup] Preloading embedding model, FAISS indexes, and warming up pipeline...")
93
+ orchestrator = get_orchestrator()
94
+ await asyncio.to_thread(orchestrator.warmup_pipeline)
95
+ print("[Space Startup] Full RAG pipeline preloaded and warmed up successfully.")
96
+
97
+ asyncio.create_task(run_warmup())
98
 
99
 
100
  @app.get("/", response_class=HTMLResponse)
 
134
  raise HTTPException(status_code=404, detail="Captain America image missing")
135
 
136
 
 
 
 
 
 
 
 
 
 
137
  @app.get("/health", response_class=JSONResponse)
138
  async def health_check() -> Dict[str, Any]:
139
  """Health check reporting system and index readiness."""
 
240
 
241
 
242
  if __name__ == "__main__":
 
243
  port = int(os.getenv("PORT", "7860"))
244
  host = os.getenv("HOST", "0.0.0.0")
245
+ print(f"[Space Startup] Starting VECTOR Command Center UI on http://{host}:{port}")
246
+ uvicorn.run(app, host=host, port=port)
 
 
 
 
packages.txt DELETED
@@ -1,3 +0,0 @@
1
- ffmpeg
2
- libsndfile1
3
- build-essential
 
 
 
 
upload_to_hf.py DELETED
@@ -1,22 +0,0 @@
1
- import os
2
- import sys
3
- from huggingface_hub import HfApi
4
-
5
- def upload():
6
- token = input("Paste your Hugging Face Token (hf_...): ").strip()
7
- if not token:
8
- print("Error: Token is required.")
9
- return
10
-
11
- print("\nUploading full repository (including all subfolders) to Hugging Face Space...")
12
- api = HfApi(token=token)
13
- api.upload_folder(
14
- folder_path=".",
15
- repo_id="rishikvelagapudi/visionquest",
16
- repo_type="space",
17
- ignore_patterns=[".git*", "*.pyc", "__pycache__", ".env", "venv", ".gemini", ".agents"]
18
- )
19
- print("\nSUCCESS! All subdirectories and code files are uploaded to Hugging Face Spaces!")
20
-
21
- if __name__ == "__main__":
22
- upload()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vector_search/embed.py CHANGED
@@ -12,10 +12,17 @@ import os
12
  from pathlib import Path
13
  from typing import List, Union
14
  import numpy as np
 
15
  import config
16
 
17
  logger = logging.getLogger(__name__)
18
 
 
 
 
 
 
 
19
  _EMBEDDER_INSTANCE = None
20
 
21
 
@@ -183,9 +190,6 @@ class PyTorchMultilingualE5Embedder:
183
  PyTorch fallback wrapper for sentence-transformers multilingual-e5-small.
184
  """
185
  def __init__(self, model_name: str = config.EMBEDDING_MODEL_NAME):
186
- import torch
187
- torch.set_grad_enabled(False)
188
- torch.set_num_threads(1)
189
  from sentence_transformers import SentenceTransformer
190
  logger.info(f"Loading PyTorch fallback embedding model: '{model_name}'...")
191
  self.model_name = model_name
@@ -193,7 +197,6 @@ class PyTorchMultilingualE5Embedder:
193
  self.model = SentenceTransformer(model_name, local_files_only=True)
194
  except Exception:
195
  self.model = SentenceTransformer(model_name)
196
- self.model.eval()
197
  self.dim = config.EMBEDDING_DIM
198
  logger.info(f"PyTorch embedding model loaded (dim={self.dim}).")
199
 
 
12
  from pathlib import Path
13
  from typing import List, Union
14
  import numpy as np
15
+ import torch
16
  import config
17
 
18
  logger = logging.getLogger(__name__)
19
 
20
+ # Optimize PyTorch CPU parallelism
21
+ try:
22
+ torch.set_num_threads(max(1, torch.get_num_threads()))
23
+ except Exception:
24
+ pass
25
+
26
  _EMBEDDER_INSTANCE = None
27
 
28
 
 
190
  PyTorch fallback wrapper for sentence-transformers multilingual-e5-small.
191
  """
192
  def __init__(self, model_name: str = config.EMBEDDING_MODEL_NAME):
 
 
 
193
  from sentence_transformers import SentenceTransformer
194
  logger.info(f"Loading PyTorch fallback embedding model: '{model_name}'...")
195
  self.model_name = model_name
 
197
  self.model = SentenceTransformer(model_name, local_files_only=True)
198
  except Exception:
199
  self.model = SentenceTransformer(model_name)
 
200
  self.dim = config.EMBEDDING_DIM
201
  logger.info(f"PyTorch embedding model loaded (dim={self.dim}).")
202
 
vector_search/rerank.py CHANGED
@@ -4,7 +4,9 @@ import re
4
  from pathlib import Path
5
  from typing import Any, Dict, List
6
  import numpy as np
 
7
  from rank_bm25 import BM25Okapi
 
8
  import config
9
 
10
  logger = logging.getLogger(__name__)
@@ -178,7 +180,6 @@ class PyTorchCrossEncoderRanker:
178
  PyTorch fallback wrapper for sentence-transformers CrossEncoder.
179
  """
180
  def __init__(self, model_name: str = config.CROSS_ENCODER_MODEL_NAME):
181
- from sentence_transformers.cross_encoder import CrossEncoder
182
  load_path = model_name
183
  local_cache = getattr(config, "CROSS_ENCODER_LOCAL_CACHE", None)
184
  if local_cache and Path(local_cache).exists():
 
4
  from pathlib import Path
5
  from typing import Any, Dict, List
6
  import numpy as np
7
+ import torch
8
  from rank_bm25 import BM25Okapi
9
+ from sentence_transformers.cross_encoder import CrossEncoder
10
  import config
11
 
12
  logger = logging.getLogger(__name__)
 
180
  PyTorch fallback wrapper for sentence-transformers CrossEncoder.
181
  """
182
  def __init__(self, model_name: str = config.CROSS_ENCODER_MODEL_NAME):
 
183
  load_path = model_name
184
  local_cache = getattr(config, "CROSS_ENCODER_LOCAL_CACHE", None)
185
  if local_cache and Path(local_cache).exists():
web_ui/index.html CHANGED
@@ -766,13 +766,13 @@
766
  </div>
767
  </div>
768
 
769
- <!-- RIGHT: EVALUATION MATRIX (SURFBOARD SHIELD SHAPE & BEACH SAND THEME) -->
770
  <div class="lg:col-span-6 shape-guardrail-matrix beach-sand-bg p-5 flex flex-col justify-between gap-4 relative z-20 bg-[#FFFBEA] opacity-100">
771
 
772
  <!-- Header -->
773
  <div class="flex items-center justify-between border-b-3 border-black pb-2.5">
774
  <h4 class="font-comic font-black text-lg md:text-xl text-black tracking-wider flex items-center gap-2">
775
- <span>🛡️ EVALUATION MATRIX 🏄‍♂️</span>
776
  </h4>
777
  <span class="comic-badge px-2.5 py-0.5 bg-black text-beachgreen text-xs shadow-brutal-sm">4-TIER ACTIVE</span>
778
  </div>
@@ -964,6 +964,18 @@
964
 
965
  try {
966
  const response = await fetch("/query", { method: "POST", body: formData });
 
 
 
 
 
 
 
 
 
 
 
 
967
  const data = await response.json();
968
  renderResults(data);
969
  } catch (err) {
@@ -1029,6 +1041,18 @@
1029
 
1030
  try {
1031
  const response = await fetch("/query", { method: "POST", body: formData });
 
 
 
 
 
 
 
 
 
 
 
 
1032
  const data = await response.json();
1033
  renderResults(data);
1034
  } catch (err) {
@@ -1429,26 +1453,8 @@
1429
  let mainIronmanLoaded = false;
1430
  mainIronmanImg.onload = () => { mainIronmanLoaded = true; };
1431
 
1432
- const thorImg = new Image();
1433
- thorImg.src = "/thor.png";
1434
- let thorLoaded = false;
1435
- thorImg.onload = () => { thorLoaded = true; };
1436
-
1437
- const capImg = new Image();
1438
- capImg.src = "/cap.png";
1439
- let capLoaded = false;
1440
- capImg.onload = () => { capLoaded = true; };
1441
-
1442
- const gwenImg = new Image();
1443
- gwenImg.src = "/spider_gwen.png";
1444
- let gwenLoaded = false;
1445
- gwenImg.onload = () => { gwenLoaded = true; };
1446
-
1447
  let mainImX = -220;
1448
  const mainThrusterParticles = [];
1449
- const thorSparks = [];
1450
- const capSparks = [];
1451
- const gwenParticles = [];
1452
 
1453
  function drawMainPageIronMan() {
1454
  if (!mainCanvas || !mainCtx) return;
@@ -1773,35 +1779,26 @@
1773
  mainCtx.restore();
1774
  }
1775
 
1776
- // ==========================================
1777
- // DRAW SPIDER-GWEN FLYING (Center Tail Wing of Avengers V-Formation)
1778
- // ==========================================
1779
- const gwenX = mainImX - 410;
1780
- const gwenY = baseLeaderY;
1781
- const gwenW = 150;
1782
- const gwenH = 220;
1783
 
1784
- if (gwenLoaded) {
1785
- mainCtx.save();
1786
- mainCtx.filter = "brightness(1.4) contrast(1.25) saturate(1.3) drop-shadow(0 0 20px rgba(255, 0, 150, 0.95))";
1787
- mainCtx.drawImage(gwenImg, gwenX, gwenY, gwenW, gwenH);
1788
- mainCtx.restore();
1789
 
1790
- // Luminous Neon Web Aura Flare
1791
- mainCtx.save();
1792
- const webGrad = mainCtx.createRadialGradient(gwenX + gwenW * 0.5, gwenY + gwenH * 0.4, 0, gwenX + gwenW * 0.5, gwenY + gwenH * 0.4, 24);
1793
- webGrad.addColorStop(0, "rgba(255, 255, 255, 0.95)");
1794
- webGrad.addColorStop(0.4, "rgba(255, 0, 150, 0.85)");
1795
- webGrad.addColorStop(1, "rgba(255, 0, 150, 0)");
1796
- mainCtx.fillStyle = webGrad;
1797
- mainCtx.beginPath();
1798
- mainCtx.arc(gwenX + gwenW * 0.5, gwenY + gwenH * 0.4, 24, 0, Math.PI * 2);
1799
- mainCtx.fill();
1800
- mainCtx.restore();
1801
- }
1802
 
1803
- requestAnimationFrame(drawMainPageIronMan);
1804
- }
 
 
 
 
 
 
1805
 
1806
  function drawLightningArc(c, x1, y1, x2, y2, roughness = 14) {
1807
  const dx = x2 - x1;
 
766
  </div>
767
  </div>
768
 
769
+ <!-- RIGHT: GUARDRAIL AUDIT MATRIX (SURFBOARD SHIELD SHAPE & BEACH SAND THEME) -->
770
  <div class="lg:col-span-6 shape-guardrail-matrix beach-sand-bg p-5 flex flex-col justify-between gap-4 relative z-20 bg-[#FFFBEA] opacity-100">
771
 
772
  <!-- Header -->
773
  <div class="flex items-center justify-between border-b-3 border-black pb-2.5">
774
  <h4 class="font-comic font-black text-lg md:text-xl text-black tracking-wider flex items-center gap-2">
775
+ <span>🛡️ GUARDRAIL AUDIT MATRIX 🏄‍♂️</span>
776
  </h4>
777
  <span class="comic-badge px-2.5 py-0.5 bg-black text-beachgreen text-xs shadow-brutal-sm">4-TIER ACTIVE</span>
778
  </div>
 
964
 
965
  try {
966
  const response = await fetch("/query", { method: "POST", body: formData });
967
+ if (!response.ok) {
968
+ const errText = await response.text();
969
+ let msg = response.statusText || ("HTTP " + response.status);
970
+ try {
971
+ const parsed = JSON.parse(errText);
972
+ msg = parsed.detail || parsed.reason || msg;
973
+ } catch (_) {
974
+ if (errText) msg = errText;
975
+ }
976
+ alert("Query Error (" + response.status + "): " + msg);
977
+ return;
978
+ }
979
  const data = await response.json();
980
  renderResults(data);
981
  } catch (err) {
 
1041
 
1042
  try {
1043
  const response = await fetch("/query", { method: "POST", body: formData });
1044
+ if (!response.ok) {
1045
+ const errText = await response.text();
1046
+ let msg = response.statusText || ("HTTP " + response.status);
1047
+ try {
1048
+ const parsed = JSON.parse(errText);
1049
+ msg = parsed.detail || parsed.reason || msg;
1050
+ } catch (_) {
1051
+ if (errText) msg = errText;
1052
+ }
1053
+ alert("Voice Query Error (" + response.status + "): " + msg);
1054
+ return;
1055
+ }
1056
  const data = await response.json();
1057
  renderResults(data);
1058
  } catch (err) {
 
1453
  let mainIronmanLoaded = false;
1454
  mainIronmanImg.onload = () => { mainIronmanLoaded = true; };
1455
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1456
  let mainImX = -220;
1457
  const mainThrusterParticles = [];
 
 
 
1458
 
1459
  function drawMainPageIronMan() {
1460
  if (!mainCanvas || !mainCtx) return;
 
1779
  mainCtx.restore();
1780
  }
1781
 
1782
+ requestAnimationFrame(drawMainPageIronMan);
1783
+ }
 
 
 
 
 
1784
 
1785
+ // Captain America Sprite Loader
1786
+ const capImg = new Image();
1787
+ capImg.src = "/cap.png";
1788
+ let capLoaded = false;
1789
+ capImg.onload = () => { capLoaded = true; };
1790
 
1791
+ let capX = -650;
1792
+ const capSparks = [];
 
 
 
 
 
 
 
 
 
 
1793
 
1794
+ // Thor Sprite & Lightning Helper
1795
+ const thorImg = new Image();
1796
+ thorImg.src = "/thor.png";
1797
+ let thorLoaded = false;
1798
+ thorImg.onload = () => { thorLoaded = true; };
1799
+
1800
+ let thorX = -450;
1801
+ const thorSparks = [];
1802
 
1803
  function drawLightningArc(c, x1, y1, x2, y2, roughness = 14) {
1804
  const dx = x2 - x1;