最近这段时间,AI 行业里最热闹的话题,莫过于一款名为“悟空”的国产 AI 应用在爆火四个月后突然“消失”在大众视野。不少用户在社交媒体上吐槽“等不到悟空更新”,也有开发者讨论“悟空是不是被砍了”。虽然官方很快给出了版本迭代的说明,但这件事背后真正值得技术人关注的,并不是某一款产品的去留,而是它折射出的一个行业信号:大厂正在集体把重心从“AI 对话玩具”转向“AI Work”。
AI Work 这个词听起来很抽象,但如果拆开看,它其实就是“AI 工作流”或“AI 办公智能体”的统称。过去我们习惯把大模型当成一个聊天窗口,问一句答一句;而 AI Work 强调的是让 AI 真正参与完成一项完整的工作任务,比如自动处理一份合同、自动跟进一条客户线索、自动生成一份周报并发送给相关人员。换句话说,从“会聊天”到“会干活”,这才是大厂争夺的下一站。
本文不打算做产品评论,而是从技术视角拆解 AI Work 到底包含哪些核心能力,为什么大厂宁愿让一款爆款应用“消失”四个月也要转型做 AI Work,以及作为开发者,我们如何快速上手搭建一个属于自己的 AI Work 工作流。
1. AI Work 是什么,和普通 AI 应用有什么区别
1.1 从“单轮对话”到“多步骤任务执行”
先来看一个最简单的对比。
普通的 AI 聊天应用,用户输入 prompt,模型返回答案。整个过程是单轮或短多轮对话,模型不负责“执行”任何外部操作。例如你问“帮我写一封请假邮件”,模型给你一封邮件文本,剩下的复制、粘贴、发送都需要你自己完成。
AI Work 则完全不同。它通常包含任务拆解、工具调用、流程编排和结果校验。同样一个需求“帮我给团队发一封请假邮件”,AI Work 会这样处理:
- 调用日历工具确认你的请假时间。
- 调用通讯录工具找到团队成员邮箱。
- 根据你的语气偏好生成邮件文案。
- 调用邮件客户端发送邮件。
- 返回发送结果,并把发送记录写入日志或 CRM。
也就是说,AI Work 不再是一个“建议者”,而是一个“执行者”。它需要具备调用外部工具(API、数据库、办公软件)的能力,并且能在多个步骤之间保持上下文连贯。
1.2 AI Work 的四个核心组成要素
从工程实现的角度看,任何一个完整的 AI Work 系统都离不开以下四个部分:
| 组成要素 | 作用 | 常见技术实现 |
|---|---|---|
| 任务编排引擎 | 把用户目标拆解为可执行的子任务 | LangChain、Dify、Coze、自研 Workflow 引擎 |
| 工具调用层 | 让 AI 能操作外部系统 | Function Calling、MCP、HTTP API、RPA |
| 上下文管理 | 在多步骤中维持状态和记忆 | 向量数据库、Redis 会话存储、短期记忆窗口 |
| 校验与兜底机制 | 保证 AI 执行结果正确可靠 | 规则校验、人工审核节点、异常重试 |
这四个要素缺一不可。尤其是“校验与兜底机制”,这是 AI Work 和普通 AI 应用最本质的区别——普通应用答错了可以重新问一次,但 AI Work 一旦自动执行了错误操作(比如误发了邮件、错误修改了数据库),后果是不可逆的。
1.3 大厂为什么需要 AI Work
回到“悟空”这个案例。如果一款 AI 应用只有聊天的娱乐价值,用户的新鲜感会快速消退,留存率断崖式下跌。但如果把一个 AI 应用嵌入到办公场景、开发场景、客服场景中,让它真正帮用户完成某项工作,用户粘性就会完全不同。
大厂看重 AI Work,本质上是在抢占工作入口。就像移动互联网时代大家都在争抢“超级 App”一样,AI 时代谁能成为用户日常工作的默认入口,谁就能获得最稳定的流量和数据闭环。而 AI Work 恰好就是这个入口的载体:它既需要大模型底座的能力,又需要云基础设施的支持,还需要庞大的企业应用生态。这三样东西,恰好都是大厂的核心优势。
对于开发者来说,这也意味着一个新的技术方向:掌握 AI 工作流搭建能力,会比单纯会调用大模型 API 更有职业竞争力。
2. 环境准备:搭建 AI Work 需要哪些工具
在动手写代码之前,先把环境准备好。本文后面的实战案例会演示一个“自动收集多篇资讯文章,生成摘要日报,并发送到指定邮箱”的 AI Work 流程。这是一个非常典型的应用场景,可以完整覆盖 AI Work 的核心环节。
2.1 基础环境
以下环境基于常见配置,版本可根据你本机实际情况调整:
| 工具 | 说明 |
|---|---|
| Python 3.9+ | 开发语言,推荐使用 3.10 或更高版本 |
| OpenAI SDK 或国内大模型 SDK | 调用大模型接口,示例中以兼容 OpenAI 接口的模型为例 |
| LangChain 0.1+ | 任务编排框架(可选,也可以直接用原生代码实现) |
| 邮件服务 | 用于最终发送日报,以 QQ 邮箱 SMTP 为例 |
如果你使用的是国内大模型服务,只需要把 API Base URL 和模型名称换成对应的值即可,代码整体结构不需要变化。
2.2 安装依赖
创建一个新的 Python 环境,并安装以下依赖:
pip install openai langchain langchain-openai如果网络环境访问外网有困难,可以使用国内大模型服务商提供的 SDK,或者直接使用requests调用 HTTP 接口。本文的示例代码以“兼容 OpenAI API 格式”为前提,这样代码的可迁移性最强。
2.3 项目结构规划
为了让教程更清晰,我们按下面的目录结构组织代码:
ai-work-demo/ ├── config.py # 配置文件,存放 API Key、邮箱参数 ├── workflow.py # 工作流核心代码 ├── tools.py # 工具函数:抓取资讯、发送邮件 └── main.py # 程序入口下面逐个文件说明。
3. 核心原理拆解:AI Work 如何“想”和“做”
在写完整代码之前,先理解 AI Work 底层的工作原理。这能帮助你在遇到问题时快速定位是哪个环节出了差错。
3.1 从“意图识别”到“任务拆解”
AI Work 的第一步是理解用户的目标,并把目标拆分成可执行的子任务。这一过程通常依赖大模型的推理能力。
例如,用户输入“帮我整理一下今天 AI 行业的重大新闻,并做成日报发给我”。大模型内部会做类似这样的拆解:
- 明确今天的日期。
- 搜索 AI 行业相关资讯来源(可以指定 URL 列表)。
- 抓取每个来源的文章标题和摘要。
- 对内容进行去重和排序。
- 把整理结果写入邮件正文。
- 调用邮件工具发送到指定地址。
在代码实现上,这个拆解结果既可以是一个 JSON 数组,也可以隐含在链式调用中。为了简单起见,本文采用一个固定的流程编排,而不是让模型自由规划步骤。实际生产环境中,两者可以结合:模型负责动态规划,代码负责安全兜底。
3.2 工具调用的核心:Function Calling
Function Calling 是让大模型能够“操控外部世界”的关键技术。它的原理是:开发者预先向模型描述一组可用的函数,模型在生成回答时,会判断是否需要调用某个函数,并输出结构化的函数调用参数。然后代码负责真正执行这个函数,再把执行结果返回给模型继续处理。
一个典型的 Function Calling 请求结构如下:
{ "choices": [ { "message": { "role": "assistant", "content": null, "tool_calls": [ { "id": "call_123", "type": "function", "function": { "name": "send_email", "arguments": "{\"to\":\"admin@example.com\",\"subject\":\"AI日报\"}" } } ] } } ] }模型本身不执行函数,它只输出“我想调用这个函数,参数是这样”。真正执行的是你的代码。这种设计很重要:执行权永远留在开发者手里,模型只是提出请求。这样我们可以在执行函数之前加入权限校验、成本控制、人工审核等安全措施。
3.3 上下文管理:多步骤任务的记忆问题
AI Work 和多轮聊天的另一个区别在于,它需要在多个工具调用之间保持状态。比如你的工作流里,第一步抓取文章列表,第二步需要根据文章内容生成摘要,第三步又要引用摘要生成邮件正文。每一步的结果都要能被后续步骤使用。
常见的实现方式有两种:
- 在代码中维护变量:每一步的结果作为一个 Python 对象传入下一步,这是最简单直接的方式。
- 使用消息历史或向量数据库:当任务步骤非常多或需要长时间跨任务的记忆时,可以把中间结果写入数据库,后续步骤按需读取。
本文的实战案例采用第一种方式,因为它足够清晰,适合理解 AI Work 的完整链路。
4. 实战案例:从 0 到 1 搭建一个资讯日报 AI Work
下面进入完整实战。我们的目标是搭建一个工作流,实现以下功能:
- 从预设的两个资讯源抓取当天文章。
- 调用大模型为每篇文章生成一句话摘要。
- 把摘要整理成 HTML 邮件正文。
- 通过 SMTP 发送到指定邮箱。
为了突出 AI Work 的“工具调用”特性,我们会把“抓取资讯”和“发送邮件”分别封装成独立工具函数,这样后续替换成真实办公软件 API 时,只需要修改tools.py。
4.1 编写配置文件 config.py
# 文件路径:ai-work-demo/config.py # 大模型 API 配置 LLM_API_KEY = "your-api-key-here" LLM_BASE_URL = "https://api.openai.com/v1" # 国内模型请换成对应地址 LLM_MODEL = "gpt-4o-mini" # 按实际可用模型调整 # 资讯源配置 NEWS_SOURCES = [ "https://36kr.com/", "https://www.jiqizhixin.com/", ] # 邮件配置 SMTP_SERVER = "smtp.qq.com" SMTP_PORT = 465 SMTP_USER = "your_email@qq.com" SMTP_PASSWORD = "your_smtp_auth_code" MAIL_TO = ["receiver@example.com"] MAIL_SUBJECT = "AI 行业资讯日报"注意,SMTP_PASSWORD在 QQ 邮箱里不是登录密码,而是在“设置-账号-开启 SMTP”后生成的授权码。其他邮箱类似,请根据你的邮件服务商调整。
4.2 编写工具函数 tools.py
# 文件路径:ai-work-demo/tools.py import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText import requests from bs4 import BeautifulSoup import config def fetch_news_titles(source_url: str, limit: int = 5) -> list[str]: """ 抓取指定网址的文章标题列表。 不同网站结构不同,这里以通用方式解析 <a> 标签中的文本。 实际使用时需要针对目标网站调整选择器。 """ headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/120.0.0.0 Safari/537.36" } try: resp = requests.get(source_url, headers=headers, timeout=10) resp.raise_for_status() except Exception as e: print(f"[工具] 抓取失败:{source_url},原因:{e}") return [] soup = BeautifulSoup(resp.text, "html.parser") titles = [] for a_tag in soup.find_all("a"): text = a_tag.get_text(strip=True) if text and len(text) >= 12 and len(text) <= 60: titles.append(text) if len(titles) >= limit: break return titles def send_email(subject: str, html_content: str) -> bool: """ 通过 SMTP 发送 HTML 格式邮件。 返回 True 表示发送成功,False 表示失败。 """ msg = MIMEMultipart("alternative") msg["From"] = config.SMTP_USER msg["To"] = ", ".join(config.MAIL_TO) msg["Subject"] = subject msg.attach(MIMEText(html_content, "html", "utf-8")) try: server = smtplib.SMTP_SSL(config.SMTP_SERVER, config.SMTP_PORT) server.login(config.SMTP_USER, config.SMTP_PASSWORD) server.sendmail(config.SMTP_USER, config.MAIL_TO, msg.as_string()) server.quit() print("[工具] 邮件发送成功") return True except Exception as e: print(f"[工具] 邮件发送失败:{e}") return False这里要注意几点:
- 抓取网页是 AI Work 里很常见的“工具”,但不同网站 HTML 结构差异很大,上面的代码只是一个通用模板。生产环境中推荐使用目标站点提供的 RSS 源或官方 API。
- 发送邮件使用
SMTP_SSL,适合 465 端口。如果使用 587 端口,需要改用SMTP配合starttls()。 - 工具函数统一加上 try-except 和日志输出,这样工作流出错时可以快速定位是哪个工具的问题。
4.3 编写工作流核心 workflow.py
这是整个 AI Work 的心脏。我们会把“抓取标题 -> 调用模型生成摘要 -> 组装日报 -> 发送邮件”组织成一个完整的流水线。
# 文件路径:ai-work-demo/workflow.py from openai import OpenAI import config from tools import fetch_news_titles, send_email class NewsDailyWorkflow: """ 资讯日报工作流 """ def __init__(self): self.client = OpenAI( api_key=config.LLM_API_KEY, base_url=config.LLM_BASE_URL, ) def collect_titles(self) -> list[str]: """ 第一步:从多个资讯源收集标题,并做简单去重 """ all_titles = [] for source in config.NEWS_SOURCES: print(f"[步骤] 正在抓取:{source}") titles = fetch_news_titles(source) all_titles.extend(titles) # 简单去重,保持顺序 seen = set() unique_titles = [] for title in all_titles: if title not in seen: seen.add(title) unique_titles.append(title) print(f"[结果] 共收集到 {len(unique_titles)} 条标题") return unique_titles def generate_daily_report(self, titles: list[str]) -> str: """ 第二步:让大模型对标题列表进行筛选、排序和摘要,生成日报正文 """ prompt = f"""你是一名 AI 行业新闻编辑。 请根据下面的新闻标题列表,挑选出最值得关注的 5 条新闻。 对每条新闻写出一句话摘要(不超过 50 字),并按重要性排序。 最终输出格式为 Markdown 列表。 新闻标题列表: {titles} """ try: resp = self.client.chat.completions.create( model=config.LLM_MODEL, messages=[ {"role": "system", "content": "你是一个专业的AI资讯编辑。"}, {"role": "user", "content": prompt}, ], temperature=0.3, ) content = resp.choices[0].message.content print("[结果] 日报内容生成完成") return content except Exception as e: print(f"[错误] 大模型调用失败:{e}") return "" def build_html_mail(self, report_content: str) -> str: """ 第三步:把 Markdown 日报包装成 HTML 邮件正文 """ # 简单把换行替换为 <br>,粗体符号替换为 <b> 标签 html_body = report_content.replace("**", "").replace("\n", "<br>") html = f""" <html> <body style="font-family: Arial, sans-serif; font-size: 14px;"> <h2>每日 AI 资讯日报</h2> <p>以下是今日值得关注的 AI 行业动态:</p> <div>{html_body}</div> <hr> <p style="color: #888; font-size: 12px;">本邮件由 AI Work 工作流自动生成</p> </body> </html> """ return html def run(self): """ 执行完整工作流 """ print("==== AI Work 工作流开始 ====") titles = self.collect_titles() if not titles: print("[终止] 未获取到任何标题,工作流结束") return report = self.generate_daily_report(titles) if not report: print("[终止] 日报生成失败,工作流结束") return html_content = self.build_html_mail(report) ok = send_email(config.MAIL_SUBJECT, html_content) if ok: print("==== AI Work 工作流执行成功 ====") else: print("==== AI Work 工作流执行完成,但邮件发送失败 ====")这段代码的核心思路是:每一步都检查上一步的结果,失败则立即终止。这是 AI Work 和普通脚本的一个关键区别——因为工作流涉及的步骤多,任何一步失败都可能产生错误结果,必须有明确的失败退出机制。
4.4 编写入口 main.py
# 文件路径:ai-work-demo/main.py from workflow import NewsDailyWorkflow if __name__ == "__main__": workflow = NewsDailyWorkflow() workflow.run()4.5 运行与验证
在项目根目录执行:
python main.py预期你会看到类似下面的输出:
==== AI Work 工作流开始 ==== [步骤] 正在抓取:https://36kr.com/ [步骤] 正在抓取:https://www.jiqizhixin.com/ [结果] 共收集到 8 条标题 [结果] 日报内容生成完成 [工具] 邮件发送成功 ==== AI Work 工作流执行成功 ====然后打开你填写的收件邮箱,会看到一封标题为“AI 行业资讯日报”的邮件,正文是 AI 生成的 5 条资讯摘要。
如果你运行后没有收到邮件,不要急着改代码,按下面的排查清单一步步查。
5. 常见问题与排查思路
AI Work 涉及的环节比普通脚本多,报错也更分散。我把最常遇到的问题整理成一张表,并给出对应的解决思路。
5.1 高频问题表
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 抓取标题为空 | 网站反爬、HTML 结构变化、请求超时 | 先手动用浏览器打开目标网址,确认标题渲染方式;改用 RSS 源或官方 API;适当降低抓取频率 |
| 大模型调用报错 API 错误 | API Key 无效、Base URL 配错、模型不存在 | 检查 config.py 中的配置;用 curl 单独测试接口连通性;确认模型名称大小写是否一致 |
| 邮件发送失败:SMTPAuthenticationError | 使用了登录密码而不是授权码 | 去邮箱设置中开启 SMTP 并生成授权码,填入 config.py |
| 邮件发送失败:超时 | SMTP 服务器地址或端口配置错误 | 确认使用 465 端口配合 SMTP_SSL,还是 587 端口配合 starttls |
| 生成的日报内容包含乱码 | 网页编码识别错误 | 在resp.text前指定resp.encoding = resp.apparent_encoding |
| 工作流中间某步失败,但未退出 | 没有检查上一步返回值 | 参照run()中的写法,每步执行后判断结果是否为空,为空则终止 |
5.2 排查建议的顺序
如果你遇到未知问题,建议按下面顺序排查:
- 先确认工具能否单独工作:直接写一个小脚本调用
fetch_news_titles("https://some-url")或send_email(...),看结果是否正常。工具是 AI Work 的地基,地基不稳,上层一切免谈。 - 再确认大模型能否单独工作:用最简单的 prompt 调用模型接口,确认 API Key、模型名、网络连通性都没问题。
- 最后才看工作流编排:如果前两步都正常,问题大概率出在步骤间的数据传递上,比如某个字段类型不对、某个返回值为 None。
这条排查思路放在任何 AI Work 项目里都适用。先拆解依赖,再定位问题,而不是在完整链路里瞎猜。
5.3 关于工具权限的特别提醒
这里必须强调一个安全边界:AI Work 一旦接入正式系统(比如企业微信、数据库、财务系统),它执行的每一步操作都应该是可回滚、可审计、可追溯的。本文示例中的“发送邮件”已经算是一个不可逆操作了,如果发给外部客户,发错了影响很严重。
所以在设计正式 AI Work 时,建议加一层人工审批节点。比如邮件发送前,先生成草稿,由人工点击“发送”后,AI 才真正执行发送动作。这也是大厂在 AI Work 落地中非常重视的“人在回路”(Human-in-the-loop)机制。
6. 工程最佳实践:从 Demo 到生产级 AI Work
文章的 Demo 代码跑通之后,如果你想把它变成一个真正能在团队里稳定运行的服务,还有几个工程层面的事情需要补齐。
6.1 用消息队列解耦长耗时任务
上面的工作流是同步执行的:抓取、生成、发送全在一个进程里。如果其中一个环节耗时较长(比如抓取 10 个信息源、调用大模型生成 10 篇摘要),用户会在 HTTP 请求里等待很久。
生产环境更合理的做法是:
- 用户提交任务后,接口立刻返回“任务已接收”。
- 后台通过 Celery、RabbitMQ 或 Kafka 异步执行工作流。
- 执行完成后通过 Webhook 或轮询通知用户结果。
这样做的好处是:任务失败可以重试,不会因为进程重启而丢失;多个任务可以并发放到队列里,由多个 Worker 消费,吞吐量大幅提升。
6.2 为大模型调用增加缓存和降级策略
AI Work 里最贵、最不稳定的环节通常是大模型调用。一个成熟的工作流应该有这样的策略:
- 缓存:相同或相似的请求,在短时间内直接返回缓存结果,避免重复调用模型。
- 降级:模型服务不可用时,可以降级为使用规则模板生成结果,保证工作流不中断。
- 重试:对于瞬时错误,使用指数退避算法重试 2 到 3 次。
缓存尤其重要,因为 AI Work 可能被定时触发(比如每天早上 8 点生成日报),如果输入源没有变化,结果也不会有太大差异,没必要每次都花钱调用模型。
6.3 日志和审计是 AI Work 的生命线
普通应用打日志是为了排查问题,AI Work 打日志是为了回答“AI 为什么做了这个操作”。建议每条日志至少包含:
- Workflow ID(每次运行生成一个唯一 ID)
- 步骤名称
- 输入的关键信息摘要
- 输出结果摘要
- 耗时
- 使用的模型版本或工具版本
- 最终执行状态
有了这些日志,当业务方质疑“为什么 AI 把邮件发给了错误的人”时,你能在几分钟内回放整条执行链路,定位是哪一步出错。没有完善日志的 AI Work,上线后一定会在某个深夜让你付出惨痛代价。
6.4 配置管理的规范化
像config.py里这种 API Key、SMTP 密码,绝对不应该硬编码在代码仓库里。生产环境中建议使用配置中心或环境变量管理:
export LLM_API_KEY=your-key export SMTP_PASSWORD=your-auth-code代码里这样读取:
import os LLM_API_KEY = os.getenv("LLM_API_KEY", "") SMTP_PASSWORD = os.getenv("SMTP_PASSWORD", "")在 Spring 项目里则可以使用 Apollo 或 Nacos 这类配置中心。核心原则是:密钥不进代码库,配置和环境隔离,不同环境(dev、test、prod)使用不同的配置源。
6.5 成本控制:别让 AI Work 变成“烧钱机器”
大模型调用按 Token 计费,AI Work 又是一个会反复调用模型的系统(每一步都可能调用一次),所以成本控制非常重要。
几个实用的建议:
- 对于简单任务,优先使用小模型,比如
gpt-4o-mini或者国产轻量模型,而不是每次都上最强模型。 - 减少 prompt 中的冗余内容,只传必要的上下文。
- 开启流式输出(stream=True)优化用户体验,同时配合缓存减少重复调用。
- 给每个工作流设置每日预算或调用次数上限,超过自动熔断。
7. 进阶方向:从单流程到多智能体协作
如果你已经掌握了本文的单流程 AI Work,下一步可以研究多智能体协作(Multi-Agent)模式。它本质上是把一个大任务分给多个角色不同的“AI 员工”,每个员工负责一个环节,员工之间通过消息传递协作。
一个典型的场景是:
- 分析师 Agent:负责收集数据、生成分析。
- 写手 Agent:负责把分析结果写成文档。
- 审查 Agent:负责检查文档中的事实错误和格式问题。
- 运营 Agent:负责把最终文档发布到指定平台。
这种模式在 LangChain、AutoGen、CrewAI 等框架中都有现成的支持。不过要提醒你的是,多智能体模式虽然看起来很酷,但它的稳定性、调试难度和 Token 成本都比单流程高出不少。建议先确保单流程在实际业务中稳定运行,再考虑多智能体化。
另外,国内大厂近期密集发布的 AI 编程助手、AI 办公套件、AI 智能体平台,本质上都是在抢 AI Work 这个赛道。作为开发者,与其焦虑“某某 AI 产品是不是要凉了”,不如花时间把 AI Work 的核心原理和工程实践摸透。这一波技术红利,至少还能吃好几年。
本文的完整代码可以直接复制运行,算是一个能跑通的 AI Work 最小示例。你可以基于它扩展出更多实用场景,比如自动生成项目周报、定时抓取竞品动态、自动处理客服工单等。如果有问题,欢迎在评论区交流探讨。