Skip to content

Latest commit

 

History

History
239 lines (192 loc) · 10.1 KB

File metadata and controls

239 lines (192 loc) · 10.1 KB

Glean

"在新闻的田野里拾穗。"

本地部署的 AI 新闻采编工作流。每天从 Google News 拉新闻 → 规则粗筛 → AI 精排合并翻译 → DuckDuckGo 验证守门 → AI 整理润色 → 中文报告。只保留 24 小时内的真热新闻,没有就不出报。

首页 · 实时采编日志

报告页 · Token 统计与分类详情

命名取自 glean(拾穗)—— 在收割后的田地里捡拾散落的麦穗。这正是这个工具做的事:在海量新闻噪音里捡有价值的、新鲜的、可信的信号。

特性

  • 6 个分类:AI / 科技 / 财经 / 宏观 / 潮流 / 人文,每类有语义定义注入 AI prompt,避免串类
  • 四层时效控制
    1. RSS 拉取按 published 时间过滤(超 30h 丢弃)
    2. AI 精排 prompt 注入今天日期,排除过时事件
    3. DuckDuckGo 当日搜索做守门员(搜不到 = 整条丢弃)
    4. 全部淘汰则不出报告
  • 混合筛选:规则便宜先压候选,AI 精排只看 top;token 可控
  • 同事件合并:相似标题自动聚合,AI 还会跨源识别合并,一条新闻列出所有来源链接
  • 全中文输出:英文标题/摘要由 AI 翻译重写
  • DDG 补全 + AI 整理 + 质量控制:摘要短的搜索补全,AI 整理成 30-80 字;含色情/博彩词的片段直接拦截
  • 防限流:RSS 抓取限并发 + 抖动 + 指数退避重试
  • 实时日志:浏览器里看流水线进度,AI 输出 token 流式可见
  • Token 报告:每次运行结束打印用量汇总,可选成本估算
  • OpenAI 兼容:DeepSeek / Qwen / Moonshot / 火山 / OneAPI 都能用

快速开始

# 首次运行:自动创建 venv、装依赖、生成 .env
./run.sh

# 编辑 .env 填 API key
vim .env

# 再跑一次
./run.sh

浏览器打开 http://127.0.0.1:8765,点【立即采编】。

目录结构

.
├── source.txt              # 采编源(Google News RSS 关键词)
├── rules.yaml              # 筛选规则 + 时效配置 + AI 配置
├── .env                    # API key 等
├── run.sh                  # 一键启动
├── app/
│   ├── main.py             # FastAPI 入口 + SSE 实时推送 + 状态管理
│   ├── fetcher.py          # 异步 RSS 抓取(限并发/重试/时效过滤)
│   ├── filter.py           # 规则粗筛 + AI 精排(流式,含合并/翻译/时效)
│   ├── scraper.py          # DDG 验证守门员 + AI 整理
│   ├── reporter.py         # 报告 JSON 持久化
│   ├── rules.py            # rules.yaml 加载
│   ├── logger.py           # 全局事件广播(日志/AI 流/状态)
│   ├── stats.py            # Token 统计
│   ├── static/style.css    # 全部样式
│   └── templates/          # base / index / report
└── data/reports/           # 历史报告 JSON

工作流程

source.txt   ──┐
               ▼
  ┌──────────────────────────┐
  │ 1. RSS 抓取               │  并发 5、指数退避重试、published > 30h 丢
  └──────────────────────────┘
               ▼
  ┌──────────────────────────┐
  │ 2. 规则粗筛               │  关键词加分 + 来源权重 + 黑名单 + 相似度去重
  └──────────────────────────┘
               ▼
  ┌──────────────────────────┐
  │ 3. AI 精排(按分类)       │  注入今天日期 + 分类语义;翻译中文 + 合并同事件
  └──────────────────────────┘
               ▼
  ┌──────────────────────────┐
  │ 4. DDG 验证 + AI 整理      │  搜不到 / 含污染词 / AI 判空  →  整条丢弃
  └──────────────────────────┘
               ▼
  ┌──────────────────────────┐
  │ 5. 保存报告               │  无新闻则不出,状态显示"今天无新闻"
  └──────────────────────────┘

配置

source.txt — 采编源

每行一条:分类 | 关键词 | 语言 | 时效

字段 说明
分类 AI / 科技 / 财经 / 宏观 / 潮流 / 人文(或任意自定义)
关键词 Google News 搜索词,建议带动作词如 "发布" "release" 减少噪音
语言 zh 中文 / en 英文
时效 1h / 12h / 1d / 7d(推荐统一 1d
AI    | 大模型 发布          | zh | 1d
科技  | humanoid robot      | en | 1d
财经  | 美股                | zh | 1d
宏观  | Fed rate decision   | en | 1d
潮流  | viral trend          | en | 1d
人文  | archaeology discovery | en | 1d

rules.yaml — 全部规则

# 分类语义定义:AI 精排时严格按这里筛选,跑错类的丢弃
category_definitions:
  AI: |
    AI 技术与行业动向:新模型/产品发布、研究突破、开源、智能体、监管、行业变局。
    严格排除:纯股价/融资/财报(财经类)。
  科技: |
    前沿科技:能源/航天/机器人/生物/量子物理/新材料/武器装备。
    严格排除:纯财报/股价;纯软件 AI 模型。
  # ... 其他分类

# RSS 抓取
fetch:
  concurrency: 5     # 同时并发数,太高会被 Google News 限流
  retries: 3         # 失败后总尝试次数,指数退避 1s/2s/4s
  max_age_hours: 30  # published 超过此小时数直接丢弃

# 规则粗筛
block_keywords:    # 命中即丢
boost_keywords:    # 关键词加分(kw: 权重)
source_weights:    # 域名权重(bloomberg.com: 2.0)
min_score: 0.8     # 低于此分数淘汰
dedup_similarity: 0.6   # 相似度去重(trigram Jaccard,0~1)

# AI
ai:
  enabled: true
  model: gpt-4o-mini
  candidates_per_category: 25     # 每类送 AI 的候选数上限
  pick_per_category: 10           # 每类最终挑出数
  fetch_detail: true              # DDG 验证开关
  enrich_timelimit: d             # DDG 时效(d/w/m/y/null)
  polish_detail: true             # AI 整理 DDG 内容
  enrich_blocklist:               # 含这些词的搜索片段直接丢
    - 小姐
    - escort
    - casino
    # ...
  # pricing:                      # 可选成本估算
  #   input: 0.15
  #   output: 0.60
  #   currency: "$"

修改 rules.yamlsource.txt 无需重启,下次点采编就重新加载。

.env — API 配置

OPENAI_API_KEY=sk-xxxxx
OPENAI_BASE_URL=https://api.openai.com/v1   # 可选
OPENAI_MODEL=gpt-4o-mini                    # 可选,覆盖 rules.yaml
PORT=8765                                    # 可选

兼容的 AI 服务

任何 OpenAI 兼容协议的服务都行,只改 .env

服务 OPENAI_BASE_URL OPENAI_MODEL
OpenAI 官方 https://api.openai.com/v1 gpt-4o-mini / gpt-4o
DeepSeek https://api.deepseek.com/v1 deepseek-chat
阿里 Qwen https://dashscope.aliyuncs.com/compatible-mode/v1 qwen3.6-flash / qwen-plus
Moonshot https://api.moonshot.cn/v1 moonshot-v1-8k
火山方舟 https://ark.cn-beijing.volces.com/api/v3 你的 endpoint id
本地 OneAPI http://127.0.0.1:3000/v1 任意已配模型

报告页

  • 阅读宽度 720px,长文舒适
  • 每条新闻:中文标题 + ★1-5 重要度徽章 + AI 推荐理由 + 加粗中文摘要 + 斜体 DDG 补充 + 多个来源标签
  • 多源合并的有绿色 N 源合并 徽章
  • 关键词显示为米黄小药丸 chip
  • 顶部 Token 卡片:调用次数、入/出/合计、按分类细分、可选成本估算
  • 历史报告可一键删除

每日自动运行

服务一直跑着,cron 触发:

# crontab -e   每天早上 8 点
0 8 * * * curl -s -X POST http://127.0.0.1:8765/run >/dev/null

服务守护用 pm2 / tmux / launchd plist 任选。

API

路径 方法 说明
/ GET 首页(实时日志 + 报告列表)
/run POST 触发采编(异步后台跑)
/status GET 当前状态 JSON
/stream GET SSE 实时事件流
/api/reports GET 报告列表 JSON
/reports/{name} GET 报告 HTML 页
/reports/{name}/delete POST 删除报告

技术栈

FastAPI + Jinja2 + httpx + feedparser + openai SDK + ddgs。无前端框架,纯 SSE + 原生 JS。

设计取舍

  • 宁缺毋滥:四层时效层层把关,宁可不出报告也不展示过时/重复/低质内容。看到"今天无新闻"是预期行为,不是 bug。
  • 规则 + AI 两层筛选:纯规则不够聪明,纯 AI 太贵。规则把候选压到每类 25 条,AI 只挑最终 top。
  • DDG 当守门员而非补充工具:原设计是"摘要短的才搜补全",现在升级为"所有 AI 选出的都要 DDG 在 1 天内搜得到"。这能过滤掉过时/伪热点/营销稿。代价是 token 用量翻倍。
  • 同事件双重合并:规则层用字符 trigram Jaccard 处理近重复,AI 层处理语义重复。
  • AI 整理 DDG 而不是直接展示:原始片段经常是英文广告语,AI 整理后短、中文、聚焦;遇到色情/无关内容自动返回空,触发丢弃。
  • 报告存 JSON 不存 DB:本地工具单用户,文件就够;后期想接 Slack/邮件推送也好处理。
  • SSE 而不是 WebSocket:单向推送够用,浏览器原生支持,无须额外库。

性能与成本参考

以 74 个源、qwen3.6-flash 为例:

  • 总耗时:约 90~180 秒(取决于网络与 DDG 响应)
  • Token:约 50k~150k(其中 60% 在 AI 精排,40% 在 DDG 整理)
  • 报告条数:通常 15~40 条(严格时效过滤后)

想省钱:把 enrich_timelimitwpolish_detailfalse,或换更便宜的模型。 想多内容:source.txt 加更多关键词、enrich_timelimitwmpick_per_category 调大。