背景
不知道你们是不是和我一样,收藏夹里堆满了各种"稍后阅读"——技术文档、行业报告、深度长文...每次点开收藏夹都像在玩考古挖掘,明明记得某篇文章提到过关键概念,却死活找不到它被埋在哪层"地质结构"里。更让人头大的是,现在大模型虽然能联网读文章,但每次只能处理单篇内容。深受此烦恼,我就做了这么个小工具,借助大模型的能力,帮助总结文章重点并打上标签,方便后期快速定位。至于存储,我选择了Notion,利用它的数据库功能实现分类和检索。你猜怎么着,这一套组合拳下来完全免费搭建!
源码地址
感谢star!!!
技术栈
-
前端框架: 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即可,根据下表创建数据库
字段名 | 类型 |
---|---|
title | Text |
url | URL |
content | Text |
tags | Text (标签是动态的,没办法用多选) |
status | Select -completed -failed - processing- pending |
error_msg | Text |
createdAt | Date |
updatedAt | Date |
Notion - DatabaseID
developers.notion.com/docs/workin…
环境变量
环境变量 | 含义 | 默认值 |
---|---|---|
REDIS_HOST | Redis地址 | localhost |
REDIS_PORT | Redis端口 | 6379 |
REDIS_PASSWORD | Redis密码 | |
REDIS_DB | Redis数据库编号 | |
TASK_MAX_ATTEMPTS | 任务最大重试次数 | 3 |
TASK_RETRY_DELAY | 任务重试延迟时间(毫秒) | 1000 |
TASK_EXPIRE_TIME | 任务过期时间(秒) | 86400 |
NOTION_TOKEN | Notion API访问令牌 | 在www.notion.so/profile/int…获取 |
NOTION_DATABASE_ID | Notion数据库ID | 上文Notion - DatabaseID |
NOTION_PROXY_URL | Notion代理服务器地址 | 一般不需要 |
NODE_ENV | 运行环境 | |
PORT | 服务器运行端口 | 3000 |
OLLAMA_BASE_URL | Ollama服务器地址 | http://localhost:6399 |
OLLAMA_MODEL | Ollama使用的模型 | llama3:latest |
OLLAMA_TEMPERATURE | Ollama温度参数 | 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 账户
- 访问 ngrok官网 注册账户。
- 登录后,获取你的认证令牌(Authtoken)。
添加认证令牌
- 运行以下命令:
ngrok config add-authtoken xxxxx
- 配置文件会保存在
~/.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,
});
还能怎么玩?
- 添加闭源大模型的能力,目前考虑用ollama是开发调用成本问题,还有就是借着春节期间deepseek的风一起玩一玩。
- 现在并没有控制文章传入模型的具体字数,如果过长的文章可以采取文本分块切割。
- 可以把Notion文章数据检索出来行程一个RAG语料库,后期结合大模型复刻出这个"第二大脑"。
你们收藏夹里最想抢救的"陈年文章"是什么?评论区见!