2stacks Claude commited on
Commit
8545511
·
verified ·
1 Parent(s): 08e7b43

Add Tavily API key UI configuration and update documentation

Browse files

Major enhancements:
- Add runtime Tavily API key configuration via UI sidebar (no restart required)
- Refactor agent creation to use factory pattern for dynamic configuration
- Add example prompts display in UI to help users get started
- Update README with current code structure and new features
- Keep data directory structure with .gitkeep

Technical changes:
- Convert MCP server configs to factory functions for dynamic instantiation
- Change agent initialization from singleton to factory pattern
- Add update_api_key() method to CustomGradioUI for runtime reconfiguration
- Increase max_steps from 6 to 10 for more complex reasoning tasks
- Use get_token() from huggingface_hub for cleaner token management
- Format code with ruff

Documentation updates:
- Update all line number references in README architecture section
- Document new Tavily UI configuration option as recommended approach
- Clarify that Tavily API key is now optional (can be set via UI or env var)
- Update CLI command from huggingface-cli to hf auth login
- Fix repository clone URL to use MCP-1st-Birthday namespace
- Update acknowledgments from DuckDuckGo to Tavily search

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Files changed (5) hide show
  1. .gitignore +1 -0
  2. README.md +40 -17
  3. app.py +58 -31
  4. data/.gitkeep +0 -0
  5. my_ui.py +56 -2
.gitignore CHANGED
@@ -80,3 +80,4 @@ dmypy.json
80
 
81
  # Project Files
82
  data/*
 
 
80
 
81
  # Project Files
82
  data/*
83
+ !data/.gitkeep
README.md CHANGED
@@ -41,36 +41,44 @@ An agentic deep research application powered by [smolagents](https://huggingface
41
 
42
  DeepSpaceSearch consists of two main Python files working together:
43
 
44
- ### MCP Integration (`app.py:55-95`)
 
45
  - **MCP Servers**: Three integrated MCP servers for extended capabilities
46
- - **Gradio Upload MCP** (`upload_files_to_gradio`): Uploads files to Gradio Space for processing
47
- - **Sa2VA Image Analysis** (`image_analysis_mcp`): Visual question answering and image segmentation
48
- - **Tavily Search** (`tavily_search_mcp`): High-quality web search API
49
  - **`MCPClient`**: Manages MCP server connections and provides tools to the agent
50
- - **Structured Output**: Enabled for consistent tool responses
 
 
51
 
52
- ### Agent System (`app.py:98-142`)
53
- - **`CodeAgent`**: Core reasoning engine from smolagents (line 118-133)
54
  - Orchestrates multi-step tasks with planning intervals
55
- - Configuration: max_steps=6, verbosity_level=1, planning_interval=3
56
  - Loads custom instructions from `instructions.txt` for agent behavior guidance
57
  - Additional authorized imports enabled for code execution flexibility
58
 
59
- ### Tool Ecosystem (`app.py:36-42, 92-95`)
 
60
  - **`image_generation_tool`**: Remote tool from HF Space (black-forest-labs/FLUX.1-schnell)
61
  - **MCP Tools**: Dynamically loaded from MCP servers (Tavily search, image analysis, file upload)
62
  - **`FinalAnswerTool`**: Required for agent to return structured responses
63
  - **Base Tools Disabled**: Custom tool selection for optimized performance
64
 
65
- ### Model Layer (`app.py:98-110`)
 
66
  - **`InferenceClientModel`**: Wrapper around Hugging Face Inference API
67
  - Default model: `Qwen/Qwen2.5-Coder-32B-Instruct` (configurable via `HF_MODEL_ID` env var)
68
  - Parameters: max_tokens=2096, temperature=0.5, top_p=0.95
 
 
 
69
 
70
- ### Custom UI (`my_ui.py:7-124`)
71
  - **`CustomGradioUI`**: Extends smolagents' `GradioUI` with custom features
72
  - **Sidebar Layout**: Text input, submit button, and file upload in sidebar
73
  - **File Upload**: Supports multiple file types with custom allowed extensions
 
 
74
  - **Ocean Theme**: Professional blue gradient interface
75
  - **Streaming Chat**: Real-time display of agent reasoning with LaTeX support
76
 
@@ -88,7 +96,7 @@ DeepSpaceSearch consists of two main Python files working together:
88
 
89
  ```bash
90
  # Clone the repository
91
- git clone https://huggingface.co/spaces/YOUR_USERNAME/DeepSpaceSearch
92
  cd DeepSpaceSearch
93
 
94
  # Create and activate virtual environment
@@ -108,7 +116,7 @@ pip install -r requirements.txt
108
  The easiest and most secure way to authenticate locally is using the Hugging Face CLI:
109
 
110
  ```bash
111
- huggingface-cli login
112
  ```
113
 
114
  This will prompt you to paste your HF token (get one at <https://huggingface.co/settings/tokens> with `inference-api` scope) and securely store it in `~/.cache/huggingface/token`.
@@ -121,10 +129,17 @@ If you prefer environment variables, create a `.env` file:
121
  HF_TOKEN=hf_... # Your HF token with inference-api scope
122
  ```
123
 
124
- **2. Tavily API Key (Required for Web Search)**
 
 
 
 
125
 
126
- DeepSpaceSearch uses Tavily for high-quality web search via MCP. Get a free API key at <https://tavily.com>:
 
 
127
 
 
128
  ```bash
129
  # Add to your .env file
130
  TAVILY_API_KEY=tvly-... # Your Tavily API key
@@ -143,6 +158,8 @@ Example `.env` with all variables:
143
  ```env
144
  # Required
145
  HF_TOKEN=hf_...
 
 
146
  TAVILY_API_KEY=tvly-...
147
 
148
  # Optional: Use a different model
@@ -155,7 +172,7 @@ HF_MODEL_ID=meta-llama/Llama-3.3-70B-Instruct
155
  python app.py
156
  ```
157
 
158
- The application will launch at http://127.0.0.1:7860
159
 
160
  ## Usage
161
 
@@ -272,6 +289,7 @@ your_tool = Tool.from_space(
272
  ## TODO
273
 
274
  ### MCP Server Integration
 
275
  - [x] **Integrate MCP servers using smolagents** ✅
276
  - Implemented three MCP servers: Tavily search, Sa2VA image analysis, and Gradio file upload
277
  - Using both stdio and HTTP-based MCP transports
@@ -289,6 +307,7 @@ your_tool = Tool.from_space(
289
  - Social media trend analysis
290
 
291
  ### Enhanced Research Capabilities
 
292
  - [ ] **Multi-source verification**
293
  - Cross-reference information across multiple sources
294
  - Add confidence scoring for research findings
@@ -305,6 +324,7 @@ your_tool = Tool.from_space(
305
  - Export to PDF/DOCX
306
 
307
  ### Tool Improvements
 
308
  - [ ] **Add calculator tool** for mathematical queries
309
  - [ ] **Add code execution tool** for running Python snippets
310
  - [ ] **Add data visualization tool** for charts and graphs
@@ -312,6 +332,7 @@ your_tool = Tool.from_space(
312
  - Implemented with support for PDF, DOCX, TXT, MD, JSON, CSV, and images
313
 
314
  ### UI/UX Enhancements
 
315
  - [ ] **Add conversation history** persistence
316
  - [ ] **Add export chat** functionality
317
  - [ ] **Add model selection** dropdown for different LLMs
@@ -319,12 +340,14 @@ your_tool = Tool.from_space(
319
  - [ ] **Dark mode** support
320
 
321
  ### Performance & Reliability
 
322
  - [ ] **Add caching** for repeated searches
323
  - [ ] **Implement retry logic** for failed API calls
324
  - [ ] **Add rate limiting** dashboard
325
  - [ ] **Optimize token usage** with streaming truncation
326
 
327
  ### Testing & Documentation
 
328
  - [ ] **Add unit tests** for core functions
329
  - [ ] **Add integration tests** for tools
330
  - [ ] **Create video demo** of capabilities
@@ -343,4 +366,4 @@ Apache 2.0 - See LICENSE file for details
343
  - Built with [smolagents](https://huggingface.co/docs/smolagents) by Hugging Face
344
  - UI powered by [Gradio](https://gradio.app)
345
  - Image generation by [FLUX.1-schnell](https://huggingface.co/black-forest-labs/FLUX.1-schnell)
346
- - Search powered by [DuckDuckGo](https://duckduckgo.com)
 
41
 
42
  DeepSpaceSearch consists of two main Python files working together:
43
 
44
+ ### MCP Integration (`app.py:57-96`)
45
+
46
  - **MCP Servers**: Three integrated MCP servers for extended capabilities
47
+ - **Gradio Upload MCP** (`get_upload_files_to_gradio_server`): Uploads files to Gradio Space for processing
48
+ - **Sa2VA Image Analysis** (`get_image_analysis_mcp`): Visual question answering and image segmentation
49
+ - **Tavily Search** (`get_tavily_search_mcp`): High-quality web search API (optional, requires API key)
50
  - **`MCPClient`**: Manages MCP server connections and provides tools to the agent
51
+ - **Dynamic Agent Creation**: Agent factory function allows runtime API key configuration
52
+
53
+ ### Agent System (`app.py:99-157`)
54
 
55
+ - **`CodeAgent`**: Core reasoning engine from smolagents (line 133-148)
 
56
  - Orchestrates multi-step tasks with planning intervals
57
+ - Configuration: max_steps=10, verbosity_level=1, planning_interval=3
58
  - Loads custom instructions from `instructions.txt` for agent behavior guidance
59
  - Additional authorized imports enabled for code execution flexibility
60
 
61
+ ### Tool Ecosystem (`app.py:38-42, 136-142`)
62
+
63
  - **`image_generation_tool`**: Remote tool from HF Space (black-forest-labs/FLUX.1-schnell)
64
  - **MCP Tools**: Dynamically loaded from MCP servers (Tavily search, image analysis, file upload)
65
  - **`FinalAnswerTool`**: Required for agent to return structured responses
66
  - **Base Tools Disabled**: Custom tool selection for optimized performance
67
 
68
+ ### Model Layer (`app.py:118-125`)
69
+
70
  - **`InferenceClientModel`**: Wrapper around Hugging Face Inference API
71
  - Default model: `Qwen/Qwen2.5-Coder-32B-Instruct` (configurable via `HF_MODEL_ID` env var)
72
  - Parameters: max_tokens=2096, temperature=0.5, top_p=0.95
73
+ - Token authentication via `get_token()` from huggingface_hub
74
+
75
+ ### Custom UI (`my_ui.py:7-176`)
76
 
 
77
  - **`CustomGradioUI`**: Extends smolagents' `GradioUI` with custom features
78
  - **Sidebar Layout**: Text input, submit button, and file upload in sidebar
79
  - **File Upload**: Supports multiple file types with custom allowed extensions
80
+ - **Tavily API Key Input**: Runtime configuration of Tavily search without environment variables
81
+ - **Examples Display**: Pre-configured example prompts to help users get started
82
  - **Ocean Theme**: Professional blue gradient interface
83
  - **Streaming Chat**: Real-time display of agent reasoning with LaTeX support
84
 
 
96
 
97
  ```bash
98
  # Clone the repository
99
+ git clone https://huggingface.co/spaces/MCP-1st-Birthday/DeepSpaceSearch
100
  cd DeepSpaceSearch
101
 
102
  # Create and activate virtual environment
 
116
  The easiest and most secure way to authenticate locally is using the Hugging Face CLI:
117
 
118
  ```bash
119
+ hf auth login
120
  ```
121
 
122
  This will prompt you to paste your HF token (get one at <https://huggingface.co/settings/tokens> with `inference-api` scope) and securely store it in `~/.cache/huggingface/token`.
 
129
  HF_TOKEN=hf_... # Your HF token with inference-api scope
130
  ```
131
 
132
+ **2. Tavily API Key (Optional for Web Search)**
133
+
134
+ DeepSpaceSearch uses Tavily for high-quality web search via MCP. Get a free API key at <https://tavily.com>.
135
+
136
+ You can configure Tavily in two ways:
137
 
138
+ **Option A: Via the UI (Recommended)**
139
+ - Simply enter your API key in the "Tavily API Key" field in the sidebar when using the application
140
+ - No need to set environment variables or restart the app
141
 
142
+ **Option B: Via Environment Variable**
143
  ```bash
144
  # Add to your .env file
145
  TAVILY_API_KEY=tvly-... # Your Tavily API key
 
158
  ```env
159
  # Required
160
  HF_TOKEN=hf_...
161
+
162
+ # Optional: Configure Tavily API key (can also be set via UI)
163
  TAVILY_API_KEY=tvly-...
164
 
165
  # Optional: Use a different model
 
172
  python app.py
173
  ```
174
 
175
+ The application will launch at <http://127.0.0.1:7860>
176
 
177
  ## Usage
178
 
 
289
  ## TODO
290
 
291
  ### MCP Server Integration
292
+
293
  - [x] **Integrate MCP servers using smolagents** ✅
294
  - Implemented three MCP servers: Tavily search, Sa2VA image analysis, and Gradio file upload
295
  - Using both stdio and HTTP-based MCP transports
 
307
  - Social media trend analysis
308
 
309
  ### Enhanced Research Capabilities
310
+
311
  - [ ] **Multi-source verification**
312
  - Cross-reference information across multiple sources
313
  - Add confidence scoring for research findings
 
324
  - Export to PDF/DOCX
325
 
326
  ### Tool Improvements
327
+
328
  - [ ] **Add calculator tool** for mathematical queries
329
  - [ ] **Add code execution tool** for running Python snippets
330
  - [ ] **Add data visualization tool** for charts and graphs
 
332
  - Implemented with support for PDF, DOCX, TXT, MD, JSON, CSV, and images
333
 
334
  ### UI/UX Enhancements
335
+
336
  - [ ] **Add conversation history** persistence
337
  - [ ] **Add export chat** functionality
338
  - [ ] **Add model selection** dropdown for different LLMs
 
340
  - [ ] **Dark mode** support
341
 
342
  ### Performance & Reliability
343
+
344
  - [ ] **Add caching** for repeated searches
345
  - [ ] **Implement retry logic** for failed API calls
346
  - [ ] **Add rate limiting** dashboard
347
  - [ ] **Optimize token usage** with streaming truncation
348
 
349
  ### Testing & Documentation
350
+
351
  - [ ] **Add unit tests** for core functions
352
  - [ ] **Add integration tests** for tools
353
  - [ ] **Create video demo** of capabilities
 
366
  - Built with [smolagents](https://huggingface.co/docs/smolagents) by Hugging Face
367
  - UI powered by [Gradio](https://gradio.app)
368
  - Image generation by [FLUX.1-schnell](https://huggingface.co/black-forest-labs/FLUX.1-schnell)
369
+ - Search powered by [Tavily](https://app.tavily.com)
app.py CHANGED
@@ -2,6 +2,7 @@ import os
2
  import warnings
3
 
4
  from dotenv import load_dotenv
 
5
  from mcp import StdioServerParameters
6
  from smolagents import (
7
  CodeAgent,
@@ -52,19 +53,23 @@ image_generation_tool = Tool.from_space(
52
  # api_name="/image_vision",
53
  # )
54
 
 
55
  # MCP Servers
56
- upload_files_to_gradio = StdioServerParameters(
57
- command="uvx", # Using uvx ensures dependencies are available
58
- args=[
59
- "--from",
60
- "gradio[mcp]",
61
- "gradio",
62
- "upload-mcp",
63
- "https://fffiloni-sa2va-simple-demo.hf.space/",
64
- "./data",
65
- ],
66
- env={"UV_PYTHON": "3.12", **os.environ},
67
- )
 
 
 
68
 
69
  # groq_compount_beta = StdioServerParameters(
70
  # command="uvx", # Using uvx ensures dependencies are available
@@ -78,26 +83,40 @@ upload_files_to_gradio = StdioServerParameters(
78
  # },
79
  # )
80
 
81
- image_analysis_mcp = {
82
- "url": "https://fffiloni-sa2va-simple-demo.hf.space/gradio_api/mcp/",
83
- "transport": "streamable-http",
84
- }
85
 
86
- tavily_search_mcp = {
87
- "url": "https://mcp.tavily.com/mcp/?tavilyApiKey=" + TAVILY_API_KEY,
88
- "transport": "streamable-http",
89
- }
 
 
90
 
91
 
92
- # Initialize MCP client at module level to keep it alive
93
- mcp_client = MCPClient(
94
- [upload_files_to_gradio, image_analysis_mcp, tavily_search_mcp], structured_output=True
95
- )
 
 
 
 
 
 
 
 
96
 
 
 
 
 
 
97
 
98
- def create_agent():
99
- # Get token from OAuth (HF Spaces) or environment variable (local dev)
100
- token = os.getenv("HF_TOKEN")
 
 
 
101
 
102
  # Create model with user-specified parameters
103
  model = InferenceClientModel(
@@ -106,7 +125,7 @@ def create_agent():
106
  top_p=0.95,
107
  model_id=HF_MODEL_ID,
108
  custom_role_conversions=None,
109
- token=token,
110
  )
111
 
112
  # Load instructions from file. This text will be appended to the system prompt.
@@ -120,14 +139,14 @@ def create_agent():
120
  additional_authorized_imports=["*"],
121
  tools=[
122
  image_generation_tool,
123
- *mcp_client.get_tools(), # Use tools from the global MCP client
124
  # web_search,
125
  # visit_webpage,
126
  final_answer,
127
  ],
128
  instructions=instructions,
129
  add_base_tools=False,
130
- max_steps=6,
131
  verbosity_level=1,
132
  planning_interval=3,
133
  )
@@ -142,8 +161,15 @@ def create_agent():
142
  return agent
143
 
144
 
 
 
 
 
 
 
 
145
  gradio_ui = CustomGradioUI(
146
- create_agent(),
147
  file_upload_folder="./data",
148
  reset_agent_memory=True,
149
  allowed_file_types=[
@@ -157,6 +183,7 @@ gradio_ui = CustomGradioUI(
157
  ".jpeg",
158
  ".jpg",
159
  ], # Customize this list!
 
160
  )
161
 
162
  if __name__ == "__main__":
 
2
  import warnings
3
 
4
  from dotenv import load_dotenv
5
+ from huggingface_hub import get_token
6
  from mcp import StdioServerParameters
7
  from smolagents import (
8
  CodeAgent,
 
53
  # api_name="/image_vision",
54
  # )
55
 
56
+
57
  # MCP Servers
58
+ def get_upload_files_to_gradio_server():
59
+ """Get the upload files to Gradio MCP server configuration."""
60
+ return StdioServerParameters(
61
+ command="uvx", # Using uvx ensures dependencies are available
62
+ args=[
63
+ "--from",
64
+ "gradio[mcp]",
65
+ "gradio",
66
+ "upload-mcp",
67
+ "https://fffiloni-sa2va-simple-demo.hf.space/",
68
+ "./data",
69
+ ],
70
+ env={"UV_PYTHON": "3.12", **os.environ},
71
+ )
72
+
73
 
74
  # groq_compount_beta = StdioServerParameters(
75
  # command="uvx", # Using uvx ensures dependencies are available
 
83
  # },
84
  # )
85
 
 
 
 
 
86
 
87
+ def get_image_analysis_mcp():
88
+ """Get the image analysis MCP configuration."""
89
+ return {
90
+ "url": "https://fffiloni-sa2va-simple-demo.hf.space/gradio_api/mcp/",
91
+ "transport": "streamable-http",
92
+ }
93
 
94
 
95
+ def get_tavily_search_mcp(api_key):
96
+ """Get the Tavily search MCP configuration with the provided API key."""
97
+ return {
98
+ "url": f"https://mcp.tavily.com/mcp/?tavilyApiKey={api_key}",
99
+ "transport": "streamable-http",
100
+ }
101
+
102
+
103
+ def create_agent(tavily_api_key=None):
104
+ """Create an agent with the specified Tavily API key (or use environment variable)."""
105
+ # Use provided API key or fall back to environment variable
106
+ api_key = tavily_api_key or TAVILY_API_KEY
107
 
108
+ # Build list of MCP servers - only include Tavily if API key is provided
109
+ mcp_servers = [
110
+ get_upload_files_to_gradio_server(),
111
+ get_image_analysis_mcp(),
112
+ ]
113
 
114
+ # Only add Tavily search if we have an API key
115
+ if api_key:
116
+ mcp_servers.append(get_tavily_search_mcp(api_key))
117
+
118
+ # Create MCP client with the appropriate servers
119
+ mcp_client = MCPClient(mcp_servers, structured_output=False)
120
 
121
  # Create model with user-specified parameters
122
  model = InferenceClientModel(
 
125
  top_p=0.95,
126
  model_id=HF_MODEL_ID,
127
  custom_role_conversions=None,
128
+ token=get_token(), # Get token from HF login (huggingface-cli login) or environment variable (HF_TOKEN)
129
  )
130
 
131
  # Load instructions from file. This text will be appended to the system prompt.
 
139
  additional_authorized_imports=["*"],
140
  tools=[
141
  image_generation_tool,
142
+ *mcp_client.get_tools(), # Use tools from the MCP client
143
  # web_search,
144
  # visit_webpage,
145
  final_answer,
146
  ],
147
  instructions=instructions,
148
  add_base_tools=False,
149
+ max_steps=10,
150
  verbosity_level=1,
151
  planning_interval=3,
152
  )
 
161
  return agent
162
 
163
 
164
+ # Example prompts for users
165
+ EXAMPLES = [
166
+ "Search the web for the latest developments in quantum computing and summarize the key findings",
167
+ "Generate an image of a futuristic city with flying cars and neon lights",
168
+ "What are the current trends in artificial intelligence research?",
169
+ ]
170
+
171
  gradio_ui = CustomGradioUI(
172
+ create_agent, # Pass the factory function, not the agent instance
173
  file_upload_folder="./data",
174
  reset_agent_memory=True,
175
  allowed_file_types=[
 
183
  ".jpeg",
184
  ".jpg",
185
  ], # Customize this list!
186
+ examples=EXAMPLES,
187
  )
188
 
189
  if __name__ == "__main__":
data/.gitkeep ADDED
File without changes
my_ui.py CHANGED
@@ -8,10 +8,33 @@ class CustomGradioUI(GradioUI):
8
  """Custom GradioUI that allows customization of the smolagents default interface."""
9
 
10
  def __init__(
11
- self, agent, file_upload_folder=None, reset_agent_memory=False, allowed_file_types=None
 
 
 
 
 
12
  ):
13
- super().__init__(agent, file_upload_folder, reset_agent_memory)
 
 
 
14
  self.allowed_file_types = allowed_file_types or [".pdf", ".docx", ".txt"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
  def create_app(self):
17
  """Override create_app to use custom allowed_file_types."""
@@ -21,6 +44,7 @@ class CustomGradioUI(GradioUI):
21
  session_state = gr.State({})
22
  stored_messages = gr.State([])
23
  file_uploads_log = gr.State([])
 
24
 
25
  with gr.Sidebar():
26
  gr.Markdown(
@@ -62,6 +86,28 @@ class CustomGradioUI(GradioUI):
62
  [upload_status, file_uploads_log],
63
  )
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  gr.HTML(
66
  "<br><br><h4><center>Powered by <a target='_blank' href='https://github.com/huggingface/smolagents'><b>smolagents</b></a></center></h4>"
67
  )
@@ -84,6 +130,14 @@ class CustomGradioUI(GradioUI):
84
  ],
85
  )
86
 
 
 
 
 
 
 
 
 
87
  # Set up event handlers
88
  text_input.submit(
89
  self.log_user_message,
 
8
  """Custom GradioUI that allows customization of the smolagents default interface."""
9
 
10
  def __init__(
11
+ self,
12
+ agent_factory,
13
+ file_upload_folder=None,
14
+ reset_agent_memory=False,
15
+ allowed_file_types=None,
16
+ examples=None,
17
  ):
18
+ # Store the factory function instead of the agent directly
19
+ self.agent_factory = agent_factory
20
+ # Create initial agent with no API key (will use env var if available)
21
+ super().__init__(agent_factory(), file_upload_folder, reset_agent_memory)
22
  self.allowed_file_types = allowed_file_types or [".pdf", ".docx", ".txt"]
23
+ self.examples = examples or []
24
+
25
+ def update_api_key(self, api_key, current_key):
26
+ """Update the agent with a new API key."""
27
+ if api_key and api_key != current_key:
28
+ # Recreate the agent with the new API key
29
+ self.agent = self.agent_factory(tavily_api_key=api_key)
30
+ return api_key, gr.Markdown("✓ API key updated successfully", visible=True)
31
+ elif not api_key and current_key:
32
+ # Reset to default (env var)
33
+ self.agent = self.agent_factory()
34
+ return "", gr.Markdown(
35
+ "API key cleared, using environment variable if set", visible=True
36
+ )
37
+ return current_key, gr.Markdown("", visible=False)
38
 
39
  def create_app(self):
40
  """Override create_app to use custom allowed_file_types."""
 
44
  session_state = gr.State({})
45
  stored_messages = gr.State([])
46
  file_uploads_log = gr.State([])
47
+ current_api_key = gr.State("") # Store current Tavily API key
48
 
49
  with gr.Sidebar():
50
  gr.Markdown(
 
86
  [upload_status, file_uploads_log],
87
  )
88
 
89
+ # Tavily API Key section
90
+ with gr.Group():
91
+ gr.Markdown("**Tavily API Key**", container=True)
92
+ gr.Markdown(
93
+ "Get your free API key at [tavily.com](https://app.tavily.com/home)",
94
+ container=False,
95
+ )
96
+ tavily_api_key_input = gr.Textbox(
97
+ label="API Key (optional)",
98
+ type="password",
99
+ placeholder="Enter your Tavily API key to enable web search",
100
+ container=False,
101
+ )
102
+ api_key_status = gr.Markdown("", visible=False)
103
+
104
+ # Update agent when API key changes
105
+ tavily_api_key_input.change(
106
+ self.update_api_key,
107
+ [tavily_api_key_input, current_api_key],
108
+ [current_api_key, api_key_status],
109
+ )
110
+
111
  gr.HTML(
112
  "<br><br><h4><center>Powered by <a target='_blank' href='https://github.com/huggingface/smolagents'><b>smolagents</b></a></center></h4>"
113
  )
 
130
  ],
131
  )
132
 
133
+ # Add examples if provided
134
+ if self.examples:
135
+ gr.Examples(
136
+ examples=self.examples,
137
+ inputs=text_input,
138
+ cache_examples=False,
139
+ )
140
+
141
  # Set up event handlers
142
  text_input.submit(
143
  self.log_user_message,