camel-ai 0.2.57__py3-none-any.whl → 0.2.59__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of camel-ai might be problematic. Click here for more details.
- camel/__init__.py +1 -2
- camel/agents/chat_agent.py +136 -9
- camel/agents/critic_agent.py +73 -8
- camel/agents/mcp_agent.py +296 -83
- camel/benchmarks/__init__.py +2 -0
- camel/benchmarks/browsecomp.py +854 -0
- camel/human.py +14 -0
- camel/loaders/__init__.py +2 -0
- camel/loaders/markitdown.py +204 -0
- camel/models/openai_compatible_model.py +3 -3
- camel/societies/role_playing.py +50 -0
- camel/societies/workforce/role_playing_worker.py +17 -8
- camel/societies/workforce/workforce.py +74 -18
- camel/toolkits/__init__.py +4 -0
- camel/toolkits/async_browser_toolkit.py +1800 -0
- camel/toolkits/base.py +12 -1
- camel/toolkits/browser_toolkit.py +19 -3
- camel/toolkits/excel_toolkit.py +3 -2
- camel/toolkits/function_tool.py +1 -1
- camel/toolkits/mcp_toolkit.py +134 -6
- camel/toolkits/search_toolkit.py +0 -169
- camel/toolkits/wolfram_alpha_toolkit.py +237 -0
- camel/types/__init__.py +10 -0
- camel/types/enums.py +3 -3
- camel/types/mcp_registries.py +157 -0
- {camel_ai-0.2.57.dist-info → camel_ai-0.2.59.dist-info}/METADATA +4 -2
- {camel_ai-0.2.57.dist-info → camel_ai-0.2.59.dist-info}/RECORD +29 -24
- {camel_ai-0.2.57.dist-info → camel_ai-0.2.59.dist-info}/WHEEL +0 -0
- {camel_ai-0.2.57.dist-info → camel_ai-0.2.59.dist-info}/licenses/LICENSE +0 -0
camel/agents/mcp_agent.py
CHANGED
|
@@ -12,18 +12,26 @@
|
|
|
12
12
|
# limitations under the License.
|
|
13
13
|
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
14
14
|
|
|
15
|
+
import asyncio
|
|
15
16
|
import json
|
|
17
|
+
import platform
|
|
16
18
|
import re
|
|
17
|
-
from typing import Optional
|
|
19
|
+
from typing import Any, Callable, Dict, List, Optional, Union, cast
|
|
18
20
|
|
|
19
21
|
from camel.agents import ChatAgent
|
|
20
22
|
from camel.logger import get_logger
|
|
21
23
|
from camel.messages import BaseMessage
|
|
22
|
-
from camel.models import BaseModelBackend
|
|
24
|
+
from camel.models import BaseModelBackend, ModelFactory
|
|
23
25
|
from camel.prompts import TextPrompt
|
|
24
26
|
from camel.responses import ChatAgentResponse
|
|
25
|
-
from camel.toolkits import MCPToolkit
|
|
26
|
-
from camel.types import
|
|
27
|
+
from camel.toolkits import FunctionTool, MCPToolkit
|
|
28
|
+
from camel.types import (
|
|
29
|
+
BaseMCPRegistryConfig,
|
|
30
|
+
MCPRegistryType,
|
|
31
|
+
ModelPlatformType,
|
|
32
|
+
ModelType,
|
|
33
|
+
RoleType,
|
|
34
|
+
)
|
|
27
35
|
|
|
28
36
|
# AgentOps decorator setting
|
|
29
37
|
try:
|
|
@@ -38,6 +46,7 @@ except (ImportError, AttributeError):
|
|
|
38
46
|
|
|
39
47
|
logger = get_logger(__name__)
|
|
40
48
|
|
|
49
|
+
|
|
41
50
|
SYS_MSG_CONTENT = """
|
|
42
51
|
You are a helpful assistant, and you prefer to use tools provided by the user
|
|
43
52
|
to solve problems.
|
|
@@ -80,22 +89,62 @@ Please answer me according to the result directly.
|
|
|
80
89
|
|
|
81
90
|
@track_agent(name="MCPAgent")
|
|
82
91
|
class MCPAgent(ChatAgent):
|
|
92
|
+
r"""A specialized agent designed to interact with MCP registries.
|
|
93
|
+
The MCPAgent enhances a base ChatAgent by integrating MCP tools from
|
|
94
|
+
various registries for search capabilities.
|
|
95
|
+
|
|
96
|
+
Attributes:
|
|
97
|
+
system_message (Optional[str]): The system message for the chat agent.
|
|
98
|
+
(default: :str:`"You are an assistant with search capabilities
|
|
99
|
+
using MCP tools."`)
|
|
100
|
+
model (BaseModelBackend): The model backend to use for generating
|
|
101
|
+
responses. (default: :obj:`ModelPlatformType.DEFAULT` with
|
|
102
|
+
`ModelType.DEFAULT`)
|
|
103
|
+
registry_configs (List[BaseMCPRegistryConfig]): List of registry
|
|
104
|
+
configurations (default: :obj:`None`)
|
|
105
|
+
local_config (Optional[Dict[str, Any]]): The local configuration for
|
|
106
|
+
the MCP agent. (default: :obj:`None`)
|
|
107
|
+
local_config_path (Optional[str]): The path to the local configuration
|
|
108
|
+
file for the MCP agent. (default: :obj:`None`)
|
|
109
|
+
function_calling_available (bool): Flag indicating whether the
|
|
110
|
+
model is equipped with the function calling ability.
|
|
111
|
+
(default: :obj:`True`)
|
|
112
|
+
**kwargs: Inherited from ChatAgent
|
|
113
|
+
"""
|
|
114
|
+
|
|
83
115
|
def __init__(
|
|
84
116
|
self,
|
|
85
|
-
|
|
117
|
+
system_message: Optional[Union[str, BaseMessage]] = (
|
|
118
|
+
"You are an assistant with search capabilities using MCP tools."
|
|
119
|
+
),
|
|
86
120
|
model: Optional[BaseModelBackend] = None,
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
121
|
+
registry_configs: Optional[
|
|
122
|
+
Union[List[BaseMCPRegistryConfig], BaseMCPRegistryConfig]
|
|
123
|
+
] = None,
|
|
124
|
+
local_config: Optional[Dict[str, Any]] = None,
|
|
125
|
+
local_config_path: Optional[str] = None,
|
|
126
|
+
tools: Optional[List[Union[FunctionTool, Callable]]] = None,
|
|
127
|
+
function_calling_available: bool = True,
|
|
128
|
+
**kwargs,
|
|
129
|
+
):
|
|
130
|
+
if model is None:
|
|
131
|
+
model = ModelFactory.create(
|
|
132
|
+
model_platform=ModelPlatformType.DEFAULT,
|
|
133
|
+
model_type=ModelType.DEFAULT,
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
if isinstance(registry_configs, BaseMCPRegistryConfig):
|
|
137
|
+
self.registry_configs = [registry_configs]
|
|
138
|
+
else:
|
|
139
|
+
self.registry_configs = registry_configs or []
|
|
140
|
+
|
|
141
|
+
if local_config_path:
|
|
142
|
+
with open(local_config_path, 'r') as f:
|
|
143
|
+
local_config = json.load(f)
|
|
144
|
+
|
|
145
|
+
self.local_config = local_config
|
|
146
|
+
self.function_calling_available = function_calling_available
|
|
90
147
|
|
|
91
|
-
Args:
|
|
92
|
-
config_path (str): Path to the MCP configuration file.
|
|
93
|
-
model (Optional[BaseModelBackend]): Model backend for the agent.
|
|
94
|
-
(default: :obj:`None`)
|
|
95
|
-
function_calling_available (bool): Flag indicating whether the
|
|
96
|
-
model is equipped with the function calling ability.
|
|
97
|
-
(default: :obj:`False`)
|
|
98
|
-
"""
|
|
99
148
|
if function_calling_available:
|
|
100
149
|
sys_msg_content = "You are a helpful assistant, and you prefer "
|
|
101
150
|
"to use tools provided by the user to solve problems."
|
|
@@ -109,63 +158,182 @@ class MCPAgent(ChatAgent):
|
|
|
109
158
|
content=sys_msg_content,
|
|
110
159
|
)
|
|
111
160
|
|
|
112
|
-
|
|
161
|
+
# Initialize the toolkit if configuration is provided
|
|
162
|
+
self.mcp_toolkit = self._initialize_mcp_toolkit()
|
|
163
|
+
|
|
164
|
+
super().__init__(
|
|
165
|
+
system_message=system_message,
|
|
166
|
+
model=model,
|
|
167
|
+
tools=tools,
|
|
168
|
+
**kwargs,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
def _initialize_mcp_toolkit(self) -> MCPToolkit:
|
|
172
|
+
r"""Initialize the MCP toolkit from the provided configuration."""
|
|
173
|
+
config_dict = {}
|
|
174
|
+
for registry_config in self.registry_configs:
|
|
175
|
+
config_dict.update(registry_config.get_config())
|
|
113
176
|
|
|
114
|
-
self.
|
|
115
|
-
|
|
116
|
-
self._text_tools = None
|
|
177
|
+
if self.local_config:
|
|
178
|
+
config_dict.update(self.local_config)
|
|
117
179
|
|
|
118
|
-
|
|
119
|
-
r"""Explicitly connect to all MCP servers."""
|
|
120
|
-
await self._mcp_toolkit.connect()
|
|
180
|
+
return MCPToolkit(config_dict=config_dict)
|
|
121
181
|
|
|
122
|
-
|
|
123
|
-
r"""
|
|
124
|
-
await self._mcp_toolkit.disconnect()
|
|
182
|
+
def add_registry(self, registry_config: BaseMCPRegistryConfig) -> None:
|
|
183
|
+
r"""Add a new registry configuration to the agent.
|
|
125
184
|
|
|
126
|
-
|
|
127
|
-
|
|
185
|
+
Args:
|
|
186
|
+
registry_config (BaseMCPRegistryConfig): The registry
|
|
187
|
+
configuration to add.
|
|
188
|
+
"""
|
|
189
|
+
self.registry_configs.append(registry_config)
|
|
190
|
+
# Reinitialize the toolkit with the updated configurations
|
|
191
|
+
self.mcp_toolkit = self._initialize_mcp_toolkit()
|
|
192
|
+
|
|
193
|
+
# If already connected, reconnect to apply changes
|
|
194
|
+
if self.mcp_toolkit and self.mcp_toolkit.is_connected():
|
|
195
|
+
try:
|
|
196
|
+
asyncio.run(self.disconnect())
|
|
197
|
+
asyncio.run(self.connect())
|
|
198
|
+
except RuntimeError as e:
|
|
199
|
+
# Handle case where we're already in an event loop
|
|
200
|
+
logger.warning(
|
|
201
|
+
f"Could not reconnect synchronously: {e}. "
|
|
202
|
+
f"Manual reconnection may be required."
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
@classmethod
|
|
206
|
+
async def create(
|
|
207
|
+
cls,
|
|
208
|
+
config_path: Optional[str] = None,
|
|
209
|
+
registry_configs: Optional[
|
|
210
|
+
Union[List[BaseMCPRegistryConfig], BaseMCPRegistryConfig]
|
|
211
|
+
] = None,
|
|
212
|
+
model: Optional[BaseModelBackend] = None,
|
|
213
|
+
function_calling_available: bool = False,
|
|
214
|
+
**kwargs,
|
|
215
|
+
) -> "MCPAgent":
|
|
216
|
+
r"""Create and connect an MCPAgent instance.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
config_path (Optional[str]): Path to the MCP configuration file.
|
|
220
|
+
If provided, will load registry configs from this file.
|
|
221
|
+
(default: :obj:`None`)
|
|
222
|
+
registry_configs (Optional[Union[List[BaseMCPRegistryConfig],
|
|
223
|
+
BaseMCPRegistryConfig]]): Registry configurations to use.
|
|
224
|
+
Can be a single config or list of configs. If both config_path
|
|
225
|
+
and registry_configs are provided, configs from both sources
|
|
226
|
+
will be combined. (default: :obj:`None`)
|
|
227
|
+
model (Optional[BaseModelBackend]): The model backend to use.
|
|
228
|
+
If None, will use the default model. (default: :obj:`None`)
|
|
229
|
+
function_calling_available (bool): Whether the model supports
|
|
230
|
+
function calling. (default: :obj:`False`)
|
|
231
|
+
**kwargs: Additional arguments to pass to MCPAgent constructor.
|
|
128
232
|
|
|
129
|
-
|
|
130
|
-
|
|
233
|
+
Returns:
|
|
234
|
+
MCPAgent: A connected MCPAgent instance ready to use.
|
|
235
|
+
|
|
236
|
+
Example:
|
|
237
|
+
>>> agent = await MCPAgent.create(
|
|
238
|
+
... config_path="path/to/config.json",
|
|
239
|
+
... function_calling_available=True
|
|
240
|
+
... )
|
|
241
|
+
>>> response = await agent.run("Hello!")
|
|
242
|
+
"""
|
|
243
|
+
# Initialize registry_configs list
|
|
244
|
+
final_registry_configs = []
|
|
131
245
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
246
|
+
# Add configs from registry_configs argument if provided
|
|
247
|
+
if registry_configs is not None:
|
|
248
|
+
if isinstance(registry_configs, BaseMCPRegistryConfig):
|
|
249
|
+
final_registry_configs.append(registry_configs)
|
|
250
|
+
else:
|
|
251
|
+
final_registry_configs.extend(registry_configs)
|
|
252
|
+
|
|
253
|
+
# Load additional configs from file if provided
|
|
254
|
+
if config_path:
|
|
255
|
+
try:
|
|
256
|
+
with open(config_path, 'r') as f:
|
|
257
|
+
config_data = json.load(f)
|
|
258
|
+
|
|
259
|
+
# Create registry configs from the loaded data
|
|
260
|
+
for _, server_config in config_data.get(
|
|
261
|
+
"mcpServers", {}
|
|
262
|
+
).items():
|
|
263
|
+
# Create a custom registry config for each server
|
|
264
|
+
registry_config = BaseMCPRegistryConfig(
|
|
265
|
+
type=MCPRegistryType.CUSTOM,
|
|
266
|
+
os=platform.system().lower(), # type: ignore [arg-type]
|
|
267
|
+
**server_config,
|
|
268
|
+
)
|
|
269
|
+
final_registry_configs.append(registry_config)
|
|
270
|
+
except Exception as e:
|
|
271
|
+
logger.error(f"Failed to load config from {config_path}: {e}")
|
|
272
|
+
raise
|
|
273
|
+
|
|
274
|
+
# Create the agent instance
|
|
275
|
+
agent = cls(
|
|
276
|
+
registry_configs=final_registry_configs,
|
|
277
|
+
model=model,
|
|
278
|
+
function_calling_available=function_calling_available,
|
|
279
|
+
**kwargs,
|
|
135
280
|
)
|
|
136
|
-
if self._function_calling_available:
|
|
137
|
-
tools = self._mcp_toolkit.get_tools()
|
|
138
|
-
for tool in tools:
|
|
139
|
-
self.add_tool(tool)
|
|
140
281
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
282
|
+
# Connect to MCP servers
|
|
283
|
+
try:
|
|
284
|
+
await agent.connect()
|
|
285
|
+
except Exception as e:
|
|
286
|
+
logger.error(f"Failed to connect to MCP servers: {e}")
|
|
287
|
+
await agent.disconnect() # Clean up if connection fails
|
|
288
|
+
raise
|
|
289
|
+
|
|
290
|
+
return agent
|
|
291
|
+
|
|
292
|
+
async def connect(self) -> None:
|
|
293
|
+
r"""Connect to the MCP servers."""
|
|
294
|
+
if self.mcp_toolkit:
|
|
295
|
+
await self.mcp_toolkit.connect()
|
|
296
|
+
if self.function_calling_available:
|
|
297
|
+
self.add_tools(
|
|
298
|
+
cast(
|
|
299
|
+
list[FunctionTool | Callable[..., Any]],
|
|
300
|
+
self.mcp_toolkit.get_tools(),
|
|
301
|
+
)
|
|
302
|
+
)
|
|
303
|
+
else:
|
|
304
|
+
prompt = TextPrompt(TOOLS_PROMPT)
|
|
305
|
+
self._text_tools = prompt.format(
|
|
306
|
+
tools=self.mcp_toolkit.get_text_tools()
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
async def disconnect(self) -> None:
|
|
310
|
+
r"""Disconnect from the MCP servers."""
|
|
311
|
+
if self.mcp_toolkit:
|
|
312
|
+
await self.mcp_toolkit.disconnect()
|
|
313
|
+
|
|
314
|
+
async def astep(
|
|
315
|
+
self, input_message: Union[BaseMessage, str], *args, **kwargs
|
|
144
316
|
) -> ChatAgentResponse:
|
|
145
|
-
r"""
|
|
317
|
+
r"""Asynchronous step function. Make sure MCP toolkit is connected
|
|
318
|
+
before proceeding.
|
|
146
319
|
|
|
147
320
|
Args:
|
|
148
|
-
|
|
149
|
-
|
|
321
|
+
input_message (Union[BaseMessage, str]): The input message.
|
|
322
|
+
*args: Additional arguments.
|
|
323
|
+
**kwargs: Additional keyword arguments.
|
|
150
324
|
|
|
151
325
|
Returns:
|
|
152
|
-
ChatAgentResponse: The
|
|
153
|
-
prompt and potentially executing MCP tool calls.
|
|
154
|
-
|
|
155
|
-
Raises:
|
|
156
|
-
RuntimeError: If the MCP server is not connected when attempting
|
|
157
|
-
to run.
|
|
326
|
+
ChatAgentResponse: The response from the agent.
|
|
158
327
|
"""
|
|
328
|
+
if self.mcp_toolkit and not self.mcp_toolkit.is_connected():
|
|
329
|
+
await self.connect()
|
|
159
330
|
|
|
160
|
-
if
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if self._function_calling_available:
|
|
164
|
-
response = await self.astep(prompt)
|
|
165
|
-
return response
|
|
331
|
+
if self.function_calling_available:
|
|
332
|
+
return await super().astep(input_message, *args, **kwargs)
|
|
166
333
|
else:
|
|
167
|
-
task = f"## Task:\n {
|
|
168
|
-
|
|
334
|
+
task = f"## Task:\n {input_message}"
|
|
335
|
+
input_message = str(self._text_tools) + task
|
|
336
|
+
response = await super().astep(input_message, *args, **kwargs)
|
|
169
337
|
content = response.msgs[0].content.lower()
|
|
170
338
|
|
|
171
339
|
tool_calls = []
|
|
@@ -193,12 +361,45 @@ class MCPAgent(ChatAgent):
|
|
|
193
361
|
else:
|
|
194
362
|
tools_results = []
|
|
195
363
|
for tool_call in tool_calls:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
364
|
+
try:
|
|
365
|
+
server_idx = tool_call.get('server_idx')
|
|
366
|
+
tool_name = tool_call.get('tool_name')
|
|
367
|
+
tool_args = tool_call.get('tool_args', {})
|
|
368
|
+
|
|
369
|
+
# Validate required fields
|
|
370
|
+
if server_idx is None or tool_name is None:
|
|
371
|
+
logger.warning(
|
|
372
|
+
f"Missing required fields in tool "
|
|
373
|
+
f"call: {tool_call}"
|
|
374
|
+
)
|
|
375
|
+
continue
|
|
376
|
+
|
|
377
|
+
# Check server index is valid
|
|
378
|
+
if (
|
|
379
|
+
not isinstance(server_idx, int)
|
|
380
|
+
or server_idx < 0
|
|
381
|
+
or server_idx >= len(self.mcp_toolkit.servers)
|
|
382
|
+
):
|
|
383
|
+
logger.warning(
|
|
384
|
+
f"Invalid server index: {server_idx}"
|
|
385
|
+
)
|
|
386
|
+
continue
|
|
387
|
+
|
|
388
|
+
server = self.mcp_toolkit.servers[server_idx]
|
|
389
|
+
result = await server.call_tool(tool_name, tool_args)
|
|
390
|
+
|
|
391
|
+
# Safely access content
|
|
392
|
+
if result.content and len(result.content) > 0:
|
|
393
|
+
tools_results.append(
|
|
394
|
+
{tool_name: result.content[0].text}
|
|
395
|
+
)
|
|
396
|
+
else:
|
|
397
|
+
tools_results.append(
|
|
398
|
+
{tool_name: "No result content available"}
|
|
399
|
+
)
|
|
400
|
+
except Exception as e:
|
|
401
|
+
logger.error(f"Error processing tool call: {e}")
|
|
402
|
+
tools_results.append({"error": str(e)})
|
|
202
403
|
results = json.dumps(tools_results)
|
|
203
404
|
final_prompt = TextPrompt(FINAL_RESPONSE_PROMPT).format(
|
|
204
405
|
results=results
|
|
@@ -206,28 +407,40 @@ class MCPAgent(ChatAgent):
|
|
|
206
407
|
response = await self.astep(final_prompt)
|
|
207
408
|
return response
|
|
208
409
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
function_calling_available: bool = False,
|
|
215
|
-
) -> "MCPAgent":
|
|
216
|
-
r"""Factory method to create and initialize an MCPAgent.
|
|
410
|
+
def step(
|
|
411
|
+
self, input_message: Union[BaseMessage, str], *args, **kwargs
|
|
412
|
+
) -> ChatAgentResponse:
|
|
413
|
+
r"""Synchronous step function. Make sure MCP toolkit is connected
|
|
414
|
+
before proceeding.
|
|
217
415
|
|
|
218
416
|
Args:
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
If None, the default model will be used. (default: :obj:`None`)
|
|
223
|
-
function_calling_available (bool): Flag indicating whether the
|
|
224
|
-
model is equipped with function calling ability. This affects
|
|
225
|
-
the system message content. (default: :obj:`False`)
|
|
417
|
+
input_message (Union[BaseMessage, str]): The input message.
|
|
418
|
+
*args: Additional arguments.
|
|
419
|
+
**kwargs: Additional keyword arguments.
|
|
226
420
|
|
|
227
421
|
Returns:
|
|
228
|
-
|
|
422
|
+
ChatAgentResponse: The response from the agent.
|
|
229
423
|
"""
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
424
|
+
try:
|
|
425
|
+
loop = asyncio.get_running_loop()
|
|
426
|
+
except RuntimeError:
|
|
427
|
+
loop = None
|
|
428
|
+
|
|
429
|
+
if loop and loop.is_running():
|
|
430
|
+
# Running inside an existing loop (e.g., Jupyter/FastAPI)
|
|
431
|
+
# Use create_task and run with a future
|
|
432
|
+
coro = self.astep(input_message, *args, **kwargs)
|
|
433
|
+
future = asyncio.ensure_future(coro)
|
|
434
|
+
return asyncio.run_coroutine_threadsafe(future, loop).result()
|
|
435
|
+
else:
|
|
436
|
+
# Safe to run normally
|
|
437
|
+
return asyncio.run(self.astep(input_message, *args, **kwargs))
|
|
438
|
+
|
|
439
|
+
async def __aenter__(self):
|
|
440
|
+
r"""Async context manager entry."""
|
|
441
|
+
await self.connect()
|
|
442
|
+
return self
|
|
443
|
+
|
|
444
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
445
|
+
r"""Async context manager exit."""
|
|
446
|
+
await self.disconnect()
|
camel/benchmarks/__init__.py
CHANGED
|
@@ -15,12 +15,14 @@
|
|
|
15
15
|
from .apibank import APIBankBenchmark
|
|
16
16
|
from .apibench import APIBenchBenchmark
|
|
17
17
|
from .base import BaseBenchmark
|
|
18
|
+
from .browsecomp import BrowseCompBenchmark
|
|
18
19
|
from .gaia import DefaultGAIARetriever, GAIABenchmark
|
|
19
20
|
from .nexus import NexusBenchmark
|
|
20
21
|
from .ragbench import RAGBenchBenchmark
|
|
21
22
|
|
|
22
23
|
__all__ = [
|
|
23
24
|
"BaseBenchmark",
|
|
25
|
+
"BrowseCompBenchmark",
|
|
24
26
|
"GAIABenchmark",
|
|
25
27
|
"DefaultGAIARetriever",
|
|
26
28
|
"NexusBenchmark",
|