用 Perplexity Agent API 做一个每日行业简报:每天早上自动联网搜索某个主题过去 24 小时的新闻,生成带编号来源的中文 Markdown 简报,并记下这次花了多少钱。
先看清成品
成品是
brief.py,每天在briefs/目录下生成一份2026-10-21-储能.md。本文已用模拟客户端实际运行测试并通过:请求使用low预设,来源按顺序去重编号,费用信息写入文件。另外用真实 SDK 和无效密钥发了请求,服务器返回 401“Invalid API key”,SDK 能接受这些参数;但 401 发生在参数校验之前,参数本身只按官方文档核对过。本文环境没有有效的 Perplexity API 密钥,没有拿到真实搜索结果。
注意:Perplexity API 按用量计费,价格以官方价格页为准,每次响应的
usage字段会给出实际费用。请在服务可用的地区使用,不要绕过地区限制。搜索结果和 AI 总结可能出错,发布前要点开来源核对;转载他人文章要遵守版权规定。
做完之后你会得到什么?
| 成果 | 说明 |
|---|---|
| 联网简报 | Agent API + 预设,自动搜索和引用 |
| 来源列表 | 从响应的 search_results 中提取并去重 |
| 费用记录 | 读取 usage.cost.total_cost |
| 定时运行 | cron 每天早上执行 |
需要准备哪些环境?
| 项目 | 要求 | 说明 |
|---|---|---|
| Perplexity API 密钥 | 在 API 控制台创建并充值 | 保存为环境变量 PERPLEXITY_API_KEY |
| Python | 3.10 或更高 | |
| SDK | pip install perplexityai |
本文使用 0.44.0 |
第一步:Agent API 和预设是什么?
Agent API(POST https://api.perplexity.ai/v1/agent)可以调用多家模型,并自带联网搜索。预设把模型、搜索设置、系统提示打包好,按名称调用即可。官方文档说明预设已改用分级命名:
| 预设 | 旧名称 | 适合 |
|---|---|---|
fast |
fast-search | 简单问答,最快 |
low |
pro-search | 日常简报,本文默认 |
medium |
deep-research | 多步调研 |
high |
advanced-deep-research | 更深入的调研 |
官方说明动态预设会随评测持续更新;需要固定配置时可以用带日期的版本,例如 fast@2026-10-16.0。
第二步:代码怎么写?
1. 项目结构
daily-brief/
├── brief.py
├── test_brief.py
└── briefs/
2. brief.py
"""每日行业简报:用 Perplexity Agent API 联网搜索,生成带来源的 Markdown 简报。
用法:python brief.py "新能源汽车" [--preset low] [--out briefs/]
"""
import argparse
import datetime as dt
from pathlib import Path
PROMPT = """请整理过去 24 小时内与「{topic}」相关的重要新闻,用简体中文输出:
1. 开头一句话总结今天最重要的变化
2. 列出 3~6 条要点,每条:标题、两句话说明、为什么重要
3. 只写有来源支持的内容,每句话后标注引用
4. 没有找到足够新的消息时,直接说明,不要用旧闻凑数"""
def sources_of(resp):
"""从响应的 search_results 输出项中收集来源,按出现顺序去重。"""
seen, out = set(), []
for item in resp.output:
if getattr(item, "type", None) != "search_results":
continue
for r in item.results:
if r.url not in seen:
seen.add(r.url)
out.append((r.title, r.url, getattr(r, "date", None)))
return out
def make_brief(client, topic: str, preset: str = "low") -> str:
resp = client.responses.create(preset=preset, input=PROMPT.format(topic=topic))
today = dt.date.today().isoformat()
lines = [f"# {topic} 每日简报({today})", "", resp.output_text.strip(), "", "## 来源", ""]
for i, (title, url, date) in enumerate(sources_of(resp), 1):
lines.append(f"{i}. [{title}]({url})" + (f"({date})" if date else ""))
cost = getattr(getattr(resp.usage, "cost", None), "total_cost", None)
if cost is not None:
lines += ["", f"> 本次费用约 {cost} 美元(来自响应中的 usage 字段)"]
return "\n".join(lines) + "\n"
def main(argv=None, client=None):
ap = argparse.ArgumentParser()
ap.add_argument("topic")
ap.add_argument("--preset", default="low")
ap.add_argument("--out", default="briefs")
a = ap.parse_args(argv)
if client is None:
from perplexity import Perplexity
client = Perplexity() # 读取环境变量 PERPLEXITY_API_KEY
md = make_brief(client, a.topic, a.preset)
out = Path(a.out) / f"{dt.date.today().isoformat()}-{a.topic}.md"
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text(md, encoding="utf-8")
print(f"已保存 {out}")
return out
if __name__ == "__main__":
main()
| 要点 | 说明 |
|---|---|
preset="low" |
不用自己挑模型和搜索参数 |
| 提示词要求“没有就说明” | 防止用旧闻凑数 |
search_results |
响应里专门列出搜索到的来源 |
文中 [web:1] |
与来源编号对应,方便核对 |
第三步:怎样测试和运行?
1. 离线测试
from types import SimpleNamespace as NS
from brief import main
class Fake:
def __init__(self):
self.calls = []
self.responses = NS(create=self._create)
def _create(self, **kw):
self.calls.append(kw)
r1 = NS(title="甲新闻", url="https://a.example/1", date="2026-10-21")
r2 = NS(title="乙新闻", url="https://b.example/2", date=None)
return NS(output=[NS(type="search_results", results=[r1, r2, r1]), NS(type="message")],
output_text="今天最重要的是……[web:1]", usage=NS(cost=NS(total_cost=0.0123)))
def test_brief(tmp_path):
c = Fake()
out = main(["储能", "--out", str(tmp_path)], client=c)
assert c.calls[0]["preset"] == "low" and "储能" in c.calls[0]["input"]
md = out.read_text(encoding="utf-8")
assert "1. [甲新闻](https://a.example/1)(2026-10-21)" in md
assert "2. [乙新闻](https://b.example/2)\n" in md
assert md.count("甲新闻") == 1
assert "0.0123" in md
pip install perplexityai pytest
python -m pytest -q
本文实际输出 1 passed。
2. 真实运行
export PERPLEXITY_API_KEY="你的密钥"
python brief.py "储能"
期望输出 已保存 briefs/2026-10-21-储能.md。打开文件,结构如下:
# 储能 每日简报(2026-10-21)
(一句话总结 + 3~6 条要点,带 [web:N] 引用)
## 来源
1. [某新闻标题](https://…)(2026-10-21)
...
> 本次费用约 0.0xx 美元(来自响应中的 usage 字段)
3. 每天自动运行
crontab -e
30 7 * * * cd /home/me/daily-brief && PERPLEXITY_API_KEY=你的密钥 .venv/bin/python brief.py "储能" >> brief.log 2>&1
出问题时该怎么调?
1. 简报里有旧闻
在提示词里写明日期范围,或改用 medium 预设让它多搜几轮。
2. 来源列表为空
打印 [item.type for item in resp.output],确认响应里是否有 search_results。
3. 费用比预期高
预设越高级,搜索和推理步骤越多。先用 fast 对比效果和费用。
常见问题怎么处理?
| 现象 | 原因 | 解决方法 |
|---|---|---|
| 401 | 密钥错误或未充值 | 到控制台检查 |
| 文件名乱码 | 系统不支持中文文件名 | 主题改用拼音 |
| 每天格式不一样 | 动态预设更新 | 用带日期的固定版本 |
| 想发到群里 | 只保存了文件 | 接入群机器人 Webhook |
| 引用编号对不上 | 模型偶尔出错 | 以来源列表为准人工核对 |
项目资源
建议先手动运行几天,对比 fast 和 low 两个预设的质量和费用,选定后再设置定时任务。
然后把主题换成你真正关心的领域,每周抽查几条来源,确认简报可靠。