Spaces:
Sleeping
Sleeping
File size: 9,549 Bytes
42db8ec acc2582 849b111 e7c1af8 849b111 42db8ec 849b111 acc2582 849b111 acc2582 849b111 acc2582 849b111 acc2582 849b111 acc2582 15873dc acc2582 849b111 acc2582 15873dc acc2582 849b111 acc2582 849b111 acc2582 42db8ec acc2582 849b111 acc2582 849b111 acc2582 849b111 cbaf4a5 849b111 acc2582 42db8ec acc2582 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
import gradio as gr
import pandas as pd
import os
from database import (
fetch_all_faq_metadata, fetch_all_podcast_metadata,
add_faq_entry, update_faq_entry, delete_faq_entry,
bulk_update_faqs, bulk_update_podcasts
)
from utils import recalculate_all_embeddings
from config import OPENAI_API_KEY
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Basic Admin Credentials (MUST be set in Hugging Face Secrets or .env)
ADMIN_USER = os.environ.get("ADMIN_USER", "admin")
ADMIN_PASS = os.environ.get("ADMIN_PASS")
if not ADMIN_PASS:
raise ValueError("CRITICAL SECURITY ERROR: ADMIN_PASS environment variable is not set.")
# Path to SQLite DB β override via DB_PATH env var if your file has a different name
DB_PATH = os.environ.get("DB_PATH", "getscene_ai.sqlite")
# ββ Helper functions ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def get_faqs():
data = fetch_all_faq_metadata()
return pd.DataFrame(data)
def get_podcasts():
data = fetch_all_podcast_metadata()
return pd.DataFrame(data)
def handle_faq_upload(file):
if file is None:
return "No file uploaded."
try:
df = pd.read_csv(file.name) if file.name.endswith('.csv') else pd.read_excel(file.name)
bulk_update_faqs(df.to_dict('records'))
return f"Successfully uploaded {len(df)} FAQs. Don't forget to Sync & Embed!"
except Exception as e:
return f"Error: {e}"
def handle_podcast_upload(file):
if file is None:
return "No file uploaded."
try:
df = pd.read_csv(file.name) if file.name.endswith('.csv') else pd.read_excel(file.name)
bulk_update_podcasts(df.to_dict('records'))
return f"Successfully uploaded {len(df)} Podcasts. Don't forget to Sync & Embed!"
except Exception as e:
return f"Error: {e}"
def run_sync():
try:
recalculate_all_embeddings()
return "Sync Complete! All missing embeddings have been generated."
except Exception as e:
return f"Sync Failed: {e}"
def prepare_download():
"""Return the SQLite file path for Gradio to serve as a download."""
if not os.path.exists(DB_PATH):
return None, f"β Database file not found at: `{DB_PATH}`. Check your DB_PATH env var."
size_mb = os.path.getsize(DB_PATH) / (1024 * 1024)
return DB_PATH, f"β
Ready β `{os.path.basename(DB_PATH)}` ({size_mb:.2f} MB). Click the file below to save it."
def check_login(username, password):
if username == ADMIN_USER and password == ADMIN_PASS:
return (
gr.update(visible=False), # Hide login panel
gr.update(visible=True), # Show dashboard
"" # Clear error
)
else:
return (
gr.update(visible=True),
gr.update(visible=False),
"β Invalid username or password."
)
def logout():
return (
gr.update(visible=True), # Show login panel
gr.update(visible=False), # Hide dashboard
"", # Clear username field
"" # Clear password field
)
# ββ UI ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
with gr.Blocks(title="Get Scene Admin Dashboard", theme=gr.themes.Base()) as demo:
# ββ LOGIN PANEL ββββββββββββββββββββββββββββββββββββββββββββββ
with gr.Column(visible=True, elem_id="login_panel") as login_panel:
gr.Markdown("# Get Scene Admin\nPlease log in to continue.")
login_user = gr.Textbox(label="Username", placeholder="Enter username")
login_pass = gr.Textbox(label="Password", placeholder="Enter password", type="password")
login_error = gr.Markdown("")
login_btn = gr.Button("Log In", variant="primary")
# ββ DASHBOARD (hidden until login) βββββββββββββββββββββββββββ
with gr.Column(visible=False) as dashboard:
with gr.Row():
gr.Markdown("# Get Scene Admin Dashboard")
logout_btn = gr.Button("Log Out", variant="stop", scale=0)
gr.Markdown("Manage FAQs, Podcasts, and Knowledge Embeddings.")
with gr.Tabs():
# ββ Tab 1: FAQs ββββββββββββββββββββββββββββββββββββββ
with gr.TabItem("Manage FAQs"):
with gr.Row():
faq_df = gr.Dataframe(
value=get_faqs,
headers=["id", "question", "answer"],
datatype=["number", "str", "str"],
interactive=True,
label="FAQ Database"
)
with gr.Row():
with gr.Column():
gr.Markdown("### Add New FAQ")
new_q = gr.Textbox(label="Question")
new_a = gr.TextArea(label="Answer")
add_btn = gr.Button("Add Entry", variant="primary")
with gr.Column():
gr.Markdown("### Bulk Upload")
faq_file = gr.File(label="Upload CSV/Excel (Columns: Question, Answer)")
upload_faq_btn = gr.Button("Bulk Upload FAQs")
faq_upload_status = gr.Textbox(label="Status", interactive=False)
def add_and_refresh(q, a):
add_faq_entry(q, a)
return get_faqs(), "", ""
add_btn.click(add_and_refresh, [new_q, new_a], [faq_df, new_q, new_a])
upload_faq_btn.click(handle_faq_upload, [faq_file], [faq_upload_status])
# ββ Tab 2: Podcasts ββββββββββββββββββββββββββββββββββ
with gr.TabItem("Podcasts"):
pod_df = gr.Dataframe(
value=get_podcasts,
headers=["id", "guest_name", "youtube_url", "summary"],
datatype=["number", "str", "str", "str"],
label="Podcast Episodes"
)
gr.Markdown("### Bulk Upload Podcasts")
pod_file = gr.File(label="Upload CSV/Excel (Columns: Guest Name, YouTube URL, Summary)")
upload_pod_btn = gr.Button("Bulk Upload Podcasts")
pod_upload_status = gr.Textbox(label="Status", interactive=False)
upload_pod_btn.click(handle_podcast_upload, [pod_file], [pod_upload_status])
# ββ Tab 3: Sync & Embed ββββββββββββββββββββββββββββββ
with gr.TabItem("Sync & Embed"):
gr.Markdown("### Recalculate Embeddings")
gr.Markdown(
"When you change text or upload new data, the 'embeddings' (AI understanding) "
"must be recalculated for the chatbot to recognize the new information."
)
sync_btn = gr.Button("π Sync & Recalculate Embeddings", variant="primary", scale=2)
sync_status = gr.Textbox(label="Sync Status", interactive=False)
sync_btn.click(run_sync, None, [sync_status])
# ββ Tab 4: Download Database βββββββββββββββββββββββββ
with gr.TabItem("β¬οΈ Download Database"):
gr.Markdown("### Download SQLite Database")
gr.Markdown(
"Click the button below to download the raw `database.db` SQLite file."
)
download_btn = gr.Button("β¬οΈ Download database.db", variant="primary")
download_status = gr.Markdown("")
db_file_output = gr.File(
label="π¦ database.db β click to save",
visible=False,
interactive=False
)
def on_download_click():
path, msg = prepare_download()
if path:
return gr.update(value=path, visible=True), msg
else:
return gr.update(visible=False), msg
download_btn.click(
on_download_click,
inputs=None,
outputs=[db_file_output, download_status]
)
# ββ WIRING ββββββββββββββββββββββββββββββββββββββββββββββββββββ
login_btn.click(
check_login,
inputs=[login_user, login_pass],
outputs=[login_panel, dashboard, login_error]
)
login_pass.submit(
check_login,
inputs=[login_user, login_pass],
outputs=[login_panel, dashboard, login_error]
)
logout_btn.click(
logout,
inputs=None,
outputs=[login_panel, dashboard, login_user, login_pass]
)
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0") |