ST-x-Tony commited on
Commit
e44799d
Β·
verified Β·
1 Parent(s): 3c4c999

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +81 -35
app.py CHANGED
@@ -32,7 +32,7 @@ from gradio_client import Client
32
  # ============================================================
33
 
34
  APP_NAME = "X-RUDRA"
35
- VERSION = "3.7.3" # bumped
36
 
37
  M1_REPO = os.getenv("M1_REPO", "Shrijanagain/M1")
38
  M2_REPO = os.getenv("M2_REPO", "Shrijanagain/M2")
@@ -74,29 +74,74 @@ def get_m2_client():
74
 
75
 
76
  # ============================================================
77
- # CASUAL QUERY DETECTOR
 
 
 
 
78
  # ============================================================
79
 
80
- def is_casual_query(text: str) -> bool:
81
- text = text.lower().strip()
82
- words = text.split()
83
- if len(words) <= 2:
84
- return True
85
- question_words = {"what", "how", "why", "when", "where", "who", "which",
86
- "can", "could", "would", "will", "is", "are", "do", "does"}
87
- if words[0] in question_words and len(words) >= 3:
88
- return False
89
- casual_patterns = [
90
- "hey", "hi", "hello", "yo", "what's up", "how are you",
91
- "good morning", "good evening", "good night",
92
- "lol", "haha", "just testing", "timepass", "nothing",
93
- "tell me a joke", "sing a song", "what's your name",
94
- "who are you", "what can you do", "help", "thanks"
95
- ]
96
- for pattern in casual_patterns:
97
- if text == pattern or text.startswith(pattern + " "):
98
- return True
99
- return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
 
102
  # ============================================================
@@ -182,7 +227,7 @@ Answer:"""
182
  else:
183
  return "I couldn't find specific information on that topic. Could you rephrase?", ""
184
 
185
- # If only one draft exists, use that as final (extract thinking if any)
186
  if not draft_m1:
187
  thinking = ""
188
  clean = draft_m2
@@ -214,17 +259,14 @@ Combine these two drafts into a single, comprehensive, accurate, and natural ans
214
 
215
  Final answer:"""
216
 
217
- # Use a higher token limit for the merge step
218
- merge_max_tokens = max(1024, max_tokens * 2) # at least 1024, double the original
219
  merged = call_model(m2_client, merge_prompt, merge_max_tokens, temperature)
220
 
221
- # If merged is too short (incomplete), retry with even more tokens
222
  if merged and len(merged) < 100:
223
  print(f"Merged answer too short ({len(merged)} chars), retrying with 2048 tokens...")
224
  merged = call_model(m2_client, merge_prompt, 2048, temperature)
225
 
226
  if not merged:
227
- # Fallback to draft_m1 if merge fails completely
228
  print("Merge failed, falling back to draft_m1")
229
  merged = draft_m1
230
 
@@ -249,7 +291,7 @@ def get_casual_model_response(query: str) -> str:
249
  try:
250
  result = client.predict(
251
  prompt=f"User: {query}\nAssistant:",
252
- max_tokens=64,
253
  temperature=0.7,
254
  api_name="/generate"
255
  )
@@ -264,7 +306,7 @@ def get_casual_model_response(query: str) -> str:
264
  try:
265
  result = client.predict(
266
  prompt=f"User: {query}\nAssistant:",
267
- max_tokens=64,
268
  temperature=0.7,
269
  api_name="/generate"
270
  )
@@ -409,7 +451,7 @@ def safe_dict(value):
409
 
410
 
411
  # ============================================================
412
- # MAIN RESEARCH FUNCTION (returns 6 outputs)
413
  # ============================================================
414
 
415
  async def do_research(question, max_results, max_rounds, use_models, freshness):
@@ -425,8 +467,12 @@ async def do_research(question, max_results, max_rounds, use_models, freshness):
425
 
426
  question = str(question).strip()
427
 
428
- # ---- Casual query ----
429
- if is_casual_query(question):
 
 
 
 
430
  answer = get_casual_model_response(question)
431
  history = [
432
  {"role": "user", "content": question},
@@ -434,7 +480,7 @@ async def do_research(question, max_results, max_rounds, use_models, freshness):
434
  ]
435
  return history, "⚑ Casual chat (model reply, no search).", "", "", "", ""
436
 
437
- # ---- Serious query ----
438
  started = time.perf_counter()
439
  try:
440
  engine = get_engine()
@@ -464,7 +510,7 @@ async def do_research(question, max_results, max_rounds, use_models, freshness):
464
  })
465
  data["sources"] = sources
466
 
467
- # Generate final answer and thinking content (tags already stripped)
468
  final_answer, thinking_content = get_combined_model_answer(question, sources)
469
 
470
  sources_md = format_sources(sources)
@@ -518,7 +564,7 @@ def health_check():
518
 
519
 
520
  # ============================================================
521
- # CSS – includes spinner animation for thinking
522
  # ============================================================
523
 
524
  CSS = """
 
32
  # ============================================================
33
 
34
  APP_NAME = "X-RUDRA"
35
+ VERSION = "3.8.1"
36
 
37
  M1_REPO = os.getenv("M1_REPO", "Shrijanagain/M1")
38
  M2_REPO = os.getenv("M2_REPO", "Shrijanagain/M2")
 
74
 
75
 
76
  # ============================================================
77
+ # MODEL-BASED INTENT CLASSIFIER
78
+ # ──────────────────────────────────────────────────────────────
79
+ # Uses M1 (or M2) to decide ACTION or CASUAL.
80
+ # No hardcoded keywords – the model decides.
81
+ # If both fail, defaults to ACTION.
82
  # ============================================================
83
 
84
+ CLASSIFIER_SYSTEM_PROMPT = """
85
+ You are an intelligent assistant that classifies user messages into two categories:
86
+ - ACTION: The user asks for information that requires research, fact‑checking, retrieval of current data, or external knowledge. This includes questions about news, comparisons, statistics, history, technology, science, politics, etc.
87
+ - CASUAL: The user is just chatting, greeting, making small talk, joking, or asking a simple question that can be answered from general knowledge without a search.
88
+
89
+ Respond with ONLY ONE WORD: ACTION or CASUAL.
90
+ Do NOT add any extra text, punctuation, or explanation.
91
+ """
92
+
93
+ def classify_intent(question: str) -> str:
94
+ prompt = f"{CLASSIFIER_SYSTEM_PROMPT}\n\nUser message: \"{question}\"\n\nClassification:"
95
+
96
+ # Try M1 first
97
+ m1_client = get_m1_client()
98
+ if m1_client is not None:
99
+ try:
100
+ result = m1_client.predict(
101
+ prompt=prompt,
102
+ max_tokens=10,
103
+ temperature=0.0,
104
+ api_name="/generate"
105
+ )
106
+ if result:
107
+ result = result.strip().upper()
108
+ if "ACTION" in result:
109
+ print(f"[Classifier] M1 β†’ ACTION")
110
+ return "ACTION"
111
+ elif "CASUAL" in result:
112
+ print(f"[Classifier] M1 β†’ CASUAL")
113
+ return "CASUAL"
114
+ else:
115
+ print(f"[Classifier] M1 ambiguous: {result}")
116
+ except Exception as e:
117
+ print(f"[Classifier] M1 call failed: {e}")
118
+
119
+ # Try M2 as fallback
120
+ m2_client = get_m2_client()
121
+ if m2_client is not None:
122
+ try:
123
+ result = m2_client.predict(
124
+ prompt=prompt,
125
+ max_tokens=10,
126
+ temperature=0.0,
127
+ api_name="/generate"
128
+ )
129
+ if result:
130
+ result = result.strip().upper()
131
+ if "ACTION" in result:
132
+ print(f"[Classifier] M2 β†’ ACTION")
133
+ return "ACTION"
134
+ elif "CASUAL" in result:
135
+ print(f"[Classifier] M2 β†’ CASUAL")
136
+ return "CASUAL"
137
+ else:
138
+ print(f"[Classifier] M2 ambiguous: {result}")
139
+ except Exception as e:
140
+ print(f"[Classifier] M2 call failed: {e}")
141
+
142
+ # Default to ACTION if classification fails
143
+ print("[Classifier] Defaulting to ACTION")
144
+ return "ACTION"
145
 
146
 
147
  # ============================================================
 
227
  else:
228
  return "I couldn't find specific information on that topic. Could you rephrase?", ""
229
 
230
+ # If only one draft exists, use that as final
231
  if not draft_m1:
232
  thinking = ""
233
  clean = draft_m2
 
259
 
260
  Final answer:"""
261
 
262
+ merge_max_tokens = max(1024, max_tokens * 2)
 
263
  merged = call_model(m2_client, merge_prompt, merge_max_tokens, temperature)
264
 
 
265
  if merged and len(merged) < 100:
266
  print(f"Merged answer too short ({len(merged)} chars), retrying with 2048 tokens...")
267
  merged = call_model(m2_client, merge_prompt, 2048, temperature)
268
 
269
  if not merged:
 
270
  print("Merge failed, falling back to draft_m1")
271
  merged = draft_m1
272
 
 
291
  try:
292
  result = client.predict(
293
  prompt=f"User: {query}\nAssistant:",
294
+ max_tokens=128,
295
  temperature=0.7,
296
  api_name="/generate"
297
  )
 
306
  try:
307
  result = client.predict(
308
  prompt=f"User: {query}\nAssistant:",
309
+ max_tokens=128,
310
  temperature=0.7,
311
  api_name="/generate"
312
  )
 
451
 
452
 
453
  # ============================================================
454
+ # MAIN RESEARCH FUNCTION
455
  # ============================================================
456
 
457
  async def do_research(question, max_results, max_rounds, use_models, freshness):
 
467
 
468
  question = str(question).strip()
469
 
470
+ # ---- Step 1: Classify intent using M1 (or M2) ----
471
+ intent = classify_intent(question)
472
+ print(f"[Intent] {intent} for: {question}")
473
+
474
+ # ---- Step 2: If casual, reply directly ----
475
+ if intent == "CASUAL":
476
  answer = get_casual_model_response(question)
477
  history = [
478
  {"role": "user", "content": question},
 
480
  ]
481
  return history, "⚑ Casual chat (model reply, no search).", "", "", "", ""
482
 
483
+ # ---- Step 3: ACTION – run research pipeline ----
484
  started = time.perf_counter()
485
  try:
486
  engine = get_engine()
 
510
  })
511
  data["sources"] = sources
512
 
513
+ # Generate final answer and thinking
514
  final_answer, thinking_content = get_combined_model_answer(question, sources)
515
 
516
  sources_md = format_sources(sources)
 
564
 
565
 
566
  # ============================================================
567
+ # CSS
568
  # ============================================================
569
 
570
  CSS = """