Repository: huggingface/smolagents

Issue:
"Skipping dangerous attribute" check
## Logs issue
I've wrapped smolagents.CodeAgent in a FastAPI app and noticed that when running the generated code with imports, thousands of INFO-level logs are produced by LocalPythonInterpreter, such as:

```markdown
2025-02-15 19:16:23,417 - INFO - Skipping dangerous attribute pandas.io.formats.printing.Any
2025-02-15 19:16:23,418 - INFO - Skipping dangerous attribute pandas.io.formats.printing.Callable
```
Full log from single run in the attached [app.log](https://github.com/user-attachments/files/18813471/app.log).

Would it be possible to adjust the logger level for these messages to DEBUG? This would help reduce log clutter during regular FastAPI execution.


Here's minimal example:
```python
import os
import logging

from fastapi import FastAPI

from smolagents import CodeAgent, LiteLLMModel, LogLevel

OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
)

logger = logging.getLogger(__name__)

model = LiteLLMModel(
    model_id="openai/gpt-4o-mini",
    api_key=OPENAI_API_KEY,
    seed=42,
)

agent = CodeAgent(
    model=model,
    tools=[],
    add_base_tools=True,
    additional_authorized_imports=["pandas"],
    verbosity_level=LogLevel.DEBUG,
)

app = FastAPI()


@app.get("/execute")
async def execute():
    logger.info("Executing agent")

    prompt = """Write code to import pandas and print version
    Return final_answer(code)
    """

    response = agent.run(prompt)

    return response


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(
        app,
        host="0.0.0.0",
        port=8000,
        log_level="info",
    )

```
Run it locally
- Terminal 1: uvicorn minimal_example_agent:app --reload
- Terminal 2: curl -X 'GET' 'http://0.0.0.0:8000/execute'

## Additional question
Lastly, I’m curious about how `dangerous_patterns` are applied at any levels. As seen in the logs, modules like `pandas.io.formats.printing.Any` are being excluded simply because their path contains 'io', even though they don’t actually use the io library.
Would it be possible to modify the logic to check only the top-level module against dangerous_patterns, rather than filtering based on any part of the path?

Discussion:

Patch:
diff --git a/docs/source/zh/_toctree.yml b/docs/source/zh/_toctree.yml
index 4da8f48..5ebe325 100644
--- a/docs/source/zh/_toctree.yml
+++ b/docs/source/zh/_toctree.yml
@@ -8,10 +8,14 @@
   sections:
   - local: tutorials/building_good_agents
     title: ✨ 构建好用的 agents
+  - local: tutorials/inspect_runs
+    title: 📊 监控 Agent 的运行
   - local: tutorials/tools
     title: 🛠️ 工具 - 深度指南
   - local: tutorials/secure_code_execution
     title: 🛡️ 使用 E2B 保护你的代码执行
+  - local: tutorials/memory
+    title: 📚 管理 Agent 的记忆
 - title: Conceptual guides
   sections:
   - local: conceptual_guides/intro_agents
@@ -21,14 +25,18 @@
 - title: Examples
   sections:
   - local: examples/text_to_sql
-    title: Self-correcting Text-to-SQL
+    title: 自我修正 Text-to-SQL
   - local: examples/rag
-    title: Master you knowledge base with agentic RAG
+    title: 借助 agentic RAG 掌控知识库
   - local: examples/multiagents
-    title: Orchestrate a multi-agent system
+    title: 编排 multi-agent 系统
+  - local: examples/web_browser
+    title: 基于视觉模型构建能够浏览网页的agent
 - title: Reference
   sections:
   - local: reference/agents
     title: Agent-related objects
+  - local: reference/models
+    title: Model-related objects
   - local: reference/tools
     title: Tool-related objects
diff --git a/docs/source/zh/examples/web_browser.mdx b/docs/source/zh/examples/web_browser.mdx
new file mode 100644
index 0000000..b72fe71
--- /dev/null
+++ b/docs/source/zh/examples/web_browser.mdx
@@ -0,0 +1,214 @@
+# 使用Agent实现网页浏览器自动化 🤖🌐
+
+[[open-in-colab]]
+
+在本notebook中，我们将创建一个**基于Agent的网页浏览器自动化系统**！该系统可以自动导航网站、与网页元素交互并提取信息。
+
+该Agent将能够：
+
+- [x] 导航到网页
+- [x] 点击元素
+- [x] 在页面内搜索
+- [x] 处理弹出窗口和模态框
+- [x] 提取信息
+
+让我们一步步搭建这个系统！
+
+首先运行以下命令安装所需依赖：
+
+```bash
+pip install smolagents selenium helium pillow -q
+```
+
+让我们导入所需的库并设置环境变量：
+
+```python
+from io import BytesIO
+from time import sleep
+
+import helium
+from dotenv import load_dotenv
+from PIL import Image
+from selenium import webdriver
+from selenium.webdriver.common.by import By
+from selenium.webdriver.common.keys import Keys
+
+from smolagents import CodeAgent, tool
+from smolagents.agents import ActionStep
+
+# Load environment variables
+load_dotenv()
+```
+
+现在我们来创建核心的浏览器交互工具，使我们的Agent能够导航并与网页交互：
+
+```python
+@tool
+def search_item_ctrl_f(text: str, nth_result: int = 1) -> str:
+    """
+    Searches for text on the current page via Ctrl + F and jumps to the nth occurrence.
+    Args:
+        text: The text to search for
+        nth_result: Which occurrence to jump to (default: 1)
+    """
+    elements = driver.find_elements(By.XPATH, f"//*[contains(text(), '{text}')]")
+    if nth_result > len(elements):
+        raise Exception(f"Match n°{nth_result} not found (only {len(elements)} matches found)")
+    result = f"Found {len(elements)} matches for '{text}'."
+    elem = elements[nth_result - 1]
+    driver.execute_script("arguments[0].scrollIntoView(true);", elem)
+    result += f"Focused on element {nth_result} of {len(elements)}"
+    return result
+
+@tool
+def go_back() -> None:
+    """Goes back to previous page."""
+    driver.back()
+
+@tool
+def close_popups() -> str:
+    """
+    Closes any visible modal or pop-up on the page. Use this to dismiss pop-up windows!
+    This does not work on cookie consent banners.
+    """
+    webdriver.ActionChains(driver).send_keys(Keys.ESCAPE).perform()
+```
+
+让我们配置使用Chrome浏览器并设置截图功能：
+
+```python
+# Configure Chrome options
+chrome_options = webdriver.ChromeOptions()
+chrome_options.add_argument("--force-device-scale-factor=1")
+chrome_options.add_argument("--window-size=1000,1350")
+chrome_options.add_argument("--disable-pdf-viewer")
+chrome_options.add_argument("--window-position=0,0")
+
+# Initialize the browser
+driver = helium.start_chrome(headless=False, options=chrome_options)
+
+# Set up screenshot callback
+def save_screenshot(memory_step: ActionStep, agent: CodeAgent) -> None:
+    sleep(1.0)  # Let JavaScript animations happen before taking the screenshot
+    driver = helium.get_driver()
+    current_step = memory_step.step_number
+    if driver is not None:
+        for previous_memory_step in agent.memory.steps:  # Remove previous screenshots for lean processing
+            if isinstance(previous_memory_step, ActionStep) and previous_memory_step.step_number <= current_step - 2:
+                previous_memory_step.observations_images = None
+        png_bytes = driver.get_screenshot_as_png()
+        image = Image.open(BytesIO(png_bytes))
+        print(f"Captured a browser screenshot: {image.size} pixels")
+        memory_step.observations_images = [image.copy()]  # Create a copy to ensure it persists
+
+    # Update observations with current URL
+    url_info = f"Current url: {driver.current_url}"
+    memory_step.observations = (
+        url_info if memory_step.observations is None else memory_step.observations + "\n" + url_info
+    )
+```
+
+现在我们来创建网页自动化Agent：
+
+```python
+from smolagents import HfApiModel
+
+# Initialize the model
+model_id = "meta-llama/Llama-3.3-70B-Instruct"  # You can change this to your preferred model
+model = HfApiModel(model_id)
+
+# Create the agent
+agent = CodeAgent(
+    tools=[go_back, close_popups, search_item_ctrl_f],
+    model=model,
+    additional_authorized_imports=["helium"],
+    step_callbacks=[save_screenshot],
+    max_steps=20,
+    verbosity_level=2,
+)
+
+# Import helium for the agent
+agent.python_executor("from helium import *", agent.state)
+```
+
+Agent需要获得关于如何使用Helium进行网页自动化的指导。以下是我们将提供的操作说明：
+
+```python
+helium_instructions = """
+You can use helium to access websites. Don't bother about the helium driver, it's already managed.
+We've already ran "from helium import *"
+Then you can go to pages!
+Code:
+```py
+go_to('github.com/trending')
+```<end_code>
+
+You can directly click clickable elements by inputting the text that appears on them.
+Code:
+```py
+click("Top products")
+```<end_code>
+
+If it's a link:
+Code:
+```py
+click(Link("Top products"))
+```<end_code>
+
+If you try to interact with an element and it's not found, you'll get a LookupError.
+In general stop your action after each button click to see what happens on your screenshot.
+Never try to login in a page.
+
+To scroll up or down, use scroll_down or scroll_up with as an argument the number of pixels to scroll from.
+Code:
+```py
+scroll_down(num_pixels=1200) # This will scroll one viewport down
+```<end_code>
+
+When you have pop-ups with a cross icon to close, don't try to click the close icon by finding its element or targeting an 'X' element (this most often fails).
+Just use your built-in tool `close_popups` to close them:
+Code:
+```py
+close_popups()
+```<end_code>
+
+You can use .exists() to check for the existence of an element. For example:
+Code:
+```py
+if Text('Accept cookies?').exists():
+    click('I accept')
+```<end_code>
+"""
+```
+
+现在我们可以运行Agent执行任务了！让我们尝试在维基百科上查找信息：
+
+```python
+search_request = """
+Please navigate to https://en.wikipedia.org/wiki/Chicago and give me a sentence containing the word "1992" that mentions a construction accident.
+"""
+
+agent_output = agent.run(search_request + helium_instructions)
+print("Final output:")
+print(agent_output)
+```
+
+您可以通过修改请求参数执行不同任务。例如，以下请求可帮助我判断是否需要更加努力工作：
+
+```python
+github_request = """
+I'm trying to find how hard I have to work to get a repo in github.com/trending.
+Can you navigate to the profile for the top author of the top trending repo, and give me their total number of commits over the last year?
+"""
+
+agent_output = agent.run(github_request + helium_instructions)
+print("Final output:")
+print(agent_output)
+```
+
+该系统在以下任务中尤为有效：
+
+- 从网站提取数据
+- 网页研究自动化
+- 用户界面测试与验证
+- 内容监控
\ No newline at end of file
diff --git a/docs/source/zh/guided_tour.mdx b/docs/source/zh/guided_tour.mdx
index 2c9db3a..8289007 100644
--- a/docs/source/zh/guided_tour.mdx
+++ b/docs/source/zh/guided_tour.mdx
@@ -33,10 +33,12 @@ rendered properly in your Markdown viewer.
     - [`TransformersModel`] 使用预初始化的 `transformers` 管道在本地机器上运行推理
     - [`HfApiModel`] 在底层使用 `huggingface_hub.InferenceClient`
     - [`LiteLLMModel`] 让您通过 [LiteLLM](https://docs.litellm.ai/) 调用 100+ 不同的模型！
+    - [`AzureOpenAIServerModel`] 允许您使用部署在 [Azure](https://azure.microsoft.com/en-us/products/ai-services/openai-service) 中的 OpenAI 模型。
+    - [`MLXModel`] 可创建 [mlx-lm](https://pypi.org/project/mlx-lm/) 流水线，以便在本地机器上运行推理。
 
 - `tools`，agent 可以用来解决任务的 `Tools` 列表。它可以是一个空列表。您还可以通过定义可选参数 `add_base_tools=True` 在您的 `tools` 列表之上添加默认工具箱。
 
-一旦有了这两个参数 `tools` 和 `model`，您就可以创建一个 agent 并运行它。您可以使用任何您喜欢的 LLM，无论是通过 [Hugging Face API](https://huggingface.co/docs/api-inference/en/index)、[transformers](https://github.com/huggingface/transformers/)、[ollama](https://ollama.com/)，还是 [LiteLLM](https://www.litellm.ai/)。
+一旦有了这两个参数 `tools` 和 `model`，您就可以创建一个 agent 并运行它。您可以使用任何您喜欢的 LLM，无论是通过 [Hugging Face API](https://huggingface.co/docs/api-inference/en/index)、[transformers](https://github.com/huggingface/transformers/)、[ollama](https://ollama.com/)、[LiteLLM](https://www.litellm.ai/)、[Azure OpenAI](https://azure.microsoft.com/en-us/products/ai-services/openai-service)，还是[mlx-lm](https://pypi.org/project/mlx-lm/).。
 
 <hfoptions id="选择一个LLM">
 <hfoption id="Hugging Face API">
@@ -109,6 +111,62 @@ agent.run(
     "Could you give me the 118th number in the Fibonacci sequence?",
 )
 ```
+</hfoption>
+<hfoption id="Azure OpenAI">
+
+要连接到 Azure OpenAI，您可以直接使用 `AzureOpenAIServerModel`，或使用 `LiteLLMModel` 并进行相应配置。
+
+初始化 `AzureOpenAIServerModel` 实例时，需要传递模型部署名称，可选择以下任一种方式：1.传递 `azure_endpoint`、`api_key` 和 `api_version` 参数；2.设置环境变量 `AZURE_OPENAI_ENDPOINT`、`AZURE_OPENAI_API_KEY` 和 `OPENAI_API_VERSION`
+
+```python
+# !pip install smolagents[openai]
+from smolagents import CodeAgent, AzureOpenAIServerModel
+
+model = AzureOpenAIServerModel(model_id="gpt-4o-mini")
+agent = CodeAgent(tools=[], model=model, add_base_tools=True)
+
+agent.run(
+    "Could you give me the 118th number in the Fibonacci sequence?",
+)
+```
+
+也可按如下方式配置 `LiteLLMModel` 连接 Azure OpenAI：
+
+- 将模型部署名称作为 `model_id` 参数传递，并确保其前缀为 `azure/`
+- 确保设置环境变量 `AZURE_API_VERSION`
+- 任选其一：1.传递 `api_base` 和 `api_key` 参数；2.设置环境变量 `AZURE_API_KEY` 和 `AZURE_API_BASE`
+
+```python
+import os
+from smolagents import CodeAgent, LiteLLMModel
+
+AZURE_OPENAI_CHAT_DEPLOYMENT_NAME="gpt-35-turbo-16k-deployment" # example of deployment name
+
+os.environ["AZURE_API_KEY"] = "" # api_key
+os.environ["AZURE_API_BASE"] = "" # "https://example-endpoint.openai.azure.com"
+os.environ["AZURE_API_VERSION"] = "" # "2024-10-01-preview"
+
+model = LiteLLMModel(model_id="azure/" + AZURE_OPENAI_CHAT_DEPLOYMENT_NAME)
+agent = CodeAgent(tools=[], model=model, add_base_tools=True)
+
+agent.run(
+   "Could you give me the 118th number in the Fibonacci sequence?",
+)
+```
+
+</hfoption>
+<hfoption id="mlx-lm">
+
+```python
+# !pip install smolagents[mlx-lm]
+from smolagents import CodeAgent, MLXModel
+
+mlx_model = MLXModel("mlx-community/Qwen2.5-Coder-32B-Instruct-4bit")
+agent = CodeAgent(model=mlx_model, tools=[], add_base_tools=True)
+
+agent.run("Could you give me the 118th number in the Fibonacci sequence?")
+```
+
 </hfoption>
 </hfoptions>
 
@@ -125,6 +183,7 @@ Python 解释器默认也不允许在安全列表之外导入，所以所有最
 ```py
 from smolagents import CodeAgent
 
+model = HfApiModel()
 agent = CodeAgent(tools=[], model=model, additional_authorized_imports=['requests', 'bs4'])
 agent.run("Could you get me the title of the page at url 'https://huggingface.co/blog'?")
 ```
@@ -364,6 +423,18 @@ GradioUI(agent).launch()
 
 ## 下一步
 
+最后，当您按需配置好agent后，即可将其分享至 Hub！
+
+```py
+agent.push_to_hub("m-ric/my_agent")
+```
+
+类似地，若要加载已推送至 Hub 的agent，在信任其工具代码的前提下，可使用：
+
+```py
+agent.from_hub("m-ric/my_agent", trust_remote_code=True)
+```
+
 要更深入地使用，您将需要查看我们的教程：
 - [我们的代码 agent 如何工作的解释](./tutorials/secure_code_execution)
 - [本指南关于如何构建好的 agent](./tutorials/building_good_agents)。
diff --git a/docs/source/zh/tutorials/inspect_runs.mdx b/docs/source/zh/tutorials/inspect_runs.mdx
new file mode 100644
index 0000000..e7beb80
--- /dev/null
+++ b/docs/source/zh/tutorials/inspect_runs.mdx
@@ -0,0 +1,195 @@
+<!--Copyright 2024 The HuggingFace Team. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+specific language governing permissions and limitations under the License.
+
+⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
+rendered properly in your Markdown viewer.
+
+-->
+# 使用 OpenTelemetry 检查运行记录
+
+[[open-in-colab]]
+
+> [!TIP]
+> 如果您是初次构建Agent，建议先阅读 [Agent 入门指南](../conceptual_guides/intro_agents) 和 [smolagents 导览](../guided_tour)。
+
+## 为什么需要记录Agent运行？
+
+调试Agent运行过程具有挑战性。
+
+验证运行是否正常进行很困难，因为Agent的工作流程本身具有 [设计上的不可预测性](../conceptual_guides/intro_agents)（如果可预测，直接使用传统代码即可）。
+
+检查运行记录同样困难：多步骤的Agent往往会快速在控制台生成大量日志，而大多数错误只是"LLM 低级错误"类型的问题，通常LLM会在后续步骤中通过生成更好的代码或工具调用来自我修正。
+
+因此，在生产环境中使用监控工具记录Agent运行过程，对于后续检查和分析至关重要！
+
+我们采用 [OpenTelemetry](https://opentelemetry.io/) 标准来实现Agent运行监控。
+
+这意味着您只需添加少量监控代码，即可在正常运行Agent时自动记录所有信息到监控平台。以下是在不同OpenTelemetry后端实现此功能的示例：
+
+在监控平台上的展示效果如下：
+
+<div class="flex justify-center">
+    <img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/smolagents/inspect_run_phoenix.gif"/>
+</div>
+
+
+## 使用 Arize AI Phoenix 配置遥测
+
+首先安装必要的软件包。这里我们选择安装 [Arize AI 的 Phoenix](https://github.com/Arize-ai/phoenix) 作为日志收集和检查方案，您也可以使用其他兼容 OpenTelemetry 的平台来完成收集与检查工作。
+
+```shell
+pip install 'smolagents[telemetry]'
+```
+
+接着在后台运行日志收集器：
+
+```shell
+python -m phoenix.server.main serve
+```
+
+最后配置 `SmolagentsInstrumentor` 来追踪Agent活动，并将追踪数据发送至 Phoenix 默认端点：
+
+```python
+from phoenix.otel import register
+from openinference.instrumentation.smolagents import SmolagentsInstrumentor
+
+register()
+SmolagentsInstrumentor().instrument()
+```
+
+完成上述配置后，即可正常运行您的Agent！
+
+```py
+from smolagents import (
+    CodeAgent,
+    ToolCallingAgent,
+    DuckDuckGoSearchTool,
+    VisitWebpageTool,
+    HfApiModel,
+)
+
+model = HfApiModel()
+
+search_agent = ToolCallingAgent(
+    tools=[DuckDuckGoSearchTool(), VisitWebpageTool()],
+    model=model,
+    name="search_agent",
+    description="This is an agent that can do web search.",
+)
+
+manager_agent = CodeAgent(
+    tools=[],
+    model=model,
+    managed_agents=[search_agent],
+)
+manager_agent.run(
+    "If the US keeps its 2024 growth rate, how many years will it take for the GDP to double?"
+)
+```
+Voilà!
+
+此时访问 `http://0.0.0.0:6006/projects/` 即可查看运行记录：
+
+<img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/smolagents/inspect_run_phoenix.png">
+
+如图所示，CodeAgent 调用了其托管的 ToolCallingAgent（注：托管Agent也可以是另一个 CodeAgent）执行美国2024年经济增长率的网络搜索。托管Agent返回报告后，管理Agent根据结果计算出经济翻倍周期！是不是很智能？
+
+## 使用 Langfuse 配置遥测
+
+本部分演示如何通过 `SmolagentsInstrumentor` 使用 **Langfuse** 监控和调试 Hugging Face **smolagents**。
+
+> **Langfuse 是什么？** [Langfuse](https://langfuse.com) 是面向LLM工程的开源平台，提供AI Agent的追踪与监控功能，帮助开发者调试、分析和优化产品。该平台通过原生集成、OpenTelemetry 和 SDKs 与各类工具框架对接。
+
+### 步骤 1: 安装依赖
+
+```python
+%pip install smolagents
+%pip install opentelemetry-sdk opentelemetry-exporter-otlp openinference-instrumentation-smolagents
+```
+
+### 步骤 2: 配置环境变量
+
+设置 Langfuse API 密钥，并配置 OpenTelemetry 端点将追踪数据发送至 Langfuse。通过注册 [Langfuse Cloud](https://cloud.langfuse.com) 或 [自托管 Langfuse](https://langfuse.com/self-hosting) 获取 API 密钥。
+
+同时需添加 [Hugging Face 令牌](https://huggingface.co/settings/tokens) (`HF_TOKEN`) 作为环境变量：
+```python
+import os
+import base64
+
+LANGFUSE_PUBLIC_KEY="pk-lf-..."
+LANGFUSE_SECRET_KEY="sk-lf-..."
+LANGFUSE_AUTH=base64.b64encode(f"{LANGFUSE_PUBLIC_KEY}:{LANGFUSE_SECRET_KEY}".encode()).decode()
+
+os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://cloud.langfuse.com/api/public/otel" # EU data region
+# os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://us.cloud.langfuse.com/api/public/otel" # US data region
+os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"Authorization=Basic {LANGFUSE_AUTH}"
+
+# your Hugging Face token
+os.environ["HF_TOKEN"] = "hf_..."
+```
+
+### 步骤 3: 初始化 `SmolagentsInstrumentor`
+
+在应用程序代码执行前初始化 `SmolagentsInstrumentor`。配置 `tracer_provider` 并添加 span processor 将追踪数据导出至 Langfuse。`OTLPSpanExporter()` 会自动使用环境变量中配置的端点和请求头。
+
+
+```python
+from opentelemetry.sdk.trace import TracerProvider
+
+from openinference.instrumentation.smolagents import SmolagentsInstrumentor
+from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
+from opentelemetry.sdk.trace.export import SimpleSpanProcessor
+
+trace_provider = TracerProvider()
+trace_provider.add_span_processor(SimpleSpanProcessor(OTLPSpanExporter()))
+
+SmolagentsInstrumentor().instrument(tracer_provider=trace_provider)
+```
+
+### 步骤 4: 运行 smolagent
+
+```python
+from smolagents import (
+    CodeAgent,
+    ToolCallingAgent,
+    DuckDuckGoSearchTool,
+    VisitWebpageTool,
+    HfApiModel,
+)
+
+model = HfApiModel(
+    model_id="deepseek-ai/DeepSeek-R1-Distill-Qwen-32B"
+)
+
+search_agent = ToolCallingAgent(
+    tools=[DuckDuckGoSearchTool(), VisitWebpageTool()],
+    model=model,
+    name="search_agent",
+    description="This is an agent that can do web search.",
+)
+
+manager_agent = CodeAgent(
+    tools=[],
+    model=model,
+    managed_agents=[search_agent],
+)
+manager_agent.run(
+    "How can Langfuse be used to monitor and improve the reasoning and decision-making of smolagents when they execute multi-step tasks, like dynamically adjusting a recipe based on user feedback or available ingredients?"
+)
+```
+
+### 步骤 5: 在 Langfuse 中查看追踪记录
+
+运行Agent后，您可以在 [Langfuse](https://cloud.langfuse.com) 平台查看 smolagents 应用生成的追踪记录。这些记录会详细展示LLM的交互步骤，帮助您调试和优化AI代理。
+
+![smolagents 追踪示例](https://langfuse.com/images/cookbook/integration-smolagents/smolagent_example_trace.png)
+
+_[Langfuse 公开示例追踪](https://cloud.langfuse.com/project/cloramnkj0002jz088vzn1ja4/traces/ce5160f9bfd5a6cd63b07d2bfcec6f54?timestamp=2025-02-11T09%3A25%3A45.163Z&display=details)_
\ No newline at end of file
diff --git a/docs/source/zh/tutorials/memory.mdx b/docs/source/zh/tutorials/memory.mdx
new file mode 100644
index 0000000..1718567
--- /dev/null
+++ b/docs/source/zh/tutorials/memory.mdx
@@ -0,0 +1,146 @@
+<!--Copyright 2024 The HuggingFace Team. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+specific language governing permissions and limitations under the License.
+
+⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
+rendered properly in your Markdown viewer.
+
+-->
+# 📚 管理Agent的记忆
+
+[[open-in-colab]]
+
+归根结底，Agent可以定义为由几个简单组件构成：它拥有工具、提示词。最重要的是，它具备对过往步骤的记忆，能够追溯完整的规划、执行和错误历史。
+
+### 回放Agent的记忆
+
+我们提供了多项功能来审查Agent的过往运行记录。
+
+您可以通过插装（instrumentation）在可视化界面中查看Agent的运行过程，该界面支持对特定步骤进行缩放操作，具体方法参见[插装指南](./inspect_runs)。
+
+您也可以使用`agent.replay()`方法实现回放：
+
+当Agent完成运行后：
+```py
+from smolagents import HfApiModel, CodeAgent
+
+agent = CodeAgent(tools=[], model=HfApiModel(), verbosity_level=0)
+
+result = agent.run("What's the 20th Fibonacci number?")
+```
+
+若要回放最近一次运行，只需使用：
+```py
+agent.replay()
+```
+
+### 动态修改Agent的记忆
+
+许多高级应用场景需要对Agent的记忆进行动态修改。
+
+您可以通过以下方式访问Agent的记忆：
+
+```py
+from smolagents import ActionStep
+
+system_prompt_step = agent.memory.system_prompt
+print("The system prompt given to the agent was:")
+print(system_prompt_step.system_prompt)
+
+task_step = agent.memory.steps[0]
+print("\n\nThe first task step was:")
+print(task_step.task)
+
+for step in agent.memory.steps:
+    if isinstance(step, ActionStep):
+        if step.error is not None:
+            print(f"\nStep {step.step_number} got this error:\n{step.error}\n")
+        else:
+            print(f"\nStep {step.step_number} got these observations:\n{step.observations}\n")
+```
+
+使用`agent.memory.get_full_steps()`可获取完整步骤字典数据。
+
+您还可以通过步骤回调（step callbacks）实现记忆的动态修改。
+
+步骤回调函数可通过参数直接访问`agent`对象，因此能够访问所有记忆步骤并根据需要进行修改。例如，假设您正在监控网页浏览Agent每个步骤的屏幕截图，希望保留最新截图同时删除旧步骤的图片以节省token消耗。
+
+可参考以下代码示例：
+_注：此代码片段不完整，部分导入语句和对象定义已精简，完整代码请访问[原始脚本](https://github.com/huggingface/smolagents/blob/main/src/smolagents/vision_web_browser.py)_
+
+```py
+import helium
+from PIL import Image
+from io import BytesIO
+from time import sleep
+
+def update_screenshot(memory_step: ActionStep, agent: CodeAgent) -> None:
+    sleep(1.0)  # Let JavaScript animations happen before taking the screenshot
+    driver = helium.get_driver()
+    latest_step = memory_step.step_number
+    for previous_memory_step in agent.memory.steps:  # Remove previous screenshots from logs for lean processing
+        if isinstance(previous_memory_step, ActionStep) and previous_memory_step.step_number <= latest_step - 2:
+            previous_memory_step.observations_images = None
+    png_bytes = driver.get_screenshot_as_png()
+    image = Image.open(BytesIO(png_bytes))
+    memory_step.observations_images = [image.copy()]
+```
+
+最后在初始化Agent时，将此函数传入`step_callbacks`参数：
+
+```py
+CodeAgent(
+    tools=[DuckDuckGoSearchTool(), go_back, close_popups, search_item_ctrl_f],
+    model=model,
+    additional_authorized_imports=["helium"],
+    step_callbacks=[update_screenshot],
+    max_steps=20,
+    verbosity_level=2,
+)
+```
+
+请访问我们的 [vision web browser code](https://github.com/huggingface/smolagents/blob/main/src/smolagents/vision_web_browser.py) 查看完整可运行示例。
+
+### 分步运行 Agents
+
+当您需要处理耗时数天的工具调用时，这种方式特别有用：您可以逐步执行Agents。这还允许您在每一步更新记忆。
+
+```py
+from smolagents import HfApiModel, CodeAgent, ActionStep, TaskStep
+
+agent = CodeAgent(tools=[], model=HfApiModel(), verbosity_level=1)
+print(agent.memory.system_prompt)
+
+task = "What is the 20th Fibonacci number?"
+
+# You could modify the memory as needed here by inputting the memory of another agent.
+# agent.memory.steps = previous_agent.memory.steps
+
+# Let's start a new task!
+agent.memory.steps.append(TaskStep(task=task, task_images=[]))
+
+final_answer = None
+step_number = 1
+while final_answer is None and step_number <= 10:
+    memory_step = ActionStep(
+        step_number=step_number,
+        observations_images=[],
+    )
+    # Run one step.
+    final_answer = agent.step(memory_step)
+    agent.memory.steps.append(memory_step)
+    step_number += 1
+
+    # Change the memory as you please!
+    # For instance to update the latest step:
+    # agent.memory.steps[-1] = ...
+
+print("The final answer is:", final_answer)
+```
\ No newline at end of file
diff --git a/examples/benchmark.ipynb b/examples/benchmark.ipynb
deleted file mode 100644
index 79f0ae0..0000000
--- a/examples/benchmark.ipynb
+++ /dev/null
@@ -1,1195 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "code",
-   "execution_count": 4,
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "\n",
-      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\u001b[0m\n",
-      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n"
-     ]
-    }
-   ],
-   "source": [
-    "!pip install -e .. datasets sympy numpy matplotlib seaborn -q  # Install dev version of smolagents + some packages"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## Constants and utilities/tools"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "# Benchmark date\n",
-    "# - set a concrete date:\n",
-    "DATE = \"2024-12-26\"\n",
-    "# - or use default: today\n",
-    "# DATE = None\n",
-    "\n",
-    "# Evaluation dataset\n",
-    "# - the dataset is gated, so you must first visit its page to request access: https://huggingface.co/datasets/smolagents-benchmark/benchmark-v1\n",
-    "EVAL_DATASET = \"smolagents-benchmark/benchmark-v1\"\n",
-    "\n",
-    "# Answers dataset: it must be a gated dataset; required to score the answers\n",
-    "ANSWERS_DATASET = \"smolagents-benchmark/answers\"\n",
-    "# Whether to push the answers dataset to the Hub\n",
-    "PUSH_ANSWERS_DATASET_TO_HUB = True\n",
-    "\n",
-    "# Results dataset\n",
-    "RESULTS_DATASET = \"smolagents-benchmark/results\"\n",
-    "# Whether to push the results dataset to the Hub\n",
-    "PUSH_RESULTS_DATASET_TO_HUB = True\n",
-    "\n",
-    "\n",
-    "import datetime\n",
-    "import json\n",
-    "import os\n",
-    "import re\n",
-    "import string\n",
-    "import time\n",
-    "import warnings\n",
-    "from typing import List\n",
-    "\n",
-    "import datasets\n",
-    "from dotenv import load_dotenv\n",
-    "from tqdm import tqdm\n",
-    "\n",
-    "from smolagents import (\n",
-    "    AgentError,\n",
-    "    CodeAgent,\n",
-    "    GoogleSearchTool,\n",
-    "    HfApiModel,\n",
-    "    PythonInterpreterTool,\n",
-    "    ToolCallingAgent,\n",
-    "    VisitWebpageTool,\n",
-    ")\n",
-    "from smolagents.agents import ActionStep\n",
-    "\n",
-    "\n",
-    "load_dotenv()\n",
-    "os.makedirs(\"output\", exist_ok=True)\n",
-    "\n",
-    "\n",
-    "def serialize_agent_error(obj):\n",
-    "    if isinstance(obj, AgentError):\n",
-    "        return {\"error_type\": obj.__class__.__name__, \"message\": obj.message}\n",
-    "    else:\n",
-    "        return str(obj)\n",
-    "\n",
-    "\n",
-    "def answer_questions(\n",
-    "    eval_ds,\n",
-    "    agent,\n",
-    "    model_id,\n",
-    "    action_type,\n",
-    "    is_vanilla_llm=False,\n",
-    "    date=DATE,\n",
-    "    output_dir=\"output\",\n",
-    "    push_to_hub_dataset=ANSWERS_DATASET if PUSH_ANSWERS_DATASET_TO_HUB else None,\n",
-    "):\n",
-    "    date = date or datetime.date.today().isoformat()\n",
-    "\n",
-    "    for task in eval_ds:\n",
-    "        file_name = f\"output/{model_id.replace('/', '__')}__{action_type}__{task}__{date}.jsonl\"\n",
-    "        answered_questions = []\n",
-    "        if os.path.exists(file_name):\n",
-    "            with open(file_name, \"r\") as f:\n",
-    "                for line in f:\n",
-    "                    answered_questions.append(json.loads(line)[\"question\"])\n",
-    "\n",
-    "        for _, example in tqdm(enumerate(eval_ds[task]), total=len(eval_ds[task])):\n",
-    "            try:\n",
-    "                question = example[\"question\"]\n",
-    "                if example[\"source\"] == \"SimpleQA\":\n",
-    "                    question += \" Answer with only the final number.\"\n",
-    "                if example[\"source\"] == \"MATH\":\n",
-    "                    question += \" Write code, not latex.\"\n",
-    "                if question in answered_questions:\n",
-    "                    continue\n",
-    "                start_time = time.time()\n",
-    "\n",
-    "                if is_vanilla_llm:\n",
-    "                    llm = agent\n",
-    "                    answer = str(llm([{\"role\": \"user\", \"content\": question}]).content)\n",
-    "                    token_count = {\n",
-    "                        \"input\": llm.last_input_token_count,\n",
-    "                        \"output\": llm.last_output_token_count,\n",
-    "                    }\n",
-    "                    intermediate_steps = str([])\n",
-    "                else:\n",
-    "                    answer = str(agent.run(question))\n",
-    "                    token_count = agent.monitor.get_total_token_counts()\n",
-    "                    intermediate_steps = str(agent.logs)\n",
-    "                    # Remove memory from logs to make them more compact.\n",
-    "                    for step in agent.logs:\n",
-    "                        if isinstance(step, ActionStep):\n",
-    "                            step.agent_memory = None\n",
-    "\n",
-    "                end_time = time.time()\n",
-    "                annotated_example = {\n",
-    "                    \"model_id\": model_id,\n",
-    "                    \"agent_action_type\": action_type,\n",
-    "                    \"question\": question,\n",
-    "                    \"answer\": answer,\n",
-    "                    \"true_answer\": example[\"true_answer\"],\n",
-    "                    \"source\": example[\"source\"],\n",
-    "                    \"intermediate_steps\": intermediate_steps,\n",
-    "                    \"start_time\": start_time,\n",
-    "                    \"end_time\": end_time,\n",
-    "                    \"token_counts\": token_count,\n",
-    "                }\n",
-    "\n",
-    "                with open(file_name, \"a\") as f:\n",
-    "                    json.dump(annotated_example, f, default=serialize_agent_error)\n",
-    "                    f.write(\"\\n\")  # add a newline for JSONL format\n",
-    "            except Exception as e:\n",
-    "                print(\"Failed:\", e)\n",
-    "\n",
-    "        if push_to_hub_dataset:\n",
-    "            ds = datasets.Dataset.from_pandas(pd.read_json(file_name, lines=True), split=\"test\", preserve_index=False)\n",
-    "            config = f\"{model_id.replace('/', '__')}__{action_type}__{task}\"\n",
-    "            data_dir = f\"{model_id}/{action_type}/{task}/{date}\"\n",
-    "            ds.push_to_hub(\n",
-    "                push_to_hub_dataset,\n",
-    "                config_name=config,\n",
-    "                data_dir=data_dir,\n",
-    "                split=\"test\",\n",
-    "                commit_message=f\"Upload {config}\",\n",
-    "            )\n",
-    "\n",
-    "\n",
-    "def normalize_number_str(number_str: str) -> float:\n",
-    "    # we replace these common units and commas to allow\n",
-    "    # conversion to float\n",
-    "    for char in [\"$\", \"%\", \",\"]:\n",
-    "        number_str = number_str.replace(char, \"\")\n",
-    "    try:\n",
-    "        return float(number_str)\n",
-    "    except ValueError:\n",
-    "        return float(\"inf\")\n",
-    "\n",
-    "\n",
-    "def split_string(\n",
-    "    s: str,\n",
-    "    char_list: list[str] = [\",\", \";\"],\n",
-    ") -> list[str]:\n",
-    "    pattern = f\"[{''.join(char_list)}]\"\n",
-    "    return re.split(pattern, s)\n",
-    "\n",
-    "\n",
-    "def is_float(element: any) -> bool:\n",
-    "    try:\n",
-    "        float(element)\n",
-    "        return True\n",
-    "    except ValueError:\n",
-    "        return False\n",
-    "\n",
-    "\n",
-    "def normalize_str(input_str, remove_punct=True) -> str:\n",
-    "    \"\"\"\n",
-    "    Normalize a string by:\n",
-    "    - Removing all white spaces\n",
-    "    - Optionally removing punctuation (if remove_punct is True)\n",
-    "    - Converting to lowercase\n",
-    "    Parameters:\n",
-    "    - input_str: str, the string to normalize\n",
-    "    - remove_punct: bool, whether to remove punctuation (default: True)\n",
-    "    Returns:\n",
-    "    - str, the normalized string\n",
-    "    \"\"\"\n",
-    "    # Remove all white spaces. Required e.g for seagull vs. sea gull\n",
-    "    no_spaces = re.sub(r\"\\s\", \"\", input_str)\n",
-    "\n",
-    "    # Remove punctuation, if specified.\n",
-    "    if remove_punct:\n",
-    "        translator = str.maketrans(\"\", \"\", string.punctuation)\n",
-    "        return no_spaces.lower().translate(translator)\n",
-    "    else:\n",
-    "        return no_spaces.lower()\n",
-    "\n",
-    "\n",
-    "def extract_numbers(text: str) -> List[str]:\n",
-    "    \"\"\"This pattern matches:\n",
-    "    - Optional negative sign\n",
-    "    - Numbers with optional comma thousand separators\n",
-    "    - Optional decimal points with decimal numbers\n",
-    "    \"\"\"\n",
-    "    pattern = r\"-?(?:\\d{1,3}(?:,\\d{3})+|\\d+)(?:\\.\\d+)?\"\n",
-    "\n",
-    "    return [el.replace(\",\", \"\") for el in re.findall(pattern, text)]\n",
-    "\n",
-    "\n",
-    "def get_question_score_gaia(\n",
-    "    model_answer: str,\n",
-    "    ground_truth: str,\n",
-    ") -> bool:\n",
-    "    \"\"\"Scoring function used to score functions from the GAIA benchmark\"\"\"\n",
-    "    if is_float(ground_truth):\n",
-    "        normalized_answer = normalize_number_str(str(model_answer))\n",
-    "        return normalized_answer == float(ground_truth)\n",
-    "\n",
-    "    elif any(char in ground_truth for char in [\",\", \";\"]):  # if gt is a list\n",
-    "        # question with the fish: normalization removes punct\n",
-    "        gt_elems = split_string(ground_truth)\n",
-    "        ma_elems = split_string(model_answer)\n",
-    "\n",
-    "        if len(gt_elems) != len(ma_elems):  # check length is the same\n",
-    "            warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-    "            return False\n",
-    "\n",
-    "        comparisons = []\n",
-    "        for ma_elem, gt_elem in zip(ma_elems, gt_elems):  # compare each element as float or str\n",
-    "            if is_float(gt_elem):\n",
-    "                normalized_ma_elem = normalize_number_str(ma_elem)\n",
-    "                comparisons.append(normalized_ma_elem == float(gt_elem))\n",
-    "            else:\n",
-    "                # we do not remove punct since comparisons can include punct\n",
-    "                comparisons.append(\n",
-    "                    normalize_str(ma_elem, remove_punct=False) == normalize_str(gt_elem, remove_punct=False)\n",
-    "                )\n",
-    "        return all(comparisons)\n",
-    "\n",
-    "    else:  # if gt is a str\n",
-    "        return normalize_str(model_answer) == normalize_str(ground_truth)\n",
-    "\n",
-    "\n",
-    "def get_correct(row):\n",
-    "    if row[\"source\"] == \"MATH\":  # Checks the last number in answer\n",
-    "        numbers_answer = extract_numbers(str(row[\"answer\"]))\n",
-    "        if len(numbers_answer) == 0:\n",
-    "            return False\n",
-    "        return float(numbers_answer[-1]) == float(row[\"true_answer\"])\n",
-    "    else:\n",
-    "        return get_question_score_gaia(str(row[\"answer\"]), str(row[\"true_answer\"]))\n",
-    "\n",
-    "\n",
-    "def score_answers(\n",
-    "    answers_subsets,\n",
-    "    answers_dataset=ANSWERS_DATASET,\n",
-    "    date=DATE,\n",
-    "    push_to_hub_dataset=RESULTS_DATASET if PUSH_RESULTS_DATASET_TO_HUB else None,\n",
-    "    set_default=True,\n",
-    "):\n",
-    "    if not answers_dataset:\n",
-    "        raise ValueError(\"Pass 'answers_dataset' to load the answers from it\")\n",
-    "    date = date or datetime.date.today().isoformat()\n",
-    "    results = []\n",
-    "    for answers_subset in answers_subsets:\n",
-    "        *model_id, action_type, task = answers_subset.split(\"__\")\n",
-    "        model_id = \"/\".join(model_id)\n",
-    "        ds = datasets.load_dataset(answers_dataset, answers_subset, split=\"test\")\n",
-    "        df = ds.to_pandas()\n",
-    "        df[\"correct\"] = df.apply(get_correct, axis=1)\n",
-    "        acc = df[\"correct\"].mean().item()\n",
-    "        result = df.loc[0, [\"model_id\", \"agent_action_type\", \"source\"]].to_dict()\n",
-    "        result[\"acc\"] = acc\n",
-    "        results.append(result)\n",
-    "    df = pd.DataFrame(results)\n",
-    "\n",
-    "    if push_to_hub_dataset:\n",
-    "        ds = datasets.Dataset.from_pandas(df)\n",
-    "        config = date\n",
-    "        set_default = set_default\n",
-    "        ds.push_to_hub(\n",
-    "            push_to_hub_dataset, config_name=config, set_default=set_default, commit_message=f\"Upload {config} results\"\n",
-    "        )\n",
-    "    return df"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## Evaluation dataset"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 4,
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "['gaia', 'math', 'simpleqa']\n"
-     ]
-    },
-    {
-     "data": {
-      "text/html": [
-       "<div>\n",
-       "<style scoped>\n",
-       "    .dataframe tbody tr th:only-of-type {\n",
-       "        vertical-align: middle;\n",
-       "    }\n",
-       "\n",
-       "    .dataframe tbody tr th {\n",
-       "        vertical-align: top;\n",
-       "    }\n",
-       "\n",
-       "    .dataframe thead th {\n",
-       "        text-align: right;\n",
-       "    }\n",
-       "</style>\n",
-       "<table border=\"1\" class=\"dataframe\">\n",
-       "  <thead>\n",
-       "    <tr style=\"text-align: right;\">\n",
-       "      <th></th>\n",
-       "      <th>question</th>\n",
-       "      <th>source</th>\n",
-       "      <th>true_answer</th>\n",
-       "      <th>true_reasoning</th>\n",
-       "    </tr>\n",
-       "  </thead>\n",
-       "  <tbody>\n",
-       "    <tr>\n",
-       "      <th>0</th>\n",
-       "      <td>What year was the municipality of Ramiriquí, B...</td>\n",
-       "      <td>SimpleQA</td>\n",
-       "      <td>1541</td>\n",
-       "      <td>['https://en.wikipedia.org/wiki/Ramiriqu%C3%AD...</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>1</th>\n",
-       "      <td>In what year did Hjalmar Hvam invent a mechani...</td>\n",
-       "      <td>SimpleQA</td>\n",
-       "      <td>1937</td>\n",
-       "      <td>['https://www.kgw.com/article/features/portlan...</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>2</th>\n",
-       "      <td>In which year did Fayaz A. Malik (an Indian ph...</td>\n",
-       "      <td>SimpleQA</td>\n",
-       "      <td>2009</td>\n",
-       "      <td>['https://en.wikipedia.org/wiki/Fayaz_A._Malik...</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>3</th>\n",
-       "      <td>In which year was John B. Goodenough elected a...</td>\n",
-       "      <td>SimpleQA</td>\n",
-       "      <td>2010</td>\n",
-       "      <td>['https://en.wikipedia.org/wiki/John_B._Gooden...</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>4</th>\n",
-       "      <td>In which year did Atul Gawande earn an M.A. in...</td>\n",
-       "      <td>SimpleQA</td>\n",
-       "      <td>1989</td>\n",
-       "      <td>['https://en.wikipedia.org/wiki/Atul_Gawande',...</td>\n",
-       "    </tr>\n",
-       "  </tbody>\n",
-       "</table>\n",
-       "</div>"
-      ],
-      "text/plain": [
-       "                                            question    source true_answer  \\\n",
-       "0  What year was the municipality of Ramiriquí, B...  SimpleQA        1541   \n",
-       "1  In what year did Hjalmar Hvam invent a mechani...  SimpleQA        1937   \n",
-       "2  In which year did Fayaz A. Malik (an Indian ph...  SimpleQA        2009   \n",
-       "3  In which year was John B. Goodenough elected a...  SimpleQA        2010   \n",
-       "4  In which year did Atul Gawande earn an M.A. in...  SimpleQA        1989   \n",
-       "\n",
-       "                                      true_reasoning  \n",
-       "0  ['https://en.wikipedia.org/wiki/Ramiriqu%C3%AD...  \n",
-       "1  ['https://www.kgw.com/article/features/portlan...  \n",
-       "2  ['https://en.wikipedia.org/wiki/Fayaz_A._Malik...  \n",
-       "3  ['https://en.wikipedia.org/wiki/John_B._Gooden...  \n",
-       "4  ['https://en.wikipedia.org/wiki/Atul_Gawande',...  "
-      ]
-     },
-     "execution_count": 4,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "import pandas as pd\n",
-    "\n",
-    "\n",
-    "# Choose the tasks to evaluate on:\n",
-    "# tasks = [\"gaia\"]\n",
-    "# or evaluate on all tasks: [\"gaia\", \"math\", \"simpleqa\"]\n",
-    "tasks = datasets.get_dataset_config_names(EVAL_DATASET)\n",
-    "print(tasks)\n",
-    "\n",
-    "\n",
-    "eval_ds = {task: datasets.load_dataset(EVAL_DATASET, task, split=\"test\") for task in tasks}\n",
-    "pd.DataFrame(eval_ds[\"simpleqa\"]).head()"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## Benchmark agents\n",
-    "\n",
-    "### Open models"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "open_model_ids = [\n",
-    "    \"meta-llama/Llama-3.3-70B-Instruct\",\n",
-    "    # \"Qwen/QwQ-32B-Preview\",\n",
-    "    \"Qwen/Qwen2.5-72B-Instruct\",\n",
-    "    \"Qwen/Qwen2.5-Coder-32B-Instruct\",\n",
-    "    \"meta-llama/Llama-3.2-3B-Instruct\",\n",
-    "    \"meta-llama/Llama-3.1-8B-Instruct\",\n",
-    "    \"mistralai/Mistral-Nemo-Instruct-2407\",\n",
-    "    # \"HuggingFaceTB/SmolLM2-1.7B-Instruct\",\n",
-    "    # \"meta-llama/Llama-3.1-70B-Instruct\",\n",
-    "]\n",
-    "\n",
-    "\n",
-    "for model_id in open_model_ids:\n",
-    "    print(f\"Evaluating '{model_id}'...\")\n",
-    "    # action_type = \"tool-calling\"\n",
-    "    # agent = ToolCallingAgent(\n",
-    "    #     tools=[GoogleSearchTool(), VisitWebpageTool(), PythonInterpreterTool()],\n",
-    "    #     model=HfApiModel(model_id),\n",
-    "    #     max_steps=10,\n",
-    "    # )\n",
-    "    # answer_questions(eval_ds, agent, model_id, action_type)\n",
-    "\n",
-    "    action_type = \"code\"\n",
-    "    agent = CodeAgent(\n",
-    "        tools=[GoogleSearchTool(), VisitWebpageTool()],\n",
-    "        model=HfApiModel(model_id),\n",
-    "        additional_authorized_imports=[\"numpy\", \"sympy\"],\n",
-    "        max_steps=10,\n",
-    "    )\n",
-    "    answer_questions(eval_ds, agent, model_id, action_type)\n",
-    "\n",
-    "    # Also evaluate vanilla model\n",
-    "    action_type = \"vanilla\"\n",
-    "    llm = HfApiModel(model_id)\n",
-    "    answer_questions(eval_ds, llm, model_id, action_type, is_vanilla_llm=True)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "### Closed models"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "from smolagents import LiteLLMModel\n",
-    "\n",
-    "\n",
-    "litellm_model_ids = [\"gpt-4o\", \"anthropic/claude-3-5-sonnet-latest\"]\n",
-    "\n",
-    "\n",
-    "for model_id in litellm_model_ids:\n",
-    "    print(f\"Evaluating '{model_id}'...\")\n",
-    "    action_type = \"tool-calling\"\n",
-    "    agent = ToolCallingAgent(\n",
-    "        tools=[\n",
-    "            GoogleSearchTool(),\n",
-    "            VisitWebpageTool(),\n",
-    "            PythonInterpreterTool([\"numpy\", \"sympy\"]),\n",
-    "        ],\n",
-    "        model=LiteLLMModel(model_id),\n",
-    "        max_steps=10,\n",
-    "    )\n",
-    "    answer_questions(eval_ds, agent, model_id, action_type)\n",
-    "\n",
-    "    action_type = \"code\"\n",
-    "    agent = CodeAgent(\n",
-    "        tools=[GoogleSearchTool(), VisitWebpageTool()],\n",
-    "        model=LiteLLMModel(model_id),\n",
-    "        additional_authorized_imports=[\"numpy\", \"sympy\"],\n",
-    "        max_steps=10,\n",
-    "    )\n",
-    "    answer_questions(eval_ds, agent, model_id, action_type)\n",
-    "\n",
-    "    # Also evaluate vanilla model\n",
-    "    action_type = \"vanilla\"\n",
-    "    llm = LiteLLMModel(model_id)\n",
-    "    answer_questions(eval_ds, llm, model_id, action_type, is_vanilla_llm=True)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 8,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "# import glob\n",
-    "# import json\n",
-    "\n",
-    "# jsonl_files = glob.glob(f\"output/*.jsonl\")\n",
-    "\n",
-    "# for file_path in jsonl_files:\n",
-    "#     if \"-Nemo-\" in file_path and \"-vanilla-\" in file_path:\n",
-    "#         print(file_path)\n",
-    "#         # Read all lines and filter out SimpleQA sources\n",
-    "#         filtered_lines = []\n",
-    "#         removed = 0\n",
-    "#         with open(file_path, \"r\", encoding=\"utf-8\") as f:\n",
-    "#             for line in f:\n",
-    "#                 try:\n",
-    "#                     data = json.loads(line.strip())\n",
-    "#                     data[\"answer\"] = data[\"answer\"][\"content\"]\n",
-    "#                     # if not any([question in data[\"question\"] for question in eval_ds[\"question\"]]):\n",
-    "#                     #     removed +=1\n",
-    "#                     # else:\n",
-    "#                     filtered_lines.append(json.dumps(data) + \"\\n\")\n",
-    "#                 except json.JSONDecodeError:\n",
-    "#                     print(\"Invalid line:\", line)\n",
-    "#                     continue  # Skip invalid JSON lines\n",
-    "#         print(f\"Removed {removed} lines.\")\n",
-    "#         # Write filtered content back to the same file\n",
-    "#         with open(\n",
-    "#             str(file_path).replace(\"-vanilla-\", \"-vanilla2-\"), \"w\", encoding=\"utf-8\"\n",
-    "#         ) as f:\n",
-    "#             f.writelines(filtered_lines)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## Score answers"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 9,
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Number of answers_subsets 54\n",
-      "Example of answers_subset Qwen__Qwen2.5-72B-Instruct__code__gaia\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
-      "/tmp/ipykernel_640885/2542893079.py:194: UserWarning: Answer lists have different lengths, returning False.\n",
-      "  warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n"
-     ]
-    },
-    {
-     "data": {
-      "text/html": [
-       "<div>\n",
-       "<style scoped>\n",
-       "    .dataframe tbody tr th:only-of-type {\n",
-       "        vertical-align: middle;\n",
-       "    }\n",
-       "\n",
-       "    .dataframe tbody tr th {\n",
-       "        vertical-align: top;\n",
-       "    }\n",
-       "\n",
-       "    .dataframe thead th {\n",
-       "        text-align: right;\n",
-       "    }\n",
-       "</style>\n",
-       "<table border=\"1\" class=\"dataframe\">\n",
-       "  <thead>\n",
-       "    <tr style=\"text-align: right;\">\n",
-       "      <th></th>\n",
-       "      <th>model_id</th>\n",
-       "      <th>agent_action_type</th>\n",
-       "      <th>source</th>\n",
-       "      <th>acc</th>\n",
-       "    </tr>\n",
-       "  </thead>\n",
-       "  <tbody>\n",
-       "    <tr>\n",
-       "      <th>0</th>\n",
-       "      <td>Qwen/Qwen2.5-72B-Instruct</td>\n",
-       "      <td>code</td>\n",
-       "      <td>GAIA</td>\n",
-       "      <td>28.12</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>1</th>\n",
-       "      <td>Qwen/Qwen2.5-72B-Instruct</td>\n",
-       "      <td>code</td>\n",
-       "      <td>MATH</td>\n",
-       "      <td>76.00</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>2</th>\n",
-       "      <td>Qwen/Qwen2.5-72B-Instruct</td>\n",
-       "      <td>code</td>\n",
-       "      <td>SimpleQA</td>\n",
-       "      <td>88.00</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>3</th>\n",
-       "      <td>Qwen/Qwen2.5-72B-Instruct</td>\n",
-       "      <td>vanilla</td>\n",
-       "      <td>GAIA</td>\n",
-       "      <td>6.25</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>4</th>\n",
-       "      <td>Qwen/Qwen2.5-72B-Instruct</td>\n",
-       "      <td>vanilla</td>\n",
-       "      <td>MATH</td>\n",
-       "      <td>30.00</td>\n",
-       "    </tr>\n",
-       "  </tbody>\n",
-       "</table>\n",
-       "</div>"
-      ],
-      "text/plain": [
-       "                    model_id agent_action_type    source    acc\n",
-       "0  Qwen/Qwen2.5-72B-Instruct              code      GAIA  28.12\n",
-       "1  Qwen/Qwen2.5-72B-Instruct              code      MATH  76.00\n",
-       "2  Qwen/Qwen2.5-72B-Instruct              code  SimpleQA  88.00\n",
-       "3  Qwen/Qwen2.5-72B-Instruct           vanilla      GAIA   6.25\n",
-       "4  Qwen/Qwen2.5-72B-Instruct           vanilla      MATH  30.00"
-      ]
-     },
-     "execution_count": 8,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "import datasets\n",
-    "import pandas as pd\n",
-    "\n",
-    "\n",
-    "# Choose the answers subsets to score:\n",
-    "# answers_subsets = [\"meta-llama__Llama-3.1-8B-Instruct__code__gaia\"]\n",
-    "# or get all the answers subsets present in the ANSWERS_DATASET\n",
-    "answers_subsets = datasets.get_dataset_config_names(ANSWERS_DATASET)\n",
-    "print(\"Number of answers_subsets\", len(answers_subsets))\n",
-    "print(\"Example of answers_subset\", answers_subsets[0])\n",
-    "\n",
-    "\n",
-    "result_df = score_answers(answers_subsets)\n",
-    "result_df[\"acc\"] = (result_df[\"acc\"] * 100).round(2)\n",
-    "result_df.head()"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 10,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "pivot_df = result_df.pivot_table(\n",
-    "    index=[\"model_id\", \"source\"],\n",
-    "    columns=[\"action_type\"],\n",
-    "    values=\"correct\",\n",
-    "    fill_value=float(\"nan\"),\n",
-    ").reset_index()"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "### Display results"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 11,
-   "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/html": [
-       "<div>\n",
-       "<style scoped>\n",
-       "    .dataframe tbody tr th:only-of-type {\n",
-       "        vertical-align: middle;\n",
-       "    }\n",
-       "\n",
-       "    .dataframe tbody tr th {\n",
-       "        vertical-align: top;\n",
-       "    }\n",
-       "\n",
-       "    .dataframe thead th {\n",
-       "        text-align: right;\n",
-       "    }\n",
-       "</style>\n",
-       "<table border=\"1\" class=\"dataframe\">\n",
-       "  <thead>\n",
-       "    <tr style=\"text-align: right;\">\n",
-       "      <th>action_type</th>\n",
-       "      <th>model_id</th>\n",
-       "      <th>source</th>\n",
-       "      <th>code</th>\n",
-       "      <th>vanilla</th>\n",
-       "    </tr>\n",
-       "  </thead>\n",
-       "  <tbody>\n",
-       "    <tr>\n",
-       "      <th>0</th>\n",
-       "      <td>Qwen/Qwen2.5-72B-Instruct</td>\n",
-       "      <td>GAIA</td>\n",
-       "      <td>28.1</td>\n",
-       "      <td>6.2</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>1</th>\n",
-       "      <td>Qwen/Qwen2.5-72B-Instruct</td>\n",
-       "      <td>MATH</td>\n",
-       "      <td>76.0</td>\n",
-       "      <td>30.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>2</th>\n",
-       "      <td>Qwen/Qwen2.5-72B-Instruct</td>\n",
-       "      <td>SimpleQA</td>\n",
-       "      <td>88.0</td>\n",
-       "      <td>10.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>3</th>\n",
-       "      <td>Qwen/Qwen2.5-Coder-32B-Instruct</td>\n",
-       "      <td>GAIA</td>\n",
-       "      <td>25.0</td>\n",
-       "      <td>3.1</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>4</th>\n",
-       "      <td>Qwen/Qwen2.5-Coder-32B-Instruct</td>\n",
-       "      <td>MATH</td>\n",
-       "      <td>86.0</td>\n",
-       "      <td>60.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>5</th>\n",
-       "      <td>Qwen/Qwen2.5-Coder-32B-Instruct</td>\n",
-       "      <td>SimpleQA</td>\n",
-       "      <td>86.0</td>\n",
-       "      <td>8.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>6</th>\n",
-       "      <td>anthropic/claude-3-5-sonnet-latest</td>\n",
-       "      <td>GAIA</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>3.1</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>7</th>\n",
-       "      <td>anthropic/claude-3-5-sonnet-latest</td>\n",
-       "      <td>MATH</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>50.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>8</th>\n",
-       "      <td>anthropic/claude-3-5-sonnet-latest</td>\n",
-       "      <td>SimpleQA</td>\n",
-       "      <td>NaN</td>\n",
-       "      <td>34.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>9</th>\n",
-       "      <td>gpt-4o</td>\n",
-       "      <td>GAIA</td>\n",
-       "      <td>25.6</td>\n",
-       "      <td>3.1</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>10</th>\n",
-       "      <td>gpt-4o</td>\n",
-       "      <td>MATH</td>\n",
-       "      <td>58.0</td>\n",
-       "      <td>40.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>11</th>\n",
-       "      <td>gpt-4o</td>\n",
-       "      <td>SimpleQA</td>\n",
-       "      <td>86.0</td>\n",
-       "      <td>6.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>12</th>\n",
-       "      <td>meta-llama/Llama-3.1-8B-Instruct</td>\n",
-       "      <td>GAIA</td>\n",
-       "      <td>3.1</td>\n",
-       "      <td>0.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>13</th>\n",
-       "      <td>meta-llama/Llama-3.1-8B-Instruct</td>\n",
-       "      <td>MATH</td>\n",
-       "      <td>14.0</td>\n",
-       "      <td>18.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>14</th>\n",
-       "      <td>meta-llama/Llama-3.1-8B-Instruct</td>\n",
-       "      <td>SimpleQA</td>\n",
-       "      <td>2.0</td>\n",
-       "      <td>6.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>15</th>\n",
-       "      <td>meta-llama/Llama-3.2-3B-Instruct</td>\n",
-       "      <td>GAIA</td>\n",
-       "      <td>3.1</td>\n",
-       "      <td>0.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>16</th>\n",
-       "      <td>meta-llama/Llama-3.2-3B-Instruct</td>\n",
-       "      <td>MATH</td>\n",
-       "      <td>40.0</td>\n",
-       "      <td>12.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>17</th>\n",
-       "      <td>meta-llama/Llama-3.2-3B-Instruct</td>\n",
-       "      <td>SimpleQA</td>\n",
-       "      <td>20.0</td>\n",
-       "      <td>0.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>18</th>\n",
-       "      <td>meta-llama/Llama-3.3-70B-Instruct</td>\n",
-       "      <td>GAIA</td>\n",
-       "      <td>31.2</td>\n",
-       "      <td>3.1</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>19</th>\n",
-       "      <td>meta-llama/Llama-3.3-70B-Instruct</td>\n",
-       "      <td>MATH</td>\n",
-       "      <td>72.0</td>\n",
-       "      <td>40.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>20</th>\n",
-       "      <td>meta-llama/Llama-3.3-70B-Instruct</td>\n",
-       "      <td>SimpleQA</td>\n",
-       "      <td>78.0</td>\n",
-       "      <td>12.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>21</th>\n",
-       "      <td>mistralai/Mistral-Nemo-Instruct-2407</td>\n",
-       "      <td>GAIA</td>\n",
-       "      <td>0.0</td>\n",
-       "      <td>3.1</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>22</th>\n",
-       "      <td>mistralai/Mistral-Nemo-Instruct-2407</td>\n",
-       "      <td>MATH</td>\n",
-       "      <td>30.0</td>\n",
-       "      <td>22.0</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>23</th>\n",
-       "      <td>mistralai/Mistral-Nemo-Instruct-2407</td>\n",
-       "      <td>SimpleQA</td>\n",
-       "      <td>30.0</td>\n",
-       "      <td>6.0</td>\n",
-       "    </tr>\n",
-       "  </tbody>\n",
-       "</table>\n",
-       "</div>"
-      ],
-      "text/plain": [
-       "action_type                              model_id    source  code  vanilla\n",
-       "0                       Qwen/Qwen2.5-72B-Instruct      GAIA  28.1      6.2\n",
-       "1                       Qwen/Qwen2.5-72B-Instruct      MATH  76.0     30.0\n",
-       "2                       Qwen/Qwen2.5-72B-Instruct  SimpleQA  88.0     10.0\n",
-       "3                 Qwen/Qwen2.5-Coder-32B-Instruct      GAIA  25.0      3.1\n",
-       "4                 Qwen/Qwen2.5-Coder-32B-Instruct      MATH  86.0     60.0\n",
-       "5                 Qwen/Qwen2.5-Coder-32B-Instruct  SimpleQA  86.0      8.0\n",
-       "6              anthropic/claude-3-5-sonnet-latest      GAIA   NaN      3.1\n",
-       "7              anthropic/claude-3-5-sonnet-latest      MATH   NaN     50.0\n",
-       "8              anthropic/claude-3-5-sonnet-latest  SimpleQA   NaN     34.0\n",
-       "9                                          gpt-4o      GAIA  25.6      3.1\n",
-       "10                                         gpt-4o      MATH  58.0     40.0\n",
-       "11                                         gpt-4o  SimpleQA  86.0      6.0\n",
-       "12               meta-llama/Llama-3.1-8B-Instruct      GAIA   3.1      0.0\n",
-       "13               meta-llama/Llama-3.1-8B-Instruct      MATH  14.0     18.0\n",
-       "14               meta-llama/Llama-3.1-8B-Instruct  SimpleQA   2.0      6.0\n",
-       "15               meta-llama/Llama-3.2-3B-Instruct      GAIA   3.1      0.0\n",
-       "16               meta-llama/Llama-3.2-3B-Instruct      MATH  40.0     12.0\n",
-       "17               meta-llama/Llama-3.2-3B-Instruct  SimpleQA  20.0      0.0\n",
-       "18              meta-llama/Llama-3.3-70B-Instruct      GAIA  31.2      3.1\n",
-       "19              meta-llama/Llama-3.3-70B-Instruct      MATH  72.0     40.0\n",
-       "20              meta-llama/Llama-3.3-70B-Instruct  SimpleQA  78.0     12.0\n",
-       "21           mistralai/Mistral-Nemo-Instruct-2407      GAIA   0.0      3.1\n",
-       "22           mistralai/Mistral-Nemo-Instruct-2407      MATH  30.0     22.0\n",
-       "23           mistralai/Mistral-Nemo-Instruct-2407  SimpleQA  30.0      6.0"
-      ]
-     },
-     "metadata": {},
-     "output_type": "display_data"
-    }
-   ],
-   "source": [
-    "display(pivot_df)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 16,
-   "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "image/png": "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9bPPPnvsd2eddVYu+7Lemnq8QRAEQRAEQRAEQRAEQRAEQTDdDG2EeuHChelRj3pUevOb35zOPffc9L3vfS996lOfSvvtt99M31oQBEEQBEEQBEEQBEEQBEGwDjO0NdaxdOnSHFg/+eST06JFi9KznvWs9PSnP32mbysIgiAIgiAIgiAIgiAIgiBYhxnajPWStf6e97wn/epXv0qnn356BNVnKf/973/zi2rvf//7pzvf+c7poQ99aPrkJz+Z6+sHQT+ELAVTgZdjf/nLXx77+alPfWo69NBDp+36t7/97fNLu4N1h6uvvjodf/zxPR1Lvz3ykY+cVpkMhmO+O/HEEyf89695zWvyB2SHXgvWTUKWgkES8hQMkloe+rHV++W4445LD3jAA3o6NuQyCIKRCqwHs59///vf6fGPf3z661//mt73vvelb33rW+kFL3hBOvroo9MBBxyQVq5cOdO3GIwIIUvBVPHtb387HXHEETN2/R/96Edpl112mbHrB9PPZz7zmfTVr361p2OVyTvvvPOm/J6C4eL9739/Ou2002b6NoJZQMhSMEhCnoJBctBBB+XPMNnqz3zmMyOZIQiCccwb/2MQTC/vfOc7001vetP08Y9/PM2dOzf/btttt00777xzzjb+4he/mPbZZ5+Zvs1gBAhZCqaKma6YtuWWW87o9YPhlbm///3v6XOf+1y6zW1uM+X3FAwXM62XgtlDyFIwSEKegkGy8cYbD53cbbTRRtN2rSAIRoPIWA9mjMsvvzy/lPbZz372WCC0sM0226THPvax6Utf+lLafffd06mnnjr23YMe9KD06le/euznD37wg+kVr3hF/vcf//jHvDXrTne6U3rwgx+cs5ULVpZf/vKXpze96U3pLne5S7rHPe6RjjzyyGl51mBqCVkKeuGss85KT37yk3OZIAsu5OU///lP3v6prz/84Q+nu93tbmm33XZL73rXu7KRrgTLa1/72vTPf/4zl2S58MILx3ZI7L///mmnnXbK8vHjH/947DqOO+SQQ/K5nve85+XfKWnm2q5rq6mFnoItrkoYOZa8eXH3L3/5y5alYJYsWZLe+MY35nP7vOENb0jXXXfdNLZi0A8XXHBBLmNH5h7+8Ifn0lT6n8yRB5l9diPc7373S8cee2z+G98ddthh6ec//3nu+06QhRe+8IVp8803X+s759lr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",
-      "text/plain": [
-       "<Figure size 1500x600 with 1 Axes>"
-      ]
-     },
-     "metadata": {},
-     "output_type": "display_data"
-    },
-    {
-     "ename": "",
-     "evalue": "",
-     "output_type": "error",
-     "traceback": [
-      "\u001b[1;31mnotebook controller is DISPOSED. \n",
-      "\u001b[1;31mView Jupyter <a href='command:jupyter.viewOutput'>log</a> for further details."
-     ]
-    }
-   ],
-   "source": [
-    "import matplotlib.pyplot as plt\n",
-    "import numpy as np\n",
-    "import pandas as pd\n",
-    "from matplotlib.legend_handler import HandlerTuple  # Added import\n",
-    "\n",
-    "\n",
-    "# Assuming pivot_df is your original dataframe\n",
-    "models = pivot_df[\"model_id\"].unique()\n",
-    "sources = pivot_df[\"source\"].unique()\n",
-    "\n",
-    "# Create figure and axis\n",
-    "plt.style.use(\"seaborn-v0_8-white\")\n",
-    "fig, ax = plt.subplots(figsize=(15, 6))\n",
-    "\n",
-    "# Set the width of each bar group and positions of the bars\n",
-    "width = 0.15  # width of each bar\n",
-    "spacing = 0.02  # space between bars within a group\n",
-    "group_spacing = 0.2  # space between model groups\n",
-    "\n",
-    "# Calculate positions for the bars\n",
-    "num_sources = len(sources)\n",
-    "total_width_per_group = (width + spacing) * num_sources * 2  # *2 for agent and vanilla\n",
-    "x = np.arange(len(models)) * (total_width_per_group + group_spacing)\n",
-    "\n",
-    "# Plot bars for each source\n",
-    "for i, source in enumerate(sources):\n",
-    "    source_data = pivot_df[pivot_df[\"source\"] == source]\n",
-    "    agent_scores = [\n",
-    "        source_data[source_data[\"model_id\"] == model][\"code\"].values[0]\n",
-    "        if len(source_data[source_data[\"model_id\"] == model]) > 0\n",
-    "        else np.nan\n",
-    "        for model in models\n",
-    "    ]\n",
-    "    vanilla_scores = [\n",
-    "        source_data[source_data[\"model_id\"] == model][\"vanilla\"].values[0]\n",
-    "        if len(source_data[source_data[\"model_id\"] == model]) > 0\n",
-    "        else np.nan\n",
-    "        for model in models\n",
-    "    ]\n",
-    "\n",
-    "    # Position calculation for each pair of bars\n",
-    "    pos = x + i * (width * 2 + spacing)\n",
-    "\n",
-    "    agent_bars = ax.bar(pos, agent_scores, width, label=f\"{source} (Agent)\", alpha=0.8)\n",
-    "    vanilla_bars = ax.bar(\n",
-    "        pos + width * 0.6,\n",
-    "        vanilla_scores,\n",
-    "        width,\n",
-    "        hatch=\"////\",\n",
-    "        alpha=0.5,\n",
-    "        hatch_linewidth=2,\n",
-    "        label=f\"{source} (Vanilla)\",\n",
-    "        color=\"white\",\n",
-    "        edgecolor=agent_bars[0].get_facecolor(),\n",
-    "    )\n",
-    "\n",
-    "# Customize the plot\n",
-    "ax.set_ylabel(\"Score\")\n",
-    "ax.set_title(\"Model Performance Comparison\")\n",
-    "\n",
-    "# Set x-axis ticks in the middle of each group\n",
-    "group_centers = x + (total_width_per_group - spacing) / 2\n",
-    "ax.set_xticks(group_centers)\n",
-    "\n",
-    "# Wrap long model names to prevent overlap\n",
-    "wrapped_labels = [\"\\n\".join(model.split(\"/\")) for model in models]\n",
-    "ax.set_xticklabels(wrapped_labels, rotation=0, ha=\"center\")\n",
-    "\n",
-    "# Modify legend to combine agent and vanilla entries\n",
-    "handles, labels = ax.get_legend_handles_labels()\n",
-    "unique_sources = sources\n",
-    "legend_elements = [\n",
-    "    (handles[i * 2], handles[i * 2 + 1], labels[i * 2].replace(\" (Agent)\", \"\")) for i in range(len(unique_sources))\n",
-    "]\n",
-    "custom_legend = ax.legend(\n",
-    "    [(agent_handle, vanilla_handle) for agent_handle, vanilla_handle, _ in legend_elements],\n",
-    "    [label for _, _, label in legend_elements],\n",
-    "    handler_map={tuple: HandlerTuple(ndivide=None)},\n",
-    "    bbox_to_anchor=(1.05, 1),\n",
-    "    loc=\"upper left\",\n",
-    ")\n",
-    "\n",
-    "ax.yaxis.grid(True, linestyle=\"--\", alpha=0.3)\n",
-    "ax.set_ylim(bottom=0)\n",
-    "plt.tight_layout()\n",
-    "ax.spines[\"top\"].set_visible(False)\n",
-    "ax.spines[\"right\"].set_visible(False)\n",
-    "\n",
-    "plt.show()"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [
-    {
-     "ename": "NameError",
-     "evalue": "name 'formatted_df' is not defined",
-     "output_type": "error",
-     "traceback": [
-      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
-      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
-      "Cell \u001b[0;32mIn[12], line 45\u001b[0m\n\u001b[1;32m     41\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m mathjax_table\n\u001b[1;32m     44\u001b[0m \u001b[38;5;66;03m# Usage (after running your previous data processing code):\u001b[39;00m\n\u001b[0;32m---> 45\u001b[0m mathjax_table \u001b[38;5;241m=\u001b[39m create_mathjax_table(pivot_df, \u001b[43mformatted_df\u001b[49m)\n\u001b[1;32m     46\u001b[0m \u001b[38;5;28mprint\u001b[39m(mathjax_table)\n",
-      "\u001b[0;31mNameError\u001b[0m: name 'formatted_df' is not defined"
-     ]
-    }
-   ],
-   "source": [
-    "def create_mathjax_table(pivot_df, formatted_df):\n",
-    "    # Start the matrix environment with 4 columns\n",
-    "    # l for left-aligned model and task, c for centered numbers\n",
-    "    mathjax_table = \"\\\\begin{array}{llcc}\\n\"\n",
-    "    mathjax_table += \"\\\\text{Model} & \\\\text{Task} & \\\\text{Agent} & \\\\text{Vanilla} \\\\\\\\\\n\"\n",
-    "    mathjax_table += \"\\\\hline\\n\"\n",
-    "\n",
-    "    # Sort the DataFrame by model_id and source\n",
-    "    formatted_df = formatted_df.sort_values([\"model_id\", \"source\"])\n",
-    "\n",
-    "    current_model = None\n",
-    "    for _, row in formatted_df.iterrows():\n",
-    "        model = row[\"model_id\"]\n",
-    "        source = row[\"source\"]\n",
-    "\n",
-    "        # Add a horizontal line between different models\n",
-    "        if current_model is not None and current_model != model:\n",
-    "            mathjax_table += \"\\\\hline\\n\"\n",
-    "\n",
-    "        # Format model name\n",
-    "        model_display = model.replace(\"_\", \"\\\\_\")\n",
-    "        if \"Qwen\" in model or \"anthropic\" in model:\n",
-    "            model_display = f\"\\\\textit{{{model_display}}}\"\n",
-    "\n",
-    "        # If it's the same model as previous row, use empty space\n",
-    "        if current_model == model:\n",
-    "            model_display = \"\\\\;\"\n",
-    "\n",
-    "        # Add the data row\n",
-    "        mathjax_table += f\"{model_display} & {source} & {row['agent']} & {row['vanilla']} \\\\\\\\\\n\"\n",
-    "\n",
-    "        current_model = model\n",
-    "\n",
-    "    mathjax_table += \"\\\\hline\\n\"\n",
-    "    mathjax_table += \"\\\\end{array}\"\n",
-    "\n",
-    "    return mathjax_table\n",
-    "\n",
-    "\n",
-    "# Usage (after running your previous data processing code):\n",
-    "# mathjax_table = create_mathjax_table(pivot_df, formatted_df)\n",
-    "# print(mathjax_table)"
-   ]
-  }
- ],
- "metadata": {
-  "kernelspec": {
-   "display_name": "test",
-   "language": "python",
-   "name": "python3"
-  },
-  "language_info": {
-   "codemirror_mode": {
-    "name": "ipython",
-    "version": 3
-   },
-   "file_extension": ".py",
-   "mimetype": "text/x-python",
-   "name": "python",
-   "nbconvert_exporter": "python",
-   "pygments_lexer": "ipython3",
-   "version": "3.12.0"
-  }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/examples/smolagents_benchmark/run.py b/examples/smolagents_benchmark/run.py
new file mode 100644
index 0000000..0939ad7
--- /dev/null
+++ b/examples/smolagents_benchmark/run.py
@@ -0,0 +1,246 @@
+import argparse
+import datetime
+import json
+import os
+import threading
+import time
+from concurrent.futures import ThreadPoolExecutor, as_completed
+from pathlib import Path
+
+import datasets
+import pandas as pd
+from dotenv import load_dotenv
+from tqdm import tqdm
+
+from smolagents import (
+    AgentError,
+    CodeAgent,
+    GoogleSearchTool,
+    HfApiModel,
+    LiteLLMModel,
+    PythonInterpreterTool,
+    ToolCallingAgent,
+    VisitWebpageTool,
+)
+from smolagents.agents import ActionStep
+
+
+load_dotenv()
+os.makedirs("output", exist_ok=True)
+
+APPEND_ANSWER_LOCK = threading.Lock()
+
+
+def parse_arguments():
+    parser = argparse.ArgumentParser(description="Runs an agent powered by the given model on smolagent benchmark.")
+    parser.add_argument(
+        "--date",
+        type=str,
+        default=None,
+        help="The date for the evaluation.",
+    )
+    parser.add_argument(
+        "--eval-dataset",
+        type=str,
+        default="smolagents/benchmark-v1",
+    )
+    # The eval dataset is gated, so you must first visit its page to request access: https://huggingface.co/datasets/smolagents-benchmark/benchmark-v1
+    parser.add_argument(
+        "--model-type",
+        type=str,
+        default="HfApiModel",
+        choices=["LiteLLMModel", "HfApiModel"],
+        help="The model type to use (LiteLLMModel or HfApiModel)",
+    )
+    parser.add_argument(
+        "--model-id",
+        type=str,
+        required=True,
+        help="The model ID to use for the specified model type",
+    )
+    parser.add_argument(
+        "--agent-action-type",
+        type=str,
+        default="code",
+        choices=["code", "tool-calling", "vanilla"],
+        help="The agent action type: 'code', 'tool-calling', or 'vanilla' to use the vanilla llm",
+    )
+    parser.add_argument(
+        "--parallel-workers",
+        type=int,
+        default=8,
+        help="The number of processes to run in parallel",
+    )
+    parser.add_argument(
+        "--push-answers-to-hub",
+        action="store_true",
+        default=False,
+        help="Push the answers to the hub",
+    )
+    parser.add_argument(
+        "--answers-dataset",
+        type=str,
+        default="smolagents/answers",
+    )
+    return parser.parse_args()
+
+
+def load_eval_dataset(eval_dataset):
+    # Choose the tasks to evaluate on:
+    # tasks = ["gaia"]
+    # or evaluate on all tasks: ["gaia", "math", "simpleqa"]
+    tasks = datasets.get_dataset_config_names(eval_dataset)
+    print(tasks)
+
+    eval_ds = {task: datasets.load_dataset(eval_dataset, task, split="test") for task in tasks}
+    print(pd.DataFrame(eval_ds["simpleqa"]).head())
+    return eval_ds
+
+
+def serialize_agent_error(obj):
+    if isinstance(obj, AgentError):
+        return {"error_type": obj.__class__.__name__, "message": obj.message}
+    else:
+        return str(obj)
+
+
+def append_answer(entry: dict, jsonl_file: str) -> None:
+    jsonl_file = Path(jsonl_file)
+    jsonl_file.parent.mkdir(parents=True, exist_ok=True)
+    with APPEND_ANSWER_LOCK, open(jsonl_file, "a", encoding="utf-8") as fp:
+        fp.write(json.dumps(entry) + "\n")
+    assert os.path.exists(jsonl_file), "File not found!"
+
+
+def answer_single_question(example, model, answers_file, action_type):
+    if action_type == "vanilla":
+        agent = model
+    elif action_type == "code":
+        agent = CodeAgent(
+            tools=[GoogleSearchTool(provider="serper"), VisitWebpageTool()],
+            model=model,
+            additional_authorized_imports=["numpy", "sympy"],
+            max_steps=10,
+        )
+    elif action_type == "tool-calling":
+        agent = ToolCallingAgent(
+            tools=[GoogleSearchTool(provider="serper"), VisitWebpageTool(), PythonInterpreterTool()],
+            model=model,
+            additional_authorized_imports=["numpy", "sympy"],
+            max_steps=10,
+        )
+
+    augmented_question = example["question"]
+    if example["source"] == "SimpleQA":
+        augmented_question += " Answer with only the final number."
+    if example["source"] == "MATH":
+        augmented_question += " Write code, not latex."
+
+    start_time = time.time()
+
+    try:
+        if action_type == "vanilla":
+            answer = agent([{"role": "user", "content": augmented_question}]).content
+            token_count = agent.last_output_token_count
+            intermediate_steps = answer
+        else:
+            # Run agent 🚀
+            answer = str(agent.run(augmented_question))
+            token_count = agent.monitor.get_total_token_counts()
+            # Remove memory from logs to make them more compact.
+            for step in agent.memory.steps:
+                if isinstance(step, ActionStep):
+                    step.agent_memory = None
+            intermediate_steps = str(agent.memory.steps)
+
+        end_time = time.time()
+    except Exception as e:
+        print("Error on ", augmented_question, e)
+        intermediate_steps = []
+    end_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+    annotated_example = {
+        "model_id": model.model_id,
+        "agent_action_type": action_type,
+        "question": augmented_question,
+        "original_question": example["question"],
+        "answer": answer,
+        "true_answer": example["true_answer"],
+        "source": example["source"],
+        "intermediate_steps": intermediate_steps,
+        "start_time": start_time,
+        "end_time": end_time,
+        "token_counts": token_count,
+    }
+    append_answer(annotated_example, answers_file)
+
+
+def answer_questions(
+    eval_ds,
+    model,
+    date,
+    action_type: str = "code",
+    output_dir: str = "output",
+    answers_dataset: str = None,
+    push_answers_to_hub: bool = False,
+    parallel_workers: int = 32,
+):
+    date = date or datetime.date.today().isoformat()
+    model_id = model.model_id
+
+    for task in eval_ds:
+        file_name = f"{output_dir}/{model_id.replace('/', '__')}__{action_type}__{task}__{date}.jsonl"
+        print(f"Starting processing and writing output to '{file_name}'")
+        answered_questions = []
+        if os.path.exists(file_name):
+            with open(file_name, "r") as f:
+                for line in f:
+                    answered_questions.append(json.loads(line)["original_question"])
+
+        examples_todo = [example for example in eval_ds[task] if example["question"] not in answered_questions]
+        print(f"Launching {parallel_workers} parallel workers.")
+
+        with ThreadPoolExecutor(max_workers=parallel_workers) as exe:
+            futures = [
+                exe.submit(answer_single_question, example, model, file_name, action_type) for example in examples_todo
+            ]
+            for f in tqdm(as_completed(futures), total=len(examples_todo), desc="Processing tasks"):
+                f.result()
+
+        print("All tasks processed.")
+
+        if push_answers_to_hub and answers_dataset:
+            print("Pushing answers to hub...")
+            ds = datasets.Dataset.from_pandas(pd.read_json(file_name, lines=True), split="test", preserve_index=False)
+            config = f"{model_id.replace('/', '__')}__{action_type}__{task}"
+            data_dir = f"{model_id}/{action_type}/{task}/{date}"
+            ds.push_to_hub(
+                answers_dataset,
+                config_name=config,
+                data_dir=data_dir,
+                split="test",
+                commit_message=f"Upload {config}",
+            )
+
+
+if __name__ == "__main__":
+    args = parse_arguments()
+
+    eval_ds = load_eval_dataset(args.eval_dataset)
+
+    if args.model_type == "LiteLLMModel":
+        model = LiteLLMModel(
+            args.model_id,
+            max_completion_tokens=8192,
+        )
+    else:
+        model = HfApiModel(args.model_id, provider="together", max_tokens=8192)
+
+    answer_questions(
+        eval_ds,
+        model,
+        args.date,
+        action_type=args.agent_action_type,
+        answers_dataset=args.answers_dataset,
+        push_answers_to_hub=args.push_answers_to_hub,
+        parallel_workers=args.parallel_workers,
+    )
diff --git a/examples/smolagents_benchmark/score.ipynb b/examples/smolagents_benchmark/score.ipynb
new file mode 100644
index 0000000..9ceb0e9
--- /dev/null
+++ b/examples/smolagents_benchmark/score.ipynb
@@ -0,0 +1,443 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!pip install -e .. datasets sympy numpy matplotlib seaborn -q  # Install dev version of smolagents + some packages"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Benchmark date\n",
+    "# - set a concrete date:\n",
+    "DATE = \"2024-12-26\"\n",
+    "# - or use default: today\n",
+    "# DATE = None\n",
+    "\n",
+    "# Evaluation dataset\n",
+    "# - the dataset is gated, so you must first visit its page to request access: https://huggingface.co/datasets/smolagents-benchmark/benchmark-v1\n",
+    "EVAL_DATASET = \"smolagents-benchmark/benchmark-v1\"\n",
+    "\n",
+    "# Answers dataset: it must be a gated dataset; required to score the answers\n",
+    "ANSWERS_DATASET = \"smolagents-benchmark/answers\"\n",
+    "# Whether to push the answers dataset to the Hub\n",
+    "PUSH_ANSWERS_DATASET_TO_HUB = True\n",
+    "\n",
+    "# Results dataset\n",
+    "RESULTS_DATASET = \"smolagents-benchmark/results\"\n",
+    "# Whether to push the results dataset to the Hub\n",
+    "PUSH_RESULTS_DATASET_TO_HUB = True"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Constants and utilities/tools"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import re\n",
+    "import string\n",
+    "import warnings\n",
+    "from concurrent.futures import ThreadPoolExecutor, as_completed\n",
+    "from datetime import datetime\n",
+    "from typing import List\n",
+    "\n",
+    "import numpy as np\n",
+    "from tqdm import tqdm\n",
+    "\n",
+    "\n",
+    "def normalize_number_str(number_str: str) -> float:\n",
+    "    # we replace these common units and commas to allow\n",
+    "    # conversion to float\n",
+    "    for char in [\"$\", \"%\", \",\"]:\n",
+    "        number_str = number_str.replace(char, \"\")\n",
+    "    try:\n",
+    "        return float(number_str)\n",
+    "    except ValueError:\n",
+    "        return float(\"inf\")\n",
+    "\n",
+    "\n",
+    "def split_string(\n",
+    "    s: str,\n",
+    "    char_list: list[str] = [\",\", \";\"],\n",
+    ") -> list[str]:\n",
+    "    pattern = f\"[{''.join(char_list)}]\"\n",
+    "    return re.split(pattern, s)\n",
+    "\n",
+    "\n",
+    "def is_float(element: any) -> bool:\n",
+    "    try:\n",
+    "        float(element)\n",
+    "        return True\n",
+    "    except ValueError:\n",
+    "        return False\n",
+    "\n",
+    "\n",
+    "def normalize_str(input_str, remove_punct=True) -> str:\n",
+    "    \"\"\"\n",
+    "    Normalize a string by:\n",
+    "    - Removing all white spaces\n",
+    "    - Optionally removing punctuation (if remove_punct is True)\n",
+    "    - Converting to lowercase\n",
+    "    Parameters:\n",
+    "    - input_str: str, the string to normalize\n",
+    "    - remove_punct: bool, whether to remove punctuation (default: True)\n",
+    "    Returns:\n",
+    "    - str, the normalized string\n",
+    "    \"\"\"\n",
+    "    # Remove all white spaces. Required e.g for seagull vs. sea gull\n",
+    "    no_spaces = re.sub(r\"\\s\", \"\", input_str)\n",
+    "\n",
+    "    # Remove punctuation, if specified.\n",
+    "    if remove_punct:\n",
+    "        translator = str.maketrans(\"\", \"\", string.punctuation)\n",
+    "        return no_spaces.lower().translate(translator)\n",
+    "    else:\n",
+    "        return no_spaces.lower()\n",
+    "\n",
+    "\n",
+    "def extract_numbers(text: str) -> List[str]:\n",
+    "    \"\"\"This pattern matches:\n",
+    "    - Optional negative sign\n",
+    "    - Numbers with optional comma thousand separators\n",
+    "    - Optional decimal points with decimal numbers\n",
+    "    \"\"\"\n",
+    "    pattern = r\"-?(?:\\d{1,3}(?:,\\d{3})+|\\d+)(?:\\.\\d+)?\"\n",
+    "\n",
+    "    return [el.replace(\",\", \"\") for el in re.findall(pattern, text)]\n",
+    "\n",
+    "\n",
+    "def get_question_score_gaia(\n",
+    "    model_answer: str,\n",
+    "    ground_truth: str,\n",
+    ") -> bool:\n",
+    "    \"\"\"Scoring function used to score functions from the GAIA benchmark\"\"\"\n",
+    "    if is_float(ground_truth):\n",
+    "        normalized_answer = normalize_number_str(str(model_answer))\n",
+    "        return normalized_answer == float(ground_truth)\n",
+    "\n",
+    "    elif any(char in ground_truth for char in [\",\", \";\"]):  # if gt is a list\n",
+    "        # question with the fish: normalization removes punct\n",
+    "        gt_elems = split_string(ground_truth)\n",
+    "        ma_elems = split_string(model_answer)\n",
+    "\n",
+    "        if len(gt_elems) != len(ma_elems):  # check length is the same\n",
+    "            warnings.warn(\"Answer lists have different lengths, returning False.\", UserWarning)\n",
+    "            return False\n",
+    "\n",
+    "        comparisons = []\n",
+    "        for ma_elem, gt_elem in zip(ma_elems, gt_elems):  # compare each element as float or str\n",
+    "            if is_float(gt_elem):\n",
+    "                normalized_ma_elem = normalize_number_str(ma_elem)\n",
+    "                comparisons.append(normalized_ma_elem == float(gt_elem))\n",
+    "            else:\n",
+    "                # we do not remove punct since comparisons can include punct\n",
+    "                comparisons.append(\n",
+    "                    normalize_str(ma_elem, remove_punct=False) == normalize_str(gt_elem, remove_punct=False)\n",
+    "                )\n",
+    "        return all(comparisons)\n",
+    "\n",
+    "    else:  # if gt is a str\n",
+    "        return normalize_str(model_answer) == normalize_str(ground_truth)\n",
+    "\n",
+    "\n",
+    "def get_correct(row):\n",
+    "    if row[\"source\"] == \"MATH\":  # Checks the last number in answer\n",
+    "        numbers_answer = extract_numbers(str(row[\"answer\"]))\n",
+    "        if len(numbers_answer) == 0:\n",
+    "            return False\n",
+    "        return np.isclose(float(numbers_answer[-1]), float(row[\"true_answer\"]), rtol=1e-5, atol=1e-7)\n",
+    "    else:\n",
+    "        return get_question_score_gaia(str(row[\"answer\"]), str(row[\"true_answer\"]))\n",
+    "\n",
+    "\n",
+    "def score_answers_subset(answers_dataset, answers_subset):\n",
+    "    try:\n",
+    "        print(answers_dataset, answers_subset)\n",
+    "        *model_id, action_type, task = answers_subset.split(\"__\")\n",
+    "        model_id = \"/\".join(model_id)\n",
+    "        ds = datasets.load_dataset(answers_dataset, answers_subset, split=\"test\")\n",
+    "        df = ds.to_pandas()\n",
+    "        df[\"correct\"] = df.apply(get_correct, axis=1)\n",
+    "        assert df[\"correct\"].notnull().sum() > 30, \"Missing answers\"\n",
+    "        acc = df[\"correct\"].mean().item()\n",
+    "        result = df.loc[0, [\"model_id\", \"agent_action_type\", \"source\"]].to_dict()\n",
+    "        result[\"acc\"] = acc\n",
+    "        return result\n",
+    "    except Exception as e:\n",
+    "        print(f\"Error with {answers_subset}: {e}\")\n",
+    "        return None\n",
+    "\n",
+    "\n",
+    "def score_answers(\n",
+    "    answers_subsets,\n",
+    "    answers_dataset=ANSWERS_DATASET,\n",
+    "    date=DATE,\n",
+    "    push_to_hub_dataset=RESULTS_DATASET if PUSH_RESULTS_DATASET_TO_HUB else None,\n",
+    "    set_default=True,\n",
+    "):\n",
+    "    if not answers_dataset:\n",
+    "        raise ValueError(\"Pass 'answers_dataset' to load the answers from it\")\n",
+    "    date = date or datetime.date.today().isoformat()\n",
+    "    results = []\n",
+    "    with ThreadPoolExecutor(max_workers=16) as exe:\n",
+    "        futures = [\n",
+    "            exe.submit(score_answers_subset, answers_dataset, answers_subset) for answers_subset in answers_subsets\n",
+    "        ]\n",
+    "        for f in tqdm(as_completed(futures), total=len(answers_subsets), desc=\"Processing tasks\"):\n",
+    "            result = f.result()\n",
+    "            if result:\n",
+    "                results.append(result)\n",
+    "    df = pd.DataFrame(results)\n",
+    "\n",
+    "    if push_to_hub_dataset:\n",
+    "        ds = datasets.Dataset.from_pandas(df)\n",
+    "        config = date\n",
+    "        set_default = set_default\n",
+    "        ds.push_to_hub(\n",
+    "            push_to_hub_dataset, config_name=config, set_default=set_default, commit_message=f\"Upload {config} results\"\n",
+    "        )\n",
+    "    return df"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Score answers"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import datasets\n",
+    "import pandas as pd\n",
+    "\n",
+    "\n",
+    "# Choose the answers subsets to score:\n",
+    "# answers_subsets = [\"meta-llama__Llama-3.1-8B-Instruct__code__gaia\"]\n",
+    "# or get all the answers subsets present in the ANSWERS_DATASET\n",
+    "answers_subsets = datasets.get_dataset_config_names(ANSWERS_DATASET)\n",
+    "print(\"Number of answers_subsets\", len(answers_subsets))\n",
+    "print(\"Example of answers_subset\", answers_subsets[0])\n",
+    "\n",
+    "result_df = score_answers(answers_subsets)\n",
+    "result_df[\"acc\"] = (result_df[\"acc\"] * 100).round(2)\n",
+    "result_df.head()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "pivot_df = result_df.pivot_table(\n",
+    "    index=[\"model_id\", \"source\"],\n",
+    "    columns=[\"agent_action_type\"],\n",
+    "    values=\"acc\",\n",
+    "    fill_value=float(\"nan\"),\n",
+    ").reset_index()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Display results"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "display(pivot_df)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import matplotlib.pyplot as plt\n",
+    "from matplotlib.legend_handler import HandlerTuple  # Added import\n",
+    "\n",
+    "\n",
+    "# Assuming pivot_df is your original dataframe\n",
+    "models = pivot_df[\"model_id\"].unique()\n",
+    "sources = pivot_df[\"source\"].unique()\n",
+    "\n",
+    "# Create figure and axis\n",
+    "plt.style.use(\"seaborn-v0_8-white\")\n",
+    "fig, ax = plt.subplots(figsize=(15, 6))\n",
+    "\n",
+    "# Set the width of each bar group and positions of the bars\n",
+    "width = 0.15  # width of each bar\n",
+    "spacing = 0.02  # space between bars within a group\n",
+    "group_spacing = 0.2  # space between model groups\n",
+    "\n",
+    "# Calculate positions for the bars\n",
+    "num_sources = len(sources)\n",
+    "total_width_per_group = (width + spacing) * num_sources * 2  # *2 for agent and vanilla\n",
+    "x = np.arange(len(models)) * (total_width_per_group + group_spacing)\n",
+    "\n",
+    "# Plot bars for each source\n",
+    "for i, source in enumerate(sources):\n",
+    "    source_data = pivot_df[pivot_df[\"source\"] == source]\n",
+    "    agent_scores = [\n",
+    "        source_data[source_data[\"model_id\"] == model][\"code\"].values[0]\n",
+    "        if len(source_data[source_data[\"model_id\"] == model]) > 0\n",
+    "        else np.nan\n",
+    "        for model in models\n",
+    "    ]\n",
+    "    vanilla_scores = [\n",
+    "        source_data[source_data[\"model_id\"] == model][\"vanilla\"].values[0]\n",
+    "        if len(source_data[source_data[\"model_id\"] == model]) > 0\n",
+    "        else np.nan\n",
+    "        for model in models\n",
+    "    ]\n",
+    "\n",
+    "    # Position calculation for each pair of bars\n",
+    "    pos = x + i * (width * 2 + spacing)\n",
+    "\n",
+    "    agent_bars = ax.bar(pos, agent_scores, width, label=f\"{source} (Agent)\", alpha=0.8)\n",
+    "    vanilla_bars = ax.bar(\n",
+    "        pos + width * 0.6,\n",
+    "        vanilla_scores,\n",
+    "        width,\n",
+    "        hatch=\"////\",\n",
+    "        alpha=0.5,\n",
+    "        hatch_linewidth=2,\n",
+    "        label=f\"{source} (Vanilla)\",\n",
+    "        color=\"white\",\n",
+    "        edgecolor=agent_bars[0].get_facecolor(),\n",
+    "    )\n",
+    "\n",
+    "# Customize the plot\n",
+    "ax.set_ylabel(\"Score\")\n",
+    "ax.set_title(\"Model Performance Comparison\")\n",
+    "\n",
+    "# Set x-axis ticks in the middle of each group\n",
+    "group_centers = x + (total_width_per_group - spacing) / 2\n",
+    "ax.set_xticks(group_centers)\n",
+    "\n",
+    "# Wrap long model names to prevent overlap\n",
+    "wrapped_labels = [\"\\n\".join(model.split(\"/\")) for model in models]\n",
+    "ax.set_xticklabels(wrapped_labels, rotation=0, ha=\"center\")\n",
+    "\n",
+    "# Modify legend to combine agent and vanilla entries\n",
+    "handles, labels = ax.get_legend_handles_labels()\n",
+    "unique_sources = sources\n",
+    "legend_elements = [\n",
+    "    (handles[i * 2], handles[i * 2 + 1], labels[i * 2].replace(\" (Agent)\", \"\")) for i in range(len(unique_sources))\n",
+    "]\n",
+    "custom_legend = ax.legend(\n",
+    "    [(agent_handle, vanilla_handle) for agent_handle, vanilla_handle, _ in legend_elements],\n",
+    "    [label for _, _, label in legend_elements],\n",
+    "    handler_map={tuple: HandlerTuple(ndivide=None)},\n",
+    "    bbox_to_anchor=(1.05, 1),\n",
+    "    loc=\"upper left\",\n",
+    ")\n",
+    "\n",
+    "ax.yaxis.grid(True, linestyle=\"--\", alpha=0.3)\n",
+    "ax.set_ylim(bottom=0)\n",
+    "plt.tight_layout()\n",
+    "ax.spines[\"top\"].set_visible(False)\n",
+    "ax.spines[\"right\"].set_visible(False)\n",
+    "\n",
+    "plt.show()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def create_mathjax_table(pivot_df, formatted_df):\n",
+    "    # Start the matrix environment with 4 columns\n",
+    "    # l for left-aligned model and task, c for centered numbers\n",
+    "    mathjax_table = \"\\\\begin{array}{llcc}\\n\"\n",
+    "    mathjax_table += \"\\\\text{Model} & \\\\text{Task} & \\\\text{Agent} & \\\\text{Vanilla} \\\\\\\\\\n\"\n",
+    "    mathjax_table += \"\\\\hline\\n\"\n",
+    "\n",
+    "    # Sort the DataFrame by model_id and source\n",
+    "    formatted_df = formatted_df.sort_values([\"model_id\", \"source\"])\n",
+    "\n",
+    "    current_model = None\n",
+    "    for _, row in formatted_df.iterrows():\n",
+    "        model = row[\"model_id\"]\n",
+    "        source = row[\"source\"]\n",
+    "\n",
+    "        # Add a horizontal line between different models\n",
+    "        if current_model is not None and current_model != model:\n",
+    "            mathjax_table += \"\\\\hline\\n\"\n",
+    "\n",
+    "        # Format model name\n",
+    "        model_display = model.replace(\"_\", \"\\\\_\")\n",
+    "        if \"Qwen\" in model or \"anthropic\" in model:\n",
+    "            model_display = f\"\\\\textit{{{model_display}}}\"\n",
+    "\n",
+    "        # If it's the same model as previous row, use empty space\n",
+    "        if current_model == model:\n",
+    "            model_display = \"\\\\;\"\n",
+    "\n",
+    "        # Add the data row\n",
+    "        mathjax_table += f\"{model_display} & {source} & {row['agent']} & {row['vanilla']} \\\\\\\\\\n\"\n",
+    "\n",
+    "        current_model = model\n",
+    "\n",
+    "    mathjax_table += \"\\\\hline\\n\"\n",
+    "    mathjax_table += \"\\\\end{array}\"\n",
+    "\n",
+    "    return mathjax_table\n",
+    "\n",
+    "\n",
+    "# Usage (after running your previous data processing code):\n",
+    "# mathjax_table = create_mathjax_table(pivot_df, formatted_df)\n",
+    "# print(mathjax_table)"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "test",
+   "language": "python",
+   "name": "test"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.12.0"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/pyproject.toml b/pyproject.toml
index 2667173..820d5d4 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
 
 [project]
 name = "smolagents"
-version = "1.10.0.dev0"
+version = "1.11.0.dev0"
 description = "🤗 smolagents: a barebones library for agents. Agents write python code to call tools or orchestrate other agents."
 authors = [
   { name="Aymeric Roucher", email="aymeric@hf.co" }, { name="Thomas Wolf"},
diff --git a/src/smolagents/__init__.py b/src/smolagents/__init__.py
index ca0b4ed..7c08d7f 100644
--- a/src/smolagents/__init__.py
+++ b/src/smolagents/__init__.py
@@ -14,7 +14,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-__version__ = "1.10.0.dev0"
+__version__ = "1.11.0.dev0"
 
 from .agent_types import *  # noqa: I001
 from .agents import *  # Above noqa avoids a circular dependency due to cli.py
diff --git a/src/smolagents/local_python_executor.py b/src/smolagents/local_python_executor.py
index 5a48f53..0dc3c1d 100644
--- a/src/smolagents/local_python_executor.py
+++ b/src/smolagents/local_python_executor.py
@@ -24,7 +24,7 @@ import re
 from collections.abc import Mapping
 from functools import wraps
 from importlib import import_module
-from types import ModuleType
+from types import BuiltinFunctionType, FunctionType, ModuleType
 from typing import Any, Callable, Dict, List, Optional, Set, Tuple
 
 import numpy as np
@@ -116,25 +116,15 @@ BASE_PYTHON_TOOLS = {
     "complex": complex,
 }
 
-DANGEROUS_PATTERNS = (
-    "_os",
-    "os",
-    "subprocess",
-    "_subprocess",
-    "pty",
-    "system",
-    "popen",
-    "spawn",
-    "shutil",
-    "sys",
-    "pathlib",
-    "io",
-    "socket",
-    "compile",
-    "eval",
-    "exec",
-    "multiprocessing",
-)
+DANGEROUS_FUNCTIONS = [
+    "builtins.compile",
+    "builtins.eval",
+    "builtins.exec",
+    "builtins.globalsbuiltins.locals",
+    "builtins.__import__",
+    "os.popen",
+    "os.system",
+]
 
 DANGEROUS_MODULES = [
     "builtins",
@@ -248,23 +238,32 @@ def safer_eval(func: Callable):
         result = func(expression, state, static_tools, custom_tools, authorized_imports=authorized_imports)
         if "*" not in authorized_imports:
             if isinstance(result, ModuleType):
-                for module in DANGEROUS_MODULES:
+                for module_name in DANGEROUS_MODULES:
                     if (
-                        module not in authorized_imports
-                        and result.__name__ == module
+                        module_name not in authorized_imports
+                        and result.__name__ == module_name
                         # builtins has no __file__ attribute
-                        and getattr(result, "__file__", "") == getattr(import_module(module), "__file__", "")
+                        and getattr(result, "__file__", "") == getattr(import_module(module_name), "__file__", "")
                     ):
-                        raise InterpreterError(f"Forbidden return value: {module}")
+                        raise InterpreterError(f"Forbidden access to module: {module_name}")
             elif isinstance(result, dict) and result.get("__name__"):
-                for module in DANGEROUS_MODULES:
+                for module_name in DANGEROUS_MODULES:
                     if (
-                        module not in authorized_imports
-                        and result["__name__"] == module
+                        module_name not in authorized_imports
+                        and result["__name__"] == module_name
                         # builtins has no __file__ attribute
-                        and result.get("__file__", "") == getattr(import_module(module), "__file__", "")
+                        and result.get("__file__", "") == getattr(import_module(module_name), "__file__", "")
+                    ):
+                        raise InterpreterError(f"Forbidden access to module: {module_name}")
+            elif isinstance(result, (FunctionType, BuiltinFunctionType)):
+                for qualified_function_name in DANGEROUS_FUNCTIONS:
+                    module_name, function_name = qualified_function_name.rsplit(".", 1)
+                    if (
+                        function_name not in static_tools
+                        and result.__name__ == function_name
+                        and result.__module__ == module_name
                     ):
-                        raise InterpreterError(f"Forbidden return value: {module}")
+                        raise InterpreterError(f"Forbidden access to function: {function_name}")
         return result
 
     return _check_return
@@ -590,14 +589,13 @@ def evaluate_assign(
         target = assign.targets[0]
         set_value(target, result, state, static_tools, custom_tools, authorized_imports)
     else:
-        if len(assign.targets) != len(result):
-            raise InterpreterError(f"Assign failed: expected {len(result)} values but got {len(assign.targets)}.")
         expanded_values = []
         for tgt in assign.targets:
             if isinstance(tgt, ast.Starred):
                 expanded_values.extend(result)
             else:
                 expanded_values.append(result)
+
         for tgt, val in zip(assign.targets, expanded_values):
             set_value(tgt, val, state, static_tools, custom_tools, authorized_imports)
     return result
@@ -641,17 +639,21 @@ def evaluate_call(
     custom_tools: Dict[str, Callable],
     authorized_imports: List[str],
 ) -> Any:
-    if not (
-        isinstance(call.func, ast.Attribute) or isinstance(call.func, ast.Name) or isinstance(call.func, ast.Subscript)
-    ):
+    if not isinstance(call.func, (ast.Call, ast.Lambda, ast.Attribute, ast.Name, ast.Subscript)):
         raise InterpreterError(f"This is not a correct function: {call.func}).")
-    if isinstance(call.func, ast.Attribute):
+
+    func, func_name = None, None
+
+    if isinstance(call.func, ast.Call):
+        func = evaluate_call(call.func, state, static_tools, custom_tools, authorized_imports)
+    elif isinstance(call.func, ast.Lambda):
+        func = evaluate_lambda(call.func, state, static_tools, custom_tools, authorized_imports)
+    elif isinstance(call.func, ast.Attribute):
         obj = evaluate_ast(call.func.value, state, static_tools, custom_tools, authorized_imports)
         func_name = call.func.attr
         if not hasattr(obj, func_name):
             raise InterpreterError(f"Object {obj} has no attribute {func_name}")
         func = getattr(obj, func_name)
-
     elif isinstance(call.func, ast.Name):
         func_name = call.func.id
         if func_name in state:
@@ -666,12 +668,12 @@ def evaluate_call(
             raise InterpreterError(
                 f"It is not permitted to evaluate other functions than the provided tools or functions defined/imported in previous code (tried to execute {call.func.id})."
             )
-
     elif isinstance(call.func, ast.Subscript):
         func = evaluate_subscript(call.func, state, static_tools, custom_tools, authorized_imports)
         if not callable(func):
             raise InterpreterError(f"This is not a correct function: {call.func}).")
         func_name = None
+
     args = []
     for arg in call.args:
         if isinstance(arg, ast.Starred):
@@ -700,20 +702,15 @@ def evaluate_call(
             return super(cls, instance)
         else:
             raise InterpreterError("super() takes at most 2 arguments")
-    else:
-        if func_name == "print":
-            state["_print_outputs"] += " ".join(map(str, args)) + "\n"
-            return None
-        else:  # Assume it's a callable object
-            if (
-                (inspect.getmodule(func) == builtins)
-                and inspect.isbuiltin(func)
-                and (func not in static_tools.values())
-            ):
-                raise InterpreterError(
-                    f"Invoking a builtin function that has not been explicitly added as a tool is not allowed ({func_name})."
-                )
-            return func(*args, **kwargs)
+    elif func_name == "print":
+        state["_print_outputs"] += " ".join(map(str, args)) + "\n"
+        return None
+    else:  # Assume it's a callable object
+        if (inspect.getmodule(func) == builtins) and inspect.isbuiltin(func) and (func not in static_tools.values()):
+            raise InterpreterError(
+                f"Invoking a builtin function that has not been explicitly added as a tool is not allowed ({func_name})."
+            )
+        return func(*args, **kwargs)
 
 
 def evaluate_subscript(
@@ -1083,15 +1080,6 @@ def get_safe_module(raw_module, authorized_imports, visited=None):
 
     # Copy all attributes by reference, recursively checking modules
     for attr_name in dir(raw_module):
-        # Skip dangerous patterns at any level
-        if any(
-            pattern in raw_module.__name__.split(".") + [attr_name]
-            and not check_module_authorized(pattern, authorized_imports)
-            for pattern in DANGEROUS_PATTERNS
-        ):
-            logger.info(f"Skipping dangerous attribute {raw_module.__name__}.{attr_name}")
-            continue
-
         try:
             attr_value = getattr(raw_module, attr_name)
         except (ImportError, AttributeError) as e:
@@ -1114,8 +1102,6 @@ def check_module_authorized(module_name, authorized_imports):
         return True
     else:
         module_path = module_name.split(".")
-        if any([module in DANGEROUS_PATTERNS and module not in authorized_imports for module in module_path]):
-            return False
         # ["A", "B", "C"] -> ["A", "A.B", "A.B.C"]
         module_subpaths = [".".join(module_path[:i]) for i in range(1, len(module_path) + 1)]
         return any(subpath in authorized_imports for subpath in module_subpaths)
@@ -1437,12 +1423,13 @@ def evaluate_python_code(
     custom_tools = custom_tools if custom_tools is not None else {}
     result = None
     state["_print_outputs"] = PrintContainer()
+    state["_operations_count"] = 0
 
     if "final_answer" in static_tools:
         previous_final_answer = static_tools["final_answer"]
 
-        def final_answer(value):
-            raise FinalAnswerException(previous_final_answer(value))
+        def final_answer(answer):  # Using 'answer' as the argument like in the original function
+            raise FinalAnswerException(previous_final_answer(answer))
 
         static_tools["final_answer"] = final_answer
 
diff --git a/src/smolagents/models.py b/src/smolagents/models.py
index 38561c5..b37c7ca 100644
--- a/src/smolagents/models.py
+++ b/src/smolagents/models.py
@@ -819,13 +819,13 @@ class TransformersModel(Model):
 
 
 class LiteLLMModel(Model):
-    """This model connects to [LiteLLM](https://www.litellm.ai/) as a gateway to hundreds of LLMs.
+    """Model to use [LiteLLM Python SDK](https://docs.litellm.ai/docs/#litellm-python-sdk) to access hundreds of LLMs.
 
     Parameters:
         model_id (`str`):
             The model identifier to use on the server (e.g. "gpt-3.5-turbo").
         api_base (`str`, *optional*):
-            The base URL of the OpenAI-compatible API server.
+            The base URL of the provider API to call the model.
         api_key (`str`, *optional*):
             The API key to use for authentication.
         custom_role_conversions (`dict[str, str]`, *optional*):
diff --git a/src/smolagents/vision_web_browser.py b/src/smolagents/vision_web_browser.py
index 46a07f9..29bcca0 100644
--- a/src/smolagents/vision_web_browser.py
+++ b/src/smolagents/vision_web_browser.py
@@ -202,7 +202,7 @@ def main():
     agent = initialize_agent(model)
 
     # Run the agent with the provided prompt
-    agent.python_executor("from helium import *", agent.state)
+    agent.python_executor("from helium import *")
     agent.run(args.prompt + helium_instructions)
 
 


Test patch:
diff --git a/tests/test_local_python_executor.py b/tests/test_local_python_executor.py
index 34b56d1..a34ac29 100644
--- a/tests/test_local_python_executor.py
+++ b/tests/test_local_python_executor.py
@@ -944,22 +944,6 @@ shift_intervals
     Got:      {result}
     """
 
-    def test_dangerous_subpackage_access_blocked(self):
-        # Direct imports with dangerous patterns should fail
-        code = "import random._os"
-        with pytest.raises(InterpreterError):
-            evaluate_python_code(code)
-
-        # Import of whitelisted modules should succeed but dangerous submodules should not exist
-        code = "import random;random._os.system('echo bad command passed')"
-        with pytest.raises(InterpreterError) as e:
-            evaluate_python_code(code)
-        assert "AttributeError: module 'random' has no attribute '_os'" in str(e)
-
-        code = "import doctest;doctest.inspect.os.system('echo bad command passed')"
-        with pytest.raises(InterpreterError):
-            evaluate_python_code(code, authorized_imports=["doctest"])
-
     def test_close_matches_subscript(self):
         code = 'capitals = {"Czech Republic": "Prague", "Monaco": "Monaco", "Bhutan": "Thimphu"};capitals["Butan"]'
         with pytest.raises(Exception) as e:
@@ -980,6 +964,11 @@ exec(compile('{unsafe_code}', 'no filename', 'exec'))
         with pytest.raises(InterpreterError):
             evaluate_python_code(dangerous_code, static_tools=BASE_PYTHON_TOOLS)
 
+    def test_final_answer_accepts_kwarg_answer(self):
+        code = "final_answer(answer=2)"
+        result, _ = evaluate_python_code(code, {"final_answer": (lambda x: 2 * x)}, state={})
+        assert result == 4
+
     def test_dangerous_builtins_are_callable_if_explicitly_added(self):
         dangerous_code = dedent("""
             eval("1 + 1")
@@ -1395,7 +1384,7 @@ class TestPrintContainer:
         ("AnyModule", ["*"], True),
         ("os", ["os"], True),
         ("AnyModule", ["AnyModule"], True),
-        ("Module.os", ["Module"], False),
+        ("Module.os", ["Module"], True),
         ("Module.os", ["Module", "os"], True),
         ("os.path", ["os"], True),
         ("os", ["os.path"], False),
@@ -1418,6 +1407,44 @@ class TestLocalPythonExecutor:
         result, _, _ = executor(code)
         assert result == 11
 
+    @pytest.mark.parametrize(
+        "code",
+        [
+            "a = b = 1; a",
+            "a = b = 1; b",
+            "a, b = c, d = 1, 1; a",
+            "a, b = c, d = 1, 1; b",
+            "a, b = c, d = 1, 1; c",
+            "a, b = c, d = {1, 2}; a",
+            "a, b = c, d = {1, 2}; c",
+            "a, b = c, d = {1: 10, 2: 20}; a",
+            "a, b = c, d = {1: 10, 2: 20}; c",
+            "a = b = (lambda: 1)(); b",
+            "a = b = (lambda: 1)(); lambda x: 10; b",
+            "a = b = (lambda x: lambda y: x + y)(0)(1); b",
+            dedent("""
+            def foo():
+                return 1;
+            a = b = foo(); b"""),
+            dedent("""
+            def foo(*args, **kwargs):
+                return sum(args)
+            a = b = foo(1,-1,1); b"""),
+            "a, b = 1, 2; a, b = b, a; b",
+        ],
+    )
+    def test_chained_assignments(self, code):
+        executor = LocalPythonExecutor([])
+        executor.send_tools({})
+        result, _, _ = executor(code)
+        assert result == 1
+
+    def test_evaluate_assign_error(self):
+        code = "a, b = 1, 2, 3; a"
+        executor = LocalPythonExecutor([])
+        with pytest.raises(InterpreterError, match=".*Cannot unpack tuple of wrong size"):
+            executor(code)
+
 
 class TestLocalPythonExecutorSecurity:
     @pytest.mark.parametrize(
@@ -1446,6 +1473,63 @@ class TestLocalPythonExecutorSecurity:
         ):
             executor("import builtins")
 
+    @pytest.mark.parametrize(
+        "additional_authorized_imports, expected_error",
+        [([], InterpreterError("Import of builtins is not allowed")), (["builtins"], None)],
+    )
+    def test_vulnerability_builtins_safe_functions(self, additional_authorized_imports, expected_error):
+        executor = LocalPythonExecutor(additional_authorized_imports)
+        with (
+            pytest.raises(type(expected_error), match=f".*{expected_error}")
+            if isinstance(expected_error, Exception)
+            else does_not_raise()
+        ):
+            executor("import builtins; builtins.print(1)")
+
+    @pytest.mark.parametrize(
+        "additional_authorized_imports, additional_tools, expected_error",
+        [
+            ([], [], InterpreterError("Import of builtins is not allowed")),
+            (["builtins"], [], InterpreterError("Forbidden access to function: exec")),
+            (["builtins"], ["exec"], None),
+        ],
+    )
+    def test_vulnerability_builtins_dangerous_functions(
+        self, additional_authorized_imports, additional_tools, expected_error
+    ):
+        executor = LocalPythonExecutor(additional_authorized_imports)
+        if additional_tools:
+            from builtins import exec
+
+            executor.send_tools({"exec": exec})
+        with (
+            pytest.raises(type(expected_error), match=f".*{expected_error}")
+            if isinstance(expected_error, Exception)
+            else does_not_raise()
+        ):
+            executor("import builtins; builtins.exec")
+
+    @pytest.mark.parametrize(
+        "additional_authorized_imports, additional_tools, expected_error",
+        [
+            ([], [], InterpreterError("Import of os is not allowed")),
+            (["os"], [], InterpreterError("Forbidden access to function: popen")),
+            (["os"], ["popen"], None),
+        ],
+    )
+    def test_vulnerability_dangerous_functions(self, additional_authorized_imports, additional_tools, expected_error):
+        executor = LocalPythonExecutor(additional_authorized_imports)
+        if additional_tools:
+            from os import popen
+
+            executor.send_tools({"popen": popen})
+        with (
+            pytest.raises(type(expected_error), match=f".*{expected_error}")
+            if isinstance(expected_error, Exception)
+            else does_not_raise()
+        ):
+            executor("import os; os.popen")
+
     @pytest.mark.parametrize(
         "additional_authorized_imports, expected_error",
         [([], InterpreterError("Import of sys is not allowed")), (["os", "sys"], None)],
@@ -1468,7 +1552,7 @@ class TestLocalPythonExecutorSecurity:
 
     @pytest.mark.parametrize(
         "additional_authorized_imports, expected_error",
-        [(["importlib"], InterpreterError("Forbidden return value: os")), (["importlib", "os"], None)],
+        [(["importlib"], InterpreterError("Forbidden access to module: os")), (["importlib", "os"], None)],
     )
     def test_vulnerability_via_importlib(self, additional_authorized_imports, expected_error):
         executor = LocalPythonExecutor(additional_authorized_imports)
@@ -1486,19 +1570,58 @@ class TestLocalPythonExecutorSecurity:
                 )
             )
 
+    @pytest.mark.parametrize(
+        "code, additional_authorized_imports, expected_error",
+        [
+            # os submodule
+            ("import queue; queue.threading._os.system(':')", [], InterpreterError("Forbidden access to module: os")),
+            ("import random; random._os.system(':')", [], InterpreterError("Forbidden access to module: os")),
+            (
+                "import random; random.__dict__['_os'].system(':')",
+                [],
+                InterpreterError("Forbidden access to module: os"),
+            ),
+            (
+                "import doctest; doctest.inspect.os.system(':')",
+                ["doctest"],
+                InterpreterError("Forbidden access to module: os"),
+            ),
+            # subprocess submodule
+            (
+                "import asyncio; asyncio.base_events.events.subprocess",
+                ["asyncio"],
+                InterpreterError("Forbidden access to module: subprocess"),
+            ),
+            # sys submodule
+            (
+                "import queue; queue.threading._sys.modules['os'].system(':')",
+                [],
+                InterpreterError("Forbidden access to module: sys"),
+            ),
+            # Allowed
+            ("import pandas; pandas.io", ["pandas"], None),
+        ],
+    )
+    def test_vulnerability_via_submodules(self, code, additional_authorized_imports, expected_error):
+        executor = LocalPythonExecutor(additional_authorized_imports)
+        with (
+            pytest.raises(type(expected_error), match=f".*{expected_error}")
+            if isinstance(expected_error, Exception)
+            else does_not_raise()
+        ):
+            executor(code)
+
     @pytest.mark.parametrize(
         "additional_authorized_imports, additional_tools, expected_error",
         [
             ([], [], InterpreterError("Import of sys is not allowed")),
-            (["sys"], [], InterpreterError("Forbidden return value: builtins")),
+            (["sys"], [], InterpreterError("Forbidden access to module: builtins")),
             (
                 ["sys", "builtins"],
                 [],
-                InterpreterError(
-                    "Invoking a builtin function that has not been explicitly added as a tool is not allowed"
-                ),
+                InterpreterError("Forbidden access to function: __import__"),
             ),
-            (["sys", "builtins"], ["__import__"], InterpreterError("Forbidden return value: os")),
+            (["sys", "builtins"], ["__import__"], InterpreterError("Forbidden access to module: os")),
             (["sys", "builtins", "os"], ["__import__"], None),
         ],
     )
@@ -1528,7 +1651,10 @@ class TestLocalPythonExecutorSecurity:
     @pytest.mark.parametrize("patch_builtin_import_module", [False, True])  # builtins_import.__module__ = None
     @pytest.mark.parametrize(
         "additional_authorized_imports, additional_tools, expected_error",
-        [([], [], InterpreterError("Forbidden return value: builtins")), (["builtins", "os"], ["__import__"], None)],
+        [
+            ([], [], InterpreterError("Forbidden access to module: builtins")),
+            (["builtins", "os"], ["__import__"], None),
+        ],
     )
     def test_vulnerability_builtins_via_traceback(
         self, patch_builtin_import_module, additional_authorized_imports, additional_tools, expected_error, monkeypatch
@@ -1562,7 +1688,10 @@ class TestLocalPythonExecutorSecurity:
     @pytest.mark.parametrize("patch_builtin_import_module", [False, True])  # builtins_import.__module__ = None
     @pytest.mark.parametrize(
         "additional_authorized_imports, additional_tools, expected_error",
-        [([], [], InterpreterError("Forbidden return value: builtins")), (["builtins", "os"], ["__import__"], None)],
+        [
+            ([], [], InterpreterError("Forbidden access to module: builtins")),
+            (["builtins", "os"], ["__import__"], None),
+        ],
     )
     def test_vulnerability_builtins_via_class_catch_warnings(
         self, patch_builtin_import_module, additional_authorized_imports, additional_tools, expected_error, monkeypatch
@@ -1597,7 +1726,7 @@ class TestLocalPythonExecutorSecurity:
     @pytest.mark.filterwarnings("ignore::DeprecationWarning")
     @pytest.mark.parametrize(
         "additional_authorized_imports, expected_error",
-        [([], InterpreterError("Forbidden return value: os")), (["os"], None)],
+        [([], InterpreterError("Forbidden access to module: os")), (["os"], None)],
     )
     def test_vulnerability_load_module_via_builtin_importer(self, additional_authorized_imports, expected_error):
         executor = LocalPythonExecutor(additional_authorized_imports)