在本教程中,我将向您展示如何使用Ollama、Qwen和Python构建一个人工智能网页搜索代理。该代理会在网上搜索特定主题,获取相关页面内容,并利用本地的大语言模型生成简洁的摘要。

目录

背景知识

我们大多数人都使用过ChatGPT或Claude向这些大语言模型发送查询请求。当模型不知道某些信息时,其回复中可能会出现一些错误或不准确的内容,这往往是因为它的知识库已经过时了。

随着工具调用技术的兴起,现在大语言模型可以利用各种工具在互联网上搜索最新信息,然后将这些信息整合到自己的回答中,从而生成更准确的输出结果、总结关键内容或从检索到的资料中提取重点信息。

在本教程中,我会向您展示自己是如何构建这样一个个人研究代理的——它能够根据用户指定的主题在互联网上进行搜索,并利用本地的LLM模型对搜索结果进行总结。这个代理完全运行在我的个人电脑上,因此可以保护用户的隐私,而且也无需支付任何API使用费用,所以它是完全免费的。

要跟随本教程操作,您需要在自己的机器上安装Ollama,并拥有一个免费的Ollama账户。本教程适用于macOS、Windows和Linux系统。我使用的电脑是一台配备32GB内存的MacBook Pro,但如果您使用的内存较少,也可以选择Ollama中配置较低内存版本的Qwen模型来运行这个代理程序。

动机与架构

开展这个项目的初衷是希望在我的电脑上运行一些能够完成各种任务的代理程序。例如,我可以让这些代理程序每天为我整理人工智能领域的新闻摘要、筛选最新的国际事件信息,或者帮助我查找新的工作职位信息。

由于这些代理程序是在本地运行的,因此所有的查询操作都不会离开我的机器。这样一来,我的搜索记录就会保持私密性,也不需要担心每次查询都会产生API使用费用的问题。

对于这个项目来说,我们会使用Ollama的网页搜索功能来获取信息,而利用本地的Qwen大语言模型来进行内容总结(而不是依赖像ChatGPT或Claude这样的托管式聊天工具)。下图展示了该代理程序的工作原理。

当在终端中运行这个代理程序时,它会首先询问用户想要研究什么主题,然后会调用Ollama的网页搜索API来获取与该主题相关的前5个搜索结果,接着下载这些页面的内容,并提取其中可读的部分作为最终输出结果。

从这五页中提取的内容会与用户的提示信息以及系统的提示一起被发送给本地的Qwen模型。系统的提示内容为:“利用这些网页结果和页面内容,以Markdown格式进行回答。”模型生成的答案会被保存为Markdown文件存储在磁盘上。

流程示意图:用户输入提示、使用Ollama的网页搜索API获取前5个搜索结果、通过Requests库下载网页内容、使用BeautifulSoup提取页面文本、再将这些数据发送给本地的Qwen模型、最终将生成的Markdown答案保存到文件中。

步骤1:安装Ollama并获取API密钥

首先,下载Ollama应用程序并注册账户,以获得API密钥

获取到API密钥后,请将其设置为一个环境变量:

export OLLAMA_API_KEY="请输入你的API密钥"

步骤2:下载Qwen模型

在本教程中,我们将使用Qwen模型。这是一个开放源代码的模型,目前属于小型模型中表现最好的之一。

我选择了参数量为40亿的版本,因为这个版本能够很好地响应结构化提示,并且可以在没有专用GPU的笔记本电脑上运行。当然,还有参数量分别为20亿或90亿的其他版本可供选择。

如果想在本地使用Qwen3.5:4b模型,请通过Ollama工具进行安装。在我的机器上,40亿参数量的模型文件大小约为3.4GB。如果你的电脑内存较少,也可以使用参数量为8000万的qwen3.5:0.8b版本。

ollama pull qwen3.5:4b

步骤3:安装Python相关依赖库

python3 -m venv venv
source venv/bin/activate
pip install ollama requests beautifulsoup4

步骤4:编写代理代码

下面的Python代码会完成四项任务:首先从终端接收用户的查询提示,然后通过Ollama的网页搜索API获取前5个搜索结果,接着使用requests库下载这些网页的内容,并利用BeautifulSoup提取每个页面的文本信息,最后将这些数据发送给本地的Qwen模型,要求其以Markdown格式生成摘要。最终,生成的答案会被保存为一个带有时间戳的.md文件。

请将这段代码保存到你的research_agent.py文件中。

这里使用的提示语比较简单,你可以根据需要对其进行调整,以便得到你想要的输出结果。

import os
import json
import requests
import ollama
from bs4 import BeautifulSoup
from datetime import datetime
from pathlib import Path

API_KEY = os.getenv("OLLAMA_API_KEY")
SEARCH_URL = "https://ollama.com/api/web_search"
MODEL = "qwen3.5:4b"

# 使用Ollama的网页搜索功能进行查询
def search_web(query):
    response = requests.post(
        SEARCH_URL,
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={"query": query, "max_results": 5},
        timeout=30,
    )
    response.raise_for_status()
    return response.json().get("results", [])

# 下载网页的全部内容
def fetch_text(url):
    try:
        response = requests.get(url, timeout=10)
        response.raise_for_status()
    except requests.RequestException as e:
        return ""
    soup = BeautifulSoup(response.text, "html.parser")
    for tag in soup(["script", "style", "nav", "footer"]):
        tag.decompose()
    return soup.get_text(separator="\n", strip=True)


def main():
    user_prompt = input("请输入你的查询提示:").strip()
    if not user.prompt:
        print("提示不能为空。")
        return

    results = search_web(userprompt)

    # 遍历搜索结果中的每个网址,下载对应的网页内容
    pages = []
    for item in results:
        url = item.get("url")
        if not url:
            continue

        print(f"正在下载页面:{url}")
        page_text = fetch_text(url)

        pages.append({
            "title": item.get("title", ""),
            "url": url,
            "snippet": item.get("content", ""),
            "page_text": page_text,
        })

    # 将这些网页数据和提示信息一起发送给Qwen模型
    prompt = f"""
    用户请求:
    {user_prompt}

    请利用这些网页结果和页面内容,以Markdown格式进行回答。

    提供的数据:
    {json.dumps(pages, ensure_ascii=False)}
    """

    # 调用本地的Qwen模型进行处理
    response = ollama.chat(
        model=MODEL,
        messages=[{"role": "user", "content": prompt}],
    )

    digest = response.message.content

    # 根据当前日期和时间生成唯一的文件名
    timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
    filename = f"digest-{timestamp}.md"

    # 将处理结果保存到文件中
    with open(filename, "w") as f:
        f.write(digest)
    
    print(f"摘要已保存成功。")

if __name__ == "__main__":
    main()

步骤5:运行智能体

python research_agent.py

该脚本会提示您输入想要研究的主题。

示例输出结果

汇总后的内容会被保存为带有时间戳的Markdown文件。智能体在获取这些信息时还会同时打印出对应的原始网址。

在相信这些总结内容之前,先快速浏览一下,并将其中的一两个观点与原始资料进行核对。本地模型相比托管式的前沿模型体积更小,因此出现错误的可能性也更大。因此进行核对有助于确保信息的准确性。

作为一次测试,我向这个研究智能体提出了“大型语言模型领域有哪些新进展?”这个问题,它随后检索到了以下5个网页内容:

输入你的查询:大型语言模型领域有哪些新进展?
正在获取信息:
https://openai.com/nl-NL/index/chatgpt-memory-dreaming/
正在获取信息:
https://pub.towardsai.net/tai-210-glm-5-2-closes-most-of-the-open-weight-gap-in-ten-weeks-2f970c5f1326
正在获取信息:
https://www.globenewswire.com/news-release/2026/06/23/3315999/0/en/Multiverse-Computing-Launches-Pulsar-16B-in-collaboration-with-NVIDIA-Frontier-Grade-Reasoning-at-Half-the-Parameters.html
正在获取信息:
https://thenextweb.com/news/anthropic-claude-tag-slack-always-on-ai-teammate
正在获取信息:
https://www.aidoers.io/blog/claude-mythos-5-and-fable-5-explained-what-anthropic-actually-shipped

已保存为汇总结果

对于一个拥有40亿参数的本地模型来说,这份总结内容的结构相当不错。它被分成了多个部分,其中包含了来自各种来源的相关信息。我仔细核对了一下,发现这些内容都是准确的。

以下就是它生成的结果:

结论

通过本教程,你学会了如何构建一个个人AI网络研究工具:该工具能够在网上进行搜索,利用本地的大语言模型对搜索结果进行总结,并以Markdown格式生成摘要。所有这些操作都在你的个人电脑上完成,没有任何数据会离开你的设备。你可以完全控制这个模型以及使用的提示语,而且无需支付任何API使用费用。

今后,你可以尝试使用不同的提示语来研究各种主题,调整系统提示语以改变输出结果,也可以换用其他本地模型(如Qwen 3.6或Mistral),或者根据自己的工作流程对脚本进行修改。尽情探索吧!

如果你喜欢本教程,可以在我的博客中找到我的更多文章(最近的文章包括一系列关于系统设计的论文);也可以在我的个人网站上查看我的其他作品;同时,你还可以在LinkedIn上关注我的最新动态。

Comments are closed.