ST-x-Tony commited on
Commit
cc9f818
Β·
verified Β·
1 Parent(s): 355fee6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -21
app.py CHANGED
@@ -7,6 +7,7 @@ from __future__ import annotations
7
 
8
  import os
9
  import json
 
10
  import time
11
  import asyncio
12
  import traceback
@@ -21,7 +22,7 @@ from gradio_client import Client
21
  # ============================================================
22
 
23
  APP_NAME = "X-RUDRA"
24
- VERSION = "3.5.0" # bumped version
25
 
26
  M1_REPO = os.getenv("M1_REPO", "Shrijanagain/M1")
27
  M2_REPO = os.getenv("M2_REPO", "Shrijanagain/M2")
@@ -124,11 +125,10 @@ def call_model(client, prompt, max_tokens=512, temperature=0.7):
124
 
125
 
126
  # ============================================================
127
- # SYNTHESIS: M1 (draft) β†’ M2 (refine)
128
  # ============================================================
129
 
130
  def get_combined_model_answer(question, sources, max_tokens=512, temperature=0.7):
131
- # Build a concise summary of top sources (max 5)
132
  top_sources = sources[:5] if sources else []
133
  sources_text = ""
134
  if top_sources:
@@ -154,20 +154,18 @@ Answer:"""
154
 
155
  draft = call_model(m1_client, prompt_m1, max_tokens, temperature)
156
  if not draft:
157
- # Fallback: try M2 directly for draft
158
  draft = call_model(m2_client, prompt_m1, max_tokens, temperature)
159
 
160
  if not draft:
161
- # Ultimate fallback – simple summarization
162
  if sources:
163
  parts = ["Based on available information:"]
164
  for i, src in enumerate(sources[:5], 1):
165
  title = src.get("title", "Untitled")
166
  snippet = src.get("snippet", src.get("description", ""))
167
  parts.append(f"{i}. {title}: {snippet[:200]}..." if snippet else f"{i}. {title}")
168
- return "\n\n".join(parts)
169
  else:
170
- return "I couldn't find specific information on that topic. Could you rephrase?"
171
 
172
  # ----- 2. M2 refines the draft -----
173
  prompt_m2 = f"""Question: {question}
@@ -180,10 +178,18 @@ Please refine and improve this answer to make it more comprehensive, accurate, a
180
  Improved answer:"""
181
 
182
  refined = call_model(m2_client, prompt_m2, max_tokens, temperature)
183
- if refined:
184
- return refined
185
- else:
186
- return draft
 
 
 
 
 
 
 
 
187
 
188
 
189
  # ============================================================
@@ -354,12 +360,12 @@ def safe_dict(value):
354
 
355
 
356
  # ============================================================
357
- # MAIN RESEARCH FUNCTION
358
  # ============================================================
359
 
360
  async def do_research(question, max_results, max_rounds, use_models, freshness):
361
  if not question or not str(question).strip():
362
- return [], "βšͺ Enter a question to start.", "", ""
363
 
364
  question = str(question).strip()
365
 
@@ -402,8 +408,8 @@ async def do_research(question, max_results, max_rounds, use_models, freshness):
402
  })
403
  data["sources"] = sources
404
 
405
- # Generate final answer using M1 + M2
406
- final_answer = get_combined_model_answer(question, sources)
407
 
408
  # Build outputs for tabs
409
  sources_md = format_sources(sources)
@@ -411,12 +417,18 @@ async def do_research(question, max_results, max_rounds, use_models, freshness):
411
  verification_md = format_verification(data.get("contradictions", []))
412
  activity_md = build_activity(data, elapsed_ms)
413
 
 
 
 
 
 
 
414
  history = [
415
  {"role": "user", "content": question},
416
  {"role": "assistant", "content": final_answer}
417
  ]
418
 
419
- return history, activity_md, sources_md, evidence_md, verification_md
420
 
421
  except Exception as exc:
422
  error = f"❌ **X-RUDRA Error**\n\n`{type(exc).__name__}: {exc}`"
@@ -428,7 +440,7 @@ async def do_research(question, max_results, max_rounds, use_models, freshness):
428
  {"role": "user", "content": question},
429
  {"role": "assistant", "content": error}
430
  ]
431
- return history, "❌ Research failed.", "", "", ""
432
 
433
 
434
  # ============================================================
@@ -455,7 +467,7 @@ def health_check():
455
 
456
 
457
  # ============================================================
458
- # CSS AND UI
459
  # ============================================================
460
 
461
  CSS = """
@@ -467,10 +479,40 @@ body { background: #f7f7f8; }
467
  #chat { border-radius: 18px; }
468
  #send { min-height: 52px; font-size: 18px; font-weight: 700; }
469
  footer { display: none !important; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
470
  """
471
 
472
 
473
- with gr.Blocks(title=APP_NAME) as demo:
 
 
 
 
474
  gr.HTML("""
475
  <div id="header">
476
  <div id="logo">⚑ X-RUDRA</div>
@@ -488,6 +530,8 @@ with gr.Blocks(title=APP_NAME) as demo:
488
  with gr.Column(scale=4):
489
  gr.Markdown("## πŸ”¬ Live Research")
490
  activity = gr.Markdown("βšͺ Waiting for your question.")
 
 
491
  gr.Markdown("---")
492
  gr.Markdown(f"""
493
  ### Model Spaces
@@ -528,8 +572,9 @@ with gr.Blocks(title=APP_NAME) as demo:
528
  inputs=question
529
  )
530
 
 
531
  inputs = [question, max_results, max_rounds, use_models, freshness]
532
- outputs = [chatbot, activity, sources, evidence, verification]
533
 
534
  send.click(fn=run_research, inputs=inputs, outputs=outputs)
535
  question.submit(fn=run_research, inputs=inputs, outputs=outputs)
@@ -549,4 +594,4 @@ if __name__ == "__main__":
549
  print("HF_TOKEN set – rate limits reduced.")
550
  else:
551
  print("HF_TOKEN not set – you may experience rate limits. Set it as a Secret in your Space.")
552
- demo.launch(server_name="0.0.0.0", server_port=PORT, css=CSS, show_error=True)
 
7
 
8
  import os
9
  import json
10
+ import re
11
  import time
12
  import asyncio
13
  import traceback
 
22
  # ============================================================
23
 
24
  APP_NAME = "X-RUDRA"
25
+ VERSION = "3.6.0"
26
 
27
  M1_REPO = os.getenv("M1_REPO", "Shrijanagain/M1")
28
  M2_REPO = os.getenv("M2_REPO", "Shrijanagain/M2")
 
125
 
126
 
127
  # ============================================================
128
+ # SYNTHESIS: M1 (draft) β†’ M2 (refine) + extract thinking
129
  # ============================================================
130
 
131
  def get_combined_model_answer(question, sources, max_tokens=512, temperature=0.7):
 
132
  top_sources = sources[:5] if sources else []
133
  sources_text = ""
134
  if top_sources:
 
154
 
155
  draft = call_model(m1_client, prompt_m1, max_tokens, temperature)
156
  if not draft:
 
157
  draft = call_model(m2_client, prompt_m1, max_tokens, temperature)
158
 
159
  if not draft:
 
160
  if sources:
161
  parts = ["Based on available information:"]
162
  for i, src in enumerate(sources[:5], 1):
163
  title = src.get("title", "Untitled")
164
  snippet = src.get("snippet", src.get("description", ""))
165
  parts.append(f"{i}. {title}: {snippet[:200]}..." if snippet else f"{i}. {title}")
166
+ return "\n\n".join(parts), ""
167
  else:
168
+ return "I couldn't find specific information on that topic. Could you rephrase?", ""
169
 
170
  # ----- 2. M2 refines the draft -----
171
  prompt_m2 = f"""Question: {question}
 
178
  Improved answer:"""
179
 
180
  refined = call_model(m2_client, prompt_m2, max_tokens, temperature)
181
+ if not refined:
182
+ refined = draft
183
+
184
+ # Extract thinking from <think> tags (if any)
185
+ thinking_content = ""
186
+ clean_answer = refined
187
+ think_match = re.search(r"<think>(.*?)</think>", refined, re.DOTALL)
188
+ if think_match:
189
+ thinking_content = think_match.group(1).strip()
190
+ clean_answer = re.sub(r"<think>.*?</think>", "", refined, flags=re.DOTALL).strip()
191
+
192
+ return clean_answer, thinking_content
193
 
194
 
195
  # ============================================================
 
360
 
361
 
362
  # ============================================================
363
+ # MAIN RESEARCH FUNCTION (returns thinking as well)
364
  # ============================================================
365
 
366
  async def do_research(question, max_results, max_rounds, use_models, freshness):
367
  if not question or not str(question).strip():
368
+ return [], "βšͺ Enter a question to start.", "", "", ""
369
 
370
  question = str(question).strip()
371
 
 
408
  })
409
  data["sources"] = sources
410
 
411
+ # Generate final answer using M1 + M2, also get thinking
412
+ final_answer, thinking_content = get_combined_model_answer(question, sources)
413
 
414
  # Build outputs for tabs
415
  sources_md = format_sources(sources)
 
417
  verification_md = format_verification(data.get("contradictions", []))
418
  activity_md = build_activity(data, elapsed_ms)
419
 
420
+ # If there's thinking content, format it nicely
421
+ if thinking_content:
422
+ thinking_md = f"### 🧠 Thinking\n\n{thinking_content}"
423
+ else:
424
+ thinking_md = ""
425
+
426
  history = [
427
  {"role": "user", "content": question},
428
  {"role": "assistant", "content": final_answer}
429
  ]
430
 
431
+ return history, activity_md, sources_md, evidence_md, verification_md, thinking_md
432
 
433
  except Exception as exc:
434
  error = f"❌ **X-RUDRA Error**\n\n`{type(exc).__name__}: {exc}`"
 
440
  {"role": "user", "content": question},
441
  {"role": "assistant", "content": error}
442
  ]
443
+ return history, "❌ Research failed.", "", "", "", ""
444
 
445
 
446
  # ============================================================
 
467
 
468
 
469
  # ============================================================
470
+ # CSS – includes spinner animation for thinking
471
  # ============================================================
472
 
473
  CSS = """
 
479
  #chat { border-radius: 18px; }
480
  #send { min-height: 52px; font-size: 18px; font-weight: 700; }
481
  footer { display: none !important; }
482
+
483
+ /* Thinking spinner animation */
484
+ @keyframes think-pulse {
485
+ 0% { opacity: 0.3; transform: scale(0.95); }
486
+ 50% { opacity: 1; transform: scale(1.05); }
487
+ 100% { opacity: 0.3; transform: scale(0.95); }
488
+ }
489
+ .thinking-spinner {
490
+ display: inline-block;
491
+ width: 12px;
492
+ height: 12px;
493
+ border-radius: 50%;
494
+ background: #6b7280;
495
+ margin-right: 8px;
496
+ animation: think-pulse 1.2s ease-in-out infinite;
497
+ }
498
+ .thinking-container {
499
+ background: #f3f4f6;
500
+ border-left: 4px solid #6366f1;
501
+ padding: 12px 16px;
502
+ border-radius: 8px;
503
+ margin: 12px 0;
504
+ font-family: monospace;
505
+ white-space: pre-wrap;
506
+ word-wrap: break-word;
507
+ }
508
  """
509
 
510
 
511
+ # ============================================================
512
+ # GRADIO UI – added thinking output
513
+ # ============================================================
514
+
515
+ with gr.Blocks(title=APP_NAME, css=CSS) as demo:
516
  gr.HTML("""
517
  <div id="header">
518
  <div id="logo">⚑ X-RUDRA</div>
 
530
  with gr.Column(scale=4):
531
  gr.Markdown("## πŸ”¬ Live Research")
532
  activity = gr.Markdown("βšͺ Waiting for your question.")
533
+ # Thinking output will appear here
534
+ thinking = gr.Markdown("", elem_id="thinking", visible=False)
535
  gr.Markdown("---")
536
  gr.Markdown(f"""
537
  ### Model Spaces
 
572
  inputs=question
573
  )
574
 
575
+ # Update outputs: added thinking
576
  inputs = [question, max_results, max_rounds, use_models, freshness]
577
+ outputs = [chatbot, activity, sources, evidence, verification, thinking]
578
 
579
  send.click(fn=run_research, inputs=inputs, outputs=outputs)
580
  question.submit(fn=run_research, inputs=inputs, outputs=outputs)
 
594
  print("HF_TOKEN set – rate limits reduced.")
595
  else:
596
  print("HF_TOKEN not set – you may experience rate limits. Set it as a Secret in your Space.")
597
+ demo.launch(server_name="0.0.0.0", server_port=PORT, show_error=True)