saad-sust commited on
Commit
92aa741
Β·
verified Β·
1 Parent(s): 74eefad

Upload 2 files

Browse files
Files changed (1) hide show
  1. app.py +37 -55
app.py CHANGED
@@ -308,14 +308,19 @@ def run_sympy(problem: str) -> dict:
308
  return default
309
 
310
 
311
- # ─── HF Inference API (completely free, no key needed) ──────────────────────────
312
  def ask_claude(problem: str, sympy_info: dict, history: list) -> str:
313
- """
314
- Uses Hugging Face Inference API with Mistral-7B β€” 100% free, no API key needed.
315
- HF_TOKEN is optional but recommended (get free at huggingface.co/settings/tokens).
316
- """
317
  import requests
318
 
 
 
 
 
 
 
 
 
 
319
  sympy_context = ""
320
  if (sympy_info.get("result")
321
  and sympy_info["result"] not in (None, "matrix_detected", "mod_detected")):
@@ -323,74 +328,51 @@ def ask_claude(problem: str, sympy_info: dict, history: list) -> str:
323
  f"SYMPY VERIFIED RESULT (your final answer MUST match this):\n"
324
  f"- Operation: {sympy_info.get('type', 'N/A')}\n"
325
  f"- Result: {sympy_info.get('result', 'N/A')}\n"
326
- f"- LaTeX: {sympy_info.get('latex', 'N/A')}\n\n"
327
  )
328
 
329
- system_text = (
330
  "You are SAAD AI, an elite BSc Mathematics tutor. "
331
- "Solve every problem step by step. "
332
- "Label every step as Step 1:, Step 2:, etc. "
333
  "Use $...$ for inline math and $$...$$ for display equations. "
334
- "State the method/theorem used at the start. "
335
- "Show ALL intermediate algebra β€” never skip steps. "
336
- "End with: **Final Answer:** $$...$$ "
337
  "NEVER make arithmetic errors. "
338
  "Topics: Calculus, Linear Algebra, Number Theory, ODEs, "
339
  "Numerical Methods, Differential Geometry, Hydro Mechanics, "
340
- "Theory of Numbers, Real Analysis II, General Math. "
341
  + sympy_context
342
  )
343
 
344
- # Build prompt with history (last 4 exchanges)
345
- conversation = ""
346
  for msg in history[-8:]:
347
- role = "User" if msg["role"] == "user" else "Assistant"
348
- conversation += f"{role}: {msg['content']}\n"
349
- conversation += f"User: {problem}\nAssistant:"
350
-
351
- full_prompt = f"<s>[INST] {system_text}\n\n{conversation} [/INST]"
352
-
353
- # HF_TOKEN is free β€” get at huggingface.co/settings/tokens
354
- # Without it, rate limits are stricter but it still works
355
- hf_token = os.environ.get("HF_TOKEN", "")
356
- headers = {"Authorization": f"Bearer {hf_token}"} if hf_token else {}
357
-
358
- # Mistral-7B-Instruct β€” excellent at math, free on HF
359
- API_URL = "https://api-inference.huggingface.co/models/mistralai/Mistral-7B-Instruct-v0.3"
360
 
 
 
 
 
361
  payload = {
362
- "inputs": full_prompt,
363
- "parameters": {
364
- "max_new_tokens": 1500,
365
- "temperature": 0.2, # low temp = more precise math
366
- "repetition_penalty": 1.1,
367
- "return_full_text": False
368
- }
369
  }
370
 
371
  try:
372
- resp = requests.post(API_URL, headers=headers, json=payload, timeout=60)
 
 
 
 
 
373
  resp.raise_for_status()
374
- data = resp.json()
375
-
376
- if isinstance(data, list) and len(data) > 0:
377
- return data[0].get("generated_text", "No response generated.")
378
- elif isinstance(data, dict) and "error" in data:
379
- # Model is loading β€” happens first time, takes ~20 seconds
380
- if "loading" in str(data["error"]).lower():
381
- return (
382
- "⏳ **Model is loading** (first request takes ~20 seconds).\n\n"
383
- "Please click **SOLVE** again in a few seconds."
384
- )
385
- return f"⚠️ HF API Error: {data['error']}"
386
- else:
387
- return "⚠️ Unexpected response format from HF API."
388
-
389
  except requests.exceptions.Timeout:
390
- return (
391
- "⏳ **Request timed out.** The model may be loading.\n\n"
392
- "Please click **SOLVE** again in a few seconds."
393
- )
394
  except Exception as e:
395
  return f"⚠️ Error: {str(e)}"
396
 
 
308
  return default
309
 
310
 
311
+ # ─── Groq API (100% free, fast, reliable) ───────────────────────────────────────
312
  def ask_claude(problem: str, sympy_info: dict, history: list) -> str:
 
 
 
 
313
  import requests
314
 
315
+ api_key = os.environ.get("GROQ_API_KEY", "")
316
+ if not api_key:
317
+ return (
318
+ "⚠️ **GROQ_API_KEY not set.**\n\n"
319
+ "1. Go to https://console.groq.com\n"
320
+ "2. Sign up free β†’ API Keys β†’ Create API Key\n"
321
+ "3. HF Space β†’ Settings β†’ Secrets β†’ add GROQ_API_KEY"
322
+ )
323
+
324
  sympy_context = ""
325
  if (sympy_info.get("result")
326
  and sympy_info["result"] not in (None, "matrix_detected", "mod_detected")):
 
328
  f"SYMPY VERIFIED RESULT (your final answer MUST match this):\n"
329
  f"- Operation: {sympy_info.get('type', 'N/A')}\n"
330
  f"- Result: {sympy_info.get('result', 'N/A')}\n"
331
+ f"- LaTeX: {sympy_info.get('latex', 'N/A')}\n"
332
  )
333
 
334
+ system_prompt = (
335
  "You are SAAD AI, an elite BSc Mathematics tutor. "
336
+ "Solve every problem with perfect step-by-step working. "
337
+ "Label every step: Step 1:, Step 2:, etc. "
338
  "Use $...$ for inline math and $$...$$ for display equations. "
339
+ "State the method or theorem used at the start. "
340
+ "Show ALL intermediate algebra, never skip steps. "
341
+ "End every solution with: **Final Answer:** $$...$$ "
342
  "NEVER make arithmetic errors. "
343
  "Topics: Calculus, Linear Algebra, Number Theory, ODEs, "
344
  "Numerical Methods, Differential Geometry, Hydro Mechanics, "
345
+ "Theory of Numbers, Real Analysis II, General Math.\n\n"
346
  + sympy_context
347
  )
348
 
349
+ messages = [{"role": "system", "content": system_prompt}]
 
350
  for msg in history[-8:]:
351
+ messages.append({"role": msg["role"], "content": msg["content"]})
352
+ messages.append({"role": "user", "content": problem})
 
 
 
 
 
 
 
 
 
 
 
353
 
354
+ headers = {
355
+ "Authorization": f"Bearer {api_key}",
356
+ "Content-Type": "application/json"
357
+ }
358
  payload = {
359
+ "model": "llama-3.3-70b-versatile",
360
+ "messages": messages,
361
+ "max_tokens": 2048,
362
+ "temperature": 0.2
 
 
 
363
  }
364
 
365
  try:
366
+ resp = requests.post(
367
+ "https://api.groq.com/openai/v1/chat/completions",
368
+ headers=headers,
369
+ json=payload,
370
+ timeout=60
371
+ )
372
  resp.raise_for_status()
373
+ return resp.json()["choices"][0]["message"]["content"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
  except requests.exceptions.Timeout:
375
+ return "⏳ Request timed out. Please try again."
 
 
 
376
  except Exception as e:
377
  return f"⚠️ Error: {str(e)}"
378