Spaces:
Paused
Paused
# app.py | |
import os | |
import time | |
import gradio as gr | |
import importlib.util | |
from huggingface_hub import hf_hub_download | |
# ---------------------------------------------------------------------- | |
# Helper to read secrets from the HF Space environment | |
# ---------------------------------------------------------------------- | |
def _secret(key: str, fallback: str = None) -> str: | |
val = os.getenv(key) | |
if val is not None: return val | |
if fallback is not None: return fallback | |
raise RuntimeError(f"Secret '{key}' not found. Please add it to your Space secrets.") | |
# ---------------------------------------------------------------------- | |
# 1. Configuration & Constants | |
# ---------------------------------------------------------------------- | |
# The private repo containing the vector DB and the logic script | |
REPO_ID = _secret("REPO_ID") | |
# Files to download from the repo | |
FILES_TO_DOWNLOAD = ["index.faiss", "index.pkl", "agent_logic.py"] | |
# A local directory to store all downloaded assets | |
LOCAL_DOWNLOAD_DIR = "downloaded_assets" | |
EMBEDDING_MODEL_NAME = "google/embeddinggemma-300m" | |
# ---------------------------------------------------------------------- | |
# 2. Bootstrap Phase: Download assets and initialize the engine | |
# (This code runs only once when the Space starts up) | |
# ---------------------------------------------------------------------- | |
print("--- [UI App] Starting bootstrap process ---") | |
os.makedirs(LOCAL_DOWNLOAD_DIR, exist_ok=True) | |
hf_token = _secret("HF_TOKEN") # A read-access token is required for private repos | |
for filename in FILES_TO_DOWNLOAD: | |
print(f"--- [UI App] Downloading '{filename}'... ---") | |
try: | |
hf_hub_download( | |
repo_id=REPO_ID, filename=filename, repo_type="dataset", | |
local_dir=LOCAL_DOWNLOAD_DIR, token=hf_token, | |
) | |
except Exception as e: | |
raise RuntimeError(f"Failed to download '{filename}'. Check repo/file names and HF_TOKEN. Error: {e}") | |
# Dynamically import the RAG_Engine class from the downloaded script | |
logic_script_path = os.path.join(LOCAL_DOWNLOAD_DIR, "agent_logic.py") | |
spec = importlib.util.spec_from_file_location("agent_logic", logic_script_path) | |
agent_logic_module = importlib.util.module_from_spec(spec) | |
spec.loader.exec_module(agent_logic_module) | |
print("--- [UI App] Agent logic module imported successfully. ---") | |
# Instantiate the engine. This single line triggers all the complex setup | |
# defined in the private_logic.py file. | |
engine = agent_logic_module.RAG_Engine( | |
local_download_dir=LOCAL_DOWNLOAD_DIR, | |
embedding_model_name=EMBEDDING_MODEL_NAME | |
) | |
print("--- [UI App] Bootstrap complete. Gradio UI is starting. ---") | |
# ---------------------------------------------------------------------- | |
# 3. Core Gradio Chat Logic (Now a simple wrapper) | |
# ---------------------------------------------------------------------- | |
def respond(message: str, history: list[dict[str, str]]): | |
""" | |
This function is called by Gradio for each user message. | |
It passes the inputs to the RAG engine and streams the output. | |
""" | |
final_response = engine.get_response(message, history) | |
# Stream the response back to the UI for a "typing" effect | |
response = "" | |
for char in final_response: | |
response += char | |
time.sleep(0.01) | |
yield response | |
# ---------------------------------------------------------------------- | |
# 4. UI Layout and Launch | |
# ---------------------------------------------------------------------- | |
chatbot = gr.ChatInterface( | |
respond, | |
type="messages", | |
title="PRECISE RAG Agent", | |
description="Silakan bertanya tentang PRECISE.", | |
examples=[ | |
["Apa rumus untuk menghitung PVR?"], | |
["Apa tujuan pengadaan PRECISE?"], | |
], | |
cache_examples=False, | |
theme=gr.themes.Soft(), | |
) | |
with gr.Blocks() as demo: | |
chatbot.render() | |
if __name__ == "__main__": | |
allowed_user = _secret("CHAT_USER") | |
allowed_pass = _secret("CHAT_PASS") | |
demo.launch( | |
auth=(allowed_user, allowed_pass), | |
server_name="0.0.0.0", | |
ssr_mode=False, | |
server_port=7860 | |
) |