bstraehle commited on
Commit
cdd5c49
·
verified ·
1 Parent(s): 33214b0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +106 -50
app.py CHANGED
@@ -4,10 +4,11 @@
4
 
5
  import gradio.utils, os, sys
6
  import gradio as gr
 
 
 
7
  from agents.crew import run_crew
8
- from contextlib import contextmanager
9
  from huggingface_hub import whoami
10
- from io import StringIO
11
  from utils.utils import (
12
  DATASET_TYPE_GAIA,
13
  DATASET_TYPE_HLE,
@@ -21,39 +22,56 @@ SPACE_ID = os.environ.get("SPACE_ID")
21
 
22
  BASE_URL = f"https://huggingface.co/spaces/{SPACE_ID}/blob/main"
23
 
24
- # Console output capture
25
 
26
- @contextmanager
27
- def capture_output():
28
- old_stdout = sys.stdout
29
- old_stderr = sys.stderr
30
-
31
- class Tee:
32
- def __init__(self, buffer, original):
33
- self.buffer = buffer
34
- self.original = original
35
-
36
- def write(self, data):
37
- self.buffer.write(data)
38
- self.original.write(data)
39
-
40
- def flush(self):
41
- self.buffer.flush()
42
- self.original.flush()
43
-
44
- try:
45
- stdout_buffer = StringIO()
46
- stderr_buffer = StringIO()
47
- sys.stdout = Tee(stdout_buffer, old_stdout)
48
- sys.stderr = Tee(stderr_buffer, old_stderr)
49
- yield stdout_buffer, stderr_buffer
50
- finally:
51
- sys.stdout = old_stdout
52
- sys.stderr = old_stderr
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
  # MCP server functions
55
 
56
- def ask(oauth_token: gr.OAuthToken, question: str, openai_api_key: str, gemini_api_key: str, anthropic_api_key: str, file_name : str = ""):
57
  """
58
  Ask General AI Assistant a question to answer.
59
  Args:
@@ -62,38 +80,44 @@ def ask(oauth_token: gr.OAuthToken, question: str, openai_api_key: str, gemini_a
62
  gemini_api_key (str): Gemini API key (always used)
63
  anthropic_api_key (str): Anthropic API key (only used by Stagehand tool)
64
  file_name (str): Optional file name
65
- Returns:
66
- tuple: (answer, console_logs) - The answer to the question and captured console output
67
  """
68
  if not question:
69
  msg = "Question is required."
70
  gr.Warning(msg)
71
- return None, msg
 
72
 
73
  if not openai_api_key:
74
  msg = "OpenAI API Key is required."
75
  gr.Warning(msg)
76
- return None, msg
 
77
 
78
  if not gemini_api_key:
79
  msg = "Gemini API Key is required."
80
  gr.Warning(msg)
81
- return None, msg
 
82
 
83
  if not anthropic_api_key:
84
  msg = "Anthropic API Key is required."
85
  gr.Warning(msg)
86
- return None, msg
 
87
 
88
  is_valid = validate_input(question, openai_api_key, gemini_api_key, anthropic_api_key)
89
 
90
  if not is_valid:
91
  msg = "Invalid input"
92
  gr.Warning(msg)
93
- return None, msg
 
94
 
95
- if file_name:
96
- file_name = f"files/{file_name}"
 
97
 
98
  try:
99
  # API keys are provided thanks to sponsor credit.
@@ -106,18 +130,49 @@ def ask(oauth_token: gr.OAuthToken, question: str, openai_api_key: str, gemini_a
106
  os.environ["GEMINI_API_KEY"] = gemini_key
107
  os.environ["ANTHROPIC_API_KEY"] = anthropic_key
108
 
109
- with capture_output() as (stdout, stderr):
110
- answer = run_crew(question, file_name)
111
-
112
- stdout_logs = stdout.getvalue()
113
- stderr_logs = stderr.getvalue()
114
- console_logs = stdout_logs + (stderr_logs if stderr_logs else "")
 
 
 
 
 
 
115
 
116
- return answer, console_logs
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  except Exception as e:
118
  msg = str(e)
119
  gr.Warning(msg)
120
- return None, f"Error: {msg}"
121
 
122
  # Helper functions
123
 
@@ -247,12 +302,13 @@ with gr.Blocks(elem_classes=["full-width-app"]) as gaia:
247
  max_lines=5
248
  )
249
 
250
- with gr.Accordion("Console Logs", open=False):
251
  console_logs = gr.Textbox(
252
  label="Output",
253
  interactive=False,
254
  lines=25,
255
- max_lines=25
 
256
  )
257
 
258
  with gr.Row():
 
4
 
5
  import gradio.utils, os, sys
6
  import gradio as gr
7
+ import threading
8
+ import queue
9
+ import time
10
  from agents.crew import run_crew
 
11
  from huggingface_hub import whoami
 
12
  from utils.utils import (
13
  DATASET_TYPE_GAIA,
14
  DATASET_TYPE_HLE,
 
22
 
23
  BASE_URL = f"https://huggingface.co/spaces/{SPACE_ID}/blob/main"
24
 
25
+ # Streaming console output capture
26
 
27
+ class StreamingCapture:
28
+ def __init__(self):
29
+ self.queue = queue.Queue()
30
+ self.old_stdout = None
31
+ self.old_stderr = None
32
+ self.stopped = False
33
+
34
+ def start(self):
35
+ self.old_stdout = sys.stdout
36
+ self.old_stderr = sys.stderr
37
+
38
+ parent = self
39
+
40
+ class QueueWriter:
41
+ def __init__(self, original, q):
42
+ self.original = original
43
+ self.q = q
44
+
45
+ def write(self, data):
46
+ if data:
47
+ self.q.put(data)
48
+ self.original.write(data)
49
+
50
+ def flush(self):
51
+ self.original.flush()
52
+
53
+ sys.stdout = QueueWriter(self.old_stdout, self.queue)
54
+ sys.stderr = QueueWriter(self.old_stderr, self.queue)
55
+
56
+ def stop(self):
57
+ self.stopped = True
58
+ if self.old_stdout:
59
+ sys.stdout = self.old_stdout
60
+ if self.old_stderr:
61
+ sys.stderr = self.old_stderr
62
+
63
+ def get_new_output(self):
64
+ output = []
65
+ while not self.queue.empty():
66
+ try:
67
+ output.append(self.queue.get_nowait())
68
+ except queue.Empty:
69
+ break
70
+ return "".join(output)
71
 
72
  # MCP server functions
73
 
74
+ def ask(oauth_token: gr.OAuthToken, question: str, openai_api_key: str, gemini_api_key: str, anthropic_api_key: str, file_name: str = ""):
75
  """
76
  Ask General AI Assistant a question to answer.
77
  Args:
 
80
  gemini_api_key (str): Gemini API key (always used)
81
  anthropic_api_key (str): Anthropic API key (only used by Stagehand tool)
82
  file_name (str): Optional file name
83
+ Yields:
84
+ tuple: (answer, console_logs) - The answer to the question and captured console output (streamed)
85
  """
86
  if not question:
87
  msg = "Question is required."
88
  gr.Warning(msg)
89
+ yield None, msg
90
+ return
91
 
92
  if not openai_api_key:
93
  msg = "OpenAI API Key is required."
94
  gr.Warning(msg)
95
+ yield None, msg
96
+ return
97
 
98
  if not gemini_api_key:
99
  msg = "Gemini API Key is required."
100
  gr.Warning(msg)
101
+ yield None, msg
102
+ return
103
 
104
  if not anthropic_api_key:
105
  msg = "Anthropic API Key is required."
106
  gr.Warning(msg)
107
+ yield None, msg
108
+ return
109
 
110
  is_valid = validate_input(question, openai_api_key, gemini_api_key, anthropic_api_key)
111
 
112
  if not is_valid:
113
  msg = "Invalid input"
114
  gr.Warning(msg)
115
+ yield None, msg
116
+ return
117
 
118
+ task_file_name = file_name
119
+ if task_file_name:
120
+ task_file_name = f"files/{task_file_name}"
121
 
122
  try:
123
  # API keys are provided thanks to sponsor credit.
 
130
  os.environ["GEMINI_API_KEY"] = gemini_key
131
  os.environ["ANTHROPIC_API_KEY"] = anthropic_key
132
 
133
+ # Streaming capture
134
+ capture = StreamingCapture()
135
+ capture.start()
136
+
137
+ result = {"answer": None, "error": None}
138
+ all_logs = ""
139
+
140
+ def run_task():
141
+ try:
142
+ result["answer"] = run_crew(question, task_file_name)
143
+ except Exception as e:
144
+ result["error"] = str(e)
145
 
146
+ # Run in background thread
147
+ thread = threading.Thread(target=run_task)
148
+ thread.start()
149
+
150
+ # Stream logs while waiting
151
+ while thread.is_alive():
152
+ new_output = capture.get_new_output()
153
+ if new_output:
154
+ all_logs += new_output
155
+ yield None, all_logs # Update console logs, answer still None
156
+ time.sleep(0.1) # Poll interval
157
+
158
+ thread.join()
159
+ capture.stop()
160
+
161
+ # Get any remaining output
162
+ new_output = capture.get_new_output()
163
+ if new_output:
164
+ all_logs += new_output
165
+
166
+ if result["error"]:
167
+ gr.Warning(result["error"])
168
+ yield None, all_logs + f"\n\nError: {result['error']}"
169
+ else:
170
+ yield result["answer"], all_logs
171
+
172
  except Exception as e:
173
  msg = str(e)
174
  gr.Warning(msg)
175
+ yield None, f"Error: {msg}"
176
 
177
  # Helper functions
178
 
 
302
  max_lines=5
303
  )
304
 
305
+ with gr.Accordion("Console Logs", open=True):
306
  console_logs = gr.Textbox(
307
  label="Output",
308
  interactive=False,
309
  lines=25,
310
+ max_lines=25,
311
+ autoscroll=True
312
  )
313
 
314
  with gr.Row():