"""user interface for RAG""" from __future__ import annotations import os import threading from typing import Any import gradio as gr import spaces from config import SETTINGS from rag_engine import RAGEngine ENGINE = RAGEngine() ENGINE_LOCK = threading.Lock() CSS = r""" :root { --surface: rgba(11, 17, 31, .76); --surface-2: rgba(20, 29, 50, .72); --line: rgba(148, 163, 184, .16); --muted: #9ba9bd; --text: #f7f9fc; --accent: #8b5cf6; --accent-2: #22d3ee; } .gradio-container { max-width: 1480px !important; margin: 0 auto !important; color: var(--text) !important; background: radial-gradient( circle at 8% 8%, rgba(139, 92, 246, .20), transparent 29% ), radial-gradient( circle at 91% 12%, rgba(34, 211, 238, .14), transparent 26% ), linear-gradient( 145deg, #050811 0%, #080d19 46%, #0b1020 100% ) !important; min-height: 100vh; } .main-shell { padding: 28px 24px 44px; } .hero { position: relative; overflow: hidden; border: 1px solid var(--line); background: linear-gradient( 135deg, rgba(19, 27, 48, .94), rgba(10, 15, 29, .84) ); border-radius: 24px; padding: 30px 32px; box-shadow: 0 28px 80px rgba(0, 0, 0, .28); margin-bottom: 18px; } .hero::after { content: ""; position: absolute; width: 330px; height: 330px; right: -110px; top: -160px; background: radial-gradient( circle, rgba(34, 211, 238, .22), transparent 65% ); } .eyebrow { color: #b8a6ff; font-size: 12px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; } .hero h1 { margin: 8px 0 7px; font-size: clamp(32px, 5vw, 57px); line-height: 1.02; letter-spacing: -.045em; } .hero p { max-width: 850px; color: #b8c3d4; font-size: 16px; line-height: 1.65; margin: 0; } .badges { display: flex; flex-wrap: wrap; gap: 9px; margin-top: 18px; } .badge { border: 1px solid var(--line); background: rgba(255, 255, 255, .035); padding: 7px 11px; border-radius: 999px; color: #cbd5e1; font-size: 12px; } .badge strong { color: #fff; } .panel, .gr-panel, .block { border-color: var(--line) !important; } .app-panel { background: var(--surface) !important; border: 1px solid var(--line) !important; border-radius: 20px !important; box-shadow: 0 18px 48px rgba(0, 0, 0, .20); } .sidebar-card { background: var(--surface-2); border: 1px solid var(--line); border-radius: 18px; padding: 18px; margin-bottom: 14px; } .sidebar-card h3 { margin: 0 0 8px; font-size: 14px; } .sidebar-card p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.55; } #chatbot { min-height: 520px; } #chatbot .message { border-radius: 16px !important; } #prompt textarea { font-size: 15px !important; line-height: 1.5 !important; } #send-button { min-width: 115px; font-weight: 800; } .source-list { display: grid; gap: 10px; } .source-card { border: 1px solid var(--line); border-radius: 14px; background: rgba(255, 255, 255, .025); overflow: hidden; } .source-card summary { cursor: pointer; list-style: none; display: grid; grid-template-columns: 28px 1fr auto; gap: 9px; align-items: center; padding: 12px 13px; } .source-card summary::-webkit-details-marker { display: none; } .source-number { display: grid; place-items: center; width: 24px; height: 24px; border-radius: 8px; background: linear-gradient( 135deg, var(--accent), var(--accent-2) ); color: white; font-size: 11px; font-weight: 900; } .source-title { color: #e5eaf2; font-size: 13px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .source-score { font-size: 11px; color: #8cdff0; font-variant-numeric: tabular-nums; } .source-body { padding: 0 14px 12px 50px; color: #b7c2d4; font-size: 12px; line-height: 1.65; } .source-meta { padding: 9px 14px; border-top: 1px solid var(--line); color: #75859c; font-size: 10px; } .empty-state { color: var(--muted); padding: 18px; text-align: center; border: 1px dashed var(--line); border-radius: 14px; } .footer-note { color: #718097; font-size: 11px; text-align: center; margin-top: 16px; } button.primary { background: linear-gradient( 135deg, #7c3aed, #0891b2 ) !important; border: none !important; } .accordion { background: rgba(255, 255, 255, .02) !important; border-color: var(--line) !important; } @media (max-width: 800px) { .main-shell { padding: 14px 10px 28px; } .hero { padding: 23px 20px; border-radius: 18px; } #chatbot { min-height: 430px; } } """ HEAD = """ """ def get_engine() -> RAGEngine: """Initialize and return the shared RAG engine.""" if not ENGINE.ready: with ENGINE_LOCK: if not ENGINE.ready: ENGINE.initialize() return ENGINE @spaces.GPU(duration=60) def run_chat( message: str, history: list[dict[str, Any]] | None, top_k: int, dense_weight: float, use_reranker: bool, temperature: float, max_tokens: int, ): """Process a question through the RAG pipeline.""" clean_message = (message or "").strip() history = list(history or []) if not clean_message: return ( history, "
Ask an RAG model questions trained on
rag-datasets/rag-mini-wikipedia.