yogies commited on
Commit
e87b1c3
·
verified ·
1 Parent(s): 8ad262c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -103
app.py CHANGED
@@ -1,133 +1,105 @@
 
 
1
  import os
 
2
  import gradio as gr
3
- from openai import OpenAI
 
 
4
 
5
  # ----------------------------------------------------------------------
6
- # Helper to read a secret (fallback is useful when you run locally)
7
  # ----------------------------------------------------------------------
8
- def _secret(key: str, fallback: str = "") -> str:
9
- """Return the value of a secret or the supplied fallback."""
10
- return os.getenv(key, fallback)
11
-
 
12
 
13
  # ----------------------------------------------------------------------
14
- # Core chat logic – system prompt comes from the secret `prec_chat`
15
  # ----------------------------------------------------------------------
16
- def respond(
17
- message: str,
18
- history: list[dict[str, str]],
19
- # model_name: str,
20
- ):
21
- """
22
- Generate a response using OpenRouter API via OpenAI client.
23
-
24
- * System prompt = secret `prec_chat`
25
- * OpenRouter API key = secret `OPENROUTER_API_KEY`
26
- """
27
- # 1️⃣ Load the system prompt (fallback = generic assistant)
28
- # system_message = _secret("prec_chat", "You are a helpful assistant.")
29
 
30
- # 2️⃣ Load the OpenRouter API key
31
- openrouter_api_key = _secret("OPENROUTER_API_KEY")
32
- if not openrouter_api_key:
33
- raise RuntimeError(
34
- "OPENROUTER_API_KEY not found in secrets. Add it to secrets.toml (or via the Space UI)."
 
 
 
 
 
 
 
 
 
35
  )
36
-
37
- # 3️⃣ Initialize OpenAI client with OpenRouter configuration
38
- # client = OpenAI(
39
- # base_url="https://openrouter.ai/api/v1",
40
- # api_key=openrouter_api_key,
41
- # )
42
-
43
- client = OpenAI(
44
- base_url="https://openrouter.ai/api/v1",
45
- api_key=openrouter_api_key,
46
- default_headers={
47
- "X-Title": "hf_precise", # Optional. Set your app name for tracking.
48
- },
 
 
49
  )
 
50
 
51
- # 4️⃣ Build the message list for the chat completion
52
- messages = []
53
- messages.extend(history) # previous conversation turns
54
- messages.append({"role": "user", "content": message}) # current user query
55
-
56
-
57
- MODEL_NAME = _secret("MODEL_NAME")
 
 
58
 
59
- # 5️⃣ Stream the response back to the UI
60
  response = ""
61
- stream = client.chat.completions.create(
62
- # model=model_name,
63
- model = MODEL_NAME,
64
- messages = messages,
65
- reasoning_effort= "high", # Use high reasoning effort
66
- max_tokens=8096,
67
- stream=True
68
- )
69
-
70
- for chunk in stream:
71
- if chunk.choices[0].delta.content is not None:
72
- token = chunk.choices[0].delta.content
73
- response += token
74
- yield response
75
-
76
-
77
- # # ──────────────────────────────────────────────────────────────────────
78
- # # List of models available through OpenRouter
79
- # # ──────────────────────────────────────────────────────────────────────
80
- AVAILABLE_MODELS = [
81
- ]
82
 
83
  # ----------------------------------------------------------------------
84
- # UI the system‑prompt textbox has been removed.
85
  # ----------------------------------------------------------------------
86
  chatbot = gr.ChatInterface(
87
  respond,
88
  type="messages",
89
- # additional_inputs=[
90
- # gr.Dropdown(
91
- # choices=AVAILABLE_MODELS,
92
- # value=AVAILABLE_MODELS[0],
93
- # label="Model",
94
- # interactive=True,
95
- # ),
96
- # ],
97
  )
98
 
99
- # ----------------------------------------------------------------------
100
- # Assemble the Blocks layout (no LoginButton – we use basic auth)
101
- # ----------------------------------------------------------------------
102
  with gr.Blocks() as demo:
103
  chatbot.render()
104
 
105
-
106
- # ----------------------------------------------------------------------
107
- # Launch – protect the UI with the credentials from secrets.
108
- # ----------------------------------------------------------------------
109
  if __name__ == "__main__":
110
- # ------------------------------------------------------------------
111
- # 1️⃣ Pull the allowed credentials from secrets (fail fast if missing)
112
- # ------------------------------------------------------------------
113
  allowed_user = _secret("CHAT_USER")
114
  allowed_pass = _secret("CHAT_PASS")
115
-
116
- if not allowed_user or not allowed_pass:
117
- raise RuntimeError(
118
- "Authentication credentials not found in secrets. "
119
- "Add CHAT_USER and CHAT_PASS to secrets.toml (or via the HF Spaces UI)."
120
- )
121
-
122
- # ------------------------------------------------------------------
123
- # 2️⃣ Launch
124
- # ------------------------------------------------------------------
125
  demo.launch(
126
- auth=(allowed_user, allowed_pass), # <-- Gradio's built‑in basic auth
127
- ssr_mode=False, # <-- avoids the i18n locale error
128
- # In a Space we **must not** set share=True (Spaces already give a public URL)
129
- # If you run locally and want a shareable link, add share=True here.
130
- server_name="0.0.0.0", # listen on all interfaces (needed in containers)
131
- # Optional: give the app a nice title
132
- # title="Secure Chatbot",
133
  )
 
1
+ # app.py
2
+
3
  import os
4
+ import time
5
  import gradio as gr
6
+ import importlib.util
7
+
8
+ from huggingface_hub import hf_hub_download
9
 
10
  # ----------------------------------------------------------------------
11
+ # Helper to read secrets from the HF Space environment
12
  # ----------------------------------------------------------------------
13
+ def _secret(key: str, fallback: str = None) -> str:
14
+ val = os.getenv(key)
15
+ if val is not None: return val
16
+ if fallback is not None: return fallback
17
+ raise RuntimeError(f"Secret '{key}' not found. Please add it to your Space secrets.")
18
 
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}'... ---")
40
+ try:
41
+ hf_hub_download(
42
+ repo_id=REPO_ID, filename=filename, repo_type="dataset",
43
+ local_dir=LOCAL_DOWNLOAD_DIR, token=hf_token,
44
  )
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
60
  )
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
+ theme=gr.themes.Soft(),
 
93
  )
94
 
 
 
 
95
  with gr.Blocks() as demo:
96
  chatbot.render()
97
 
 
 
 
 
98
  if __name__ == "__main__":
 
 
 
99
  allowed_user = _secret("CHAT_USER")
100
  allowed_pass = _secret("CHAT_PASS")
 
 
 
 
 
 
 
 
 
 
101
  demo.launch(
102
+ auth=(allowed_user, allowed_pass),
103
+ server_name="0.0.0.0",
104
+ server_port=7860
 
 
 
 
105
  )