Essi commited on
Commit
e3677e5
·
1 Parent(s): ef1d4eb

feat: add debug tracing for error handling and increase timeout in subprocess execution

Browse files
Files changed (3) hide show
  1. app.py +1 -0
  2. helpers.py +12 -0
  3. tools.py +9 -2
app.py CHANGED
@@ -150,6 +150,7 @@ def gather_context(state: AgentState) -> AgentState:
150
  def generate_answer(state: AgentState) -> AgentState:
151
  # Skip LLM for deterministic labels or tasks that already used LLMs
152
  if state["label"] in {"code", "excel", "image", "math"}:
 
153
  return state
154
 
155
  prompt = [
 
150
  def generate_answer(state: AgentState) -> AgentState:
151
  # Skip LLM for deterministic labels or tasks that already used LLMs
152
  if state["label"] in {"code", "excel", "image", "math"}:
153
+ print(f"[DEBUG] ANSWER ({state['label']}) >>> {state['answer']}")
154
  return state
155
 
156
  prompt = [
helpers.py CHANGED
@@ -1,6 +1,8 @@
1
  import csv
2
  from io import BytesIO
3
  from pathlib import Path
 
 
4
  from zipfile import BadZipFile, ZipFile
5
 
6
  import requests
@@ -63,3 +65,13 @@ def sniff_excel_type(blob: bytes) -> str:
63
  def get_prompt(prompt_key: str, **kwargs: str) -> str:
64
  """Get a prompt by key and fill in placeholders via `.format(**kwargs)`"""
65
  return _PROMPTS[prompt_key].format(**kwargs)
 
 
 
 
 
 
 
 
 
 
 
1
  import csv
2
  from io import BytesIO
3
  from pathlib import Path
4
+ from sys import stderr
5
+ from traceback import print_exception
6
  from zipfile import BadZipFile, ZipFile
7
 
8
  import requests
 
65
  def get_prompt(prompt_key: str, **kwargs: str) -> str:
66
  """Get a prompt by key and fill in placeholders via `.format(**kwargs)`"""
67
  return _PROMPTS[prompt_key].format(**kwargs)
68
+
69
+
70
+ def print_debug_trace(err: Exception, label: str = "") -> None:
71
+ """
72
+ Print the full stack trace of `err` to STDERR so it shows up in HF logs.
73
+ """
74
+ banner = f"[TRACE {label}]" if label else "[TRACE]"
75
+ print(banner, file=stderr)
76
+ print_exception(type(err), err, err.__traceback__, file=stderr)
77
+ print("-" * 60, file=stderr)
tools.py CHANGED
@@ -18,7 +18,7 @@ from langchain_core.tools import tool
18
  from langchain_openai import ChatOpenAI
19
  from youtube_transcript_api import YouTubeTranscriptApi
20
 
21
- from helpers import get_prompt
22
 
23
  # --------------------------------------------------------------------------- #
24
  # ARITHMETIC (SAFE CALCULATOR) #
@@ -54,6 +54,7 @@ def calculator(expression: str) -> str:
54
  value = _safe_eval(tree.body)
55
  return str(value)
56
  except Exception as exc:
 
57
  return f"calc_error:{exc}"
58
 
59
 
@@ -100,6 +101,7 @@ def web_multi_search(query: str, k: int = 6) -> str:
100
  ]
101
  return json.dumps(formatted, ensure_ascii=False)
102
  except Exception as exc:
 
103
  return f"search_error:{exc}"
104
 
105
 
@@ -126,6 +128,7 @@ def youtube_transcript(url: str, chars: int = 10_000) -> str:
126
  text = " ".join(piece["text"] for piece in transcript)
127
  return text[:chars]
128
  except Exception as exc:
 
129
  return f"yt_error:{exc}"
130
 
131
 
@@ -187,6 +190,7 @@ def vision_task(img_bytes: bytes, question: str) -> str:
187
  reply = vision_llm.invoke(messages).content.strip()
188
  return reply
189
  except Exception as exc:
 
190
  return f"img_error:{exc}"
191
 
192
 
@@ -201,11 +205,12 @@ def run_py(code: str) -> str:
201
  f.write(code)
202
  path = f.name
203
  proc = subprocess.run(
204
- ["python", path], capture_output=True, text=True, timeout=30
205
  )
206
  out = proc.stdout.strip().splitlines()
207
  return out[-1] if out else ""
208
  except Exception as exc:
 
209
  return f"py_error:{exc}"
210
 
211
 
@@ -223,6 +228,7 @@ def transcribe_via_whisper(audio_bytes: bytes) -> str:
223
  print(f"[DEBUG] Whisper transcript (first 200 chars): {output[:200]}")
224
  return output
225
  except Exception as exc:
 
226
  return f"asr_error:{exc}"
227
 
228
 
@@ -262,6 +268,7 @@ def analyze_excel_file(xls_bytes: bytes, question: str) -> str:
262
  else str(result)
263
  )
264
  except Exception as e:
 
265
  return f"eval_error:{e}"
266
 
267
 
 
18
  from langchain_openai import ChatOpenAI
19
  from youtube_transcript_api import YouTubeTranscriptApi
20
 
21
+ from helpers import get_prompt, print_debug_trace
22
 
23
  # --------------------------------------------------------------------------- #
24
  # ARITHMETIC (SAFE CALCULATOR) #
 
54
  value = _safe_eval(tree.body)
55
  return str(value)
56
  except Exception as exc:
57
+ print_debug_trace(exc, "Calculator")
58
  return f"calc_error:{exc}"
59
 
60
 
 
101
  ]
102
  return json.dumps(formatted, ensure_ascii=False)
103
  except Exception as exc:
104
+ print_debug_trace(exc, "Multi Search")
105
  return f"search_error:{exc}"
106
 
107
 
 
128
  text = " ".join(piece["text"] for piece in transcript)
129
  return text[:chars]
130
  except Exception as exc:
131
+ print_debug_trace(exc, "YouTube")
132
  return f"yt_error:{exc}"
133
 
134
 
 
190
  reply = vision_llm.invoke(messages).content.strip()
191
  return reply
192
  except Exception as exc:
193
+ print_debug_trace(exc, "vision")
194
  return f"img_error:{exc}"
195
 
196
 
 
205
  f.write(code)
206
  path = f.name
207
  proc = subprocess.run(
208
+ ["python", path], capture_output=True, text=True, timeout=45
209
  )
210
  out = proc.stdout.strip().splitlines()
211
  return out[-1] if out else ""
212
  except Exception as exc:
213
+ print_debug_trace(exc, "run_py")
214
  return f"py_error:{exc}"
215
 
216
 
 
228
  print(f"[DEBUG] Whisper transcript (first 200 chars): {output[:200]}")
229
  return output
230
  except Exception as exc:
231
+ print_debug_trace(exc, "Whisper")
232
  return f"asr_error:{exc}"
233
 
234
 
 
268
  else str(result)
269
  )
270
  except Exception as e:
271
+ print_debug_trace(e, "Excel")
272
  return f"eval_error:{e}"
273
 
274