大多数人工智能助手都是被动的,它们会等待我们发出指令才会开始行动。在本教程中,我将向您展示如何构建能够按照预定时间表运行、处理您关心的任务,并自动生成每日摘要的本地人工智能助手。每个这样的助手其实都是一种人工智能代理,而我们的目标就是通过基于定时任务的自动化设置来替代那些重复性工作,从而节省您的时间。

我们将使用Python来创建一个简单的本地调度器、一个用于存放各种人工智能代理的目录,以及能够在本地运行模型的Ollama工具,这样就可以避免每次调用API时产生的费用,并让推理过程在您自己的机器上完成。

目录

背景知识

我们很多人都已经拥有能够完成各种有用任务的人工智能助手了,但这些助手仍然需要被人为地触发才能开始工作。那么,如果能够构建一个每天自动运行、无需人工干预就能调用这些助手并获取结果的系统该多好呢?例如,Claude就使用了`/loop`命令来安排重复性任务的执行。

在本教程中,我们将构建这样一个轻量级的每日调度器。它每天都会按照预定时间表启动三个只读模式的人工智能代理来执行相应任务。这种机制完全可以被扩展用来自动化几乎任何需要重复运行的人工智能驱动的工作流程。这些人工智能助手实际上就是您的私人助理,会帮助您完成各项任务。

要学习本教程,您需要在自己的机器上安装Ollama。这个示例在MacOS、Windows和Linux系统上都能正常运行。我使用的是一台配备32GB内存的MacBook Pro,但如果您使用的机器内存较少,也可以选择Ollama中配置较低内存要求的Qwen模型来使用。

动机与架构

这个项目背后的动机很简单:我希望让人工智能代理来为我处理那些重复性的任务。这样一来,我就不必亲自去做这些工作了,而是可以让专门的代理自动完成这些任务。

这种方法的另一个好处是能够保护隐私并让我更好地控制整个流程。由于所有操作都在本地进行,因此代理程序、提示信息以及输出结果都保存在我的机器上。这样就不需要依赖外部自动化平台,也不需要将工作流程数据发送给第三方服务。

该系统的架构被设计得相当简洁。每天会运行一次调度程序,它会调用一组只读权限的人工智能代理来执行相应的任务。

每个代理程序负责完成一项特定的任务:例如查看谷歌股票的走势、汇总最新的人工智能相关新闻,或者生成天气预报。调度程序会独立地运行这些代理程序,收集它们的输出结果,并将这些结果以Markdown格式保存在`outputs`文件夹中。随着需求的变化,我们还可以向该文件夹中添加更多的代理程序,从而创建更多重复性工作流程。而调度程序的代码本身则无需进行任何修改。

project/
├── scheduler.py
├── outputs/
├── agents/
    ├── googl_stock.py
    ├── ai_news.py
    └── weather_brief.py

步骤1:安装Ollama并下载模型

首先,为你的操作系统安装Ollama。

我们将使用Qwen作为本地模型。

ollama pull qwen3.5:4b

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

创建一个虚拟环境,然后安装以下包:

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

请确保使用的LangChain版本大于或等于1.0.0。

其中一个示例代理程序会使用Ollama提供的网络搜索API来获取最新的人工智能新闻。该API需要一个Ollama账户,以及一个在`OLLAMA_API_KEY`变量中设置的API密钥。

请按照以下方式设置API密钥:

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

步骤3:定义代理程序的格式

每个代理程序都是位于`agents/`文件夹中的Python文件,这类文件包含两个关键属性:

  • 名称

  • run()

run()这个函数不接受任何参数,其返回值会被保存为带有时间戳的Markdown文件,文件保存在`outputs/`文件夹中。

请创建相应的文件夹结构:

mkdir -p agents outputs
touch agents/__init__.py

步骤4:创建代理程序调度器

代理程序调度器会完成三项主要任务:

  1. 从`agents/`文件夹中加载所有的代理程序模块。

  2. 依次调用每个代理程序的`run()`函数。

  3. 将所有输出结果保存到`outputs/`文件夹中。

这就是整个代理调度器的工作原理。它并不使用任何状态文件,也不包含针对每个代理的单独调度逻辑。操作系统调度器负责决定代理调度器何时执行任务,而代理调度器会每次为所有代理执行相应的操作,并将它们的输出结果保存到`outputs/`文件夹中,形式为Markdown文件。

如果要添加更多的代理,只需将它们放入`agents/`文件夹即可,代理调度器本身无需进行任何修改。

请将以下代码保存为`scheduler.py`:

import importlib
from datetime import datetime
from pathlib import Path

# 包含所有代理脚本的文件夹。
AGENTS_DIR = Path("agents")

# 用于保存输出文件的文件夹。
OUTPUTS_DIR = Path("outputs")


def loadAgents():
    """从agents/文件夹中导入所有有效的代理模块。"""
    agents = []

    # 遍历agents/文件夹中的所有Python文件
    for path in sorted(AGENTS_DIR.glob("*.py)):
        # 跳过像__init__.py这样的辅助文件
        if path.name.startswith("_"):
            continue

        # 将该文件作为Python模块导入
        module = importlib.import_module(f"agents.{path.stem}")

        # 只保留那些定义了NAME和run()方法的模块
        if hasattr(module, "NAME") and hasattr(module, "run"):
            agents.append(module)
        else:
            print(f"[skip] {path.name} (缺少NAME或run())")

    return agents


def main():
    """加载所有代理,运行它们,并保存它们的输出结果。"""
    # 如果outputs/文件夹还不存在,则创建它。
    OUTPUTS_DIR.mkdir(exist_ok=True)

    # 运行所有找到的代理
    for agent in loadAgents():
        print(f"[run] {agent.NAME}")

        try:
            # 调用代理的run()方法
            output = agent.run()

            # 生成带有时间戳的文件名
            timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
            out_path = OUTPUTS_DIR / f"{agent.NAME}-{timestamp}.md"

            # 将输出结果写入文件
            out_path.write_text(output)

            print(f"[ok] {agent NAME} -> {out_path}")
        except Exception as e:
            # 如果有代理出现异常,记录错误信息并继续执行其他代理。
            print(f "[fail] {agent.NAME}: {e}")


if __name__ == "__main__":
    main()

步骤5:添加三个真实的代理

这里有三个简单、仅用于读取数据的代理脚本。

代理1:GOOGL股票信息查询

请将以下代码保存为`agents/googl_stock.py`。

这个代理会获取GOOGL股票的每日报价数据,计算价格变化幅度,然后让本地模型生成简短的总结文本。

import requests
from langchain.agents import create_agent
from langchain_ollama import ChatOllama

NAME = "googl-stock"

def fetch_googl():
url = "https://query1.finance.yahoo.com/v8/finance/chart/GOOGL?interval=1d&range=1d"
r = requests.get(url, headers={"User-Agent": "Mozilla/5.0"}, timeout=15)
r.raise_for_status()

meta = r.json()["chart"]["result"][0]["meta"]
price = meta["regularMarketPrice"]
prev = meta["chartPreviousClose"]
change = price - prev
pct = (change / prev) * 100 if prev else 0

return {
"symbol": "GOOGL",
"price": round(price, 2),
"previous_close": round(prev, 2),
"change": round(change, 2),
"pct_change": round(pct, 2),
}

def run():
data = fetch_googl()

agent = create_agent(
model=ChatOllama(model="qwen3.5:4b", temperature=0),
tools=[],
system_prompt=(
"你的任务是撰写简短的股票总结。"
"根据给定的股票数据,用两段简洁的Markdown格式文字说明"
"价格的变化情况以及今天是上涨日还是下跌日。"
),
)

result = agent.invoke({
"messages": [{"role": "user", "content": str(data)}]
})

return (
"# GOOGL每日总结\n\n"
f"{result['messages'][-1].content}\n\n"
f"**原始数据:** `{data}`\n"
)

Agent 2:AI新闻摘要生成器

将此代码保存为agents/ai_news.py文件。

该代理使用Ollama的网络搜索API获取最新的AI新闻内容,然后让本地模型将这些信息整理成简短的摘要。其中使用的OLLAMA_API_KEY与我之前用于个人Web研究AI代理教程中的密钥是相同的。

import os
import requests
from langchain.agents import create_agent
from langchain_ollama import ChatOllama

NAME = "ai-news"

def search_news():
    r = requests.post(
        "https://ollama.com/api/web_search",
        headers={"Authorization": f"Bearer {os.getenv('OLLAMA_API_KEY')}"},
        json({"query": "latest AI news", "max_results": 5},
        timeout=30,
    )
    r.raise_for_status()
    return r.json()["results"]

def run():
    results = search_news()

    agent = create_agent(
        model=ChatOllama(model="qwen3.5:4b", temperature=0),
        tools=[],
        systemprompt=(
            "你的任务是生成简短的AI新闻摘要。"
            "根据搜索结果,生成3-5条Markdown格式的要点,每条要点都要概括一条重要新闻,并附上其来源链接。"
        ),
    )

    result = agent.invoke({
        "messages": [{"role": "user", "content": str(results)}]
    })

    return f"# 每日AI新闻摘要\n\n{result['messages'][-1].content}\n"

Agent 3:天气简报生成器

将此代码保存为agents/weather_brief.py文件。

import requests
from langchain.agents import create_agent
from langchain_ollama import ChatOllama

NAME = "weather-brief"

def fetch_weather():
    r = requests.get("https://wttr.in/New+York?format=j1", timeout=15)
    r.raise_for_status()

    current = r.json()["current_condition"][0]
    return {
        "temp_f": current["temp_F"],
        "feels_like_f": current["FeelsLikeF"],
        "humidity": current["humidity"],
        "wind_mph": current["windspeedMiles"],
        "description": current["weatherDesc"][0]["value"],
    }


def run():
    weather = fetch_weather()

    agent = create_agent(
        model=ChatOllama(model="qwen3.5:4b", temperature=0),
        tools=[],
        systemprompt=(
            "你的任务是生成简短的天气简报。"
            "根据当前的天气数据,用简洁的Markdown格式写2条要点,描述天气状况。"
        ),
    )

    result = agent.invoke({
        "messages": [{"role": "user", "content": str(weather)}]
    })

    return f"# 每日天气简报\n\n{result['messages'][-1].content}\n"

步骤6:将代理调度器添加到cron任务中

代理调度器的设计目的是让操作系统的调度系统来触发它的执行。每次它运行时,会自动执行agents/文件夹中的所有代理程序。

在虚拟环境中使用Python时,需要使用完整的路径。调度程序通常不会继承你shell中的PATH环境变量,因此直接使用python命令往往无法达到预期的效果。

MacOS和Linux

在macOS上,你可以使用launchdcron。虽然launchd是macOS原生的调度工具,但在这个教程中我选择使用cron,因为它在Linux系统中也同样适用。

创建一个名为`run_scheduler.sh`的脚本,并将其放在你的代码文件所在的位置。在脚本中的占位符处填写Ollama API密钥。

#!/bin/bash

export OLLAMA_API_KEY=""
cd /full/path/to/project
/full/path/to/project/venv/bin/python3 scheduler.py >>> runner.log 2>&1

在终端中执行`chmod +x run_scheduler.sh`命令,使其可执行。然后可以通过`./run_scheduler.sh`来测试该脚本。

打开你的crontab文件:

crontab -e

添加以下这条指令:

0 8 * * * /full/path/to/project/run_scheduler.sh

这样就可以让`scheduler.py`每天早上8点自动运行了。runner.log文件会记录程序运行的正常输出结果以及出现的错误信息。

需要注意的是,如果你的机器在crontab任务应该执行的时候处于睡眠状态,那么这个任务通常就会被忽略掉。

使用Windows的任务调度器

在PowerShell中,可以这样操作:

schtasks /Create /SC DAILY /TN "AI Runner" /TR "C:\path\to\venv\Scripts\python.exe C:\path\to\scheduler.py" /ST 08:00

在任务设置中,将工作目录设置为你的项目文件夹,这样`agents/`和`outputs/`这些路径才能正确被识别。

示例输出结果

首先手动运行调度程序:

python scheduler.py

下面是程序运行一次后的输出结果:

$ python scheduler.py
[run]  ai-news
[ok]   ai-news -> outputs/ai-news-2026-07-05_17-52-12.md
[run]  googl-stock
[ok]   googl-stock -> outputs/googl-stock-2026-07-05_17-53-18.md
[run]  weather-brief
[ok]   weather-brief -> outputs/weather-brief-2026-07-05_17-53-54.md

所有输出结果都会被保存在`outputs/`文件夹中。下面展示了每个任务的输出内容:

outputs % ls
ai-news-2026-07-05_17-52-12.md
googl-stock-2026-07-05_17-53-18.md	
weather-brief-2026-07-05_17-53-54.md
$cat googl-stock-2026-07-05_17-53-18.md 
# GOOGL每日总结

*   GOOGL收盘价为359.91美元,较前一天的收盘价361.21美元下跌了1.30美元,跌幅为0.36%。
*   对于这只股票来说,今天属于下跌的一天。

**原始数据:`{'symbol': 'GOOGL', 'price': 359.91, 'previous_close': 361.21, 'change': -1.3, 'pct_change': -0.36'}`
cat ai-news-2026-07-05_17-52-12.md 
# 每日AI新闻摘要

* 在令特朗普政府不得不进行安全测试之后,Anthropic的Fable 5和Mythos 5模型已经在全球范围内正式发布,出口限制也已被取消。
    https://arstechnica.com/tech-policy/2026/07/after-spooking-trump-into-safety-testing-anthropic-ai-models-get-global-release/
* OpenAI展示了三个GPT-5.6模型(Sol、Terra和Luna),但这些模型的使用范围仅限于获得美国政府批准的机构。
    https://www.deeplearning.ai/the-batch/gpt-5-6-lands-in-limbo
...

在相信这些结果之前,先对它们进行抽查验证。规模较小的本地模型仍然可能会出现错误,而无人监控的自动化系统会放大这些小错误,因为没有人能够实时发现并纠正它们。

如果你想更频繁地运行测试,可以将cron任务的调度时间从* 8 * * *改为*/10 * * * *,这样它就会每10分钟执行一次。一旦你对当前的设置和结果感到满意,就可以将cron任务恢复为每天早上8点的调度时间,即将其设置为* 8 * * *

如果你想进一步扩展这个系统,接下来可以尝试添加新的自动化脚本,测试不同的调度方案,或者设置通知功能,以便在自动化任务完成后收到提醒。

总结

通过本教程,你成功构建了一个简单的本地AI自动化调度系统,该系统能够从指定的文件夹中执行多个自动化脚本。每个自动化脚本实际上都只是一个Python文件,它会调用大型语言模型来完成任务。这个调度系统会加载这些脚本,运行它们,并将执行结果保存到磁盘上。

这样的设置为轻量级的本地自动化提供了便利。要添加新的自动化脚本,只需将其文件放入agents/文件夹中即可,无需再次修改调度配置。这些脚本会在本地通过Ollama框架运行,输出结果也会保存在你的机器上,而且不会产生使用大型语言模型API所带来的费用。

今后,你可以根据自己的需求添加更多的自动化脚本。比如,可以编写一个脚本来汇总昨天在Git中发生的变更,或者设置一个提醒功能,以便在关注的代码库有新版本发布时及时获知。任何你希望早上自动处理的事情,都可以通过这种方式来实现。祝你在探索这些功能的过程中取得成功!

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

Comments are closed.