ST-x-Tony commited on
Commit
2bc9710
·
verified ·
1 Parent(s): 7a682ac

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +129 -56
app.py CHANGED
@@ -13,6 +13,7 @@ import traceback
13
 
14
  import gradio as gr
15
  import spaces
 
16
 
17
 
18
  # ============================================================
@@ -20,26 +21,62 @@ import spaces
20
  # ============================================================
21
 
22
  APP_NAME = "X-RUDRA"
23
- VERSION = "3.2.1" # bumped version
24
 
 
25
  M1_REPO = os.getenv("M1_REPO", "Shrijanagain/M1")
26
  M2_REPO = os.getenv("M2_REPO", "Shrijanagain/M2")
27
  PORT = int(os.getenv("PORT", "7860"))
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
  # ============================================================
31
  # CASUAL QUERY DETECTOR
32
  # ============================================================
33
 
34
  def is_casual_query(text: str) -> bool:
35
- """Return True if the query is casual/timepass, False if it's a serious research question."""
36
  text = text.lower().strip()
37
-
38
- # Very short queries (1‑2 words) are almost always casual
39
  if len(text.split()) <= 2:
40
  return True
41
-
42
- # List of casual patterns (expand as needed)
43
  casual_patterns = [
44
  "hey", "hi", "hello", "yo", "what's up", "how are you",
45
  "good morning", "good evening", "good night",
@@ -47,17 +84,14 @@ def is_casual_query(text: str) -> bool:
47
  "tell me a joke", "sing a song", "what's your name",
48
  "who are you", "what can you do", "help", "thanks"
49
  ]
50
-
51
- # Check if the query starts with or contains any casual pattern
52
  for pattern in casual_patterns:
53
  if text.startswith(pattern) or pattern in text:
54
  return True
55
-
56
  return False
57
 
58
 
59
  # ============================================================
60
- # LAZY ENGINE
61
  # ============================================================
62
 
63
  _ENGINE = None
@@ -71,27 +105,7 @@ def get_engine():
71
 
72
 
73
  # ============================================================
74
- # SAFE HELPERS
75
- # ============================================================
76
-
77
- def safe_dict(value):
78
- if isinstance(value, dict):
79
- return value
80
- if hasattr(value, "model_dump"):
81
- try:
82
- return value.model_dump()
83
- except Exception:
84
- pass
85
- if hasattr(value, "dict"):
86
- try:
87
- return value.dict()
88
- except Exception:
89
- pass
90
- return {"result": str(value)}
91
-
92
-
93
- # ============================================================
94
- # FORMATTERS
95
  # ============================================================
96
 
97
  def format_sources(sources):
@@ -161,7 +175,6 @@ def format_verification(contradictions):
161
 
162
 
163
  def extract_answer(data):
164
- # Try common fields
165
  for key in ("final_answer", "answer", "response", "final", "synthesis", "summary"):
166
  val = data.get(key)
167
  if isinstance(val, str) and val.strip():
@@ -208,7 +221,71 @@ def build_activity(data, elapsed_ms):
208
 
209
 
210
  # ============================================================
211
- # RESEARCH FUNCTION – WITH CASUAL FILTER
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  # ============================================================
213
 
214
  async def do_research(question, max_results, max_rounds, use_models, freshness):
@@ -218,24 +295,18 @@ async def do_research(question, max_results, max_rounds, use_models, freshness):
218
  question = str(question).strip()
219
 
220
  # ------------------------------------------------------------
221
- # 1. CASUAL FILTERskip expensive search for timepass
222
  # ------------------------------------------------------------
223
  if is_casual_query(question):
224
- casual_response = (
225
- f"👋 Hey there! I'm X‑RUDRA, your research assistant. "
226
- f"I'm designed to help with serious questions, deep dives, and fact‑finding. "
227
- f"If you have a specific topic you'd like me to research, just ask!\n\n"
228
- f"*(Your message `{question}` seemed casual, so I skipped the heavy research.)*"
229
- )
230
  history = [
231
  {"role": "user", "content": question},
232
- {"role": "assistant", "content": casual_response}
233
  ]
234
- empty_activity = "⚡ Skipped research (casual query)."
235
- return history, empty_activity, "", "", ""
236
 
237
  # ------------------------------------------------------------
238
- # 2. SERIOUS QUERY – run the engine
239
  # ------------------------------------------------------------
240
  started = time.perf_counter()
241
 
@@ -251,15 +322,13 @@ async def do_research(question, max_results, max_rounds, use_models, freshness):
251
  data = safe_dict(report)
252
  elapsed_ms = int((time.perf_counter() - started) * 1000)
253
 
254
- # Debug: print raw data to logs
255
  print("\n" + "="*60)
256
- print("RAW ENGINE DATA:")
257
  print(json.dumps(data, indent=2, default=str)[:3000])
258
  print("="*60 + "\n")
259
 
260
- # ------------------------------------------------------------
261
- # 3. EXTRACT SOURCES – convert 'results' to 'sources' if needed
262
- # ------------------------------------------------------------
263
  sources = data.get("sources", [])
264
  if not sources:
265
  results = data.get("results", [])
@@ -275,9 +344,7 @@ async def do_research(question, max_results, max_rounds, use_models, freshness):
275
  })
276
  data["sources"] = sources
277
 
278
- # ------------------------------------------------------------
279
- # 4. EXTRACT ANSWER – if missing, synthesize from sources
280
- # ------------------------------------------------------------
281
  answer = extract_answer(data)
282
  if answer is None:
283
  if sources:
@@ -291,9 +358,6 @@ async def do_research(question, max_results, max_rounds, use_models, freshness):
291
  else:
292
  answer = "No information found. Try rephrasing your question."
293
 
294
- # ------------------------------------------------------------
295
- # 5. BUILD OUTPUTS
296
- # ------------------------------------------------------------
297
  claims = data.get("claims", [])
298
  sources_md = format_sources(sources)
299
  evidence_md = format_evidence(claims)
@@ -344,7 +408,7 @@ def health_check():
344
 
345
 
346
  # ============================================================
347
- # CSS AND UI
348
  # ============================================================
349
 
350
  CSS = """
@@ -358,6 +422,11 @@ body { background: #f7f7f8; }
358
  footer { display: none !important; }
359
  """
360
 
 
 
 
 
 
361
  with gr.Blocks(title=APP_NAME) as demo:
362
  gr.HTML("""
363
  <div id="header">
@@ -433,4 +502,8 @@ if __name__ == "__main__":
433
  print("M1:", M1_REPO)
434
  print("M2:", M2_REPO)
435
  print("Lazy engine initialization: ON")
 
 
 
 
436
  demo.launch(server_name="0.0.0.0", server_port=PORT, css=CSS, show_error=True)
 
13
 
14
  import gradio as gr
15
  import spaces
16
+ from gradio_client import Client
17
 
18
 
19
  # ============================================================
 
21
  # ============================================================
22
 
23
  APP_NAME = "X-RUDRA"
24
+ VERSION = "3.3.1"
25
 
26
+ # M1 and M2 Spaces – change these to your own if needed
27
  M1_REPO = os.getenv("M1_REPO", "Shrijanagain/M1")
28
  M2_REPO = os.getenv("M2_REPO", "Shrijanagain/M2")
29
  PORT = int(os.getenv("PORT", "7860"))
30
 
31
+ # ------------------------------------------------------------
32
+ # HF_TOKEN is recommended to avoid rate limits
33
+ # Set it as a Secret in your Space settings.
34
+ # ------------------------------------------------------------
35
+ HF_TOKEN = os.getenv("HF_TOKEN")
36
+ if HF_TOKEN:
37
+ os.environ["HF_TOKEN"] = HF_TOKEN # ensures the transformers lib uses it
38
+
39
+
40
+ # ============================================================
41
+ # GRADIO CLIENTS FOR M1 / M2 (LAZY)
42
+ # ============================================================
43
+
44
+ _M1_CLIENT = None
45
+ _M2_CLIENT = None
46
+
47
+ def get_m1_client():
48
+ global _M1_CLIENT
49
+ if _M1_CLIENT is None:
50
+ try:
51
+ # Construct the public URL of the Space
52
+ url = f"https://{M1_REPO.replace('/', '-')}.hf.space"
53
+ _M1_CLIENT = Client(url)
54
+ except Exception as e:
55
+ print(f"Could not connect to M1: {e}")
56
+ _M1_CLIENT = None
57
+ return _M1_CLIENT
58
+
59
+ def get_m2_client():
60
+ global _M2_CLIENT
61
+ if _M2_CLIENT is None:
62
+ try:
63
+ url = f"https://{M2_REPO.replace('/', '-')}.hf.space"
64
+ _M2_CLIENT = Client(url)
65
+ except Exception as e:
66
+ print(f"Could not connect to M2: {e}")
67
+ _M2_CLIENT = None
68
+ return _M2_CLIENT
69
+
70
 
71
  # ============================================================
72
  # CASUAL QUERY DETECTOR
73
  # ============================================================
74
 
75
  def is_casual_query(text: str) -> bool:
76
+ """Return True if the query is casual/timepass."""
77
  text = text.lower().strip()
 
 
78
  if len(text.split()) <= 2:
79
  return True
 
 
80
  casual_patterns = [
81
  "hey", "hi", "hello", "yo", "what's up", "how are you",
82
  "good morning", "good evening", "good night",
 
84
  "tell me a joke", "sing a song", "what's your name",
85
  "who are you", "what can you do", "help", "thanks"
86
  ]
 
 
87
  for pattern in casual_patterns:
88
  if text.startswith(pattern) or pattern in text:
89
  return True
 
90
  return False
91
 
92
 
93
  # ============================================================
94
+ # LAZY ENGINE (for serious queries)
95
  # ============================================================
96
 
97
  _ENGINE = None
 
105
 
106
 
107
  # ============================================================
108
+ # FORMATTERS (Sources, Evidence, Verification)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  # ============================================================
110
 
111
  def format_sources(sources):
 
175
 
176
 
177
  def extract_answer(data):
 
178
  for key in ("final_answer", "answer", "response", "final", "synthesis", "summary"):
179
  val = data.get(key)
180
  if isinstance(val, str) and val.strip():
 
221
 
222
 
223
  # ============================================================
224
+ # SAFE DICT HELPER
225
+ # ============================================================
226
+
227
+ def safe_dict(value):
228
+ if isinstance(value, dict):
229
+ return value
230
+ if hasattr(value, "model_dump"):
231
+ try:
232
+ return value.model_dump()
233
+ except Exception:
234
+ pass
235
+ if hasattr(value, "dict"):
236
+ try:
237
+ return value.dict()
238
+ except Exception:
239
+ pass
240
+ return {"result": str(value)}
241
+
242
+
243
+ # ============================================================
244
+ # GET MODEL RESPONSE FOR CASUAL QUERIES
245
+ # ============================================================
246
+
247
+ def get_casual_model_response(query: str) -> str:
248
+ """Call M1 (or M2) to generate a friendly reply for casual queries."""
249
+ # Try M1 first
250
+ client = get_m1_client()
251
+ if client is not None:
252
+ try:
253
+ # Assuming the endpoint is /generate with inputs: prompt, max_tokens, temperature
254
+ result = client.predict(
255
+ prompt=f"User: {query}\nAssistant:",
256
+ max_tokens=64,
257
+ temperature=0.7,
258
+ api_name="/generate"
259
+ )
260
+ if result and isinstance(result, str) and result.strip():
261
+ return result.strip()
262
+ except Exception as e:
263
+ print(f"M1 casual call failed: {e}")
264
+
265
+ # Try M2
266
+ client = get_m2_client()
267
+ if client is not None:
268
+ try:
269
+ result = client.predict(
270
+ prompt=f"User: {query}\nAssistant:",
271
+ max_tokens=64,
272
+ temperature=0.7,
273
+ api_name="/generate"
274
+ )
275
+ if result and isinstance(result, str) and result.strip():
276
+ return result.strip()
277
+ except Exception as e:
278
+ print(f"M2 casual call failed: {e}")
279
+
280
+ # Ultimate fallback
281
+ return (
282
+ f"👋 Hi there! I'm X‑RUDRA, your research assistant. "
283
+ f"How can I help you today? (Your message `{query}` was casual, so I kept it light.)"
284
+ )
285
+
286
+
287
+ # ============================================================
288
+ # MAIN RESEARCH FUNCTION
289
  # ============================================================
290
 
291
  async def do_research(question, max_results, max_rounds, use_models, freshness):
 
295
  question = str(question).strip()
296
 
297
  # ------------------------------------------------------------
298
+ # CASUAL QUERYget a model‑generated reply (no web search)
299
  # ------------------------------------------------------------
300
  if is_casual_query(question):
301
+ answer = get_casual_model_response(question)
 
 
 
 
 
302
  history = [
303
  {"role": "user", "content": question},
304
+ {"role": "assistant", "content": answer}
305
  ]
306
+ return history, "⚡ Casual chat (model reply, no search).", "", "", ""
 
307
 
308
  # ------------------------------------------------------------
309
+ # SERIOUS QUERY – run the engine (web + models)
310
  # ------------------------------------------------------------
311
  started = time.perf_counter()
312
 
 
322
  data = safe_dict(report)
323
  elapsed_ms = int((time.perf_counter() - started) * 1000)
324
 
325
+ # Debug (optional)
326
  print("\n" + "="*60)
327
+ print("RAW ENGINE DATA (first 3000 chars):")
328
  print(json.dumps(data, indent=2, default=str)[:3000])
329
  print("="*60 + "\n")
330
 
331
+ # Convert 'results' to 'sources' if needed
 
 
332
  sources = data.get("sources", [])
333
  if not sources:
334
  results = data.get("results", [])
 
344
  })
345
  data["sources"] = sources
346
 
347
+ # Extract or synthesise answer
 
 
348
  answer = extract_answer(data)
349
  if answer is None:
350
  if sources:
 
358
  else:
359
  answer = "No information found. Try rephrasing your question."
360
 
 
 
 
361
  claims = data.get("claims", [])
362
  sources_md = format_sources(sources)
363
  evidence_md = format_evidence(claims)
 
408
 
409
 
410
  # ============================================================
411
+ # CSS
412
  # ============================================================
413
 
414
  CSS = """
 
422
  footer { display: none !important; }
423
  """
424
 
425
+
426
+ # ============================================================
427
+ # GRADIO UI
428
+ # ============================================================
429
+
430
  with gr.Blocks(title=APP_NAME) as demo:
431
  gr.HTML("""
432
  <div id="header">
 
502
  print("M1:", M1_REPO)
503
  print("M2:", M2_REPO)
504
  print("Lazy engine initialization: ON")
505
+ if HF_TOKEN:
506
+ print("HF_TOKEN set – rate limits reduced.")
507
+ else:
508
+ print("HF_TOKEN not set – you may experience rate limits. Set it as a Secret in your Space.")
509
  demo.launch(server_name="0.0.0.0", server_port=PORT, css=CSS, show_error=True)