Type something to search...
Smolagents + Web Scraper + DeepSeek V3 Python = 强大的人工智能研究代理

Smolagents + Web Scraper + DeepSeek V3 Python = 强大的人工智能研究代理

在这段视频中,我将快速演示如何使用 Smolagents、Web Scraper 和 DeepSeek V3 创建一个多代理聊天机器人,为您的业务或个人使用提供强大的代理聊天机器人。

如果您关注 AI 社区,您可能已经注意到许多关于 Nvidia 的病毒视频,其中宣布的 AI 代理价值十亿美元,或者您可能听说过 Zark 说我们明年不会招聘中级工程师。

我问自己,这怎么会发生?当我开发 AI 代理系统时,花了我很多天。构建智能代理一直是一个极其复杂且技术要求高的任务,涉及许多复杂和琐碎的步骤,如 API 集成、环境配置和依赖管理。

想象一下,在喝完一杯咖啡的时间里构建一个 AI 代理。Smolagents 让这一切成为可能。这是 Hugging Face 团队创建的新一代代理框架,它使构建 AI 变得更加简单。这对开发者来说就像是一份礼物——简单而强大。

Smolagents 看到了这一点,想要在复杂性和简单性之间找到完美的平衡。代码代理是 Smolagents 最大的特点。

最令人印象深刻的是,只需三行代码即可构建您的第一个代理。它甚至可以构建代理检索生成(Agent-RAG)系统。与功能丰富但复杂的 Crew AI 和 Autogen 不同。

在新年初,DeepSeek 推出了其最新的大规模语言模型 DeepSeek V3,一个强大的专家混合(MoE)语言模型,总参数数量为 671B。

DeepSeek V3 吸引关注的最大原因是其低价格。不要认为“便宜就意味着不好”!DeepSeek V3 价格相当低,但实现了高精度的自然语言处理。

它的性能可与 GPT-4 和 Claude 等竞争模型媲美,但价格更低。对于预算有限的公司和个人来说,这是一个非常有吸引力的选择。

用户可以自由定制,使得为特定行业和应用创建 AI 模型变得轻而易举。这种灵活性使 DeepSeek V3 与竞争对手区分开来。

那么,让我给您快速演示一个实时聊天机器人,让您了解我的意思。

我访问了一个房地产网站,抓取了代理的姓名、电话号码和公司名称。我为代理提供了深思熟虑的输入和工具,以获得更好的结果,因为我们知道 DeepSeek V3 在编码能力方面表现更好,并且在基于思维链和工具的方法上效果良好。

如果您查看 SmolAgents 生成输出的方式,您会看到我构建了一个抓取器来收集房地产代理信息——包括姓名、电话号码和公司名称。我使其灵活,以便您可以指定州、市和要抓取的页面数量。

我使用 requests 库来获取网页,并确保如果响应代码不是 200,则抓取器停止。我使用特定类在 HTML 中搜索代理姓名、电话号码和公司名称,清理数据并将其添加到列表中。如果没有找到代理,脚本将返回错误信息。

抓取后,我将数据组织成字典,并编写另一个函数将其保存为 CSV 文件。我用空字符串填充较短的项,以确保所有列表的长度相同。然后,我使用 Pandas 创建一个 DataFrame,并以 UTF-8 编码保存。如果保存成功,我将返回一个包含文件名和条目计数的消息;否则,我将返回错误。

在视频结束时,您将了解什么是 Smolagents、它的特点、为什么值得关注、Smolagents 如何工作,以及如何使用 Smolagents 创建超级 AI 代理。

免责声明:本文仅用于教育目的。我们不鼓励任何人抓取网站,特别是那些可能有反对此类行为的条款和条件的网站。

在我们开始之前!🦸🏻‍♀️

如果你喜欢这个主题并想要支持我:

  1. 我的文章点赞50次;这真的会对我有很大帮助。👏
  2. 关注我在Medium上的账号,并订阅以免费获取我的最新文章🫶
  3. 加入这个大家庭 — 订阅我的YouTube频道

什么是 SmolAgents?

Smolagents 是一个轻量级的 Python 库,使开发者能够以简约的方式构建高效的代理。它解决了代理开发中的常见痛点:繁琐的代码、低效的流程以及整合各种工具的困难。它支持安全的“以代码写出其行为的代理”,并与 Hugging Face Hub 集成。它还为您处理了许多非例行的复杂性。例如,确保系统提示、解析器和执行链接中的代码格式一致性。

为什么值得关注?

SmolAgents 旨在实现简单性和 LLM-无关的设计,专注于支持安全的代码编写代理。它还与 Hugging Face Hub 集成。

代理系统逐步摆脱传统的狭窄任务工作流程,扩展了解决更复杂现实问题的可能性。Hugging Face 的工程师表示,代理为 LLM 提供了访问外部世界的能力。

Smolagents 使用代码而不是 JSON 作为描述动作的新方式。这允许更多的组合、数据管理和多功能性。构建代理涉及诸如解析代理输出和基于先前迭代综合提示等挑战,这些都是 Smolagents 提供的关键特性之一。

Hugging Face 还与其他模型进行了基准测试,发现开放模型在与封闭模型的竞争中,在减少 30% 的步骤和 API 调用方面优于传统解决方案,同时在困难的基准测试中表现更强。

除了 Smolagents,其他公司,如 OpenAI 的 Swarm 和微软的 Magentic-One。出于安全考虑,SmolAgents 包含内置的沙盒模式以实现安全的代码执行,而其与 Hugging Face Hub 的集成则允许仅用一行代码轻松共享。

SmolAgents 的工作原理

SmolAgents 旨在兼顾可用性和效率。其直观的 API 使开发人员能够轻松构建智能代理,以完成诸如命令理解、e-source 连接、动态代码生成和执行等任务。具体功能包括:

语言理解:利用先进的自然语言处理 (NLP) 模型,SmolAgents 能够理解命令和查询。

智能搜索:连接外部数据源,以提供快速准确的搜索结果。

动态代码执行:代理可以根据需要生成和执行代码,以解决特定问题。

SmolAgents 的模块化设计使其适用于多种场景,无论是快速原型开发还是全规模生产环境应用。通过利用预训练模型,开发人员可以节省大量时间和精力,并在无需从头定制模型的情况下获得强大的性能。

开始编码

现在让我们一步一步地探索并揭开如何创建 SmolAgents 的答案。我们将安装支持该模型的库。为此,我们将执行 pip install requirements

pip install -r requirements.txt

下一步是我们通常的步骤,我们将导入相关库,其重要性会随着我们的进展而显现。

Codeagent:是默认代理。它将在每一步编写并执行 Python 代码片段。

LiteLLM Model:允许你调用 100+ 个不同的模型

tool:代理可以用来解决任务的工具列表 Tools

一旦你有了这两个参数,toolsmodel,你就可以创建一个代理并运行它。你可以通过 Hugging Face APItransformersollamaLiteLLM 使用任何你想要的 LLM。

from typing import Optional, Dict
from smolagents import CodeAgent, tool, LiteLLMModel , GradioUI
import requests
import os
import time
from bs4 import BeautifulSoup
import pandas as pd

我开始创建一个抓取函数,从一个名为 realtor.com 的网站抓取并收集房地产代理的信息。我们将获取姓名、电话号码和公司名称。

你可以指定 state(例如,“CA”代表加利福尼亚州)、city(例如,“Angeles”)和你想要抓取的页面数量。

初始化列表以存储数据,并使用头部动态模拟每个页面 URL 的浏览器请求。

然后我创建了一个循环,从第 1 页运行到所需的页面数量。对于第一页,链接很简单,第二页我们在链接中添加了页面数量。

我使用 requests 库下载网页。如果 HTTP 响应状态码 不是 200(OK),抓取器将停止并返回错误。

我们通过类 agent-name 在 HTML 中进行搜索。如果找到,去掉多余的空格并将其添加到列表中。或者检查电话号码的所有可能位置。如果找到,它会清理号码并将其添加到列表中,以及公司名称。如果没有找到代理,它将返回错误消息。否则,它将数据组织成字典并发送回去。

@tool
def scrape_realtor(state: str, city_name: str, num_pages: Optional[int] = 2) -> Dict[str, any]:
    """Scrapes realtor.com for agent information in specified city and state
    
    Args:
        state: State abbreviation (e.g., 'CA', 'NY')
        city_name: City name with hyphens instead of spaces (e.g., 'buffalo')
        num_pages: Number of pages to scrape (default: 2)
    """
    try:
        # Initialize results
        results = []         # Names
        phone_results = []   # Phone numbers
        office_results = []  # Office names
        pages_scraped = 0
        
        # Set up headers
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
            "Accept-Language": "en-US,en;q=0.5",
            "Connection": "keep-alive"
        }

        # Process pages
        for page in range(1, num_pages + 1):
            # Construct URL
            if page == 1:
                url = f'https://www.realtor.com/realestateagents/{city_name}_{state}/'
            else:
                url = f'https://www.realtor.com/realestateagents/{city_name}_{state}/pg-{page}'
            
            print(f"正在抓取第 {page} 页...")
            
            # Get page content
            r = requests.get(url, headers=headers)
            if r.status_code != 200:
                return {"error": f"无法访问第 {page} 页:状态码 {r.status_code}"}

            soup = BeautifulSoup(r.text, features="html.parser")
            
            # Find all agent cards
            agent_cards = soup.find_all('div', class_='agent-list-card')
            
            for card in agent_cards:
                # Find name
                name_elem = card.find('div', class_='agent-name')
                if name_elem:
                    name = name_elem.text.strip()
                    if name and name not in results:
                        results.append(name)
                        print(f"找到代理:{name}")

                # Find phone
                phone_elem = card.find('a', {'data-testid': 'agent-phone'}) or \
                            card.find(class_='btn-contact-me-call') or \
                            card.find('a', href=lambda x: x and x.startswith('tel:'))
                
                if phone_elem:
                    phone = phone_elem.get('href', '').replace('tel:', '').strip()
                    if phone:
                        phone_results.append(phone)
                        print(f"找到电话:{phone}")

                # Get office/company name
                office_elem = card.find('div', class_='agent-group') or \
                            card.find('div', class_='text-semibold')
                if office_elem:
                    office = office_elem.text.strip()
                    office_results.append(office)
                    print(f"找到办公室:{office}")
                else:
                    office_results.append("")
            
            pages_scraped += 1
            time.sleep(2)  # 限制请求速率

        if not results:
            return {"error": "未找到代理。网站结构可能已更改或该位置没有结果。"}

        # Return structured data
        return {
            "names": results,
            "phones": phone_results,
            "offices": office_results,
            "total_agents": len(results),
            "pages_scraped": pages_scraped,
            "city": city_name,
            "state": state
        }
        
    except Exception as e:
        return {"error": f"抓取错误:{str(e)}"}

接下来,我创建另一个函数,将抓取的房地产数据保存到 CSV 文件中。它接受一个包含抓取信息的字典 data 和一个可选的文件名。如果 data 包含错误,它将返回错误消息。

否则,它确保所有列表(namesphonesoffices)的长度相等,通过用空字符串填充较短的列表。然后从这些列表创建一个 DataFrame,并使用 UTF-8 编码写入 CSV 文件。如果操作成功,它将返回成功消息,包含文件名和保存的条目数量;否则,它将返回错误消息。

@tool
def save_to_csv(data: Dict[str, any], filename: Optional[str] = None) -> str:
    """Saves scraped realtor data to CSV file
    
    Args:
        data: Dictionary containing scraping results
        filename: Optional filename (default: cityname.csv)
    """
    try:
        if "error" in data:
            return f"错误:{data['error']}"
            
        if not filename:
            filename = f"{data['city'].replace('-', '')}.csv"
            
        # Ensure all lists are of equal length
        max_length = max(len(data['names']), len(data['phones']), len(data['offices']))
        
        # Pad shorter lists with empty strings
        data['names'].extend([""] * (max_length - len(data['names'])))
        data['phones'].extend([""] * (max_length - len(data['phones'])))
        data['offices'].extend([""] * (max_length - len(data['offices'])))
        
        # Create DataFrame with just names, phones, and offices
        df = pd.DataFrame({
            'Names': data['names'],
            'Phone': data['phones'],
            'Office': data['offices']
        })
        
        df.to_csv(filename, index=False, encoding='utf-8')
        return f"数据已保存到 {filename}。总条目:{len(df)}"
        
    except Exception as e:
        return f"保存 CSV 时出错:{str(e)}"

要使用 LiteLLMModel,你需要设置环境变量 ANTHROPIC_API_KEYOPENAI_API_KEY,或者在初始化时传递 api_key 变量。

我们默认使用 CodeAgent 来执行 Python 代码。这应该是安全的,因为可以调用的唯一函数是你提供的工具和一组预定义的安全函数或来自 math 模块的函数,因此你已经限制了可以执行的内容。

Python 解释器也不允许默认情况下在安全列表之外导入,因此所有最明显的攻击都不应该是问题。你可以通过将授权模块作为字符串列表传递的方式授权额外的导入

deepseek_model = LiteLLMModel(
        model_id="ollama/nezahatkorkmaz/deepseek-v3"
    )

    # Create agent with tools
    agent = CodeAgent(
        tools=[scrape_realtor, save_to_csv],
        model=deepseek_model,
        additional_authorized_imports=["pandas", "bs4", "time"]
    )

最后,让我们运行代理,启动代理的 Gradio 界面,并测试聊天机器人。请记住,你的提示越精确,得到的结果就会越好

 result = agent.run("""
Thought: Let's scrape realtor data
Code:
```python

## 爬取房地产数据
data = scrape_realtor(state="NY", city_name="buffalo", num_pages=2)

## 保存到 CSV
if "error" not in data:
    result = save_to_csv(data)
    print(result)
else:
    print(f"错误: {data['error']}")

""")

print(result)
GradioUI(agent).launch()

## 结论:

Hugging Face 一直对开发者用户有着深刻的理解。加上其社区的优势,它发布的许多框架都得到了良好的反馈。

这个框架可能是过去两年整个 AI 社区思考和积累的结果。

它提醒我们,有时候,小而精致是最佳选择。

在 2025 年,当代理技术蓬勃发展时,SmolAgents 以最简单的方式解决了最关键的问题。

**寻找灵魂伴侣是困难的,自我修养也很难。抓住前沿技术的机会,与我们一起成为创新的超级个体(掌握 AIGC 时代的个人力量)。**

### 参考:

* <https://github.com/huggingface/smolagents/blob/main/docs/source/en/guided_tour.md>

> ***🧙‍♂️ 我是一个AI生成专家!如果您想在项目上合作,请在这里提交[询问](https://docs.google.com/forms/d/e/1FAIpQLSelxGSNOdTXULOG0HbhM21lIW_mTgq7NsDbUTbx4qw-xLEkMQ/viewform)或与我预约[一对一咨询](https://calendly.com/gao-dalie/ai-consulting-call)电话。***

*📚 欢迎查看我的其他文章:*

Related Posts

使用 ChatGPT 搜索网络功能的 10 种创意方法

使用 ChatGPT 搜索网络功能的 10 种创意方法

例如,提示和输出 你知道可以使用 ChatGPT 的“搜索网络”功能来完成许多任务,而不仅仅是基本的网络搜索吗? 对于那些不知道的人,ChatGPT 新的“搜索网络”功能提供实时信息。 截至撰写此帖时,该功能仅对使用 ChatGPT 4o 和 4o-mini 的付费会员开放。 ![](https://images.weserv.nl/?url=https://cdn-im

阅读更多
在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和科技这样一个动态的行业中,保持领先意味着不断提升你的技能。无论你是希望深入了解人工智能模型性能、掌握数据分析,还是希望通过人工智能转变传统领域如法律,这些课程都是你成功的捷径。以下是一个精心策划的高价值课程列表,可以助力你的职业发展,并让你始终处于创新的前沿。 1. 生成性人工智能简介课程: [生成性人工智能简介](https://genai.works

阅读更多
10 个强大的 Perplexity AI 提示,让您的营销任务自动化

10 个强大的 Perplexity AI 提示,让您的营销任务自动化

在当今快速变化的数字世界中,营销人员总是在寻找更智能的方法来简化他们的工作。想象一下,有一个个人助理可以为您创建受众档案,建议营销策略,甚至为您撰写广告文案。这听起来像是一个梦想? 多亏了像 Perplexity 这样的 AI 工具,这个梦想现在成为现实。通过正确的提示,您可以将 AI 转变为您的 个人营销助理。在本文中,我将分享 10 个强大的提示,帮助您自动

阅读更多
10+ 面向 UI/UX 设计师的顶级 ChatGPT 提示

10+ 面向 UI/UX 设计师的顶级 ChatGPT 提示

人工智能技术,如机器学习、自然语言处理和数据分析,正在重新定义传统设计方法。从自动化重复任务到实现个性化用户体验,人工智能使设计师能够更加专注于战略思维和创造力。随着这一趋势的不断增长,UI/UX 设计师越来越多地采用 AI 驱动的工具来促进他们的工作。利用人工智能不仅能提供基于数据的洞察,还为满足多样化用户需求的创新设计解决方案开辟了机会。 1. 用户角色开发 目的

阅读更多
在几分钟内完成数月工作的 100 种人工智能工具

在几分钟内完成数月工作的 100 种人工智能工具

人工智能(AI)的快速发展改变了企业的运作方式,使人们能够在短短几分钟内完成曾经需要几周或几个月的任务。从内容创作到网站设计,AI工具帮助专业人士节省时间,提高生产力,专注于创造力。以下是按功能分类的100个AI工具的全面列表,以及它们在现实世界中的使用实例。 1. 研究工具 研究可能耗时,但人工智能工具使查找、分析和组织数据变得更加容易。**ChatGPT, Cop

阅读更多
你从未知道的 17 个令人惊叹的 GitHub 仓库

你从未知道的 17 个令人惊叹的 GitHub 仓库

Github 隐藏的宝石!! 立即收藏的代码库 学习编程相对简单,但掌握编写更好代码的艺术要困难得多。GitHub 是开发者的宝藏,那里“金子”是其他人分享的精心编写的代码。通过探索 GitHub,您可以发现如何编写更清晰的代码,理解高质量代码的样子,并学习成为更熟练开发者的基本步骤。 1. notwaldorf/emoji-translate *谁需

阅读更多