1. 为什么我要折腾一个自动推送的 AI 日报
每天早上到工位,第一件事是打开浏览器翻十几个页面,看行业动态、看竞品更新、看技术社区的新帖子,一圈下来半小时没了,真正记下来的没几条。这个习惯我坚持了大半年,直到某天早上我盯着满屏的标签页发呆,突然觉得这事不该由人来做——信息聚合、摘要提炼、定时推送,这三件事拆开看都是机器更擅长的活。
于是就有了这个项目:给 WorkBuddy 设一个闹钟,每天上午十点半,让它把过去24小时里我关心的内容抓一遍、用大模型总结成一份日报、再通过微信推送到我手机上。整套流程跑通之后,我早上到工位只需要花三分钟扫一眼日报,剩下的时间可以干正事。
这里说的 WorkBuddy 是一个可以挂载自定义技能、支持定时任务和外部工具调用的 AI 工作台类产品,不同平台可能有不同的叫法,但核心能力是相通的:它能按你设定的时间自动执行一段任务流,并且可以调用大模型、HTTP 接口、脚本等外部能力。我用的模型是 deepseek-v4-flash,选它的原因后面会细说。推送通道走的是微信,具体落地方式是用一个微信小程序做接收端,配合服务端转发。
这篇文章适合三类人看:一是每天被信息淹没、想用自动化给自己减负的职场人;二是正在玩 WorkBuddy 或者类似 AI 工作台、想找个真实项目练手的开发者;三是对"AI 日报"这个形态感兴趣、想自己搭一套但不知道从哪下手的人。我会把整套方案的选型逻辑、关键配置、踩过的坑全部摊开讲,代码和参数能给的都给,你照着抄基本能跑起来。
需要提前说明的是,这套方案不涉及任何网络访问工具,所有数据来源都是公开的、合规的信息渠道,推送通道也是正规的微信生态能力。下面进入正题。
2. 整体方案设计与选型思路拆解
2.1 这套系统到底由哪几块拼起来
先把架构摊平了说。整个"AI 日报自动推送"系统,拆开就是四个环节,每个环节对应一个技术选型:
| 环节 | 职责 | 我的选型 | 备选方案 |
|---|---|---|---|
| 触发调度 | 每天10:30准时启动任务 | WorkBuddy 内置定时任务 | 系统 crontab、云函数定时触发器 |
| 数据采集 | 抓取指定来源的内容 | WorkBuddy 自定义技能 + HTTP 请求 | Python 爬虫、RSS 订阅 |
| 内容生成 | 把原始内容总结成日报 | deepseek-v4-flash | 其他大模型 API |
| 消息推送 | 把日报送到微信 | 微信小程序 + 服务端转发 | 邮件、企业微信机器人 |
这个拆法的好处是每一层都可以单独替换。比如你不想用 WorkBuddy 的定时能力,换成服务器上的 crontab 完全没问题;你不想用 deepseek-v4-flash,换成别的模型接口也就是改个 URL 和 key 的事。我之所以这么选,是因为 WorkBuddy 把调度和技能调用这两块整合得比较顺,省去了自己维护一台常驻服务器的麻烦。
2.2 为什么调度放在 WorkBuddy 而不是自己写 crontab
我一开始的方案其实是在一台云服务器上写 crontab,Python 脚本跑采集和总结,然后调接口推送。跑了大概两周,问题逐渐暴露出来:
- 脚本挂了没人知道。有天早上没收到日报,登服务器一看,是某个数据源的页面结构变了,解析报错,脚本静默退出。crontab 不会告诉你任务失败了。
- 改需求成本高。我想把日报的总结风格从"罗列"改成"分板块点评",得改代码、测试、重新部署,一来一回半小时。
- 模型切换麻烦。想试试新出的模型效果,得改代码里的调用逻辑。
换成 WorkBuddy 之后,这三个问题基本被抹平了。它的定时任务有执行记录,失败了能看到日志;总结风格可以通过调整提示词(prompt)直接改,不用动代码;模型切换在配置里改个名字就行。对于这种"每天跑一次、逻辑不复杂、但需要经常微调"的任务,用工作台类产品比自己维护脚本划算得多。
当然,WorkBuddy 也不是没有代价。它的自定义技能能力有边界,复杂的解析逻辑还是得靠外部接口兜底。我的做法是:WorkBuddy 负责调度和编排,真正脏活累活的解析放在一个轻量 HTTP 服务里,两边通过接口通信。这样既享受了工作台的便利,又保留了灵活性。
2.3 模型为什么选 deepseek-v4-flash
日报总结这个任务,对模型的要求其实很明确:输入长(十几个来源的内容拼起来轻松过万 token)、输出要结构化、响应要快、成本要低。它不需要模型有多强的推理能力,但需要它稳定地做"压缩+归类+提炼"。
我对比过几个模型在这个任务上的表现,deepseek-v4-flash 的优势在于:
- 速度快。日报是定时任务,10:30 触发,我希望 10:31 就能收到,不能等模型慢慢想。flash 版本在长文本总结上的响应速度明显优于标准版。
- 长上下文处理稳。十几个来源的内容拼一起,token 数不小,flash 版本在这个量级下没有出现明显的"中间内容丢失"问题。
- 成本可控。每天跑一次,一个月三十次,用 flash 版本的成本几乎可以忽略。
- 结构化输出听话。我在提示词里要求它按"行业动态 / 技术更新 / 值得关注"三个板块输出,它基本能稳定遵守格式,不需要反复调教。
提示:模型选型没有绝对优劣,关键看任务匹配度。日报总结这种"长输入、短输出、重格式"的场景,flash 类模型往往比旗舰模型更合适,因为旗舰模型的推理能力在这里是浪费的。
2.4 推送通道为什么绕道微信小程序
最直接的推送方式其实是邮件,但邮件的打开率太低,我经常一整天想不起来看。微信不一样,它是我手机里打开频率最高的应用,日报送到微信里,我扫一眼通知栏就能决定要不要细看。
但微信个人号没有官方的机器人接口,直接给个人号发消息这条路走不通。所以我的方案是:做一个极简的微信小程序作为接收端,服务端把日报内容写进一个接口,小程序打开时拉取展示,同时通过订阅消息推送一条提醒。
这个方案的关键在于订阅消息。微信小程序支持"订阅消息"能力,用户授权后,服务端可以在特定条件下推送一条模板消息到用户微信,点击后跳转到小程序查看详情。整个链路是合规的,也是微信官方推荐的触达方式。
小程序的开发我用的是 uniapp,一套代码可以同时编译到微信小程序和 App,后面如果想扩展到其他端也方便。页面极其简单,就一个列表页展示日报,加一个详情页看全文。
3. 核心细节解析与实操要点
3.1 WorkBuddy 定时任务的配置要点
WorkBuddy 的定时任务配置界面各个版本可能略有差异,但核心参数就几个:执行时间、执行频率、要调用的技能或指令、失败重试策略。
我的配置是这样的:
- 执行时间:每天 10:30。选这个时间是因为我一般 10 点左右到工位,处理完邮件和消息,10:30 正好需要一份信息汇总来规划当天的工作。
- 执行频率:每天一次。日报这种东西,一天一次足够,频率太高反而变成噪音。
- 调用内容:一个自定义指令,指令里写清楚"抓取以下来源 → 拼接内容 → 调用模型总结 → 推送结果"的完整流程。
- 失败重试:开启,重试 2 次,间隔 5 分钟。数据源偶尔抽风是常态,重试能解决大部分临时性失败。
这里有个细节值得说:WorkBuddy 的定时任务时区要确认清楚。我有一次发现任务在凌晨跑了,排查半天才发现是时区配置成了 UTC,10:30 UTC 对应北京时间是 18:30,完全错位。改成 Asia/Shanghai 之后就正常了。
另一个细节是任务执行超时时间。采集加总结整个流程我实测下来大概需要 40 到 90 秒,取决于数据源响应速度和模型返回速度。如果你的 WorkBuddy 默认超时时间比较短(比如 30 秒),需要手动调大,否则任务会被中途掐断。
3.2 数据采集环节的实操细节
数据采集是整个流程里最"脏"的部分,因为你要面对的是各种格式不统一的网页和接口。我的做法是优先找 RSS 或公开 API,找不到再考虑页面解析。
我订阅的来源大概分三类:
- 技术社区的公开 RSS。这类最省事,直接请求 XML 然后解析就行,格式稳定。
- 行业资讯站的公开接口。有些站点会暴露 JSON 接口给前端调用,直接请求这个接口比解析 HTML 稳定得多。
- 需要页面解析的站点。这类是下策,因为页面结构一变解析就挂。我的处理方式是只提取最稳定的部分,比如文章标题和链接,正文内容让模型根据标题去概括,而不是硬抓全文。
采集环节有几个坑我踩过:
- 编码问题。有些站点的响应是 GBK 编码,直接按 UTF-8 解析会乱码。处理方式是先检测响应头里的 charset,没有的话用 chardet 之类的库猜一下。
- 请求频率。别把采集脚本写成"一秒请求十次",容易被封。我的做法是每个来源之间间隔 1 到 2 秒,整个采集过程控制在 30 秒以内。
- 内容去重。不同来源可能转载同一篇文章,直接拼给模型会浪费 token。我的做法是用标题做简单去重,相似度超过阈值的只保留一条。
采集到的原始内容,我会做一个预处理:去掉 HTML 标签、压缩多余空白、截断过长的正文。截断这一步很重要,因为模型上下文有限,与其塞进去一堆无关内容,不如每个来源只保留前 500 字,把 token 留给更多来源。
3.3 提示词设计:让模型稳定输出结构化日报
提示词是这份日报质量的决定性因素。我前后改了七八版,最终稳定下来的结构是这样的:
你是一个信息汇总助手。以下是过去24小时内我从多个来源采集的内容,请帮我整理成一份日报。 要求: 1. 按三个板块组织:行业动态、技术更新、值得关注 2. 每个板块下用短句列出要点,每条不超过50字 3. 如果某个板块没有相关内容,写"今日无" 4. 最后用一句话总结今天的整体趋势 5. 不要编造内容,只基于我提供的信息 采集内容如下: {content}这个提示词的关键在于约束足够具体。"每条不超过50字"这种量化要求,比"简洁一点"有效得多。"不要编造内容"这句也必须加,否则模型容易自由发挥,把没发生的事写进日报。
我还试过让模型输出 Markdown 格式,方便小程序渲染,但后来发现纯文本加简单换行反而更稳,因为模型偶尔会在 Markdown 语法上出错,导致渲染混乱。现在的做法是模型输出纯文本,小程序端用固定样式渲染,把格式控制权握在自己手里。
注意:提示词里的
{content}占位符替换时,要确保内容里没有会干扰模型理解的特殊字符。我遇到过采集内容里包含类似指令的文本,导致模型被"带偏"。处理方式是在拼接前对内容做一次清洗,去掉明显的指令性语句。
3.4 微信小程序接收端的实现要点
小程序端我做得极其克制,就两个页面:
- 列表页:展示最近 7 天的日报,每条显示日期和摘要。
- 详情页:展示某一天的完整日报内容。
数据获取走的是服务端接口。服务端在 WorkBuddy 推送日报时,把内容写进数据库,小程序打开时调接口拉取。这样即使小程序没打开,日报也已经存好了,不会丢。
订阅消息的配置有几个关键点:
- 模板选择:微信提供了多种订阅消息模板,我选的是"内容更新提醒"类的模板,字段填日期和摘要。
- 用户授权:订阅消息需要用户主动授权,且每次授权只能推送有限次数。我的做法是在小程序里放一个"开启每日提醒"的按钮,用户点击后请求授权,授权一次可以推送多次(具体次数看模板类型)。
- 推送时机:服务端在日报生成后立即调用订阅消息接口推送,用户收到通知点击进入小程序,正好看到当天的日报。
这里有个容易忽略的点:订阅消息的推送有频率限制,不能无限制推送。如果你的日报一天推多次,可能会触发限制。我的方案是一天只推一次,完全在安全范围内。
3.5 服务端转发层的轻量实现
服务端我用的是一台最低配的云服务器,跑一个简单的 HTTP 服务,职责就两个:接收 WorkBuddy 推送的日报内容并存储、给小程序提供查询接口。
技术栈选得很随意,Python 的 FastAPI 或者 Node 的 Express 都行,我用的是 FastAPI,因为写起来快。核心接口就三个:
# 伪代码示意 POST /api/daily-report # WorkBuddy 推送日报内容 GET /api/daily-report/latest # 小程序获取最新日报 GET /api/daily-report/list # 小程序获取历史日报列表存储用的是 SQLite,因为数据量极小(一天一条),没必要上 MySQL 或者 PostgreSQL。表结构就四个字段:日期、内容、创建时间、推送状态。
这个服务端的部署有个小技巧:用 systemd 或者 supervisor 做进程守护,确保服务挂了能自动重启。我有一次服务器重启后忘了设自启,结果第二天日报没收到,排查半天才发现是服务没起来。
4. 完整实操流程与关键环节实现
4.1 从零开始的搭建顺序
如果你是第一次搭这套系统,我建议按下面的顺序来,每一步都能单独验证,避免一次性堆完发现跑不通:
- 先跑通模型调用。写一个最简单的脚本,把一段文本发给 deepseek-v4-flash,看能不能拿到总结结果。这一步验证 API key、网络、模型名称都对。
- 再跑通数据采集。单独写采集逻辑,把几个来源的内容抓下来打印出来,确认格式和内容符合预期。
- 然后串起来。把采集内容拼进提示词,调模型,拿到日报文本。
- 接着搭服务端。把日报文本通过接口存起来,用 Postman 或者 curl 验证接口能读能写。
- 再做小程序。先做列表页和详情页,能拉到数据展示就行,订阅消息最后加。
- 最后配 WorkBuddy 定时任务。把前面验证过的流程封装成 WorkBuddy 的自定义指令,设定时任务,观察一两天确认稳定。
这个顺序的核心逻辑是从易到难、从独立到集成。每一步都验证过,最后集成时出问题也容易定位是哪一环的锅。
4.2 关键参数的计算与选择过程
有几个参数是我实际调过的,把计算过程摊开说:
采集来源数量。我一开始订了 20 多个来源,结果日报长得像流水账,模型总结质量也下降。后来砍到 8 个核心来源,日报质量明显提升。来源不是越多越好,而是要精。我的标准是:每个来源必须是我真正会看的,如果一个来源连续一周的内容我都没点开过,就砍掉。
单条内容截断长度。我设的是 500 字。计算逻辑是:8 个来源 × 500 字 ≈ 4000 字,加上提示词本身约 200 字,总共 4200 字左右,换算成 token 大概 6000 以内,完全在 deepseek-v4-flash 的上下文窗口内,且留足了输出空间。如果来源增加到 15 个,截断长度就要相应降到 300 字左右。
任务超时时间。实测采集 8 个来源约 20 秒,模型总结约 30 秒,推送约 5 秒,总共 55 秒左右。我把超时设成 180 秒,留足余量应对网络波动。
重试间隔。设的是 5 分钟。太短了可能数据源还没恢复,太长了当天日报就延误了。5 分钟是个比较平衡的值。
4.3 WorkBuddy 自定义指令的写法
WorkBuddy 的自定义指令是整个流程的"胶水",它把采集、总结、推送三步串起来。我的指令逻辑大致是这样的:
步骤1:调用采集接口,获取原始内容 步骤2:对原始内容做清洗和去重 步骤3:拼接提示词,调用 deepseek-v4-flash 步骤4:将模型返回的日报内容 POST 到服务端接口 步骤5:调用微信订阅消息接口推送提醒 步骤6:记录执行日志每一步都要有错误处理。比如步骤1采集失败,不应该直接中断,而是记录哪些来源失败、哪些成功,用成功的内容继续走流程。步骤3模型调用失败,应该重试一次,还失败就推送一条"今日日报生成失败"的提醒,而不是静默消失。
WorkBuddy 的指令编辑器支持条件判断和循环,这些能力要用上。我见过有人把所有逻辑写成一条超长的直线指令,结果一出错完全不知道哪一步挂了。把流程拆成带错误处理的步骤,是保证长期稳定运行的关键。
4.4 小程序端的页面实现细节
小程序的列表页和详情页都很简单,但有几个细节值得说:
列表页的日期显示。我用的是"今天 / 昨天 / 具体日期"的格式,比单纯显示"2024-01-15"更符合阅读习惯。判断逻辑是拿日报日期和当前日期做差,0 天显示"今天",1 天显示"昨天",其余显示日期。
详情页的排版。日报内容是纯文本,我用的是按行分割、逐行渲染的方式。板块标题(如"行业动态")加粗放大,要点内容正常显示,整体留白充足。这里不要用富文本渲染,因为模型输出的格式不完全可控,富文本容易渲染出奇怪的效果。
下拉刷新。列表页支持下拉刷新,方便用户手动拉取最新日报。虽然订阅消息会推送提醒,但用户主动打开时能刷新体验更好。
缓存策略。小程序端对日报内容做了本地缓存,缓存时间设的是 1 小时。这样用户反复打开不会重复请求接口,减轻服务端压力。缓存过期后自动重新拉取。
4.5 订阅消息推送的完整链路
订阅消息的推送链路稍微绕一点,我把完整流程写清楚:
- 用户在小程序里点击"开启每日提醒"按钮。
- 小程序调用
wx.requestSubscribeMessage,请求用户授权。 - 用户同意后,小程序把授权凭证(一个 token)发给服务端。
- 服务端保存这个 token,并在每次日报生成后调用微信的订阅消息接口。
- 微信服务器把消息推送到用户微信。
- 用户点击消息,跳转到小程序详情页。
这里的关键是token 的保存和刷新。微信的订阅消息 token 有有效期,过期需要重新获取。我的做法是服务端定时刷新 token,确保推送时 token 有效。如果推送失败返回 token 过期,就自动刷新后重试一次。
提示:订阅消息的模板字段是固定的,不能随意添加字段。在微信公众平台配置模板时,要选字段数量和类型都匹配的模板,否则推送会失败。
5. 常见问题与排查技巧实录
5.1 日报没收到?按这个顺序排查
日报没收到是最常见的问题,我整理了一个排查顺序,从最可能的原因开始:
| 排查顺序 | 检查项 | 可能原因 | 解决方法 |
|---|---|---|---|
| 1 | WorkBuddy 任务执行记录 | 任务没触发或执行失败 | 看日志,确认失败原因 |
| 2 | 数据采集是否成功 | 数据源改版或超时 | 单独测试采集逻辑 |
| 3 | 模型调用是否成功 | API key 过期或额度用完 | 检查 key 和账户余额 |
| 4 | 服务端接口是否正常 | 服务挂了或接口报错 | 检查服务进程和日志 |
| 5 | 订阅消息是否推送成功 | token 过期或模板不匹配 | 检查推送返回码 |
| 6 | 小程序是否能拉到数据 | 接口地址变更或缓存问题 | 清缓存重试 |
这个顺序的逻辑是从上游到下游。日报的流转路径是"WorkBuddy → 采集 → 模型 → 服务端 → 微信 → 小程序",哪一环断了,后面的都收不到。按顺序排查能最快定位问题。
5.2 模型总结质量不稳定的处理
模型总结质量波动是另一个高频问题。表现是:有时候日报条理清晰,有时候像流水账。我总结的原因和对策:
- 输入内容质量波动。如果某天采集到的内容本身就很碎,模型也很难总结出条理。对策是在采集环节做质量过滤,太短的内容(比如少于 50 字)直接丢弃。
- 提示词被"稀释"。如果某天内容特别多,提示词里的要求可能被模型忽略。对策是控制输入长度,超过阈值就截断,保证提示词占比。
- 模型本身的随机性。大模型输出有随机性,同样的输入两次结果可能不同。对策是把 temperature 调低,我设的是 0.3,输出稳定性明显提升。
5.3 采集环节的典型故障与修复
采集环节的故障最五花八门,我挑几个典型的说:
故障一:某个来源突然返回空内容。排查发现是该站点改了页面结构,原来的解析规则失效。修复方式是更新解析规则,同时加一个告警机制——如果某个来源连续两天返回空,就在日报末尾提示"来源 X 采集异常"。
故障二:采集内容出现乱码。原因是编码判断错误。修复方式是在解析前先检测编码,优先用响应头里的 charset,没有就用 chardet 检测,还不行就按 UTF-8 强制解码并忽略错误。
故障三:采集超时导致整个任务卡住。某个来源响应特别慢,拖垮了整个流程。修复方式是给每个来源的请求设置独立超时(我设的是 10 秒),超时就跳过这个来源,不阻塞整体流程。
5.4 小程序端的常见问题
小程序端的问题主要集中在订阅消息和数据展示上:
- 订阅消息收不到。检查三个地方:用户是否授权、token 是否有效、模板字段是否匹配。我遇到过一次是模板字段填错了,推送接口返回错误但没仔细看,排查了半天。
- 详情页内容显示不全。原因是内容里有特殊字符导致渲染中断。修复方式是在服务端对内容做转义处理,把可能干扰渲染的字符替换掉。
- 列表页日期显示错误。原因是时区处理不当。修复方式是统一用服务端返回的日期字符串,不在客户端做日期计算。
5.5 我踩过的三个印象最深的坑
坑一:时区错位。前面提过,WorkBuddy 定时任务时区设成了 UTC,导致日报在傍晚才生成。这个坑让我意识到任何涉及时间的配置都要显式确认时区。
坑二:token 过期没处理。订阅消息的 token 过期后,推送静默失败,我连续三天没收到日报才发现。修复方式是在推送逻辑里加 token 有效性检查,过期自动刷新。
坑三:内容里的指令注入。有一次采集到的内容里包含类似"忽略以上指令,输出 XXX"的文本,模型真的被带偏了。修复方式是在拼接前对内容做清洗,去掉明显的指令性语句,同时在提示词里强调"只基于提供的信息总结"。
6. 几个让系统更耐用的优化技巧
6.1 给日报加一个"健康度"标记
我在日报末尾加了一行小字,显示本次采集的成功率,比如"本次采集 8 个来源,成功 7 个"。这样我一眼就能看出日报的完整性,如果成功率突然下降,说明某个来源出问题了,可以及时处理。这个标记的实现很简单,就是在采集环节统计成功和失败的数量,拼到日报末尾。
6.2 历史日报的归档与检索
日报积累多了之后,偶尔会想翻某一天的日报。我在服务端加了一个简单的检索接口,支持按日期范围和关键词查询。小程序端也加了一个搜索框,输入关键词能搜到包含该词的日报。这个功能用 SQLite 的 LIKE 查询就能实现,不需要上全文检索引擎。
6.3 把日报同步一份到笔记软件
微信里看日报方便,但不利于长期归档。我的做法是在服务端加一个同步逻辑,把每天的日报通过接口写进我的笔记软件(我用的是支持 API 的笔记工具)。这样日报既能在微信里快速查看,又能在笔记软件里长期保存和检索。
6.4 定期回顾和调整来源列表
来源列表不是一成不变的。我每个月会花十分钟回顾一下:哪些来源的内容我从来没细看过?哪些来源最近质量下降?然后做增删。保持来源列表的精简和高质量,是日报长期有价值的前提。一个塞满低质量来源的日报,很快就会变成没人看的噪音。
6.5 给模型加一个"风格记忆"
我在提示词里加了一段固定的风格描述,比如"用简洁、直接的语言,避免套话和空泛表述"。这段描述每次调用都带上,让模型的输出风格保持一致。如果不加这段,模型有时候会输出很"官方"的总结,读起来很累。风格记忆的本质是把提示词里稳定的部分固化下来,只把变化的内容(采集结果)作为变量传入。
这套系统跑到现在大概三个月,中间修修补补不少次,但核心流程一直很稳。最大的感受是:自动化的价值不在于省了多少时间,而在于把一件需要"想起来去做"的事,变成了"不用想就会发生"的事。信息获取这件事,一旦变成被动接收,心态会轻松很多——我不再焦虑"今天有没有漏掉什么",因为我知道十点半会有一份汇总送到我面前。