Spaces:
Sleeping
Sleeping
Charles Azam
commited on
Commit
·
fe6be00
1
Parent(s):
bd41508
feat: add support for images
Browse files
gradio_app.py
CHANGED
@@ -4,7 +4,9 @@ from deepengineer.backend.gradio_tools import run_agent_stream
|
|
4 |
with gr.Blocks() as demo:
|
5 |
gr.Markdown("# Agent Interface with Real‑Time Tool Logging")
|
6 |
user_input = gr.Textbox(label="User Message")
|
7 |
-
agent_output = gr.Markdown(
|
|
|
|
|
8 |
log_output = gr.Textbox(label="Tool Invocation Log", interactive=False)
|
9 |
|
10 |
send = gr.Button("Send")
|
|
|
4 |
with gr.Blocks() as demo:
|
5 |
gr.Markdown("# Agent Interface with Real‑Time Tool Logging")
|
6 |
user_input = gr.Textbox(label="User Message")
|
7 |
+
agent_output = gr.Markdown(
|
8 |
+
label="Agent Response",
|
9 |
+
)
|
10 |
log_output = gr.Textbox(label="Tool Invocation Log", interactive=False)
|
11 |
|
12 |
send = gr.Button("Send")
|
src/deepengineer/backend/gradio_tools.py
CHANGED
@@ -1,8 +1,55 @@
|
|
1 |
import threading
|
2 |
import time
|
3 |
import queue
|
|
|
|
|
4 |
|
5 |
from deepengineer.deepsearch.main_agent import main_search
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
7 |
|
8 |
def run_agent_stream(user_input: str):
|
@@ -11,7 +58,7 @@ def run_agent_stream(user_input: str):
|
|
11 |
– starts the agent in a background thread
|
12 |
– while the agent runs, flushes anything that tools
|
13 |
have pushed into `log_queue`
|
14 |
-
– finally yields the agent
|
15 |
Yields tuples: (agent_output, log_output)
|
16 |
"""
|
17 |
log_queue = queue.Queue()
|
@@ -21,11 +68,11 @@ def run_agent_stream(user_input: str):
|
|
21 |
print("Emptying log queue")
|
22 |
log_queue.get_nowait()
|
23 |
|
24 |
-
answer_container = {"text": None}
|
25 |
done = threading.Event()
|
26 |
|
27 |
def _worker():
|
28 |
-
answer_container["text"],
|
29 |
done.set()
|
30 |
|
31 |
threading.Thread(target=_worker, daemon=True).start()
|
@@ -45,5 +92,12 @@ def run_agent_stream(user_input: str):
|
|
45 |
log_line = log_queue.get()
|
46 |
log_buffer += log_line + "\n"
|
47 |
|
48 |
-
# final
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import threading
|
2 |
import time
|
3 |
import queue
|
4 |
+
import re
|
5 |
+
from pathlib import Path
|
6 |
|
7 |
from deepengineer.deepsearch.main_agent import main_search
|
8 |
+
from deepengineer.common_path import DATA_DIR
|
9 |
+
|
10 |
+
|
11 |
+
def parse_markdown_images(markdown_text: str, image_dir: Path) -> str:
|
12 |
+
"""
|
13 |
+
Parse markdown text and convert image references to absolute file paths
|
14 |
+
that Gradio can display.
|
15 |
+
|
16 |
+
Args:
|
17 |
+
markdown_text: The markdown text containing image references
|
18 |
+
image_dir: The directory containing the generated images
|
19 |
+
|
20 |
+
Returns:
|
21 |
+
Modified markdown text with absolute file paths for images
|
22 |
+
"""
|
23 |
+
if not markdown_text or not image_dir:
|
24 |
+
return markdown_text
|
25 |
+
|
26 |
+
# Pattern to match markdown image syntax: 
|
27 |
+
image_pattern = r'!\[([^\]]*)\]\(([^)]+)\)'
|
28 |
+
|
29 |
+
def replace_image_path(match):
|
30 |
+
alt_text = match.group(1)
|
31 |
+
image_path = match.group(2)
|
32 |
+
|
33 |
+
# If the path is already absolute, return as is
|
34 |
+
if Path(image_path).is_absolute():
|
35 |
+
return f''
|
36 |
+
|
37 |
+
# If it's a relative path, try to find it in the image directory
|
38 |
+
if image_dir.exists():
|
39 |
+
# Look for the image file in the image directory
|
40 |
+
for img_file in image_dir.glob('*'):
|
41 |
+
if img_file.name == Path(image_path).name:
|
42 |
+
return f'})'
|
43 |
+
|
44 |
+
# If not found by name, try to find any image file
|
45 |
+
image_files = list(image_dir.glob('*.png')) + list(image_dir.glob('*.jpg')) + list(image_dir.glob('*.jpeg'))
|
46 |
+
if image_files:
|
47 |
+
return f'})'
|
48 |
+
|
49 |
+
# If no image found, return the original reference
|
50 |
+
return match.group(0)
|
51 |
+
|
52 |
+
return re.sub(image_pattern, replace_image_path, markdown_text)
|
53 |
|
54 |
|
55 |
def run_agent_stream(user_input: str):
|
|
|
58 |
– starts the agent in a background thread
|
59 |
– while the agent runs, flushes anything that tools
|
60 |
have pushed into `log_queue`
|
61 |
+
– finally yields the agent's answer with embedded images
|
62 |
Yields tuples: (agent_output, log_output)
|
63 |
"""
|
64 |
log_queue = queue.Queue()
|
|
|
68 |
print("Emptying log queue")
|
69 |
log_queue.get_nowait()
|
70 |
|
71 |
+
answer_container = {"text": None, "image_dir": None}
|
72 |
done = threading.Event()
|
73 |
|
74 |
def _worker():
|
75 |
+
answer_container["text"], answer_container["image_dir"] = main_search(user_input, log_queue)
|
76 |
done.set()
|
77 |
|
78 |
threading.Thread(target=_worker, daemon=True).start()
|
|
|
92 |
log_line = log_queue.get()
|
93 |
log_buffer += log_line + "\n"
|
94 |
|
95 |
+
# Process the final answer to include images
|
96 |
+
final_answer = answer_container["text"]
|
97 |
+
image_dir = answer_container["image_dir"]
|
98 |
+
|
99 |
+
if final_answer and image_dir:
|
100 |
+
final_answer = parse_markdown_images(final_answer, image_dir)
|
101 |
+
|
102 |
+
# final yield: agent_output filled with processed markdown, log_output frozen
|
103 |
+
yield (final_answer, log_buffer.rstrip())
|
src/deepengineer/deepsearch/main_agent.py
CHANGED
@@ -69,7 +69,7 @@ def create_main_search_agent(
|
|
69 |
return search_agent
|
70 |
|
71 |
|
72 |
-
def main_search(task: str, log_queue: queue.Queue | None = None):
|
73 |
output_image_path = create_output_image_path()
|
74 |
MAIN_PROMPT = """
|
75 |
You are DeepDraft, an advanced research and analysis agent specialized in deep technical research, data visualization, and comprehensive information synthesis. You have access to powerful tools for web search, document analysis, and data visualization.
|
@@ -90,6 +90,10 @@ You have the tools to search the web using Linkup API for comprehensive research
|
|
90 |
### **Data Visualization Tools**
|
91 |
- You can always use the tool `SaveMatplotlibFigTool` to save a figure at the end of a matplotlib code block. You can then include the figure in your final answer.
|
92 |
|
|
|
|
|
|
|
|
|
93 |
You have one question to answer. It is paramount that you provide a correct answer.
|
94 |
Give it all you can: I know for a fact that you have access to all the relevant tools to solve it and find the correct answer (the answer does exist).
|
95 |
Failure or 'I cannot answer' or 'None found' will not be tolerated, success will be rewarded.
|
|
|
69 |
return search_agent
|
70 |
|
71 |
|
72 |
+
def main_search(task: str, log_queue: queue.Queue | None = None) -> tuple[str, Path]:
|
73 |
output_image_path = create_output_image_path()
|
74 |
MAIN_PROMPT = """
|
75 |
You are DeepDraft, an advanced research and analysis agent specialized in deep technical research, data visualization, and comprehensive information synthesis. You have access to powerful tools for web search, document analysis, and data visualization.
|
|
|
90 |
### **Data Visualization Tools**
|
91 |
- You can always use the tool `SaveMatplotlibFigTool` to save a figure at the end of a matplotlib code block. You can then include the figure in your final answer.
|
92 |
|
93 |
+
## Answer format
|
94 |
+
You must answer the question in markdown format. Remember, you are a coding agent and you can pass the answer only by using the `final_answer("your markdown answer")` tool.
|
95 |
+
Also, if you want to include images in your answer, you MUST include the image in the markdown like this: .
|
96 |
+
|
97 |
You have one question to answer. It is paramount that you provide a correct answer.
|
98 |
Give it all you can: I know for a fact that you have access to all the relevant tools to solve it and find the correct answer (the answer does exist).
|
99 |
Failure or 'I cannot answer' or 'None found' will not be tolerated, success will be rewarded.
|