devrajsinh2012 commited on
Commit
76b3d38
Β·
verified Β·
1 Parent(s): 4d919b5

Upload folder using huggingface_hub

Browse files
Files changed (6) hide show
  1. .gitignore +0 -1
  2. Dockerfile +31 -45
  3. README.md +1 -1
  4. backend/main.py +172 -193
  5. backend/static/index.html +957 -1
  6. frontend/package.json +43 -43
.gitignore CHANGED
@@ -58,7 +58,6 @@ backend/data/storage/
58
  backend/data/temp/
59
  backend/data/tts_cache/
60
  backend/data/agents/
61
- data/
62
  *.db
63
 
64
  # Test data (optional - uncomment if you want to include)
 
58
  backend/data/temp/
59
  backend/data/tts_cache/
60
  backend/data/agents/
 
61
  *.db
62
 
63
  # Test data (optional - uncomment if you want to include)
Dockerfile CHANGED
@@ -1,45 +1,31 @@
1
- # Stage 1: Build Frontend
2
- FROM node:18-alpine AS frontend-builder
3
- WORKDIR /app/frontend
4
- COPY frontend/package*.json ./
5
- RUN npm ci || npm install
6
- COPY frontend/ ./
7
- ENV REACT_APP_API_URL=""
8
- RUN npm run build
9
-
10
- # Stage 2: Python Backend Runtime
11
- FROM python:3.11-slim
12
-
13
- WORKDIR /app
14
-
15
- # Install system dependencies
16
- RUN apt-get update && apt-get install -y \
17
- gcc \
18
- g++ \
19
- postgresql-client \
20
- && rm -rf /var/lib/apt/lists/*
21
-
22
- # Copy requirements and install Python packages
23
- COPY backend/requirements.txt .
24
- RUN pip install --no-cache-dir -r requirements.txt
25
- RUN python -m spacy download en_core_web_sm
26
-
27
- # Copy backend application code
28
- COPY backend/ ./backend/
29
-
30
- # Copy built frontend assets into backend/static
31
- COPY --from=frontend-builder /app/frontend/build/ ./backend/static/
32
-
33
- # Entry point environment
34
- ENV PYTHONPATH=/app/backend
35
-
36
- # Set environment for model caching to /tmp (only writable dir in HF Spaces)
37
- ENV HF_HOME=/tmp/.cache/huggingface
38
- ENV FASTEMBED_CACHE_PATH=/tmp/.cache/fastembed
39
- ENV SENTENCE_TRANSFORMERS_HOME=/tmp/.cache/sentence-transformers
40
-
41
- # Expose port 7860 (required by Hugging Face Spaces)
42
- EXPOSE 7860
43
-
44
- # Run FastAPI with uvicorn
45
- CMD ["uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "7860"]
 
1
+ FROM python:3.11-slim
2
+
3
+ WORKDIR /app
4
+
5
+ # Install system dependencies
6
+ RUN apt-get update && apt-get install -y \
7
+ gcc \
8
+ g++ \
9
+ postgresql-client \
10
+ && rm -rf /var/lib/apt/lists/*
11
+
12
+ # Copy requirements and install Python packages
13
+ COPY backend/requirements.txt .
14
+ RUN pip install --no-cache-dir -r requirements.txt
15
+ RUN python -m spacy download en_core_web_sm
16
+
17
+ # Copy application code from backend directory
18
+ COPY backend/ ./backend/
19
+ # Main entry point needs to be at root level for some runners, or we point pythonpath
20
+ ENV PYTHONPATH=/app/backend
21
+
22
+ # Set environment for model caching to /tmp (only writable dir in HF Spaces)
23
+ ENV HF_HOME=/tmp/.cache/huggingface
24
+ ENV FASTEMBED_CACHE_PATH=/tmp/.cache/fastembed
25
+ ENV SENTENCE_TRANSFORMERS_HOME=/tmp/.cache/sentence-transformers
26
+
27
+ # Expose port 7860 (required by Hugging Face Spaces)
28
+ EXPOSE 7860
29
+
30
+ # Run FastAPI with uvicorn (pointing to nested app)
31
+ CMD ["uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "7860"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
README.md CHANGED
@@ -3,7 +3,7 @@ title: Mexar
3
  emoji: 🧠
4
  colorFrom: blue
5
  colorTo: indigo
6
- sdk: static
7
  pinned: false
8
  license: mit
9
  ---
 
3
  emoji: 🧠
4
  colorFrom: blue
5
  colorTo: indigo
6
+ sdk: docker
7
  pinned: false
8
  license: mit
9
  ---
backend/main.py CHANGED
@@ -1,193 +1,172 @@
1
- """
2
- MEXAR Core Engine - FastAPI Backend Application
3
- Main entry point for the MEXAR Phase 2 API.
4
-
5
- This is a clean, minimal main.py that only includes routers.
6
- All endpoints are handled by the api/ modules.
7
- """
8
-
9
- import os
10
- import logging
11
- from pathlib import Path
12
- from contextlib import asynccontextmanager
13
-
14
- from fastapi import FastAPI
15
- from fastapi.middleware.cors import CORSMiddleware
16
- from fastapi.responses import JSONResponse
17
- from dotenv import load_dotenv
18
-
19
- # Load environment variables
20
- load_dotenv()
21
-
22
- # Configure logging
23
- logging.basicConfig(
24
- level=logging.INFO,
25
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
26
- )
27
- logger = logging.getLogger(__name__)
28
-
29
- # Ensure data directories exist
30
- DATA_DIRS = [
31
- Path("data/storage"),
32
- Path("data/temp"),
33
- ]
34
- for dir_path in DATA_DIRS:
35
- dir_path.mkdir(parents=True, exist_ok=True)
36
-
37
-
38
- # Lifespan context manager
39
- @asynccontextmanager
40
- async def lifespan(app: FastAPI):
41
- """Application lifespan handler - database initialization."""
42
- logger.info("MEXAR Core Engine starting up...")
43
-
44
- # Initialize database tables
45
- try:
46
- from core.database import engine, Base
47
- from models.user import User
48
- from models.agent import Agent, CompilationJob
49
- from models.conversation import Conversation, Message
50
- from models.chunk import DocumentChunk
51
- from sqlalchemy import text
52
-
53
- # Enable vector extension only for postgres
54
- if "sqlite" not in str(engine.url):
55
- try:
56
- with engine.connect() as conn:
57
- conn.execute(text("CREATE EXTENSION IF NOT EXISTS vector"))
58
- conn.commit()
59
- except Exception as vector_err:
60
- logger.warning(f"Vector extension check skipped: {vector_err}")
61
-
62
- Base.metadata.create_all(bind=engine)
63
- logger.info("Database tables created/verified successfully")
64
- except Exception as e:
65
- logger.warning(f"Database initialization: {e}")
66
-
67
- yield
68
- logger.info("MEXAR Core Engine shutting down...")
69
-
70
-
71
- # Create FastAPI app
72
- app = FastAPI(
73
- title="MEXAR Core Engine",
74
- description="Multimodal Explainable AI Reasoning Assistant - Phase 2",
75
- version="2.0.0",
76
- lifespan=lifespan
77
- )
78
-
79
- # Configure CORS
80
- # Configure CORS
81
- # CRITICAL: Configure CORS for Vercel frontend
82
- FRONTEND_URL = os.getenv("FRONTEND_URL", "http://localhost:3000")
83
-
84
- allow_origins = [
85
- "*",
86
- FRONTEND_URL,
87
- "https://*.vercel.app",
88
- "http://localhost:3000",
89
- "http://localhost:3001"
90
- ]
91
-
92
- app.add_middleware(
93
- CORSMiddleware,
94
- allow_origins=allow_origins,
95
- allow_credentials=True,
96
- allow_methods=["*"],
97
- allow_headers=["*"],
98
- )
99
-
100
- # Import and include Phase 2 routers
101
- from api import auth, agents, chat, compile, websocket, admin, prompts, diagnostics
102
-
103
- app.include_router(auth.router)
104
- app.include_router(agents.router)
105
- app.include_router(chat.router)
106
- app.include_router(compile.router)
107
- app.include_router(websocket.router)
108
- app.include_router(admin.router)
109
- app.include_router(prompts.router)
110
- app.include_router(diagnostics.router)
111
-
112
-
113
- from fastapi.staticfiles import StaticFiles
114
- from fastapi.responses import FileResponse
115
-
116
- STATIC_DIR = Path(__file__).parent / "static"
117
-
118
- # Mount static subfolder for compiled CSS/JS assets if present
119
- if (STATIC_DIR / "static").exists():
120
- app.mount("/static", StaticFiles(directory=str(STATIC_DIR / "static")), name="static_assets")
121
-
122
-
123
- # ===== CORE UTILITY ENDPOINTS =====
124
-
125
- @app.get("/api/health")
126
- async def health_check():
127
- """Health check endpoint."""
128
- return {
129
- "status": "healthy",
130
- "groq_configured": bool(os.getenv("GROQ_API_KEY"))
131
- }
132
-
133
-
134
- @app.get("/{full_path:path}")
135
- async def serve_spa(full_path: str):
136
- """Serve React SPA frontend for root and all client-side routes."""
137
- # Do not intercept API, docs, or WebSocket endpoints
138
- if full_path.startswith("api/") or full_path.startswith("ws/") or full_path in ["docs", "redoc", "openapi.json"]:
139
- return JSONResponse(status_code=404, content={"detail": "Not found"})
140
-
141
- # Direct static file request (e.g. favicon.ico, asset-manifest.json)
142
- if full_path:
143
- file_path = STATIC_DIR / full_path
144
- if file_path.exists() and file_path.is_file():
145
- return FileResponse(file_path)
146
-
147
- # Fallback to index.html for SPA routing
148
- index_path = STATIC_DIR / "index.html"
149
- if index_path.exists():
150
- return FileResponse(index_path, media_type="text/html")
151
-
152
- return JSONResponse(
153
- status_code=404,
154
- content={
155
- "name": "MEXAR Core Engine",
156
- "version": "2.0.0",
157
- "status": "operational",
158
- "docs": "/docs"
159
- }
160
- )
161
-
162
-
163
-
164
-
165
-
166
-
167
- # ===== ERROR HANDLERS =====
168
-
169
- @app.exception_handler(Exception)
170
- async def global_exception_handler(request, exc):
171
- """Global exception handler."""
172
- logger.error(f"Unhandled exception: {exc}")
173
- return JSONResponse(
174
- status_code=500,
175
- content={
176
- "success": False,
177
- "error": "Internal server error",
178
- "detail": str(exc)
179
- }
180
- )
181
-
182
-
183
- # ===== MAIN ENTRY POINT =====
184
-
185
- if __name__ == "__main__":
186
- import uvicorn
187
- uvicorn.run(
188
- "main:app",
189
- host="0.0.0.0",
190
- port=8000,
191
- reload=True,
192
- log_level="info"
193
- )
 
1
+ """
2
+ MEXAR Core Engine - FastAPI Backend Application
3
+ Main entry point for the MEXAR Phase 2 API.
4
+
5
+ This is a clean, minimal main.py that only includes routers.
6
+ All endpoints are handled by the api/ modules.
7
+ """
8
+
9
+ import os
10
+ import logging
11
+ from pathlib import Path
12
+ from contextlib import asynccontextmanager
13
+
14
+ from fastapi import FastAPI
15
+ from fastapi.middleware.cors import CORSMiddleware
16
+ from fastapi.responses import JSONResponse
17
+ from dotenv import load_dotenv
18
+
19
+ # Load environment variables
20
+ load_dotenv()
21
+
22
+ # Configure logging
23
+ logging.basicConfig(
24
+ level=logging.INFO,
25
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
26
+ )
27
+ logger = logging.getLogger(__name__)
28
+
29
+ # Ensure data directories exist
30
+ DATA_DIRS = [
31
+ Path("data/storage"),
32
+ Path("data/temp"),
33
+ ]
34
+ for dir_path in DATA_DIRS:
35
+ dir_path.mkdir(parents=True, exist_ok=True)
36
+
37
+
38
+ # Lifespan context manager
39
+ @asynccontextmanager
40
+ async def lifespan(app: FastAPI):
41
+ """Application lifespan handler - database initialization."""
42
+ logger.info("MEXAR Core Engine starting up...")
43
+
44
+ # Initialize database tables
45
+ try:
46
+ from core.database import engine, Base
47
+ from models.user import User
48
+ from models.agent import Agent, CompilationJob
49
+ from models.conversation import Conversation, Message
50
+ from models.chunk import DocumentChunk
51
+ from sqlalchemy import text
52
+
53
+ # Enable vector extension only for postgres
54
+ if "sqlite" not in str(engine.url):
55
+ try:
56
+ with engine.connect() as conn:
57
+ conn.execute(text("CREATE EXTENSION IF NOT EXISTS vector"))
58
+ conn.commit()
59
+ except Exception as vector_err:
60
+ logger.warning(f"Vector extension check skipped: {vector_err}")
61
+
62
+ Base.metadata.create_all(bind=engine)
63
+ logger.info("Database tables created/verified successfully")
64
+ except Exception as e:
65
+ logger.warning(f"Database initialization: {e}")
66
+
67
+ yield
68
+ logger.info("MEXAR Core Engine shutting down...")
69
+
70
+
71
+ # Create FastAPI app
72
+ app = FastAPI(
73
+ title="MEXAR Core Engine",
74
+ description="Multimodal Explainable AI Reasoning Assistant - Phase 2",
75
+ version="2.0.0",
76
+ lifespan=lifespan
77
+ )
78
+
79
+ # Configure CORS
80
+ # Configure CORS
81
+ # CRITICAL: Configure CORS for Vercel frontend
82
+ FRONTEND_URL = os.getenv("FRONTEND_URL", "http://localhost:3000")
83
+
84
+ allow_origins = [
85
+ "*",
86
+ FRONTEND_URL,
87
+ "https://*.vercel.app",
88
+ "http://localhost:3000",
89
+ "http://localhost:3001"
90
+ ]
91
+
92
+ app.add_middleware(
93
+ CORSMiddleware,
94
+ allow_origins=allow_origins,
95
+ allow_credentials=True,
96
+ allow_methods=["*"],
97
+ allow_headers=["*"],
98
+ )
99
+
100
+ # Import and include Phase 2 routers
101
+ from api import auth, agents, chat, compile, websocket, admin, prompts, diagnostics
102
+
103
+ app.include_router(auth.router)
104
+ app.include_router(agents.router)
105
+ app.include_router(chat.router)
106
+ app.include_router(compile.router)
107
+ app.include_router(websocket.router)
108
+ app.include_router(admin.router)
109
+ app.include_router(prompts.router)
110
+ app.include_router(diagnostics.router)
111
+
112
+
113
+ # ===== CORE UTILITY ENDPOINTS =====
114
+
115
+ @app.get("/")
116
+ async def root():
117
+ """Root endpoint - serves landing page."""
118
+ from fastapi.responses import FileResponse
119
+ from pathlib import Path
120
+
121
+ html_path = Path(__file__).parent / "static" / "index.html"
122
+ if html_path.exists():
123
+ return FileResponse(html_path, media_type="text/html")
124
+ else:
125
+ # Fallback to JSON if HTML not found
126
+ return {
127
+ "name": "MEXAR Core Engine",
128
+ "version": "2.0.0",
129
+ "status": "operational",
130
+ "docs": "/docs"
131
+ }
132
+
133
+
134
+ @app.get("/api/health")
135
+ async def health_check():
136
+ """Health check endpoint."""
137
+ return {
138
+ "status": "healthy",
139
+ "groq_configured": bool(os.getenv("GROQ_API_KEY"))
140
+ }
141
+
142
+
143
+
144
+
145
+
146
+ # ===== ERROR HANDLERS =====
147
+
148
+ @app.exception_handler(Exception)
149
+ async def global_exception_handler(request, exc):
150
+ """Global exception handler."""
151
+ logger.error(f"Unhandled exception: {exc}")
152
+ return JSONResponse(
153
+ status_code=500,
154
+ content={
155
+ "success": False,
156
+ "error": "Internal server error",
157
+ "detail": str(exc)
158
+ }
159
+ )
160
+
161
+
162
+ # ===== MAIN ENTRY POINT =====
163
+
164
+ if __name__ == "__main__":
165
+ import uvicorn
166
+ uvicorn.run(
167
+ "main:app",
168
+ host="0.0.0.0",
169
+ port=8000,
170
+ reload=True,
171
+ log_level="info"
172
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/static/index.html CHANGED
@@ -1 +1,957 @@
1
- <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🧠</text></svg>"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#6366f1"/><meta name="description" content="MEXAR ULTIMATE - Advanced Multimodal AI Reasoning Engine"/><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"><title>MEXAR Ultimate</title><script defer="defer" src="/static/js/main.c544f0ac.js"></script><link href="/static/css/main.c45c55fa.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>MEXAR β€” Multimodal Explainable AI Reasoning Assistant</title>
7
+ <meta name="description" content="Build domain-specific AI agents from your documents. Grounded, cited, and faithfully scored answers with full explainability.">
8
+ <link rel="preconnect" href="https://fonts.googleapis.com">
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
11
+ <style>
12
+ :root {
13
+ --bg-primary: #080c14;
14
+ --bg-secondary: #0d1420;
15
+ --bg-card: #111827;
16
+ --bg-card-hover: #1a2236;
17
+ --border: rgba(99, 120, 255, 0.15);
18
+ --border-bright: rgba(99, 120, 255, 0.4);
19
+ --accent-blue: #6378ff;
20
+ --accent-cyan: #00d4ff;
21
+ --accent-purple: #a855f7;
22
+ --accent-green: #10b981;
23
+ --accent-orange: #f59e0b;
24
+ --text-primary: #f1f5f9;
25
+ --text-secondary: #94a3b8;
26
+ --text-muted: #475569;
27
+ --glow-blue: rgba(99, 120, 255, 0.3);
28
+ --glow-cyan: rgba(0, 212, 255, 0.2);
29
+ }
30
+
31
+ * { margin: 0; padding: 0; box-sizing: border-box; }
32
+
33
+ body {
34
+ font-family: 'Inter', sans-serif;
35
+ background: var(--bg-primary);
36
+ color: var(--text-primary);
37
+ min-height: 100vh;
38
+ overflow-x: hidden;
39
+ }
40
+
41
+ /* ── Animated gradient background ── */
42
+ body::before {
43
+ content: '';
44
+ position: fixed;
45
+ top: 0; left: 0; right: 0; bottom: 0;
46
+ background:
47
+ radial-gradient(ellipse 80% 50% at 20% 20%, rgba(99,120,255,0.08) 0%, transparent 60%),
48
+ radial-gradient(ellipse 60% 40% at 80% 80%, rgba(168,85,247,0.06) 0%, transparent 60%),
49
+ radial-gradient(ellipse 50% 30% at 50% 50%, rgba(0,212,255,0.04) 0%, transparent 60%);
50
+ pointer-events: none;
51
+ z-index: 0;
52
+ }
53
+
54
+ .container {
55
+ position: relative;
56
+ z-index: 1;
57
+ max-width: 1100px;
58
+ margin: 0 auto;
59
+ padding: 0 2rem;
60
+ }
61
+
62
+ /* ── NAV ── */
63
+ nav {
64
+ padding: 1.5rem 0;
65
+ display: flex;
66
+ align-items: center;
67
+ justify-content: space-between;
68
+ border-bottom: 1px solid var(--border);
69
+ }
70
+
71
+ .nav-logo {
72
+ display: flex;
73
+ align-items: center;
74
+ gap: 0.6rem;
75
+ font-size: 1.35rem;
76
+ font-weight: 800;
77
+ letter-spacing: -0.5px;
78
+ }
79
+
80
+ .nav-logo .brain { font-size: 1.6rem; }
81
+
82
+ .nav-logo .text-gradient {
83
+ background: linear-gradient(135deg, var(--accent-blue), var(--accent-cyan));
84
+ -webkit-background-clip: text;
85
+ -webkit-text-fill-color: transparent;
86
+ background-clip: text;
87
+ }
88
+
89
+ .nav-links { display: flex; gap: 0.75rem; align-items: center; }
90
+
91
+ .nav-link {
92
+ padding: 0.5rem 1rem;
93
+ border-radius: 8px;
94
+ text-decoration: none;
95
+ font-size: 0.875rem;
96
+ font-weight: 500;
97
+ color: var(--text-secondary);
98
+ transition: all 0.2s;
99
+ border: 1px solid transparent;
100
+ }
101
+
102
+ .nav-link:hover {
103
+ color: var(--text-primary);
104
+ background: rgba(255,255,255,0.06);
105
+ border-color: var(--border);
106
+ }
107
+
108
+ .nav-link.primary {
109
+ background: linear-gradient(135deg, var(--accent-blue), var(--accent-purple));
110
+ color: white;
111
+ border: none;
112
+ }
113
+
114
+ .nav-link.primary:hover {
115
+ opacity: 0.9;
116
+ transform: translateY(-1px);
117
+ box-shadow: 0 4px 20px var(--glow-blue);
118
+ }
119
+
120
+ /* ── HERO ── */
121
+ .hero {
122
+ padding: 5rem 0 4rem;
123
+ text-align: center;
124
+ }
125
+
126
+ .hero-badge {
127
+ display: inline-flex;
128
+ align-items: center;
129
+ gap: 0.5rem;
130
+ padding: 0.4rem 1rem;
131
+ border-radius: 100px;
132
+ background: rgba(99,120,255,0.1);
133
+ border: 1px solid rgba(99,120,255,0.3);
134
+ font-size: 0.8rem;
135
+ font-weight: 600;
136
+ color: var(--accent-cyan);
137
+ text-transform: uppercase;
138
+ letter-spacing: 0.08em;
139
+ margin-bottom: 2rem;
140
+ }
141
+
142
+ .hero-badge .dot {
143
+ width: 6px; height: 6px;
144
+ border-radius: 50%;
145
+ background: var(--accent-cyan);
146
+ animation: pulse 2s infinite;
147
+ }
148
+
149
+ @keyframes pulse {
150
+ 0%, 100% { opacity: 1; }
151
+ 50% { opacity: 0.3; }
152
+ }
153
+
154
+ .hero h1 {
155
+ font-size: clamp(2.8rem, 6vw, 5rem);
156
+ font-weight: 900;
157
+ line-height: 1.05;
158
+ letter-spacing: -2px;
159
+ margin-bottom: 1.5rem;
160
+ }
161
+
162
+ .hero h1 .line1 { display: block; color: var(--text-primary); }
163
+ .hero h1 .line2 {
164
+ display: block;
165
+ background: linear-gradient(135deg, var(--accent-blue) 0%, var(--accent-cyan) 50%, var(--accent-purple) 100%);
166
+ -webkit-background-clip: text;
167
+ -webkit-text-fill-color: transparent;
168
+ background-clip: text;
169
+ }
170
+
171
+ .hero-subtitle {
172
+ font-size: 1.15rem;
173
+ color: var(--text-secondary);
174
+ max-width: 600px;
175
+ margin: 0 auto 2.5rem;
176
+ line-height: 1.7;
177
+ font-weight: 400;
178
+ }
179
+
180
+ .hero-cta {
181
+ display: flex;
182
+ gap: 1rem;
183
+ justify-content: center;
184
+ flex-wrap: wrap;
185
+ margin-bottom: 3.5rem;
186
+ }
187
+
188
+ .btn {
189
+ display: inline-flex;
190
+ align-items: center;
191
+ gap: 0.5rem;
192
+ padding: 0.85rem 1.8rem;
193
+ border-radius: 10px;
194
+ font-size: 0.95rem;
195
+ font-weight: 600;
196
+ text-decoration: none;
197
+ transition: all 0.25s;
198
+ cursor: pointer;
199
+ border: none;
200
+ }
201
+
202
+ .btn-primary {
203
+ background: linear-gradient(135deg, var(--accent-blue), var(--accent-purple));
204
+ color: white;
205
+ box-shadow: 0 4px 24px var(--glow-blue);
206
+ }
207
+
208
+ .btn-primary:hover {
209
+ transform: translateY(-2px);
210
+ box-shadow: 0 8px 32px rgba(99,120,255,0.5);
211
+ }
212
+
213
+ .btn-secondary {
214
+ background: rgba(255,255,255,0.05);
215
+ color: var(--text-primary);
216
+ border: 1px solid var(--border);
217
+ }
218
+
219
+ .btn-secondary:hover {
220
+ background: rgba(255,255,255,0.1);
221
+ border-color: var(--border-bright);
222
+ transform: translateY(-1px);
223
+ }
224
+
225
+ .btn-outline {
226
+ background: transparent;
227
+ color: var(--text-secondary);
228
+ border: 1px solid var(--border);
229
+ }
230
+
231
+ .btn-outline:hover {
232
+ color: var(--text-primary);
233
+ border-color: var(--border-bright);
234
+ }
235
+
236
+ /* ── STATS ROW ── */
237
+ .stats-row {
238
+ display: grid;
239
+ grid-template-columns: repeat(4, 1fr);
240
+ gap: 1px;
241
+ background: var(--border);
242
+ border-radius: 16px;
243
+ overflow: hidden;
244
+ border: 1px solid var(--border);
245
+ margin-bottom: 5rem;
246
+ }
247
+
248
+ .stat-item {
249
+ background: var(--bg-card);
250
+ padding: 1.5rem;
251
+ text-align: center;
252
+ }
253
+
254
+ .stat-value {
255
+ font-size: 1.8rem;
256
+ font-weight: 800;
257
+ background: linear-gradient(135deg, var(--accent-blue), var(--accent-cyan));
258
+ -webkit-background-clip: text;
259
+ -webkit-text-fill-color: transparent;
260
+ background-clip: text;
261
+ display: block;
262
+ margin-bottom: 0.25rem;
263
+ }
264
+
265
+ .stat-label {
266
+ font-size: 0.8rem;
267
+ color: var(--text-muted);
268
+ font-weight: 500;
269
+ text-transform: uppercase;
270
+ letter-spacing: 0.05em;
271
+ }
272
+
273
+ /* ── PIPELINE SECTION ── */
274
+ .section { margin-bottom: 5rem; }
275
+
276
+ .section-label {
277
+ font-size: 0.75rem;
278
+ font-weight: 700;
279
+ text-transform: uppercase;
280
+ letter-spacing: 0.1em;
281
+ color: var(--accent-cyan);
282
+ margin-bottom: 0.75rem;
283
+ }
284
+
285
+ .section-title {
286
+ font-size: 2rem;
287
+ font-weight: 800;
288
+ letter-spacing: -0.5px;
289
+ margin-bottom: 0.75rem;
290
+ }
291
+
292
+ .section-subtitle {
293
+ color: var(--text-secondary);
294
+ font-size: 1rem;
295
+ line-height: 1.7;
296
+ max-width: 560px;
297
+ margin-bottom: 2.5rem;
298
+ }
299
+
300
+ /* Pipeline steps */
301
+ .pipeline {
302
+ display: grid;
303
+ gap: 1rem;
304
+ }
305
+
306
+ .pipeline-step {
307
+ display: flex;
308
+ align-items: flex-start;
309
+ gap: 1.25rem;
310
+ padding: 1.25rem 1.5rem;
311
+ background: var(--bg-card);
312
+ border: 1px solid var(--border);
313
+ border-radius: 12px;
314
+ transition: all 0.25s;
315
+ position: relative;
316
+ overflow: hidden;
317
+ }
318
+
319
+ .pipeline-step::before {
320
+ content: '';
321
+ position: absolute;
322
+ left: 0; top: 0; bottom: 0;
323
+ width: 3px;
324
+ background: linear-gradient(180deg, var(--accent-blue), var(--accent-cyan));
325
+ opacity: 0;
326
+ transition: opacity 0.25s;
327
+ }
328
+
329
+ .pipeline-step:hover {
330
+ border-color: var(--border-bright);
331
+ background: var(--bg-card-hover);
332
+ }
333
+
334
+ .pipeline-step:hover::before { opacity: 1; }
335
+
336
+ .step-number {
337
+ min-width: 32px;
338
+ height: 32px;
339
+ border-radius: 8px;
340
+ background: rgba(99,120,255,0.15);
341
+ border: 1px solid rgba(99,120,255,0.3);
342
+ display: flex;
343
+ align-items: center;
344
+ justify-content: center;
345
+ font-size: 0.8rem;
346
+ font-weight: 700;
347
+ color: var(--accent-blue);
348
+ font-family: 'JetBrains Mono', monospace;
349
+ }
350
+
351
+ .step-content { flex: 1; }
352
+
353
+ .step-title {
354
+ font-size: 0.95rem;
355
+ font-weight: 600;
356
+ margin-bottom: 0.3rem;
357
+ display: flex;
358
+ align-items: center;
359
+ gap: 0.6rem;
360
+ }
361
+
362
+ .step-desc {
363
+ font-size: 0.85rem;
364
+ color: var(--text-secondary);
365
+ line-height: 1.5;
366
+ }
367
+
368
+ .step-tag {
369
+ font-size: 0.72rem;
370
+ font-weight: 600;
371
+ padding: 0.2rem 0.55rem;
372
+ border-radius: 6px;
373
+ font-family: 'JetBrains Mono', monospace;
374
+ }
375
+
376
+ .tag-blue { background: rgba(99,120,255,0.15); color: var(--accent-blue); }
377
+ .tag-cyan { background: rgba(0,212,255,0.12); color: var(--accent-cyan); }
378
+ .tag-green { background: rgba(16,185,129,0.12); color: var(--accent-green); }
379
+ .tag-purple { background: rgba(168,85,247,0.12); color: var(--accent-purple); }
380
+ .tag-orange { background: rgba(245,158,11,0.12); color: var(--accent-orange); }
381
+
382
+ /* ── FEATURES GRID ── */
383
+ .features-grid {
384
+ display: grid;
385
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
386
+ gap: 1.25rem;
387
+ }
388
+
389
+ .feature-card {
390
+ padding: 1.75rem;
391
+ background: var(--bg-card);
392
+ border: 1px solid var(--border);
393
+ border-radius: 14px;
394
+ transition: all 0.3s;
395
+ position: relative;
396
+ overflow: hidden;
397
+ }
398
+
399
+ .feature-card::after {
400
+ content: '';
401
+ position: absolute;
402
+ top: 0; left: 0; right: 0;
403
+ height: 1px;
404
+ background: linear-gradient(90deg, transparent, var(--accent-blue), transparent);
405
+ opacity: 0;
406
+ transition: opacity 0.3s;
407
+ }
408
+
409
+ .feature-card:hover {
410
+ border-color: var(--border-bright);
411
+ background: var(--bg-card-hover);
412
+ transform: translateY(-2px);
413
+ }
414
+
415
+ .feature-card:hover::after { opacity: 1; }
416
+
417
+ .feature-icon {
418
+ font-size: 1.8rem;
419
+ margin-bottom: 1rem;
420
+ display: block;
421
+ }
422
+
423
+ .feature-title {
424
+ font-size: 1rem;
425
+ font-weight: 700;
426
+ margin-bottom: 0.5rem;
427
+ }
428
+
429
+ .feature-desc {
430
+ font-size: 0.875rem;
431
+ color: var(--text-secondary);
432
+ line-height: 1.6;
433
+ }
434
+
435
+ /* ── ENDPOINTS ── */
436
+ .endpoints-table {
437
+ width: 100%;
438
+ border-collapse: separate;
439
+ border-spacing: 0;
440
+ background: var(--bg-card);
441
+ border: 1px solid var(--border);
442
+ border-radius: 14px;
443
+ overflow: hidden;
444
+ }
445
+
446
+ .endpoints-table th {
447
+ padding: 0.9rem 1.25rem;
448
+ background: rgba(99,120,255,0.08);
449
+ font-size: 0.75rem;
450
+ font-weight: 700;
451
+ text-transform: uppercase;
452
+ letter-spacing: 0.07em;
453
+ color: var(--text-muted);
454
+ text-align: left;
455
+ }
456
+
457
+ .endpoints-table td {
458
+ padding: 0.85rem 1.25rem;
459
+ font-size: 0.875rem;
460
+ border-top: 1px solid var(--border);
461
+ color: var(--text-secondary);
462
+ }
463
+
464
+ .endpoints-table tr:hover td {
465
+ background: rgba(255,255,255,0.02);
466
+ color: var(--text-primary);
467
+ }
468
+
469
+ .method-badge {
470
+ display: inline-block;
471
+ padding: 0.2rem 0.55rem;
472
+ border-radius: 5px;
473
+ font-size: 0.72rem;
474
+ font-weight: 700;
475
+ font-family: 'JetBrains Mono', monospace;
476
+ }
477
+
478
+ .method-get { background: rgba(16,185,129,0.15); color: var(--accent-green); }
479
+ .method-post { background: rgba(99,120,255,0.15); color: var(--accent-blue); }
480
+ .method-ws { background: rgba(245,158,11,0.15); color: var(--accent-orange); }
481
+ .method-delete { background: rgba(239,68,68,0.15); color: #f87171; }
482
+
483
+ .endpoint-path {
484
+ font-family: 'JetBrains Mono', monospace;
485
+ font-size: 0.85rem;
486
+ color: var(--text-primary);
487
+ }
488
+
489
+ /* ── TECH STACK ── */
490
+ .tech-grid {
491
+ display: grid;
492
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
493
+ gap: 1rem;
494
+ }
495
+
496
+ .tech-card {
497
+ padding: 1.25rem;
498
+ background: var(--bg-card);
499
+ border: 1px solid var(--border);
500
+ border-radius: 10px;
501
+ text-align: center;
502
+ transition: all 0.25s;
503
+ }
504
+
505
+ .tech-card:hover {
506
+ border-color: var(--border-bright);
507
+ transform: translateY(-2px);
508
+ }
509
+
510
+ .tech-name {
511
+ font-size: 0.9rem;
512
+ font-weight: 600;
513
+ margin-bottom: 0.3rem;
514
+ }
515
+
516
+ .tech-desc {
517
+ font-size: 0.78rem;
518
+ color: var(--text-muted);
519
+ }
520
+
521
+ /* ── FALLBACK CHAIN ── */
522
+ .fallback-chain {
523
+ display: flex;
524
+ align-items: center;
525
+ flex-wrap: wrap;
526
+ gap: 0;
527
+ padding: 1.5rem;
528
+ background: var(--bg-card);
529
+ border: 1px solid var(--border);
530
+ border-radius: 14px;
531
+ }
532
+
533
+ .fallback-item {
534
+ display: flex;
535
+ align-items: center;
536
+ gap: 0.75rem;
537
+ }
538
+
539
+ .model-chip {
540
+ padding: 0.4rem 0.9rem;
541
+ background: rgba(99,120,255,0.1);
542
+ border: 1px solid rgba(99,120,255,0.25);
543
+ border-radius: 8px;
544
+ font-family: 'JetBrains Mono', monospace;
545
+ font-size: 0.8rem;
546
+ color: var(--accent-blue);
547
+ white-space: nowrap;
548
+ }
549
+
550
+ .model-chip.primary {
551
+ background: rgba(168,85,247,0.1);
552
+ border-color: rgba(168,85,247,0.25);
553
+ color: var(--accent-purple);
554
+ }
555
+
556
+ .arrow-down {
557
+ font-size: 0.9rem;
558
+ color: var(--text-muted);
559
+ padding: 0 0.5rem;
560
+ }
561
+
562
+ /* ── FOOTER ── */
563
+ footer {
564
+ padding: 2.5rem 0;
565
+ border-top: 1px solid var(--border);
566
+ display: flex;
567
+ align-items: center;
568
+ justify-content: space-between;
569
+ flex-wrap: wrap;
570
+ gap: 1rem;
571
+ }
572
+
573
+ .footer-brand {
574
+ font-weight: 700;
575
+ background: linear-gradient(135deg, var(--accent-blue), var(--accent-cyan));
576
+ -webkit-background-clip: text;
577
+ -webkit-text-fill-color: transparent;
578
+ background-clip: text;
579
+ }
580
+
581
+ .footer-links { display: flex; gap: 1.5rem; }
582
+ .footer-link {
583
+ font-size: 0.875rem;
584
+ color: var(--text-muted);
585
+ text-decoration: none;
586
+ transition: color 0.2s;
587
+ }
588
+ .footer-link:hover { color: var(--text-primary); }
589
+
590
+ /* ── CODE BLOCK ── */
591
+ .code-block {
592
+ background: #0a0e1a;
593
+ border: 1px solid var(--border);
594
+ border-radius: 10px;
595
+ padding: 1.25rem 1.5rem;
596
+ font-family: 'JetBrains Mono', monospace;
597
+ font-size: 0.82rem;
598
+ color: #a8c4e0;
599
+ line-height: 1.7;
600
+ overflow-x: auto;
601
+ }
602
+
603
+ .code-block .comment { color: #4a6378; }
604
+ .code-block .key { color: #6378ff; }
605
+ .code-block .val { color: #10b981; }
606
+ .code-block .cmd { color: #f59e0b; }
607
+
608
+ /* ── Divider ── */
609
+ .divider {
610
+ height: 1px;
611
+ background: linear-gradient(90deg, transparent, var(--border-bright), transparent);
612
+ margin: 4rem 0;
613
+ }
614
+
615
+ @media (max-width: 768px) {
616
+ .stats-row { grid-template-columns: repeat(2, 1fr); }
617
+ .nav-links .nav-link:not(.primary) { display: none; }
618
+ .hero h1 { letter-spacing: -1px; }
619
+ footer { flex-direction: column; text-align: center; }
620
+ }
621
+ </style>
622
+ </head>
623
+ <body>
624
+
625
+ <div class="container">
626
+ <!-- NAV -->
627
+ <nav>
628
+ <div class="nav-logo">
629
+ <span class="brain">🧠</span>
630
+ <span class="text-gradient">MEXAR</span>
631
+ </div>
632
+ <div class="nav-links">
633
+ <a href="/docs" class="nav-link">API Docs</a>
634
+ <a href="/redoc" class="nav-link">ReDoc</a>
635
+ <a href="https://github.com/devrajsinh2012/Mexar" class="nav-link" target="_blank">GitHub</a>
636
+ <a href="https://mexar.vercel.app" class="nav-link primary" target="_blank">Open App β†’</a>
637
+ </div>
638
+ </nav>
639
+
640
+ <!-- HERO -->
641
+ <section class="hero">
642
+ <div class="hero-badge">
643
+ <span class="dot"></span>
644
+ API v2.0.0 Β· Operational
645
+ </div>
646
+
647
+ <h1>
648
+ <span class="line1">AI Agents That Know</span>
649
+ <span class="line2">What They Don't Know</span>
650
+ </h1>
651
+
652
+ <p class="hero-subtitle">
653
+ Build domain-specific AI agents from your documents.
654
+ Every answer is grounded in your data, cited with inline references,
655
+ and scored for hallucination risk using DeBERTa-v3 NLI.
656
+ </p>
657
+
658
+ <div class="hero-cta">
659
+ <a href="/docs" class="btn btn-primary">πŸ“– Explore API Docs</a>
660
+ <a href="https://mexar.vercel.app" class="btn btn-secondary" target="_blank">πŸš€ Launch App</a>
661
+ <a href="https://github.com/devrajsinh2012/Mexar" class="btn btn-outline" target="_blank">⭐ GitHub</a>
662
+ </div>
663
+
664
+ <!-- STATS -->
665
+ <div class="stats-row">
666
+ <div class="stat-item">
667
+ <span class="stat-value">~1.2s</span>
668
+ <span class="stat-label">Faithfulness Scoring</span>
669
+ </div>
670
+ <div class="stat-item">
671
+ <span class="stat-value">0.907</span>
672
+ <span class="stat-label">Guardrail F1 Score</span>
673
+ </div>
674
+ <div class="stat-item">
675
+ <span class="stat-value">781</span>
676
+ <span class="stat-label">Indexed Vector Chunks</span>
677
+ </div>
678
+ <div class="stat-item">
679
+ <span class="stat-value">5+</span>
680
+ <span class="stat-label">Groq Model Fallbacks</span>
681
+ </div>
682
+ </div>
683
+ </section>
684
+
685
+ <!-- PIPELINE -->
686
+ <section class="section">
687
+ <div class="section-label">How It Works</div>
688
+ <h2 class="section-title">The MEXAR RAG Pipeline</h2>
689
+ <p class="section-subtitle">
690
+ Every query goes through a 9-stage intelligent pipeline β€” from multimodal input
691
+ all the way to a cited, faithfulness-verified response.
692
+ </p>
693
+
694
+ <div class="pipeline">
695
+ <div class="pipeline-step">
696
+ <div class="step-number">01</div>
697
+ <div class="step-content">
698
+ <div class="step-title">
699
+ 🎀 Multimodal Input Processing
700
+ <span class="step-tag tag-orange">optional</span>
701
+ </div>
702
+ <div class="step-desc">Audio β†’ Groq Whisper v3 STT Β· Images β†’ Groq Vision Β· Video β†’ OpenCV frame extraction β†’ Vision</div>
703
+ </div>
704
+ </div>
705
+
706
+ <div class="pipeline-step">
707
+ <div class="step-number">02</div>
708
+ <div class="step-content">
709
+ <div class="step-title">
710
+ πŸ” Intent &amp; Prompt Analysis
711
+ <span class="step-tag tag-blue">LLM</span>
712
+ </div>
713
+ <div class="step-desc">Parse query intent (factual / analytical / comparative), detect domain topic, optionally rewrite query for retrieval clarity.</div>
714
+ </div>
715
+ </div>
716
+
717
+ <div class="pipeline-step">
718
+ <div class="step-number">03</div>
719
+ <div class="step-content">
720
+ <div class="step-title">
721
+ πŸ›‘οΈ Domain Guardrail Check
722
+ <span class="step-tag tag-green">F1 = 0.9072</span>
723
+ </div>
724
+ <div class="step-desc">TF-IDF cosine similarity vs agent signature + spaCy NER Jaccard overlap. Threshold = 0.25. Out-of-domain queries rejected with explanation β€” no hallucination.</div>
725
+ </div>
726
+ </div>
727
+
728
+ <div class="pipeline-step">
729
+ <div class="step-number">04</div>
730
+ <div class="step-content">
731
+ <div class="step-title">
732
+ ⚑ Hybrid Vector + Keyword Retrieval
733
+ <span class="step-tag tag-cyan">pgvector + BM25</span>
734
+ </div>
735
+ <div class="step-desc">Dense: FastEmbed bge-small-en-v1.5 (384-dim) cosine search via pgvector. Sparse: PostgreSQL tsvector BM25 full-text search. Fused via Reciprocal Rank Fusion (RRF): score = Ξ£ 1/(rank + 60).</div>
736
+ </div>
737
+ </div>
738
+
739
+ <div class="pipeline-step">
740
+ <div class="step-number">05</div>
741
+ <div class="step-content">
742
+ <div class="step-title">
743
+ 🎯 Cross-Encoder Reranking
744
+ <span class="step-tag tag-purple">sentence-transformers</span>
745
+ </div>
746
+ <div class="step-desc">Re-scores top-20 retrieved candidates using a cross-encoder for precision. Selects final top-5 context chunks for answer generation.</div>
747
+ </div>
748
+ </div>
749
+
750
+ <div class="pipeline-step">
751
+ <div class="step-number">06</div>
752
+ <div class="step-content">
753
+ <div class="step-title">
754
+ 🧠 LLM Answer Generation
755
+ <span class="step-tag tag-blue">Groq</span>
756
+ </div>
757
+ <div class="step-desc">System prompt with retrieved context. Multi-model inference: llama-3.3-70b β†’ llama-3.1-8b β†’ mixtral-8x7b β†’ gemma2-9b. Automatic quota fallback.</div>
758
+ </div>
759
+ </div>
760
+
761
+ <div class="pipeline-step">
762
+ <div class="step-number">07</div>
763
+ <div class="step-content">
764
+ <div class="step-title">
765
+ πŸ“Ž Source Attribution
766
+ <span class="step-tag tag-cyan">citations</span>
767
+ </div>
768
+ <div class="step-desc">Match answer sentences to source chunks. Assign [1], [2], [3] inline reference markers. Track provenance per claim.</div>
769
+ </div>
770
+ </div>
771
+
772
+ <div class="pipeline-step">
773
+ <div class="step-number">08</div>
774
+ <div class="step-content">
775
+ <div class="step-title">
776
+ βœ… DeBERTa-v3 Faithfulness Scoring
777
+ <span class="step-tag tag-green">NLI</span>
778
+ </div>
779
+ <div class="step-desc">Extract claims from answer. For each claim-chunk pair: NLI inference (entailment β†’ faithful, contradiction β†’ hallucinated). Batched via torch.inference_mode() β€” ~1.2s/query (50Γ— speedup vs baseline).</div>
780
+ </div>
781
+ </div>
782
+
783
+ <div class="pipeline-step">
784
+ <div class="step-number">09</div>
785
+ <div class="step-content">
786
+ <div class="step-title">
787
+ πŸ”¬ Explainability Packaging
788
+ <span class="step-tag tag-purple">transparent</span>
789
+ </div>
790
+ <div class="step-desc">Reasoning trace Β· Confidence breakdown Β· Sources cited Β· Guardrail decision log β€” all surfaced to the frontend UI panel.</div>
791
+ </div>
792
+ </div>
793
+ </div>
794
+ </section>
795
+
796
+ <div class="divider"></div>
797
+
798
+ <!-- FEATURES -->
799
+ <section class="section">
800
+ <div class="section-label">Capabilities</div>
801
+ <h2 class="section-title">Everything You Need</h2>
802
+ <p class="section-subtitle">A complete RAG platform β€” from document ingestion to explainable, grounded answers.</p>
803
+
804
+ <div class="features-grid">
805
+ <div class="feature-card">
806
+ <span class="feature-icon">πŸ”</span>
807
+ <div class="feature-title">Hybrid Search + RRF Fusion</div>
808
+ <div class="feature-desc">Vector cosine (pgvector) and BM25 keyword search fused via Reciprocal Rank Fusion for optimal retrieval across all document types.</div>
809
+ </div>
810
+ <div class="feature-card">
811
+ <span class="feature-icon">βœ…</span>
812
+ <div class="feature-title">Faithfulness Verification</div>
813
+ <div class="feature-desc">DeBERTa-v3-base NLI model scores every answer claim against retrieved context. Quantified hallucination risk, not just vibes.</div>
814
+ </div>
815
+ <div class="feature-card">
816
+ <span class="feature-icon">πŸ›‘οΈ</span>
817
+ <div class="feature-title">Domain Guardrails</div>
818
+ <div class="feature-desc">TF-IDF + spaCy NER Jaccard similarity prevents answering out-of-domain questions. Tuned to F1 = 0.9072 at threshold 0.25.</div>
819
+ </div>
820
+ <div class="feature-card">
821
+ <span class="feature-icon">πŸ“Ž</span>
822
+ <div class="feature-title">Inline Source Citations</div>
823
+ <div class="feature-desc">Every sentence references its source chunk with [1], [2] markers. Click any citation to see the exact source text and file name.</div>
824
+ </div>
825
+ <div class="feature-card">
826
+ <span class="feature-icon">πŸ—£οΈ</span>
827
+ <div class="feature-title">Multimodal Input</div>
828
+ <div class="feature-desc">Ask questions via audio (Groq Whisper), upload images for visual Q&A (Groq Vision), or extract info from video frames (OpenCV).</div>
829
+ </div>
830
+ <div class="feature-card">
831
+ <span class="feature-icon">🧠</span>
832
+ <div class="feature-title">Explainability Panel</div>
833
+ <div class="feature-desc">Full reasoning trace exposed in the UI: retrieval scores, reranker scores, confidence breakdown, guardrail decision, and sources cited.</div>
834
+ </div>
835
+ <div class="feature-card">
836
+ <span class="feature-icon">πŸ”Š</span>
837
+ <div class="feature-title">Text-to-Speech</div>
838
+ <div class="feature-desc">ElevenLabs API integration with per-sentence TTS playback. Falls back to Web Speech API automatically.</div>
839
+ </div>
840
+ <div class="feature-card">
841
+ <span class="feature-icon">⚑</span>
842
+ <div class="feature-title">Real-time WebSocket Chat</div>
843
+ <div class="feature-desc">Streaming responses via WebSocket with compilation progress tracking. No polling required.</div>
844
+ </div>
845
+ <div class="feature-card">
846
+ <span class="feature-icon">πŸ“</span>
847
+ <div class="feature-title">5 Document Formats</div>
848
+ <div class="feature-desc">Upload PDF, DOCX, CSV, JSON, or TXT files. Semantic chunking preserves context boundaries for better retrieval quality.</div>
849
+ </div>
850
+ </div>
851
+ </section>
852
+
853
+ <div class="divider"></div>
854
+
855
+ <!-- ENDPOINTS -->
856
+ <section class="section">
857
+ <div class="section-label">REST API</div>
858
+ <h2 class="section-title">API Endpoints</h2>
859
+ <p class="section-subtitle">Full interactive documentation available at <a href="/docs" style="color: var(--accent-blue); text-decoration: none;">/docs</a></p>
860
+
861
+ <table class="endpoints-table">
862
+ <thead>
863
+ <tr>
864
+ <th>Method</th>
865
+ <th>Endpoint</th>
866
+ <th>Description</th>
867
+ </tr>
868
+ </thead>
869
+ <tbody>
870
+ <tr><td><span class="method-badge method-post">POST</span></td><td class="endpoint-path">/api/auth/register</td><td>Create a new user account</td></tr>
871
+ <tr><td><span class="method-badge method-post">POST</span></td><td class="endpoint-path">/api/auth/login</td><td>Login and receive JWT bearer token</td></tr>
872
+ <tr><td><span class="method-badge method-get">GET</span></td><td class="endpoint-path">/api/agents/</td><td>List all compiled agents for current user</td></tr>
873
+ <tr><td><span class="method-badge method-post">POST</span></td><td class="endpoint-path">/api/agents/</td><td>Create a new agent</td></tr>
874
+ <tr><td><span class="method-badge method-post">POST</span></td><td class="endpoint-path">/api/compile/</td><td>Start knowledge compilation from uploaded files</td></tr>
875
+ <tr><td><span class="method-badge method-get">GET</span></td><td class="endpoint-path">/api/compile/{job_id}</td><td>Poll compilation job status + progress</td></tr>
876
+ <tr><td><span class="method-badge method-post">POST</span></td><td class="endpoint-path">/api/chat/</td><td>Send a query to an agent (REST)</td></tr>
877
+ <tr><td><span class="method-badge method-ws">WS</span></td><td class="endpoint-path">/ws/chat/{agent_id}</td><td>Real-time streaming chat via WebSocket</td></tr>
878
+ <tr><td><span class="method-badge method-get">GET</span></td><td class="endpoint-path">/api/health</td><td>Health check β€” returns API + Groq status</td></tr>
879
+ </tbody>
880
+ </table>
881
+ </section>
882
+
883
+ <div class="divider"></div>
884
+
885
+ <!-- GROQ FALLBACK -->
886
+ <section class="section">
887
+ <div class="section-label">Reliability</div>
888
+ <h2 class="section-title">Multi-Model Fallback Chain</h2>
889
+ <p class="section-subtitle">Automatic failover across Groq models when rate limits are hit β€” zero downtime.</p>
890
+
891
+ <div class="fallback-chain">
892
+ <div class="fallback-item">
893
+ <span class="model-chip primary">openai/gpt-oss-120b</span>
894
+ <span class="arrow-down">β†’ quota β†’</span>
895
+ </div>
896
+ <div class="fallback-item">
897
+ <span class="model-chip">llama-3.3-70b-versatile</span>
898
+ <span class="arrow-down">β†’ quota β†’</span>
899
+ </div>
900
+ <div class="fallback-item">
901
+ <span class="model-chip">llama-3.1-8b-instant</span>
902
+ <span class="arrow-down">β†’ quota β†’</span>
903
+ </div>
904
+ <div class="fallback-item">
905
+ <span class="model-chip">mixtral-8x7b-32768</span>
906
+ <span class="arrow-down">β†’ quota β†’</span>
907
+ </div>
908
+ <div class="fallback-item">
909
+ <span class="model-chip">gemma2-9b-it</span>
910
+ </div>
911
+ </div>
912
+ </section>
913
+
914
+ <div class="divider"></div>
915
+
916
+ <!-- QUICK START -->
917
+ <section class="section">
918
+ <div class="section-label">Getting Started</div>
919
+ <h2 class="section-title">Quick Integration</h2>
920
+ <p class="section-subtitle">Start querying your agent in three steps.</p>
921
+
922
+ <div class="code-block">
923
+ <span class="comment"># 1. Register and login</span>
924
+ <span class="cmd">POST</span> /api/auth/register { "email": "you@example.com", "password": "..." }
925
+ <span class="cmd">POST</span> /api/auth/login β†’ <span class="val">{ "access_token": "eyJ..." }</span>
926
+
927
+ <span class="comment"># 2. Compile an agent from your documents</span>
928
+ <span class="cmd">POST</span> /api/compile/ <span class="key">Authorization:</span> Bearer {token}
929
+ <span class="key">Files:</span> report.pdf, research.docx
930
+ β†’ <span class="val">{ "job_id": 42, "status": "compiling" }</span>
931
+
932
+ <span class="comment"># 3. Chat with your agent</span>
933
+ <span class="cmd">POST</span> /api/chat/ <span class="key">Authorization:</span> Bearer {token}
934
+ <span class="val">{ "agent_id": 36, "message": "What are the key findings?" }</span>
935
+ β†’ <span class="val">{ "answer": "...[1][2]", "faithfulness": 0.87, "sources": [...] }</span>
936
+ </div>
937
+ </section>
938
+
939
+ <!-- FOOTER -->
940
+ <footer>
941
+ <div>
942
+ <span class="footer-brand">MEXAR Core Engine v2.0.0</span>
943
+ <div style="font-size: 0.8rem; color: var(--text-muted); margin-top: 0.3rem;">
944
+ Built with FastAPI Β· pgvector Β· Groq Β· DeBERTa-v3
945
+ </div>
946
+ </div>
947
+ <div class="footer-links">
948
+ <a href="/docs" class="footer-link">API Docs</a>
949
+ <a href="/redoc" class="footer-link">ReDoc</a>
950
+ <a href="https://mexar.vercel.app" class="footer-link" target="_blank">Frontend App</a>
951
+ <a href="https://github.com/devrajsinh2012/Mexar" class="footer-link" target="_blank">GitHub</a>
952
+ </div>
953
+ </footer>
954
+ </div>
955
+
956
+ </body>
957
+ </html>
frontend/package.json CHANGED
@@ -1,44 +1,44 @@
1
- {
2
- "name": "mexar-frontend",
3
- "version": "1.0.0",
4
- "description": "MEXAR Core Engine - Frontend",
5
- "private": true,
6
- "dependencies": {
7
- "@emotion/react": "^11.11.3",
8
- "@emotion/styled": "^11.11.0",
9
- "@mui/icons-material": "^5.15.6",
10
- "@mui/material": "^5.15.6",
11
- "axios": "^1.6.5",
12
- "d3": "^7.9.0",
13
- "react": "^18.2.0",
14
- "react-dom": "^18.2.0",
15
- "react-dropzone": "^14.2.3",
16
- "react-router-dom": "^6.21.3",
17
- "react-scripts": "5.0.1",
18
- "recharts": "^2.10.4"
19
- },
20
- "scripts": {
21
- "start": "react-scripts start",
22
- "build": "react-scripts build",
23
- "test": "react-scripts test",
24
- "eject": "react-scripts eject"
25
- },
26
- "proxy": "http://127.0.0.1:8000",
27
- "eslintConfig": {
28
- "extends": [
29
- "react-app"
30
- ]
31
- },
32
- "browserslist": {
33
- "production": [
34
- ">0.2%",
35
- "not dead",
36
- "not op_mini all"
37
- ],
38
- "development": [
39
- "last 1 chrome version",
40
- "last 1 firefox version",
41
- "last 1 safari version"
42
- ]
43
- }
44
  }
 
1
+ {
2
+ "name": "mexar-frontend",
3
+ "version": "1.0.0",
4
+ "description": "MEXAR Core Engine - Frontend",
5
+ "private": true,
6
+ "dependencies": {
7
+ "@emotion/react": "^11.11.3",
8
+ "@emotion/styled": "^11.11.0",
9
+ "@mui/icons-material": "^5.15.6",
10
+ "@mui/material": "^5.15.6",
11
+ "axios": "^1.6.5",
12
+ "d3": "^7.9.0",
13
+ "react": "^18.2.0",
14
+ "react-dom": "^18.2.0",
15
+ "react-dropzone": "^14.2.3",
16
+ "react-router-dom": "^6.21.3",
17
+ "react-scripts": "5.0.1",
18
+ "recharts": "^2.10.4"
19
+ },
20
+ "scripts": {
21
+ "start": "react-scripts start",
22
+ "build": "CI=false react-scripts build",
23
+ "test": "react-scripts test",
24
+ "eject": "react-scripts eject"
25
+ },
26
+ "proxy": "http://127.0.0.1:8000",
27
+ "eslintConfig": {
28
+ "extends": [
29
+ "react-app"
30
+ ]
31
+ },
32
+ "browserslist": {
33
+ "production": [
34
+ ">0.2%",
35
+ "not dead",
36
+ "not op_mini all"
37
+ ],
38
+ "development": [
39
+ "last 1 chrome version",
40
+ "last 1 firefox version",
41
+ "last 1 safari version"
42
+ ]
43
+ }
44
  }