import os import gradio as gr import rag_engine as rag print("Loading RAG engine...") RETRIEVER = rag.build_retriever() print(f"Loaded {len(RETRIEVER['texts'])} FAQ entries.") API_KEY = os.environ.get("OPENROUTER_API_KEY", "") DEFAULT_ACCENT = "#667eea" DEFAULT_BOT_NAME = "FlowBar Support" DEFAULT_TAGLINE = "Ask me anything about FlowBar -- account setup, features, billing, or troubleshooting." PRESET_COLORS = [ ("Violet", "#667eea"), ("Teal", "#0d9488"), ("Blue", "#3b82f6"), ("Green", "#22c55e"), ("Orange", "#f97316"), ("Pink", "#ec4899"), ("Red", "#ef4444"), ("Gold", "#eab308"), ("Gray", "#6b7280"), ] def respond(message, history): if not message.strip(): return "Please enter a question." results = rag.search(RETRIEVER, message, top_k=3) if not results: return "I could not find relevant info. Try rephrasing." if API_KEY: text, _ = rag.generate_response(message, results, API_KEY) else: text, _ = rag.generate_response_light(message, results) return text def _is_dark_color(hex_color): """Returns True if accent is dark (text needs to be white for contrast).""" hex_color = hex_color.lstrip("#") r, g, b = int(hex_color[0:2], 16), int(hex_color[2:4], 16), int(hex_color[4:6], 16) luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255 return luminance < 0.5 def make_custom_css(accent): """Return full CSS with accent color applied to visible elements.""" text_color = "#ffffff" if _is_dark_color(accent) else "#1a1a2e" # Gradio 5.20 wraps every CSS rule with high-specificity container prefix, # so we duplicate each rule with the same prefix to match specificity. # With equal specificity, the later rule (our dynamic injection) wins. p = ".gradio-container.gradio-container-5-20-0 .contain" return f""" .gradio-container {{ max-width: 800px !important; margin: 0 auto; min-height: 600px; }} .bot-row {{ background: #2d2d3d !important; }} {p} .bot-row {{ background: #2d2d3d !important; }} footer {{ display: none !important; }} {p} footer {{ display: none !important; }} /* --- Accent: header text --- */ h1 {{ color: {accent} !important; text-align: center; margin-bottom: 4px; }} {p} h1 {{ color: {accent} !important; text-align: center; margin-bottom: 4px; }} /* --- Accent: send button --- */ .submit-button, button.primary {{ background: {accent} !important; border-color: {accent} !important; color: {text_color} !important; }} {p} .submit-button, {p} button.primary {{ background: {accent} !important; border-color: {accent} !important; color: {text_color} !important; }} .submit-button:hover, button.primary:hover {{ filter: brightness(1.15) !important; }} {p} .submit-button:hover, {p} button.primary:hover {{ filter: brightness(1.15) !important; }} /* --- Accent: example buttons --- */ button.example {{ border-color: {accent}66 !important; color: {accent} !important; }} {p} button.example {{ border-color: {accent}66 !important; color: {accent} !important; }} button.example:hover {{ background: {accent}22 !important; border-color: {accent} !important; }} {p} button.example:hover {{ background: {accent}22 !important; border-color: {accent} !important; }} /* --- Accent: user chat bubbles --- */ .user-row {{ background: {accent} !important; color: {text_color} !important; border-radius: 18px 18px 4px 18px !important; }} {p} .user-row {{ background: {accent} !important; color: {text_color} !important; border-radius: 18px 18px 4px 18px !important; }} /* --- Accent: accordion toggle text --- */ .label-wrap {{ color: {accent} !important; }} {p} .label-wrap {{ color: {accent} !important; }} /* --- Accent: accordion open state --- */ .label-wrap.open {{ border-color: {accent} !important; }} {p} .label-wrap.open {{ border-color: {accent} !important; }} """ def make_header(name, tagline, accent): return f"""
{tagline}