Spaces:
Running
Running
File size: 7,951 Bytes
e87b1c3 0ff301d e87b1c3 4e4df74 e87b1c3 57ec1a6 e87b1c3 4e4df74 de611b5 e87b1c3 859ac01 e87b1c3 de611b5 e87b1c3 de611b5 57ec1a6 e87b1c3 57ec1a6 e87b1c3 57ec1a6 e87b1c3 0ff301d e87b1c3 57ec1a6 e87b1c3 57ec1a6 e87b1c3 21bc7cc e87b1c3 57ec1a6 e87b1c3 57ec1a6 e87b1c3 d94ed24 e87b1c3 4e4df74 e87b1c3 57ec1a6 e87b1c3 57ec1a6 4e8dab9 57ec1a6 e87b1c3 57ec1a6 e87b1c3 57ec1a6 40b4466 de611b5 57ec1a6 de611b5 57ec1a6 4e4df74 57ec1a6 6aabd52 57ec1a6 6aabd52 57ec1a6 4e4df74 57ec1a6 6aabd52 57ec1a6 6aabd52 57ec1a6 6aabd52 57ec1a6 6aabd52 4e4df74 859ac01 de611b5 e87b1c3 2b88a3b 57ec1a6 de611b5 |
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 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# app.py
import os
import time
import gradio as gr
import importlib.util
import markdown
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. Custom CSS for better styling
# ----------------------------------------------------------------------
custom_css = """
/* Main container styling */
.contain {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
padding: 20px;
}
/* Header styling */
.header {
text-align: center;
margin-bottom: 30px;
}
.header h1 {
color: #2c3e50;
font-weight: 700;
margin-bottom: 10px;
font-size: 2.5rem;
}
.header p {
color: #7f8c8d;
font-size: 1.2rem;
}
/* Chat container styling */
.gr-chat-message {
padding: 16px 20px;
border-radius: 18px;
margin: 10px 0;
line-height: 1.5;
}
.gr-chat-message-user {
background: linear-gradient(135deg, #3498db 0%, #2980b9 100%);
color: white;
margin-left: 20%;
}
.gr-chat-message-bot {
background: linear-gradient(135deg, #ecf0f1 0%, #ffffff 100%);
color: #2c3e50;
margin-right: 20%;
border: 1px solid #e0e0e0;
}
/* Chat input styling */
.gr-text-input textarea {
border-radius: 12px;
padding: 15px;
font-size: 16px;
border: 2px solid #bdc3c7;
}
.gr-text-input textarea:focus {
border-color: #3498db;
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2);
}
/* Button styling */
.gr-button {
background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%);
color: white;
border: none;
border-radius: 12px;
padding: 12px 24px;
font-weight: 600;
transition: all 0.3s ease;
}
.gr-button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
/* Example styling */
.gr-examples {
border-radius: 12px;
background: white;
padding: 15px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.gr-examples button {
background: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 8px;
padding: 10px 15px;
margin: 5px;
transition: all 0.2s ease;
}
.gr-examples button:hover {
background: #e9ecef;
transform: translateY(-1px);
}
/* Formula styling */
.formula {
background-color: #f8f9fa;
border-left: 4px solid #3498db;
padding: 15px;
margin: 15px 0;
border-radius: 0 8px 8px 0;
overflow-x: auto;
}
.formula p {
margin: 0;
font-family: monospace;
color: #2c3e50;
}
/* Responsive adjustments */
@media (max-width: 768px) {
.gr-chat-message-user, .gr-chat-message-bot {
margin-left: 10%;
margin-right: 10%;
}
.header h1 {
font-size: 2rem;
}
}
"""
# ----------------------------------------------------------------------
# 5. UI Layout and Launch
# ----------------------------------------------------------------------
with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
# Header section
with gr.Row():
with gr.Column(scale=1):
gr.HTML("""
<div class="header">
<h1>🤖 PRECISE RAG Agent</h1>
<p>Silakan bertanya tentang PRECISE dan sistem promosinya</p>
</div>
""")
# Chat interface
chatbot = gr.ChatInterface(
respond,
type="messages",
examples=[
["Apa rumus untuk menghitung PVR?"],
["Apa tujuan pengadaan PRECISE?"],
["Jelaskan tentang promo 'beli 4 gratis 2'"],
],
cache_examples=False,
)
# Additional information section
with gr.Accordion("📊 Informasi Formula PVR", open=False):
gr.Markdown("""
**PVR untuk promo "beli 4 gratis 2" dihitung dengan rumus:**
```math
\\text{PVR} = \\frac{\\text{added\\_value}}{\\text{purchase\\_value}}
= \\frac{\\text{target\\_value} \\times \\text{avg\\_price\\_AVP}}
{\\text{target\\_value} \\times \\text{avg\\_price\\_AVP}
+ \\text{condition\\_value} \\times \\text{avg\\_price\\_REP}}
```
Keterangan:
- **added_value**: Nilai tambah dari promo
- **purchase_value**: Nilai pembelian keseluruhan
- **target_value**: Jumlah produk target dalam promo
- **avg_price_AVP**: Harga rata-rata produk AVP
- **condition_value**: Jumlah produk kondisi dalam promo
- **avg_price_REP**: Harga rata-rata produk REP
""")
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
) |