一个最小实现的开源参考架构,用于构建AI共读助手,通过真实原文窗口、章节摘要、持久化讨论历史和页面批注,避免AI编造内容、剧透和遗忘。

Stars

35

7 天增长

暂无数据

Fork 数

6

开放 Issue

0

开源协议

MIT

最近更新

2026-07-05

AI 仓库情报摘要
FR-AI / ANALYSIS

为什么值得关注

它直面AI阅读助手的三大痛点——编造书内容、剧透未读章节、丢失对话上下文——并提供了经过实践验证的设计模式和一系列真实踩坑清单。

适合谁使用

  • 构建自定义AI共读工具的开发者
  • 关注AI辅助阅读或学习产品设计的从业者
  • 希望自部署阅读助手以保护隐私的爱好者
  • 研究LLM与人协作阅读体验的研究人员

典型使用场景

  • 与LLM共读一本电子书,AI只讨论当前段落并记住之前的讨论
  • 在书籍页面上为AI对话生成持久、可验证的批注
  • 构建跨会话和章节的讨论历史阅读日志
  • 将阅读上下文整合到个人AI助手的记忆系统中

项目优势

  • 通过输入真实原文窗口(选中句±300字)并指示只讨论该段,消除AI编造
  • 采用惰性生成章节摘要、仅补到读者当前进度,防止剧透
  • 利用SQLite持久化讨论历史,并通过时间感知提示区分过去与现在
  • 支持双向批注:AI标记原文,读者可点击批注继续讨论

使用前须知

  • 无维护承诺——按现状共享,不保证回复issue或PR
  • 需自行部署并配置LLM端点(API密钥、模型、基础URL)
  • 未实现多用户支持和权限管理;代码为骨架,需按需扩展

README 快速开始

coread — 和你的 AI 一起读一本书

一个可以跑起来的最小实现 + 一份思路笔记:怎么让 AI 陪你真的共读一本书—— 不编造书里的内容、不剧透你没读到的章节、记得你们聊过什么、还能在页面上留下它的画线批注。

这不是一个「产品」,是一份参考架构。核心价值在下面的设计思路防踩坑清单; 代码是能跑的骨架,人设、记忆系统、部署方式都留了接口让你换成自己的。

维护预期:本仓按现状(as is)分享,各自 clone 各自部署,不承诺维护—— issue 和 PR 随缘看,不回复不代表冒犯。它的使命在你读完 README 那一刻就完成了。

跑起来

npm install
LLM_BASE_URL=https://api.openai.com/v1 \
LLM_API_KEY=sk-xxx \
LLM_MODEL=你的模型 \
node server.js
# 打开 http://localhost:3900/reading 导入一本 epub(请用公版书或你有权使用的书)

任何 OpenAI 兼容端点都行(OpenRouter / DeepSeek / vLLM / Ollama…)。 可选 DIGEST_MODEL 指定一个便宜模型专门做章节摘要。 人设写在 persona.md(已 gitignore,参考 persona.md.example)。

设计思路:为什么这样做

1. AI 没有「读过」这本书——每一轮都要喂真字。 哪怕模型训练时见过这本书,靠印象聊书必然编造细节。解法是每轮把读者正读的真实原文窗口 (选中句 ±300 字)放进上下文,并明确指令「就这段文字本身聊,绝不凭印象补充」。 这是整个系统的地基,做不好其他都白搭。(lib/prompt.js: passageWindow

2. 「读过全书」用章节摘要索引伪造,而且只造到读者的进度为止。 原文窗口只解决"这一段",聊到前情就抓瞎。给每章用便宜模型生成 ≤120 字脉络摘要(懒生成, 读者翻到哪补到哪),聊天时注入到当前章为止的全部摘要。截止线同时就是防剧透线—— AI"只读到"读者读到的地方,后面的它真的不知道,想剧透都没材料。(lib/digest.js

3. 讨论历史落库,服务端无状态。 聊天历史存 SQLite(按书为单位,讨论是一条连续的河,不按章节切断),每轮从库里取最近 N 条重建 messages。刷新页面、换章节、服务重启,讨论都续得上。用户消息在生成之前落库—— 生成失败也留痕。

4. 时间感知。 共读历史是以周为单位延续的。system prompt 里每轮带当前时间;距上次讨论超过几小时, 再补一句「距上次聊这本书已过去约 N 天——之前的讨论都是那时候的事」。不然模型会把 三天前的讨论当成十分钟前。(lib/prompt.js: timeAnchor

5. AI 的批注留在页面上。 聊到好句子,AI 可以在回复末尾用 [批注:原文片段|批注内容] 标记留一条画线批注—— 服务端摘出标记、校验原文片段真是本章子串才入库(防编造原文),从回复里剥掉标记。 读者重开这一章,能看见 AI 留下的线。反过来,点开任何一条已有批注也能「聊这条」。 共读因此有了双向的、留得下来的痕迹,而不是聊完就散。

6. 记忆回写:共读不是孤岛。 如果你的 AI 还有其他会话入口(日常聊天/其他界面),读者合上书出去说「我刚读完那章」, 那边的 AI 应该接得住。两层做法(lib/memory.js,默认留接口不实现):

  • 长期:每轮共读写一条带 reading/书名 tag 的轻记忆进你自己的记忆系统,靠语义检索被动浮现;
  • 短期:最近 3 小时读过书 → 给其他会话注入一行「TA 刚在读《X》到第 N 章,聊了…」, 过窗自动消失。一句 SQL 的事,却是「余温」的关键。

防踩坑清单(每一条都是真踩过的)

  1. 长回复被中间层掐断。 浏览器和 LLM 之间隔着任何反代/隧道/CDN(Cloudflare 免费层 100s), 长生成就会被当死请求掐掉。唯一正解是 SSE 全链路 + 心跳:让字节一直在流。 事后打捞(从服务端历史里把生成完的回复捞回来补投)只配当保险丝。
  2. SSE 清理挂错事件。 下游心跳定时器的清理要挂 res.on('close')不是 req—— POST 的 req 读完 body 就触发 close,挂错位置心跳当场被拆,还极难排查。
  3. UTF-8 被网络分块切碎。 收响应体写 data += chunk 等于把 Buffer 隐式转字符串, 一个中文字 3 字节被切在块边界就变 。流式用 StringDecoder/TextDecoder({stream:true}), 非流式 Buffer.concat 攒齐再解码。回复越长越容易撞上,而共读回复恰恰都长。
  4. SSE 手工分帧。 帧以空行(\n\n)分隔,但网络包不管帧边界——必须自己攒缓冲区再切, 半截 JSON 要静默跳过等下一块。
  5. 别把浏览器 JS 塞进服务端模板字符串。 正则和 \n 要转义两层(\\n 才能吐出 \n), 一处写错就是静默的前端 bug。浏览器代码放独立静态文件。
  6. 懒生成必须「失败即停」。 章节摘

项目描述

Read a book together with your AI — grounded in the real text, spoiler-safe, with shared margin notes. 和你的 AI 真正共读一本书。

相关仓库与替代方案

根据分类、Topic 和编程语言匹配的相似项目。

react
精选
react GitHub avatar

react

React is a JavaScript library for building user interfaces with declarative, component-based, and cross-platform design.

Web 开发前端框架
246,741
tandpfun
精选
tandpfun GitHub avatar

wardrobe

A GPT‑image powered app that extracts individual garment cutouts from photos, organizes them into a digital wardrobe, and generates modeled outfit previews.

JavaScript
1,570
mshumer
精选
mshumer GitHub avatar

Claude-of-Duty

A browser-based first-person shooter built entirely with procedural generation and orchestrated AI agents, featuring 55k lines of Three.js/WebGL2 code and no art assets.

AI 与机器学习AI 智能体
1,234