File size: 9,413 Bytes
0d7df8b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
import io
from contextlib import redirect_stdout
import gradio as gr
from smolagents import (
    load_tool,
    CodeAgent,
    ToolCallingAgent,
    VLLMModel,
    DuckDuckGoSearchTool,
    VisitWebpageTool,
    HfApiModel, 
    GradioUI,
    AgentLogger,
    LogLevel
)

from smolagents.models import MLXModel

import re
import html
import datetime


# Set up your model and logger
model = HfApiModel()
logger = AgentLogger(level=LogLevel.INFO)

# Import tool from Hub
image_generation_tool = load_tool("m-ric/text-to-image", trust_remote_code=True)


# Create your agents
search_agent = ToolCallingAgent(
    tools=[DuckDuckGoSearchTool(), VisitWebpageTool()],
    model=model,
    name="search_agent",
    description="This is an agent that can do web search.",
    max_steps=12,
    verbosity_level=1
)

mentor_agent = ToolCallingAgent(
    tools=[DuckDuckGoSearchTool(), VisitWebpageTool()],
    model=model,
    name="mentor_agent",
    description="This is an agent that creates a persona of a mentor based on the hackathon idea and gives feedback.",
    max_steps=12,
    planning_interval=2,
    verbosity_level=1
)

design_research_agent = ToolCallingAgent(
    tools=[DuckDuckGoSearchTool(), VisitWebpageTool()],
    model=model,
    name="design_research_agent",
    description="Searches online for 3-star reviews and conversations on sites like Reddit as a form of 'user research",
    max_steps=12,
    planning_interval=2,
    verbosity_level=1
)

visual_design_agent = ToolCallingAgent(
    tools=[image_generation_tool],
    model=MLXModel(model_id="HuggingFaceTB/SmolLM-135M-Instruct"),
    name="visual_design_agent",
    description="Creates, reviews, and iterates on front-end mockups of product ideas",
    max_steps=12,
    planning_interval=2,
    verbosity_level=1
)


# Create a manager agent that can create more agents
manager_agent = CodeAgent(
    tools=[],
    model=model,
    managed_agents=[search_agent, mentor_agent, design_research_agent, visual_design_agent],
    name="manager_agent",
    description="This agent can solve problems using code and delegate to other agents when needed.",
    max_steps=12,
    verbosity_level=1,
    planning_interval=4
)


# Capture agent visualization
def get_agent_visualization():
    buffer = io.StringIO()
    with redirect_stdout(buffer):
        logger.visualize_agent_tree(manager_agent)
    return buffer.getvalue()

def clean_ansi_codes(text):
    """Remove ANSI color codes for clean display"""
    ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
    return ansi_escape.sub('', text)

# Create a custom Gradio UI that extends the GradioUI class
class MonitoringGradioUI(GradioUI):
    def __init__(self, agent, file_upload_folder=None):
        super().__init__(agent, file_upload_folder)
        self.name = "Agent Interface with Monitoring"
        
    def launch(self, share=True, **kwargs):
        with gr.Blocks(theme="ocean", fill_height=True) as demo:
            # Add session state to store session-specific data
            session_state = gr.State({})
            stored_messages = gr.State([])
            file_uploads_log = gr.State([])
            
            with gr.Tab("Chat"):
                with gr.Sidebar():
                    gr.Markdown(
                        f"# {self.name.replace('_', ' ').capitalize()}"
                        "\n> This web UI allows you to interact with a `smolagents` agent that can use tools and execute steps to complete tasks."
                        + (f"\n\n**Agent description:**\n{self.description}" if self.description else "")
                    )

                    with gr.Group():
                        gr.Markdown("**Your request**", container=True)
                        text_input = gr.Textbox(
                            lines=3,
                            label="Chat Message",
                            container=False,
                            placeholder="Enter your prompt here and press Shift+Enter or press the button",
                        )
                        submit_btn = gr.Button("Submit", variant="primary")

                    # If an upload folder is provided, enable the upload feature
                    if self.file_upload_folder is not None:
                        upload_file = gr.File(label="Upload a file")
                        upload_status = gr.Textbox(label="Upload Status", interactive=False, visible=False)
                        upload_file.change(
                            self.upload_file,
                            [upload_file, file_uploads_log],
                            [upload_status, file_uploads_log],
                        )

                    gr.HTML("<br><br><h4><center>Powered by:</center></h4>")
                    with gr.Row():
                        gr.HTML("""<div style="display: flex; align-items: center; gap: 8px; font-family: system-ui, -apple-system, sans-serif;">
                <img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/smolagents/mascot_smol.png" style="width: 32px; height: 32px; object-fit: contain;" alt="logo">
                <a target="_blank" href="https://github.com/huggingface/smolagents"><b>huggingface/smolagents</b></a>
                </div>""")

                # Main chat interface
                chatbot = gr.Chatbot(
                    label="Agent",
                    type="messages",
                    avatar_images=(
                        None,
                        "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/smolagents/mascot_smol.png",
                    ),
                    resizeable=True,
                    scale=1,
                )
                
                # Set up event handlers
                text_input.submit(
                    self.log_user_message,
                    [text_input, file_uploads_log],
                    [stored_messages, text_input, submit_btn],
                ).then(self.interact_with_agent, [stored_messages, chatbot, session_state], [chatbot]).then(
                    lambda: (
                        gr.Textbox(
                            interactive=True, placeholder="Enter your prompt here and press Shift+Enter or the button"
                        ),
                        gr.Button(interactive=True),
                    ),
                    None,
                    [text_input, submit_btn],
                )

                submit_btn.click(
                    self.log_user_message,
                    [text_input, file_uploads_log],
                    [stored_messages, text_input, submit_btn],
                ).then(self.interact_with_agent, [stored_messages, chatbot, session_state], [chatbot]).then(
                    lambda: (
                        gr.Textbox(
                            interactive=True, placeholder="Enter your prompt here and press Shift+Enter or the button"
                        ),
                        gr.Button(interactive=True),
                    ),
                    None,
                    [text_input, submit_btn],
                )
            
            # Add the Monitoring tab
            with gr.Tab("Agent Monitoring"):
                # Get the visualization text
                agent_viz = get_agent_visualization()
                agent_viz_clean = clean_ansi_codes(agent_viz)
                
                # Convert the tree characters to HTML with proper formatting
                html_viz = agent_viz_clean.replace("β”œβ”€β”€", "β”œβ”€ ").replace("└──", "└─ ").replace("β”‚", "β”‚ ")
                html_viz = html.escape(html_viz)
                html_viz = f"<pre style='font-family: monospace; white-space: pre; font-size: 14px;'>{html_viz}</pre>"
                
                viz_html = gr.HTML(value=html_viz)
                
                # Add a refresh button
                refresh_btn = gr.Button("Refresh Agent Tree")
                
                def refresh_viz():
                    new_viz = get_agent_visualization()
                    new_viz_clean = clean_ansi_codes(new_viz)
                    html_viz = new_viz_clean.replace("β”œβ”€β”€", "β”œβ”€ ").replace("└──", "└─ ").replace("β”‚", "β”‚ ")
                    html_viz = html.escape(html_viz)
                    html_viz = f"<pre style='font-family: monospace; white-space: pre; font-size: 14px;'>{html_viz}</pre>"
                    return html_viz
                
                refresh_btn.click(refresh_viz, None, viz_html)
                
                # Add some explanatory text
                gr.Markdown("""
                ### Monitoring Information
                
                This tab shows the structure of your agent, including:
                - Hierarchical organization of agents
                - Available tools for each agent
                - Agent configurations
                
                Use the refresh button to update the visualization if you modify your agent structure.
                """)

        demo.launch(debug=True, share=share, **kwargs)

# Create and launch your UI
# Make sure uploads directory exists
import os
os.makedirs("./uploads", exist_ok=True)

ui = MonitoringGradioUI(manager_agent, file_upload_folder="./uploads")
ui.launch(share=True)  # Set share=False if you don't want to create a public link