yogies commited on
Commit
6aabd52
·
verified ·
1 Parent(s): 2b88a3b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -32
app.py CHANGED
@@ -19,21 +19,17 @@ def _secret(key: str, fallback: str = None) -> str:
19
  # ----------------------------------------------------------------------
20
  # 1. Configuration & Constants
21
  # ----------------------------------------------------------------------
22
- # The private repo containing the vector DB and the logic script
23
  REPO_ID = _secret("REPO_ID")
24
- # Files to download from the repo
25
  FILES_TO_DOWNLOAD = ["index.faiss", "index.pkl", "agent_logic.py"]
26
- # A local directory to store all downloaded assets
27
  LOCAL_DOWNLOAD_DIR = "downloaded_assets"
28
  EMBEDDING_MODEL_NAME = "google/embeddinggemma-300m"
29
 
30
  # ----------------------------------------------------------------------
31
  # 2. Bootstrap Phase: Download assets and initialize the engine
32
- # (This code runs only once when the Space starts up)
33
  # ----------------------------------------------------------------------
34
  print("--- [UI App] Starting bootstrap process ---")
35
  os.makedirs(LOCAL_DOWNLOAD_DIR, exist_ok=True)
36
- hf_token = _secret("HF_TOKEN") # A read-access token is required for private repos
37
 
38
  for filename in FILES_TO_DOWNLOAD:
39
  print(f"--- [UI App] Downloading '{filename}'... ---")
@@ -45,15 +41,12 @@ for filename in FILES_TO_DOWNLOAD:
45
  except Exception as e:
46
  raise RuntimeError(f"Failed to download '{filename}'. Check repo/file names and HF_TOKEN. Error: {e}")
47
 
48
- # Dynamically import the RAG_Engine class from the downloaded script
49
  logic_script_path = os.path.join(LOCAL_DOWNLOAD_DIR, "agent_logic.py")
50
  spec = importlib.util.spec_from_file_location("agent_logic", logic_script_path)
51
  agent_logic_module = importlib.util.module_from_spec(spec)
52
  spec.loader.exec_module(agent_logic_module)
53
  print("--- [UI App] Agent logic module imported successfully. ---")
54
 
55
- # Instantiate the engine. This single line triggers all the complex setup
56
- # defined in the private_logic.py file.
57
  engine = agent_logic_module.RAG_Engine(
58
  local_download_dir=LOCAL_DOWNLOAD_DIR,
59
  embedding_model_name=EMBEDDING_MODEL_NAME
@@ -61,41 +54,96 @@ engine = agent_logic_module.RAG_Engine(
61
  print("--- [UI App] Bootstrap complete. Gradio UI is starting. ---")
62
 
63
  # ----------------------------------------------------------------------
64
- # 3. Core Gradio Chat Logic (Now a simple wrapper)
65
  # ----------------------------------------------------------------------
66
- def respond(message: str, history: list[dict[str, str]]):
67
  """
68
- This function is called by Gradio for each user message.
69
- It passes the inputs to the RAG engine and streams the output.
70
  """
71
- final_response = engine.get_response(message, history)
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
- # Stream the response back to the UI for a "typing" effect
74
- response = ""
75
  for char in final_response:
76
- response += char
77
  time.sleep(0.01)
78
- yield response
79
 
80
  # ----------------------------------------------------------------------
81
- # 4. UI Layout and Launch
82
  # ----------------------------------------------------------------------
83
- chatbot = gr.ChatInterface(
84
- respond,
85
- type="messages",
86
- title="PRECISE RAG Agent",
87
- description="Silakan bertanya tentang PRECISE.",
88
- examples=[
89
- ["Apa rumus untuk menghitung PVR?"],
90
- ["Apa tujuan pengadaan PRECISE?"],
91
- ],
92
- cache_examples=False,
93
- theme=gr.themes.Soft(),
94
- )
95
 
96
- with gr.Blocks() as demo:
97
- chatbot.render()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  if __name__ == "__main__":
100
  allowed_user = _secret("CHAT_USER")
101
  allowed_pass = _secret("CHAT_PASS")
 
19
  # ----------------------------------------------------------------------
20
  # 1. Configuration & Constants
21
  # ----------------------------------------------------------------------
 
22
  REPO_ID = _secret("REPO_ID")
 
23
  FILES_TO_DOWNLOAD = ["index.faiss", "index.pkl", "agent_logic.py"]
 
24
  LOCAL_DOWNLOAD_DIR = "downloaded_assets"
25
  EMBEDDING_MODEL_NAME = "google/embeddinggemma-300m"
26
 
27
  # ----------------------------------------------------------------------
28
  # 2. Bootstrap Phase: Download assets and initialize the engine
 
29
  # ----------------------------------------------------------------------
30
  print("--- [UI App] Starting bootstrap process ---")
31
  os.makedirs(LOCAL_DOWNLOAD_DIR, exist_ok=True)
32
+ hf_token = _secret("HF_TOKEN")
33
 
34
  for filename in FILES_TO_DOWNLOAD:
35
  print(f"--- [UI App] Downloading '{filename}'... ---")
 
41
  except Exception as e:
42
  raise RuntimeError(f"Failed to download '{filename}'. Check repo/file names and HF_TOKEN. Error: {e}")
43
 
 
44
  logic_script_path = os.path.join(LOCAL_DOWNLOAD_DIR, "agent_logic.py")
45
  spec = importlib.util.spec_from_file_location("agent_logic", logic_script_path)
46
  agent_logic_module = importlib.util.module_from_spec(spec)
47
  spec.loader.exec_module(agent_logic_module)
48
  print("--- [UI App] Agent logic module imported successfully. ---")
49
 
 
 
50
  engine = agent_logic_module.RAG_Engine(
51
  local_download_dir=LOCAL_DOWNLOAD_DIR,
52
  embedding_model_name=EMBEDDING_MODEL_NAME
 
54
  print("--- [UI App] Bootstrap complete. Gradio UI is starting. ---")
55
 
56
  # ----------------------------------------------------------------------
57
+ # 3. Core Gradio Chat Logic
58
  # ----------------------------------------------------------------------
59
+ def add_message_and_respond(message: str, history: list):
60
  """
61
+ Adds the user's message to the chat history and gets the bot's streaming response.
 
62
  """
63
+ # Add the user's message to the UI immediately
64
+ history.append([message, None])
65
+ yield history
66
+
67
+ # Convert chat history to the format the engine expects
68
+ history_for_engine = []
69
+ for user_msg, bot_msg in history[:-1]: # Exclude the current turn
70
+ history_for_engine.append({"role": "user", "content": user_msg})
71
+ if bot_msg:
72
+ history_for_engine.append({"role": "assistant", "content": bot_msg})
73
+
74
+ # Get the response from the agent
75
+ final_response = engine.get_response(message, history_for_engine)
76
 
77
+ # Stream the complete response back to the UI
78
+ history[-1][1] = ""
79
  for char in final_response:
80
+ history[-1][1] += char
81
  time.sleep(0.01)
82
+ yield history
83
 
84
  # ----------------------------------------------------------------------
85
+ # 4. UI Layout and Launch (Beautified with gr.Blocks)
86
  # ----------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
+ # Custom CSS for a cleaner look
89
+ css = """
90
+ #chatbot { min-height: 600px; }
91
+ .footer { text-align: center; color: #777; font-size: 0.8em; padding: 10px 0; }
92
+ """
93
+
94
+ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
95
+ # Header
96
+ gr.Markdown("<h1>🤖 PRECISE RAG Agent</h1>")
97
+ gr.Markdown("Tanya Jawab Cerdas Mengenai Dokumentasi Sistem PRECISE")
98
+
99
+ # Main Chatbot Interface
100
+ chatbot = gr.Chatbot(
101
+ elem_id="chatbot",
102
+ label="Conversation",
103
+ bubble_fill=False,
104
+ render_math=True # <-- THE FIX FOR FORMULAS!
105
+ )
106
+
107
+ # Input area
108
+ with gr.Row():
109
+ msg = gr.Textbox(
110
+ label="Your Question",
111
+ placeholder="Ketik pertanyaan Anda di sini dan tekan Enter...",
112
+ scale=4, # Make the textbox wider
113
+ )
114
+ submit_btn = gr.Button("Send", variant="primary", scale=1)
115
 
116
+ # Example questions
117
+ gr.Examples(
118
+ examples=[
119
+ "Apa tujuan pengadaan PRECISE?",
120
+ "Apa keunggulan utama PRECISE dibandingkan sistem perhitungan target promosi yang lama?",
121
+ "Apakah PRECISE sudah terbukti memberikan manfaat finansial? Bisakah diberikan contohnya?",
122
+ "Selain akurasi, aspek teknis apa yang membuat PRECISE unik?"
123
+ ],
124
+ inputs=msg,
125
+ )
126
+
127
+ # Footer
128
+ gr.Markdown("<hr><p class='footer'>Powered by OpenRouter and LangChain. All rights reserved.</p>")
129
+
130
+ # --- Event Handlers ---
131
+
132
+ # Define the action for submitting a message (either by pressing Enter or clicking the button)
133
+ def submit_action(message, history):
134
+ yield from add_message_and_respond(message, history)
135
+
136
+ # When the user submits, call the action and update the chatbot
137
+ # Then, clear the input textbox
138
+ msg.submit(submit_action, [msg, chatbot], chatbot)
139
+ msg.submit(lambda: "", None, msg) # Clears textbox
140
+
141
+ submit_btn.click(submit_action, [msg, chatbot], chatbot)
142
+ submit_btn.click(lambda: "", None, msg) # Clears textbox
143
+
144
+ # ----------------------------------------------------------------------
145
+ # 5. Launch the App
146
+ # ----------------------------------------------------------------------
147
  if __name__ == "__main__":
148
  allowed_user = _secret("CHAT_USER")
149
  allowed_pass = _secret("CHAT_PASS")