avi080704 commited on
Commit
413f492
·
verified ·
1 Parent(s): e3945a7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +42 -17
app.py CHANGED
@@ -24,19 +24,19 @@ GROQ_MODELS = [
24
  m.strip()
25
  for m in os.getenv(
26
  "GROQ_MODELS",
27
- # 8b only — 30K TPM is plenty. 70b's 6K TPM is too tight for tool-calling agents.
28
  "llama-3.1-8b-instant",
29
  ).split(",")
30
  if m.strip()
31
  ]
32
- # Smarter model used ONLY for the final formatting/synthesis pass (one short call -> fits in TPM).
33
  GROQ_FINAL_MODEL = os.getenv("GROQ_FINAL_MODEL", "llama-3.3-70b-versatile")
34
  GROQ_VISION_MODEL = os.getenv("GROQ_VISION_MODEL", "meta-llama/llama-4-scout-17b-16e-instruct")
35
  GROQ_WHISPER_MODEL = os.getenv("GROQ_WHISPER_MODEL", "whisper-large-v3-turbo")
36
 
37
- MAX_TOOL_ITERATIONS = 6
38
- TOOL_RESULT_MAX_CHARS = 1400 # tighter -> stays under 6K TPM for 70b
39
- HISTORY_TRIM_AFTER = 5 # trim aggressively
40
  ANSWER_CACHE_PATH = os.getenv("ANSWER_CACHE_PATH", "/tmp/answers_cache.json")
41
  RESULTS_CSV_PATH = "/tmp/gaia_results.csv"
42
  INTER_QUESTION_SLEEP = float(os.getenv("INTER_QUESTION_SLEEP", "3"))
@@ -61,28 +61,30 @@ def tool_web_search(query: str, max_results: int = 5) -> str:
61
  search_depth="basic",
62
  include_answer=True,
63
  )
64
- lines = []
65
  if res.get("answer"):
66
  lines.append(f"Answer: {res['answer']}")
67
  for r in res.get("results", [])[:max_results]:
68
  lines.append(
69
  f"- {r.get('title', '')}\n {r.get('url', '')}\n {r.get('content', '')[:300]}"
70
  )
71
- if lines:
72
  return "\n".join(lines)
73
  except Exception as e:
74
  print(f"tavily search failed, falling back to DDG: {e}")
 
 
75
 
76
  try:
77
  from duckduckgo_search import DDGS
78
- results = []
79
  with DDGS() as ddgs:
80
  for r in ddgs.text(query, max_results=max_results):
81
  results.append(
82
  f"- {r.get('title', '')}\n {r.get('href', '')}\n {r.get('body', '')[:300]}"
83
  )
84
- if not results:
85
- return "No results."
86
  return "\n".join(results)
87
  except Exception as e:
88
  return f"web_search error: {e}"
@@ -701,11 +703,11 @@ class GroqAgent:
701
  return self._synthesize(question, collected_facts)
702
 
703
  def _synthesize(self, question: str, facts: list[str]) -> str:
704
- """Final answer pass on a short context. Uses smarter model if available."""
705
- # Keep total facts under ~3500 chars to be safe with TPM on 70b.
706
- joined = "\n\n".join(facts[-6:]) # last 6 tool outputs
707
- if len(joined) > 3500:
708
- joined = joined[-3500:]
709
 
710
  synth_messages = [
711
  {
@@ -715,7 +717,10 @@ class GroqAgent:
715
  "research notes below, then output ONLY the final answer string. "
716
  "No preamble, no labels, no explanation, no quotes, no trailing period. "
717
  "Match the question's required format exactly (number-only / IOC code / "
718
- "first name only / two-decimal currency / comma-space list / etc.)."
 
 
 
719
  ),
720
  },
721
  {
@@ -728,7 +733,11 @@ class GroqAgent:
728
  },
729
  ]
730
  # Try the smarter final model first; fall back to the regular pool.
 
731
  for model_choice in (GROQ_FINAL_MODEL, *self.models):
 
 
 
732
  try:
733
  resp = self._chat(synth_messages, use_tools=False, max_tokens=120, model=model_choice)
734
  ans = (resp.choices[0].message.content or "").strip()
@@ -738,7 +747,23 @@ class GroqAgent:
738
  except Exception as e:
739
  print(f"synth with {model_choice} failed: {e}")
740
  continue
741
- return ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
742
 
743
  def _finalize(self, raw: str, question: str, facts: list[str] | None = None) -> str:
744
  """Post-process and, if the answer still looks like a sentence, ask the model to reformat."""
 
24
  m.strip()
25
  for m in os.getenv(
26
  "GROQ_MODELS",
27
+ # 8b only end-to-end. 70b is too tight on free tier and breaks synthesis.
28
  "llama-3.1-8b-instant",
29
  ).split(",")
30
  if m.strip()
31
  ]
32
+ # Smarter model used for the final synthesis pass. Tried first, falls back to 8b.
33
  GROQ_FINAL_MODEL = os.getenv("GROQ_FINAL_MODEL", "llama-3.3-70b-versatile")
34
  GROQ_VISION_MODEL = os.getenv("GROQ_VISION_MODEL", "meta-llama/llama-4-scout-17b-16e-instruct")
35
  GROQ_WHISPER_MODEL = os.getenv("GROQ_WHISPER_MODEL", "whisper-large-v3-turbo")
36
 
37
+ MAX_TOOL_ITERATIONS = 7
38
+ TOOL_RESULT_MAX_CHARS = 1500
39
+ HISTORY_TRIM_AFTER = 6
40
  ANSWER_CACHE_PATH = os.getenv("ANSWER_CACHE_PATH", "/tmp/answers_cache.json")
41
  RESULTS_CSV_PATH = "/tmp/gaia_results.csv"
42
  INTER_QUESTION_SLEEP = float(os.getenv("INTER_QUESTION_SLEEP", "3"))
 
61
  search_depth="basic",
62
  include_answer=True,
63
  )
64
+ lines = ["[provider: tavily]"]
65
  if res.get("answer"):
66
  lines.append(f"Answer: {res['answer']}")
67
  for r in res.get("results", [])[:max_results]:
68
  lines.append(
69
  f"- {r.get('title', '')}\n {r.get('url', '')}\n {r.get('content', '')[:300]}"
70
  )
71
+ if len(lines) > 1:
72
  return "\n".join(lines)
73
  except Exception as e:
74
  print(f"tavily search failed, falling back to DDG: {e}")
75
+ else:
76
+ print("[search] TAVILY_API_KEY not set; using DDG.")
77
 
78
  try:
79
  from duckduckgo_search import DDGS
80
+ results = ["[provider: duckduckgo]"]
81
  with DDGS() as ddgs:
82
  for r in ddgs.text(query, max_results=max_results):
83
  results.append(
84
  f"- {r.get('title', '')}\n {r.get('href', '')}\n {r.get('body', '')[:300]}"
85
  )
86
+ if len(results) == 1:
87
+ return "[provider: duckduckgo] No results."
88
  return "\n".join(results)
89
  except Exception as e:
90
  return f"web_search error: {e}"
 
703
  return self._synthesize(question, collected_facts)
704
 
705
  def _synthesize(self, question: str, facts: list[str]) -> str:
706
+ """Final answer pass on a short context. Tries smarter model first."""
707
+ # Keep total facts well under any TPM cap.
708
+ joined = "\n\n".join(facts[-6:])
709
+ if len(joined) > 2500:
710
+ joined = joined[-2500:]
711
 
712
  synth_messages = [
713
  {
 
717
  "research notes below, then output ONLY the final answer string. "
718
  "No preamble, no labels, no explanation, no quotes, no trailing period. "
719
  "Match the question's required format exactly (number-only / IOC code / "
720
+ "first name only / surname only / two-decimal currency / comma-space list). "
721
+ "If the notes are insufficient, give your single best guess based on "
722
+ "general knowledge in the same strict format. Never refuse, never apologize, "
723
+ "never reply with an empty string."
724
  ),
725
  },
726
  {
 
733
  },
734
  ]
735
  # Try the smarter final model first; fall back to the regular pool.
736
+ attempts = []
737
  for model_choice in (GROQ_FINAL_MODEL, *self.models):
738
+ if model_choice in attempts:
739
+ continue
740
+ attempts.append(model_choice)
741
  try:
742
  resp = self._chat(synth_messages, use_tools=False, max_tokens=120, model=model_choice)
743
  ans = (resp.choices[0].message.content or "").strip()
 
747
  except Exception as e:
748
  print(f"synth with {model_choice} failed: {e}")
749
  continue
750
+ # Last-resort: zero-shot guess with no notes, smallest possible prompt.
751
+ try:
752
+ resp = self._chat(
753
+ [
754
+ {"role": "system", "content": "Answer in 1-5 words. No explanation."},
755
+ {"role": "user", "content": question[:500]},
756
+ ],
757
+ use_tools=False,
758
+ max_tokens=40,
759
+ model=self.models[0],
760
+ )
761
+ return self._postprocess_answer(
762
+ (resp.choices[0].message.content or "").strip(), question
763
+ )
764
+ except Exception as e:
765
+ print(f"last-resort guess failed: {e}")
766
+ return "unknown"
767
 
768
  def _finalize(self, raw: str, question: str, facts: list[str] | None = None) -> str:
769
  """Post-process and, if the answer still looks like a sentence, ask the model to reformat."""