CultriX commited on
Commit
9f8395f
·
verified ·
1 Parent(s): f7d50ac

Update run.py

Browse files
Files changed (1) hide show
  1. run.py +35 -41
run.py CHANGED
@@ -48,8 +48,11 @@ class StreamingHandler(logging.Handler):
48
 
49
  def emit(self, record):
50
  msg = self.format(record)
51
- for callback in self.callbacks:
52
- callback(msg) # Do not append newline here, let the callback format if needed
 
 
 
53
 
54
 
55
  class StreamingCapture(StringIO):
@@ -57,27 +60,19 @@ class StreamingCapture(StringIO):
57
  def __init__(self):
58
  super().__init__()
59
  self.callbacks = []
60
- self._buffer = ""
61
 
62
  def add_callback(self, callback):
63
  self.callbacks.append(callback)
64
 
65
  def write(self, s):
66
- super().write(s)
67
- self._buffer += s
68
- # Flush the buffer line by line or after significant chunks
69
- while '\n' in self._buffer:
70
- line, self._buffer = self._buffer.split('\n', 1)
71
- if line.strip(): # Only send non-empty lines
72
- for callback in self.callbacks:
73
- callback(line + '\n') # Add newline back for complete lines
74
-
75
- def flush(self):
76
- # Ensure any remaining content in the buffer is sent
77
- if self._buffer.strip():
78
  for callback in self.callbacks:
79
- callback(self._buffer)
80
- self._buffer = ""
 
 
 
81
  super().flush()
82
 
83
 
@@ -123,7 +118,7 @@ def create_agent(
123
  print("[DEBUG] Using default API endpoint:", api_endpoint)
124
  model_params["base_url"] = api_endpoint
125
  model_params["api_key"] = openai_api_key
126
-
127
 
128
  model = LiteLLMModel(**model_params)
129
  print("[DEBUG] Model initialized")
@@ -147,23 +142,22 @@ def create_agent(
147
 
148
  search_tool = None
149
  if search_provider == "searxng":
150
- print("[DEBUG] Using SearxNG-compatible DuckDuckGoSearchTool with base_url override")
151
  search_tool = DuckDuckGoSearchTool()
152
  if custom_search_url:
153
- # Note: DuckDuckGoSearchTool itself does not inherently support a 'base_url' for SearxNG directly.
154
- # This would typically require modifying the tool or using a custom tool implementation.
155
- # For this example, we'll assume the DuckDuckGoSearchTool could be configured or subclassed
156
- # to point to a SearxNG instance if its underlying search mechanism allowed.
157
- # As a workaround, if SearxNG is chosen, ensure the tool selected is compatible.
158
- # For simplicity, we keep DuckDuckGoSearchTool, but in a real scenario,
159
- # you'd use a dedicated SearxNG tool.
160
- search_tool.base_url = custom_search_url # This line might not have effect without custom logic in DuckDuckGoSearchTool
161
  elif search_provider == "serper":
162
- print("[DEBUG] Using DuckDuckGoSearchTool for Serper search functionality (requires SerpAPI key)")
163
- search_tool = DuckDuckGoSearchTool() # DuckDuckGoSearchTool for general web search
164
- # If Serper API key is explicitly provided, it should be passed to a Serper-specific tool
165
- # For this setup, SerpAPI key is already in browser_config for ArchiveSearchTool,
166
- # but a dedicated Serper search tool might be needed if not using SerpAPI with the browser directly.
 
167
  else:
168
  print("[DEBUG] No specific search provider selected, or provider not directly supported. Defaulting to DuckDuckGoSearchTool.")
169
  search_tool = DuckDuckGoSearchTool()
@@ -184,7 +178,7 @@ def create_agent(
184
  model=model,
185
  tools=[tool for tool in WEB_TOOLS if tool is not None], # Filter out None if search_tool was not set
186
  max_steps=20,
187
- verbosity_level=3,
188
  planning_interval=4,
189
  name="search_agent",
190
  description="A team member that will search the internet to answer your question.",
@@ -199,7 +193,7 @@ Additionally, if after some searching you find out that you need more informatio
199
  model=model,
200
  tools=[visualizer, TextInspectorTool(model, text_limit)],
201
  max_steps=16,
202
- verbosity_level=3,
203
  additional_authorized_imports=AUTHORIZED_IMPORTS,
204
  planning_interval=4,
205
  managed_agents=[text_webbrowser_agent],
@@ -240,9 +234,15 @@ def run_agent_with_streaming(agent, question, stream_callback=None):
240
 
241
  try:
242
  # Configure logging to capture everything
 
243
  root_logger.setLevel(logging.DEBUG)
 
 
244
  root_logger.addHandler(log_handler)
 
245
  smolagents_logger.setLevel(logging.DEBUG)
 
 
246
  smolagents_logger.addHandler(log_handler)
247
 
248
  # Redirect stdout/stderr
@@ -275,7 +275,7 @@ def run_agent_with_streaming(agent, question, stream_callback=None):
275
  sys.stdout = original_stdout
276
  sys.stderr = original_stderr
277
 
278
- # Ensure any remaining buffered output is flushed
279
  stdout_capture.flush()
280
  stderr_capture.flush()
281
 
@@ -302,12 +302,6 @@ def main():
302
  print("[DEBUG] CLI arguments parsed:", args)
303
 
304
  if args.gradio:
305
- # This part should ideally be handled by app.py directly.
306
- # However, if run.py is also executable to launch Gradio,
307
- # it should call app.py's launch_interface.
308
- # For this refactor, we are assuming app.py is the primary entry point for Gradio.
309
- # If you intend run.py to be runnable with --gradio, you would import and call launch_interface() from app.py here.
310
- # For now, this main function only supports CLI mode if --gradio is not passed.
311
  print("Please run `app.py` directly to launch the Gradio interface.")
312
  return
313
  else:
 
48
 
49
  def emit(self, record):
50
  msg = self.format(record)
51
+ # Check if the message is actually different or non-empty after stripping
52
+ # to avoid sending redundant empty strings, though `highlight_text` in app.py handles empty.
53
+ if msg.strip():
54
+ for callback in self.callbacks:
55
+ callback(msg + '\n') # Add newline to ensure distinct lines are processed by app.py's splitter
56
 
57
 
58
  class StreamingCapture(StringIO):
 
60
  def __init__(self):
61
  super().__init__()
62
  self.callbacks = []
 
63
 
64
  def add_callback(self, callback):
65
  self.callbacks.append(callback)
66
 
67
  def write(self, s):
68
+ # Pass the raw string 's' directly to callbacks immediately
69
+ if s: # Only send if there's actual content
 
 
 
 
 
 
 
 
 
 
70
  for callback in self.callbacks:
71
+ callback(s)
72
+ super().write(s) # Still write to the underlying StringIO buffer
73
+
74
+
75
+ def flush(self):
76
  super().flush()
77
 
78
 
 
118
  print("[DEBUG] Using default API endpoint:", api_endpoint)
119
  model_params["base_url"] = api_endpoint
120
  model_params["api_key"] = openai_api_key
121
+ # It's important that if an API key is missing for the chosen model, it fails here or upstream.
122
 
123
  model = LiteLLMModel(**model_params)
124
  print("[DEBUG] Model initialized")
 
142
 
143
  search_tool = None
144
  if search_provider == "searxng":
145
+ print("[DEBUG] Using DuckDuckGoSearchTool (acting as a generic web search) for SearxNG context.")
146
  search_tool = DuckDuckGoSearchTool()
147
  if custom_search_url:
148
+ # Note: As mentioned before, DuckDuckGoSearchTool doesn't natively use a custom base_url
149
+ # for a completely different search engine like SearxNG. This line will likely have no effect.
150
+ # For true SearxNG integration, you'd need a custom tool or a modified DuckDuckGoSearchTool
151
+ # that knows how to query SearxNG instances.
152
+ print(f"[WARNING] DuckDuckGoSearchTool does not directly support 'custom_search_url' for SearxNG. Consider a dedicated SearxNG tool.")
153
+ # search_tool.base_url = custom_search_url # This line is often not effective for DDCSTool
 
 
154
  elif search_provider == "serper":
155
+ print("[DEBUG] Using DuckDuckGoSearchTool (acting as a generic web search) for Serper context.")
156
+ search_tool = DuckDuckGoSearchTool() # You would need a separate SerperTool for direct Serper API calls.
157
+ if search_api_key:
158
+ print("[DEBUG] Serper API Key provided. Ensure your search tool (if custom) uses it.")
159
+ # If you had a dedicated SerperTool, you'd pass search_api_key to it.
160
+ # e.g., search_tool = SerperTool(api_key=search_api_key)
161
  else:
162
  print("[DEBUG] No specific search provider selected, or provider not directly supported. Defaulting to DuckDuckGoSearchTool.")
163
  search_tool = DuckDuckGoSearchTool()
 
178
  model=model,
179
  tools=[tool for tool in WEB_TOOLS if tool is not None], # Filter out None if search_tool was not set
180
  max_steps=20,
181
+ verbosity_level=3, # Keep this high for detailed output
182
  planning_interval=4,
183
  name="search_agent",
184
  description="A team member that will search the internet to answer your question.",
 
193
  model=model,
194
  tools=[visualizer, TextInspectorTool(model, text_limit)],
195
  max_steps=16,
196
+ verbosity_level=3, # Keep this high for detailed output
197
  additional_authorized_imports=AUTHORIZED_IMPORTS,
198
  planning_interval=4,
199
  managed_agents=[text_webbrowser_agent],
 
234
 
235
  try:
236
  # Configure logging to capture everything
237
+ # Set logging levels very low to capture all verbose output
238
  root_logger.setLevel(logging.DEBUG)
239
+ for handler in root_logger.handlers: # Remove existing handlers to avoid duplicate output
240
+ root_logger.removeHandler(handler)
241
  root_logger.addHandler(log_handler)
242
+
243
  smolagents_logger.setLevel(logging.DEBUG)
244
+ for handler in smolagents_logger.handlers: # Remove existing handlers
245
+ smolagents_logger.removeHandler(handler)
246
  smolagents_logger.addHandler(log_handler)
247
 
248
  # Redirect stdout/stderr
 
275
  sys.stdout = original_stdout
276
  sys.stderr = original_stderr
277
 
278
+ # Ensure any remaining buffered output is flushed (especially important for stdout/stderr)
279
  stdout_capture.flush()
280
  stderr_capture.flush()
281
 
 
302
  print("[DEBUG] CLI arguments parsed:", args)
303
 
304
  if args.gradio:
 
 
 
 
 
 
305
  print("Please run `app.py` directly to launch the Gradio interface.")
306
  return
307
  else: