拯救你的收藏夹!我用AI给囤积的文章做了个"第二大脑"

212 阅读5分钟

背景

不知道你们是不是和我一样,收藏夹里堆满了各种"稍后阅读"——技术文档、行业报告、深度长文...每次点开收藏夹都像在玩考古挖掘,明明记得某篇文章提到过关键概念,却死活找不到它被埋在哪层"地质结构"里。更让人头大的是,现在大模型虽然能联网读文章,但每次只能处理单篇内容。深受此烦恼,我就做了这么个小工具,借助大模型的能力,帮助总结文章重点并打上标签,方便后期快速定位。至于存储,我选择了Notion,利用它的数据库功能实现分类和检索。你猜怎么着,这一套组合拳下来完全免费搭建!

源码地址

感谢star!!!

github.com/Allen619/ur…

技术栈

  • 前端框架: Nextjs 15, React 19

  • UI 组件:

    • Tailwind CSS
    • Radix UI
  • 后端技术:

    • Playwright + Readability (网页内容抓取)
    • LangChain (AI 处理)
    • BullMQ (任务队列)
    • Redis (缓存与队列)
  • AI 模型:

    • Ollama
    • 支持自定义 AI 模型配置

前期准备

先薅一个免费的算力服务器

腾讯云给每个用户开放了每个月10000分钟的GPU算力时长。不过这两天经常提示算力不够,看来是都饿了鸭😼。找个人少的时间选择ollama模板创建即可。

ide.cloud.tencent.com/dashboard/g…

创建Notion数据库

随便新建一个页面,按下/database即可,根据下表创建数据库

字段名类型
titleText
urlURL
contentText
tagsText (标签是动态的,没办法用多选)
statusSelect -completed -failed - processing- pending
error_msgText
createdAtDate
updatedAtDate

Notion - DatabaseID

developers.notion.com/docs/workin…

环境变量

环境变量含义默认值
REDIS_HOSTRedis地址localhost
REDIS_PORTRedis端口6379
REDIS_PASSWORDRedis密码
REDIS_DBRedis数据库编号
TASK_MAX_ATTEMPTS任务最大重试次数3
TASK_RETRY_DELAY任务重试延迟时间(毫秒)1000
TASK_EXPIRE_TIME任务过期时间(秒)86400
NOTION_TOKENNotion API访问令牌www.notion.so/profile/int…获取
NOTION_DATABASE_IDNotion数据库ID上文Notion - DatabaseID
NOTION_PROXY_URLNotion代理服务器地址一般不需要
NODE_ENV运行环境
PORT服务器运行端口3000
SERPAPI_API_KEYSerpAPI访问密钥
OLLAMA_BASE_URLOllama服务器地址http://localhost:6399
OLLAMA_MODELOllama使用的模型llama3:latest
OLLAMA_TEMPERATUREOllama温度参数0.5
RESPONSE_LANGUAGE响应语言设置zh-CN

快速部署

进入cloud ide

# 下载代码
git clone https://github.com/Allen619/url_reader.git

cd url_reader/

# 安装启动redis
apt install redis-server
redis-server &
redis-cli ping # PONG

#配置env文件
#详情查看环境变量

# 安装依赖并构建
npm install && npx playwright install  && npm run build

# 启动服务
npm run start

建立隧道

OK,经过上面的部署你已经成功搭建好了整套服务🎉那怎么通过本地浏览器访问呢,上ngrok~!

# 下载
wget https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-amd64.tgz
tar -xvzf ngrok-v3-stable-linux-amd64.tgz

mv ngrok /usr/local/bin/
ngrok --version

配置 Ngrok

注册 Ngrok 账户

  1. 访问 ngrok官网 注册账户。
  2. 登录后,获取你的认证令牌(Authtoken)。

添加认证令牌

  1. 运行以下命令:
ngrok config add-authtoken xxxxx
  1. 配置文件会保存在 ~/.config/ngrok/ngrok.yml(Linux/macOS)或 %HOMEPATH%.ngrok2\ngrok.yml(Windows)。

代理你的服务

ngrok http 3000

接下来你就会看到这个界面,点击去,Visit!

Tips:多个链接可以点右上角的智能拆分吼!

操作到这里就大功告成了~

实现细节

前端及接口

  • 页面主要是传统的NextJS+Radix UI+ReactQuery构建的前端页面交互及请求。
  • 利用 BullMQ 和 Redis 构建任务队列,将提交的 URL 异步分发给后台 Worker 进行网页加载和 AI 摘要生成,再通过 Notion API 同步更新任务状态与结果。

AI处理

Loader

这个部分我尝试了很多方案,比如CheerioWebBaseLoader、SerpAPI等,基本都会超出大模型的输入上限或者是内容重复、缺失导致结果不准确。简单说下我考虑的方向吧。

  • CheerioWebBaseLoader + RAG:CheerioWebBaseLoader把链接提取出来(会带有很多html标签和JS脚本,与原文内容无关),所以需要用到文本切割以及部署向量数据库和嵌入计算。实现过于繁杂并且检索出来的结果不稳定。
  • Refine Chain(总结链):需要agent内部多次调用模型,且可能会发生上下文不连贯不稳定的表现。
  • SerpAPI:LangchainJS内容集成的tools,它返回的内容过于简单并且像微信公众号的内容无法读取。

以上几种方案都存在一个问题就是无法获取js动态加载的内容,也会导致内容不完整结果不准确的问题。最终还是选择先让Playwright读取网页内容再交给@mozilla/readability这个库获取文章正文内容,接着把正文传递给prompt即可。

const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
const html = await page.goto(this.url, { waitUntil: 'networkidle' });

// 使用 Readability 处理
const dom = new JSDOM(html);
const reader = new Readability(dom.window.document);
const article = reader.parse();

Model:ollama+开源模型

import { Ollama } from '@langchain/ollama';

new Ollama({
  baseUrl: baseUrl,
  model: modelName,
  temperature: 0.1,
});

Prompt

const prompt = PromptTemplate.fromTemplate(`
分析以下文章内容,并提取关键信息。
文章内容:
{content}

请生成以下内容:
1. 原文的标题
2. 不超过1000字的详细摘要,包含主要论点和关键细节
3. 3-5个关键词标签
4. 主体语言请使用${this.language}回复。

{format_instructions}`);

Output:控制输出格式

import { StructuredOutputParser } from '@langchain/core/output_parsers';
import { z } from 'zod';

export const SummarySchema = z.object({
  title: z.string().min(1, '标题不能为空'),
  content: z.string().min(1, '内容不能为空'),
  tags: z.array(z.string()).min(3).max(5),
});

this.parser = StructuredOutputParser.fromZodSchema(SummarySchema);
const formatInstructions = this.parser.getFormatInstructions();

const formattedPrompt = await prompt.format({
  content,
  format_instructions: formatInstructions,
});

还能怎么玩?

  1. 添加闭源大模型的能力,目前考虑用ollama是开发调用成本问题,还有就是借着春节期间deepseek的风一起玩一玩。
  2. 现在并没有控制文章传入模型的具体字数,如果过长的文章可以采取文本分块切割。
  3. 可以把Notion文章数据检索出来行程一个RAG语料库,后期结合大模型复刻出这个"第二大脑"。

你们收藏夹里最想抢救的"陈年文章"是什么?评论区见!