first commit
This commit is contained in:
@@ -0,0 +1,411 @@
|
||||
# ChatPapers 开发文档
|
||||
|
||||
> 版本:v0.2(草案)
|
||||
> 更新日期:2026-07-20
|
||||
> 关联需求:[requirements.md](./requirements.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 技术选型
|
||||
|
||||
### 1.1 平台与形态
|
||||
|
||||
| 项 | 选择 | 理由 |
|
||||
| --- | --- | --- |
|
||||
| 宿主 | Zotero 9 Desktop | 需求明确;2026 年已有多款插件 bump 至 `9.*` |
|
||||
| 扩展形态 | Bootstrapped Extension | Zotero 官方推荐路径(非 WebExtension 受限 API) |
|
||||
| 清单 | `manifest.json` + `bootstrap.js` | Zotero 7+ 标准;9 需注意 bootstrap 导出方式 |
|
||||
| 目标版本字段 | `strict_min_version: "9.0"`,`strict_max_version: "9.*"` | 与需求一致;若兼容 8 需额外回归 |
|
||||
|
||||
### 1.2 语言与工具链
|
||||
|
||||
| 项 | 选择 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| 语言 | TypeScript | 类型安全;配合 `zotero-types` |
|
||||
| 构建 | esbuild(经 `zotero-plugin-scaffold`) | 社区主流;热重载友好 |
|
||||
| 脚手架 | [zotero-plugin-template](https://github.com/windingwind/zotero-plugin-template) + [zotero-plugin-scaffold](https://github.com/zotero-plugin-dev/zotero-plugin-scaffold) | 一键 build / start / release |
|
||||
| UI Toolkit | `zotero-plugin-toolkit`(注意 Z9 API 迁移) | 菜单、快捷键、进度等;部分旧 API 已迁至原生 |
|
||||
| 本地化 | Fluent(`.ftl`) | Zotero 未来方向;避免 DTD |
|
||||
| 包管理 | pnpm 或 npm | 团队自定,文档示例用 npm |
|
||||
|
||||
### 1.3 Zotero 9 开发注意点
|
||||
|
||||
根据社区插件迁移经验,落地时需特别注意:
|
||||
|
||||
1. **`bootstrap.js` 导出方式**
|
||||
Zotero 9 通过 `scope[method]` 解析生命周期函数。`bootstrap` 入口应产出**顶层** `function install/startup/shutdown/uninstall/...`,避免被 esbuild IIFE 包死导致钩子找不到。常见做法:对 `bootstrap.ts` **transpile 不 bundle**,或显式配置 esbuild 保留全局函数。
|
||||
|
||||
2. **废弃 `ChromeUtils.import`**
|
||||
Firefox 128+ / Zotero 9 路径下优先使用 ESM / 官方推荐的模块加载方式,避免遗留 JSM import。
|
||||
|
||||
3. **UI 注册**
|
||||
优先使用 Zotero 原生 PreferencePane、菜单注入点;Toolkit 大版本升级后核对 Breaking Changes。
|
||||
|
||||
4. **无重启启停**
|
||||
`shutdown` / `onMainWindowUnload` 必须移除 DOM、监听、定时器、未完成的 fetch AbortController。
|
||||
|
||||
### 1.4 参考文档
|
||||
|
||||
- [Zotero 7 for Developers](https://www.zotero.org/support/dev/zotero_7_for_developers)(基础仍适用,9 在此之上演进)
|
||||
- [Zotero Plugin Dev Docs](https://windingwind.github.io/doc-for-zotero-plugin-dev/)
|
||||
- [Zotero Plugin Scaffold](https://zotero-plugin.dev/zotero-plugin-scaffold/)
|
||||
- 官方示例:[make-it-red](https://github.com/zotero/make-it-red)
|
||||
|
||||
---
|
||||
|
||||
## 2. 工程结构(目标)
|
||||
|
||||
以 template 为起点,建议收敛为以下结构:
|
||||
|
||||
```text
|
||||
chatpapers/
|
||||
├── addon/ # 打包进 xpi 的静态资源
|
||||
│ ├── bootstrap.js # 由 bootstrap.ts 转译生成(顶层函数)
|
||||
│ ├── manifest.json
|
||||
│ ├── prefs.js # 默认偏好
|
||||
│ ├── locale/
|
||||
│ │ ├── en-US/chatpapers.ftl
|
||||
│ │ └── zh-CN/chatpapers.ftl
|
||||
│ └── content/ # 图标、样式、偏好 XHTML 等
|
||||
├── src/
|
||||
│ ├── index.ts # 插件主入口(bundle)
|
||||
│ ├── addon.ts # Addon 单例、生命周期编排
|
||||
│ ├── hooks.ts # startup/shutdown/window hooks 业务
|
||||
│ ├── modules/
|
||||
│ │ ├── ui/
|
||||
│ │ │ ├── readerPane.ts # PDF Reader 侧边栏注入
|
||||
│ │ │ ├── chatView.ts # 对话 UI
|
||||
│ │ │ └── prefs.ts # 偏好面板
|
||||
│ │ ├── pdf/
|
||||
│ │ │ ├── extractor.ts # 文本提取适配层
|
||||
│ │ │ └── context.ts # 上下文裁剪 / 分块
|
||||
│ │ ├── llm/
|
||||
│ │ │ ├── client.ts # OpenAI 兼容客户端(stream / models)
|
||||
│ │ │ ├── providers.ts # Ollama / LM Studio / OpenRouter 等预设
|
||||
│ │ │ ├── prompts.ts # 系统提示与总结模板
|
||||
│ │ │ └── types.ts
|
||||
│ │ ├── storage/
|
||||
│ │ │ ├── prefs.ts # Preference 读写封装
|
||||
│ │ │ └── sessions.ts # 会话持久化
|
||||
│ │ └── zotero/
|
||||
│ │ ├── notes.ts # 创建/追加 Note
|
||||
│ │ └── items.ts # 元数据读取
|
||||
│ └── utils/
|
||||
│ ├── logger.ts
|
||||
│ └── abort.ts
|
||||
├── docs/
|
||||
│ ├── requirements.md
|
||||
│ └── development.md
|
||||
├── zotero-plugin.config.ts
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
└── readme.md
|
||||
```
|
||||
|
||||
**命名约定**
|
||||
|
||||
- 插件 ID:`yehongyu@njau.edu.cn`
|
||||
- Pref 前缀:`extensions.chatpapers.*`
|
||||
- Fluent 文件:`chatpapers.ftl`(避免与其它插件冲突)
|
||||
- 日志前缀:`[ChatPapers]`
|
||||
|
||||
---
|
||||
|
||||
## 3. 架构设计
|
||||
|
||||
### 3.1 分层
|
||||
|
||||
```text
|
||||
┌─────────────────────────────────────────┐
|
||||
│ UI Layer(Reader Pane / Prefs / Menus) │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Application Services │
|
||||
│ ChatSession · Summarize · SaveNote │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Adapters │
|
||||
│ PdfExtractor · LlmClient · PrefStore │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Zotero Platform APIs │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
原则:
|
||||
|
||||
- UI 不直接 `fetch`;统一经 `LlmClient`
|
||||
- PDF 提取细节隔离在 `PdfExtractor`,便于 Z9 API 变更时单点替换
|
||||
- 所有偏好读写经 `PrefStore`,禁止散落魔法字符串
|
||||
|
||||
### 3.2 核心时序:提问
|
||||
|
||||
```text
|
||||
User 发送
|
||||
→ ChatView 收集:input + selection? + session history
|
||||
→ ContextBuilder:metadata + pdfText(截断) + messages
|
||||
→ LlmClient.chatStream(messages, AbortSignal)
|
||||
→ 逐 chunk 更新 UI
|
||||
→ 完成:写入 SessionStore
|
||||
```
|
||||
|
||||
### 3.3 核心时序:保存笔记
|
||||
|
||||
```text
|
||||
User 点击「保存为笔记」
|
||||
→ 取当前 Assistant 消息(或总结全文)
|
||||
→ Notes.createChildNote(item, { title, bodyHtmlOrMd })
|
||||
→ Toast / 状态提示成功
|
||||
```
|
||||
|
||||
Markdown → Zotero Note:优先转为简单 HTML(标题、段落、列表),保持可读。
|
||||
|
||||
---
|
||||
|
||||
## 4. 关键模块设计要点
|
||||
|
||||
### 4.1 Reader 侧边栏
|
||||
|
||||
- 在 Reader 窗口加载后注册侧边栏 Tab(具体 DOM/API 以 Zotero 9 Reader 为准,实现前用 DevTools 探测现网结构)
|
||||
- Pane 与 `itemID` / `attachmentKey` 绑定;切换 PDF 时重置或切换会话
|
||||
- 卸载时移除 Tab 与事件,防止重复注入
|
||||
|
||||
### 4.2 PDF 文本提取
|
||||
|
||||
实现顺序建议:
|
||||
|
||||
1. **优先**:使用 Zotero 已索引全文 / Reader 内可获取的文本 API(若可用)
|
||||
2. **次选**:通过 PDF.js / 附件本地路径做页面级提取
|
||||
3. **失败**:UI 提示「无文本层」,不发起无效大请求
|
||||
|
||||
`ContextBuilder` 策略(MVP):
|
||||
|
||||
- 若 `len(text) <= maxContextChars`:全文注入
|
||||
- 否则:标题页元数据 + 前 N 字 + 后 M 字,或「先让模型做分段摘要」二选一(由需求待决策项决定)
|
||||
|
||||
### 4.3 LLM Client
|
||||
|
||||
MVP 以 **单一 OpenAI 兼容客户端** 覆盖 Ollama、LM Studio、OpenRouter 及各类云端;差异用 **Provider 预设表** 表达,而不是为每个厂商写一套协议。
|
||||
|
||||
```http
|
||||
POST {baseUrl}/chat/completions
|
||||
Authorization: Bearer {apiKey} # 本地预设可省略
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"model": "...",
|
||||
"messages": [...],
|
||||
"stream": true,
|
||||
"temperature": 0.3,
|
||||
"max_tokens": 2048
|
||||
}
|
||||
```
|
||||
|
||||
#### Provider 预设(与需求 §4.4 对齐)
|
||||
|
||||
| 预设 | 默认 Base URL | Key | 额外行为 |
|
||||
| --- | --- | --- | --- |
|
||||
| Ollama | `http://127.0.0.1:11434/v1` | 可空 | 可选 `GET /v1/models` 刷新列表;连接失败提示启动 Ollama |
|
||||
| LM Studio | `http://127.0.0.1:1234/v1` | 可空 | 可选拉取 models;提示开启 Local Server |
|
||||
| OpenRouter | `https://openrouter.ai/api/v1` | 必填 | 附加可选头 `HTTP-Referer`、`X-Title` |
|
||||
| OpenAI / DeepSeek / 硅基流动 | 各官方 `/v1` | 必填 | 标准 Bearer |
|
||||
| 自定义 | 用户输入 | 按需 | 无额外头 |
|
||||
|
||||
建议代码结构:
|
||||
|
||||
```text
|
||||
src/modules/llm/
|
||||
├── client.ts # 统一 chatStream / listModels
|
||||
├── providers.ts # 预设常量:id → { baseUrl, needsKey, headers? }
|
||||
├── url.ts # Base URL 规范化(补 /v1、去尾斜杠)
|
||||
├── prompts.ts
|
||||
└── types.ts
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 解析 SSE `data: {...}`;处理 `[DONE]`
|
||||
- `AbortController` 支持停止生成
|
||||
- 统一错误类型:`AuthError` / `RateLimitError` / `NetworkError` / `LocalServerDown` / `ProviderError`
|
||||
- **禁止**将 API Key 打进日志;verbose 模式下对 Header 脱敏
|
||||
- Base URL 规范化:兼容 `http://127.0.0.1:11434` 与 `.../v1`
|
||||
- 切换预设时:写入默认 Base URL,**不覆盖**用户已改过的自定义 URL(可用「重置为预设默认」按钮)
|
||||
|
||||
本地联调建议:
|
||||
|
||||
- Ollama:`ollama pull qwen2.5` → Base URL 默认 → model 填实际名
|
||||
- LM Studio:加载模型并 Start Server → 端口若非 1234 则改 URL
|
||||
- OpenRouter:填 Key + 模型如 `openai/gpt-4o-mini`
|
||||
|
||||
### 4.4 会话存储
|
||||
|
||||
MVP 可选方案:
|
||||
|
||||
| 方案 | 优点 | 缺点 |
|
||||
| --- | --- | --- |
|
||||
| A. Preferences 存 JSON | 实现快 | 容量与性能差 |
|
||||
| B. 插件数据目录 JSON 文件 | 清晰、易清理 | 需处理路径与并发 |
|
||||
| C. IndexedDB / SQLite | 可扩展 | 实现成本高 |
|
||||
|
||||
**建议 MVP 用 B**,路径形如:`{profile}/chatpapers/sessions/{itemKey}-{attachmentKey}.json`。
|
||||
|
||||
### 4.5 偏好面板
|
||||
|
||||
使用 `Zotero.PreferencePanes.register`(Z9 推荐原生 API)注册:
|
||||
|
||||
- **Provider**:下拉预设(Ollama / LM Studio / OpenRouter / … / 自定义)+「重置为预设默认」
|
||||
- 基本:Base URL、Key(本地可空)、Model、「刷新模型列表」
|
||||
- 生成:temperature、maxTokens、timeout、maxContextChars
|
||||
- OpenRouter 高级:Referer / Title(可折叠)
|
||||
- 提示词:system / summary 可编辑文本框
|
||||
- 隐私说明:明确当前预设是本地还是云端
|
||||
|
||||
---
|
||||
|
||||
## 5. 开发环境搭建
|
||||
|
||||
### 5.1 前置依赖
|
||||
|
||||
- Node.js 20+(LTS)
|
||||
- 已安装 **Zotero 9** 桌面版
|
||||
- Git
|
||||
|
||||
### 5.2 初始化(计划命令)
|
||||
|
||||
需求确认后,推荐从官方模板生成:
|
||||
|
||||
```bash
|
||||
# 示例:使用 zotero-plugin-template 克隆后改名
|
||||
npx tiged windingwind/zotero-plugin-template chatpapers
|
||||
cd chatpapers
|
||||
npm install
|
||||
```
|
||||
|
||||
随后修改:
|
||||
|
||||
- `package.json` → `addonName` / `addonID` / `addonRef`
|
||||
- `addon/manifest.json` → `strict_*_version` 设为 Zotero 9
|
||||
- 清理 demo 代码,按本文结构迁入模块
|
||||
|
||||
### 5.3 本地调试
|
||||
|
||||
典型脚本(以 scaffold 为准):
|
||||
|
||||
```bash
|
||||
npm run start # 启动 Zotero + 加载未打包插件 + 热重载
|
||||
npm run build # 产出 build/ 与 xpi
|
||||
npm run lint
|
||||
```
|
||||
|
||||
调试技巧:
|
||||
|
||||
1. 在 Zotero 中打开错误控制台(查看 `[ChatPapers]` 日志)
|
||||
2. 对 Reader 窗口使用独立 DevTools(若可用)检查侧边栏 DOM
|
||||
3. 用错误 Base URL 验证错误提示路径
|
||||
4. 用本地 Ollama(`http://127.0.0.1:11434/v1`)验证兼容协议
|
||||
|
||||
### 5.4 环境变量
|
||||
|
||||
Scaffold 通常需要本机 Zotero 可执行文件路径,例如:
|
||||
|
||||
```bash
|
||||
# Windows 示例(按实际安装路径调整)
|
||||
set ZOTERO_PLUGIN_ZOTERO_CMD=C:\Program Files\Zotero\zotero.exe
|
||||
```
|
||||
|
||||
具体变量名以当前 `zotero-plugin-scaffold` 文档为准。
|
||||
|
||||
---
|
||||
|
||||
## 6. 编码规范
|
||||
|
||||
1. **只改任务相关代码**;不顺手大重构模板无关文件
|
||||
2. TypeScript `strict`;避免无必要 `any`
|
||||
3. 异步:统一 `async/await`;外部请求必须可 Abort
|
||||
4. UI 字符串全部走 Fluent,禁止硬编码中文/英文(开发期临时除外,合并前清掉)
|
||||
5. 公共工具放 `utils/`;业务不互相深层耦合
|
||||
6. 每个模块顶部保持短注释(「做什么」),避免长篇叙述
|
||||
|
||||
### 6.1 建议的 npm scripts
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"start": "zotero-plugin serve",
|
||||
"build": "zotero-plugin build",
|
||||
"lint": "eslint .",
|
||||
"release": "zotero-plugin release"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
(实际命令以模板生成结果为准。)
|
||||
|
||||
---
|
||||
|
||||
## 7. 测试策略
|
||||
|
||||
| 层级 | 内容 | 时机 |
|
||||
| --- | --- | --- |
|
||||
| 手工冒烟 | 安装、侧边栏、提问、总结、存笔记、禁用清理 | 每个里程碑 |
|
||||
| 单元测试 | `ContextBuilder` 截断、URL 规范化、错误映射 | M2+ |
|
||||
| 集成(可选) | scaffold + Mocha 在真实 Zotero 中跑 | M4 |
|
||||
|
||||
最低验收清单见需求文档里程碑 M1–M4。
|
||||
|
||||
**手工测试用例(MVP)**
|
||||
|
||||
1. 未配置 API Key → 发送时友好提示
|
||||
2. 错误 Key → 401 可读错误
|
||||
3. 正常 PDF → 流式回复(分别用 Ollama / OpenRouter 各测一次)
|
||||
4. 选中文本提问 → 上下文包含选区
|
||||
5. 超长 PDF → 截断提示仍可回答
|
||||
6. 无文本 PDF → 明确失败原因
|
||||
7. Ollama 未启动 → `LocalServerDown` 友好提示
|
||||
8. 保存笔记 → 条目下可见 Note
|
||||
9. 禁用插件 → 侧边栏与菜单消失,无报错
|
||||
|
||||
---
|
||||
|
||||
## 8. 发布流程
|
||||
|
||||
1. 更新版本号(`package.json` / `manifest.json`)
|
||||
2. `npm run build` 生成 `.xpi`
|
||||
3. GitHub Release 上传 `.xpi`
|
||||
4. 配置 `update_url` 指向 `updates.json`(Scaffold 可生成)
|
||||
5. 在干净 Zotero 9 Profile 中验证安装与更新
|
||||
|
||||
版本号遵循 SemVer:`MAJOR.MINOR.PATCH`。
|
||||
|
||||
---
|
||||
|
||||
## 9. 实施计划(与需求里程碑对齐)
|
||||
|
||||
| 阶段 | 工程任务 | 预估 |
|
||||
| --- | --- | --- |
|
||||
| M0 | 确认需求待决策项;冻结插件 ID / 协议 | 0.5d |
|
||||
| M1 | 从 template 初始化;偏好页;Reader 占位 Pane | 2–3d |
|
||||
| M2 | PDF 提取 + 非流式/流式 Client + 单轮对话 | 3–5d |
|
||||
| M3 | 多轮 UI、总结模板、存 Note、Abort | 3–4d |
|
||||
| M4 | 会话持久化、i18n、日志脱敏、打包与 README 使用说明 | 2–3d |
|
||||
|
||||
以上为单人全职粗估,随 Reader API 熟悉度波动。
|
||||
|
||||
---
|
||||
|
||||
## 10. 目录外约定
|
||||
|
||||
- 密钥与真实 API Key **不得**提交仓库;提供 `.env.example`(若需要)仅含路径类配置
|
||||
- `docs/` 变更随功能演进;重大行为变更先更新需求再改代码
|
||||
- Issue / PR 标题建议前缀:`feat:` / `fix:` / `docs:` / `chore:`
|
||||
|
||||
---
|
||||
|
||||
## 11. 下一步(工程开工清单)
|
||||
|
||||
需求方确认 [requirements.md §10 待决策事项](./requirements.md#10-待决策事项需产品确认) 后,按序执行:
|
||||
|
||||
1. 从 `zotero-plugin-template` 初始化仓库代码
|
||||
2. 改名与 Zotero 9 manifest
|
||||
3. 落地 `PrefStore` + 空 Reader Pane
|
||||
4. 实现 `LlmClient` 与最小 Chat UI
|
||||
5. 接通 PDF 文本与「保存为笔记」
|
||||
|
||||
如需,可在确认待决策项后直接进入 M1 脚手架初始化。
|
||||
@@ -0,0 +1,344 @@
|
||||
# ChatPapers 需求文档
|
||||
|
||||
> 版本:v0.2(草案)
|
||||
> 更新日期:2026-07-20
|
||||
> 状态:待确认(Provider 预设范围已按产品意见更新)
|
||||
> 关联:基于仓库根目录初步需求整理
|
||||
|
||||
---
|
||||
|
||||
## 1. 背景与目标
|
||||
|
||||
### 1.1 背景
|
||||
|
||||
研究人员日常在 Zotero 中管理大量 PDF 文献。现有 AI 阅读工具多为独立网页或外部应用,存在以下摩擦:
|
||||
|
||||
- 需反复上传 PDF,上下文与 Zotero 条目割裂
|
||||
- 对话结果难以回流到文献库(笔记、标签、批注)
|
||||
- 工作流在「文献管理器 ↔ AI 工具」之间频繁切换
|
||||
|
||||
### 1.2 产品目标
|
||||
|
||||
在 **Zotero 9** 内提供原生体验的 AI 论文助手,使用户能够:
|
||||
|
||||
1. **对着当前 PDF 提问**(选中文本 / 全文上下文)
|
||||
2. **一键生成结构化总结**(摘要、贡献、方法、局限等)
|
||||
3. **把有价值的 AI 输出沉淀为 Zotero Note**,与条目长期绑定
|
||||
|
||||
### 1.3 成功标准(MVP)
|
||||
|
||||
| 指标 | 目标 |
|
||||
| --- | --- |
|
||||
| 安装 | 用户可通过 `.xpi` 安装到 Zotero 9,启用后无需重启即可使用 |
|
||||
| 可用性 | 打开带 PDF 附件的条目后,≤ 3 次点击进入对话 |
|
||||
| 核心路径 | 「打开 PDF → 提问 → 得到带引用页码的回答 → 存为笔记」可完整走通 |
|
||||
| 配置 | 一键切换常用 Provider 预设(含 Ollama / LM Studio / OpenRouter),并可自定义端点;错误提示可读、可排查 |
|
||||
| 隐私 | API Key 仅存本地;本地 Provider 默认不外传;云端仅向用户所选端点发送 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 用户与场景
|
||||
|
||||
### 2.1 目标用户
|
||||
|
||||
| 角色 | 描述 | 核心诉求 |
|
||||
| --- | --- | --- |
|
||||
| 研究生 / 科研人员 | 高频阅读、需要快速把握论文要点 | 总结、方法/实验追问 |
|
||||
| 文献综述作者 | 批量阅读、需要可比的结构化输出 | 固定模板总结、笔记归档 |
|
||||
| 隐私敏感用户 | 不愿使用封闭云端上传产品 | 自备 API / 本地模型兼容端点 |
|
||||
|
||||
### 2.2 核心用户故事
|
||||
|
||||
1. **作为**科研人员,**我希望**在阅读 PDF 时直接向 AI 提问选中段落,**以便**快速理解术语与论证。
|
||||
2. **作为**科研人员,**我希望**一键生成论文结构化摘要并写入笔记,**以便**后续检索与写作引用。
|
||||
3. **作为**用户,**我希望**使用自己的 API Key 与自定义 Base URL,**以便**接入公司代理、国产大模型或任意 OpenAI 兼容服务。
|
||||
4. **作为**用户,**我希望**一键选择 Ollama / LM Studio / OpenRouter 等常用接入,**以便**本地离线或聚合云端模型都能立刻用上。
|
||||
5. **作为**用户,**我希望**对话历史按「条目 / PDF」隔离保存,**以便**下次打开同一篇论文可续聊。
|
||||
6. **作为**用户,**我希望**回答尽量标注依据页码或原文片段,**以便**回读核验,降低幻觉风险。
|
||||
|
||||
---
|
||||
|
||||
## 3. 范围定义
|
||||
|
||||
### 3.1 范围内(In Scope)— MVP
|
||||
|
||||
- Zotero 9 Bootstrapped 插件安装与生命周期管理
|
||||
- PDF Reader 侧边栏 Chat UI(多轮对话)
|
||||
- 当前打开 PDF 的文本提取与上下文组装
|
||||
- 选中文本作为「引用上下文」提问
|
||||
- 一键总结(可配置 Prompt 模板)
|
||||
- OpenAI Chat Completions 兼容协议(含流式输出)作为统一接入层
|
||||
- **常用 Provider 预设(MVP 必做)**:Ollama、LM Studio、OpenRouter,以及 OpenAI / DeepSeek 等(见 §4.4)
|
||||
- 偏好设置页:Provider 预设、API Key、Base URL、Model、温度、最大 Token、语言、Prompt;本地端点可「探测可用模型」
|
||||
- 将选中回复 / 总结保存为当前 Item 的子 Note
|
||||
- 中英双语界面(Fluent:`zh-CN` / `en-US`)
|
||||
|
||||
### 3.2 范围内 — 后续版本(Post-MVP)
|
||||
|
||||
| 阶段 | 能力 |
|
||||
| --- | --- |
|
||||
| v0.2 | 多 PDF / 多条目联合对话;从主窗口条目菜单发起 Chat |
|
||||
| v0.3 | 批注(Highlight)联动:基于高亮内容追问;回复一键生成高亮建议 |
|
||||
| v0.4 | RAG:长文分块 + 向量检索(可插拔 Embedding Provider) |
|
||||
| v0.5 | 本地服务健康检查增强、模型拉取引导、离线模式全局提示 |
|
||||
| v0.6 | 批量总结 Collection;导出 Markdown / 结构化 JSON |
|
||||
| 探索 | MCP Server;Anthropic / Gemini 原生协议;图表/公式 OCR |
|
||||
|
||||
### 3.3 范围外(Out of Scope)— 当前明确不做
|
||||
|
||||
- 不替代 Zotero 原生 PDF 阅读器
|
||||
- 不做独立桌面端或 Web SaaS
|
||||
- 不自建账号体系与云端同步对话(对话仅本地)
|
||||
- 不提供付费模型转售 / 内置官方 Key
|
||||
- 不保证扫描版纯图片 PDF 的 OCR(可作为后续可选引擎)
|
||||
- 不兼容 Zotero 6 / 7 / 8(以 Zotero 9 为主;若成本低可放宽 `strict_min_version`)
|
||||
|
||||
---
|
||||
|
||||
## 4. 功能需求
|
||||
|
||||
### 4.1 安装与入口
|
||||
|
||||
| ID | 需求 | 优先级 |
|
||||
| --- | --- | --- |
|
||||
| F-01 | 提供可安装的 `.xpi`;`manifest.json` 声明兼容 Zotero 9 | P0 |
|
||||
| F-02 | 插件启用/禁用无需重启 Zotero;`shutdown` 清理 UI 与监听 | P0 |
|
||||
| F-03 | PDF Reader 右侧边栏提供 ChatPapers Tab / Pane | P0 |
|
||||
| F-04 | 主窗口「工具 → ChatPapers 设置」或偏好面板入口 | P0 |
|
||||
| F-05 | 条目右键菜单:「用 ChatPapers 总结」(Post-MVP 可升为 P0) | P1 |
|
||||
|
||||
### 4.2 上下文与 PDF
|
||||
|
||||
| ID | 需求 | 优先级 |
|
||||
| --- | --- | --- |
|
||||
| F-10 | 识别当前 Reader 打开的 PDF Attachment,绑定 Item Key | P0 |
|
||||
| F-11 | 提取 PDF 纯文本(优先 Zotero / PDF.js 已有全文能力) | P0 |
|
||||
| F-12 | 超长文本按策略截断或分块(见 5.2);UI 提示「已截断」 | P0 |
|
||||
| F-13 | 支持将 Reader 中选中文本注入本轮用户消息 | P0 |
|
||||
| F-14 | 可选:附带条目标题、作者、年份、DOI、摘要到 System Prompt | P1 |
|
||||
| F-15 | 扫描版 / 无文本层 PDF:明确提示无法提取,引导用户处理 | P1 |
|
||||
|
||||
### 4.3 对话与总结
|
||||
|
||||
| ID | 需求 | 优先级 |
|
||||
| --- | --- | --- |
|
||||
| F-20 | 多轮对话;支持停止生成(Abort) | P0 |
|
||||
| F-21 | 流式展示 Token(SSE / stream) | P0 |
|
||||
| F-22 | 内置「总结」动作:使用可编辑模板生成结构化摘要 | P0 |
|
||||
| F-23 | 预设快捷指令:术语解释、方法复述、局限与质疑、相关工作 | P1 |
|
||||
| F-24 | Markdown 渲染回复(标题、列表、代码块、引用) | P0 |
|
||||
| F-25 | 复制回复;清空当前会话;新建会话 | P0 |
|
||||
| F-26 | 会话按 `itemKey + attachmentKey` 本地持久化 | P1 |
|
||||
| F-27 | 回答尽量要求模型标注页码 / 引用片段(Prompt 约束 + UI 展示) | P1 |
|
||||
|
||||
### 4.4 AI Provider
|
||||
|
||||
**设计原则**:不绑定单一厂商。MVP 以 **OpenAI Chat Completions 兼容协议** 为统一客户端;各服务通过「预设 + 可编辑 Base URL / Model / Key」接入。Ollama、LM Studio、OpenRouter 均为 **P0**。
|
||||
|
||||
| ID | 需求 | 优先级 |
|
||||
| --- | --- | --- |
|
||||
| F-30 | 统一客户端支持 OpenAI 兼容 `POST .../chat/completions`(含 stream) | P0 |
|
||||
| F-31 | 可配置 Base URL、API Key、Model、Timeout;切换预设时自动填充默认值且允许覆写 | P0 |
|
||||
| F-32 | 内置 Provider 预设表(见下方);含 **Ollama / LM Studio / OpenRouter** 及常用云端 | P0 |
|
||||
| F-33 | 请求失败:展示 HTTP 状态、可理解错误与重试;本地服务未启动时给出启动提示 | P0 |
|
||||
| F-34 | 本地 Provider(Ollama / LM Studio):可选「刷新模型列表」(调用兼容 `/models` 或等价接口) | P1 |
|
||||
| F-35 | 本地 Provider:API Key 可为空;UI 不强制填写 | P0 |
|
||||
| F-36 | OpenRouter:支持可选 `HTTP-Referer` / `X-Title` 等推荐头(可配置) | P1 |
|
||||
| F-37 | 可选记录最近一次请求的 Token 用量(若 API 返回) | P2 |
|
||||
| F-38 | Anthropic Messages / Gemini 原生协议(非兼容层) | P2(Post-MVP) |
|
||||
|
||||
#### MVP 内置 Provider 预设
|
||||
|
||||
| 预设 ID | 显示名 | 默认 Base URL | API Key | 说明 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `ollama` | Ollama | `http://127.0.0.1:11434/v1` | 可空 | 本机本地模型;需用户先 `ollama serve` |
|
||||
| `lmstudio` | LM Studio | `http://127.0.0.1:1234/v1` | 可空 | 本机 Local Server;端口以用户设置为准 |
|
||||
| `openrouter` | OpenRouter | `https://openrouter.ai/api/v1` | 必填 | 聚合多模型;模型名形如 `vendor/model` |
|
||||
| `openai` | OpenAI | `https://api.openai.com/v1` | 必填 | 官方 API |
|
||||
| `deepseek` | DeepSeek | `https://api.deepseek.com/v1` | 必填 | 常用国产云端 |
|
||||
| `siliconflow` | 硅基流动 | `https://api.siliconflow.cn/v1` | 必填 | 常用聚合 |
|
||||
| `custom` | 自定义 | 用户填写 | 按服务要求 | 任意 OpenAI 兼容网关 / 代理 |
|
||||
|
||||
> 说明:上述默认端口/路径以各产品当前常见配置为准;设置页需提示「若改过端口请手动改 Base URL」。
|
||||
|
||||
### 4.5 与 Zotero 数据联动
|
||||
|
||||
| ID | 需求 | 优先级 |
|
||||
| --- | --- | --- |
|
||||
| F-40 | 「保存为笔记」:创建子 Note,标题可配置(默认含日期) | P0 |
|
||||
| F-41 | 可选将总结追加到已有 Note,而非总是新建 | P1 |
|
||||
| F-42 | 不自动修改条目元数据(标题、标签等),除非用户显式操作 | P0 |
|
||||
| F-43 | (后续)根据 AI 建议创建 Highlight Annotation | P2 |
|
||||
|
||||
### 4.6 设置与安全
|
||||
|
||||
| ID | 需求 | 优先级 |
|
||||
| --- | --- | --- |
|
||||
| F-50 | 偏好面板完整配置项(见附录 A) | P0 |
|
||||
| F-51 | API Key 使用 Zotero Preferences / 安全存储惯例,不明文写入日志 | P0 |
|
||||
| F-52 | 默认不上传全文以外的库数据;设置页说明「将发送哪些内容」 | P0 |
|
||||
| F-53 | 「发送前预览上下文」开关(调试用) | P2 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 非功能需求
|
||||
|
||||
### 5.1 兼容性
|
||||
|
||||
- 目标:Zotero 9(发布于 2026 年)
|
||||
- `applications.zotero.strict_max_version`:`9.*`
|
||||
- `strict_min_version`:建议 `9.0`(若需覆盖 8.x,需单独验证后下调)
|
||||
- OS:Windows / macOS / Linux(随 Zotero 官方桌面端)
|
||||
|
||||
### 5.2 性能与限制
|
||||
|
||||
| 项 | 建议默认值 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| 单次上下文最大字符 | 80,000(可配置) | 超出则截断或分块摘要后再问 |
|
||||
| 流式首字延迟 | 受模型与网络影响;UI 需有 loading | — |
|
||||
| 并发请求 | 单会话同时仅 1 个进行中请求 | 新请求可取消旧请求 |
|
||||
| 会话历史条数 | 默认保留最近 50 轮 | 可清理 |
|
||||
|
||||
### 5.3 可靠性
|
||||
|
||||
- 网络超时可配置(默认 120s)
|
||||
- Provider 4xx/5xx 不导致插件崩溃
|
||||
- PDF 提取失败有明确降级提示
|
||||
|
||||
### 5.4 可维护性
|
||||
|
||||
- TypeScript 源码 + ESLint
|
||||
- 模块边界清晰:UI / PDF / LLM / Storage / Prefs
|
||||
- 关键日志带命名空间前缀,可开关 verbose
|
||||
|
||||
### 5.5 国际化与无障碍
|
||||
|
||||
- Fluent 本地化,至少中英
|
||||
- 侧边栏控件具备可访问名称;支持键盘发送(Enter / Ctrl+Enter 策略可配置)
|
||||
|
||||
### 5.6 许可
|
||||
|
||||
- 建议开源协议:AGPL-3.0 或 MIT(待决策)
|
||||
- 第三方依赖遵循各自许可,在 NOTICE 中声明
|
||||
|
||||
---
|
||||
|
||||
## 6. 信息架构与交互草案
|
||||
|
||||
### 6.1 主要界面
|
||||
|
||||
1. **PDF Reader 侧边栏 — Chat**
|
||||
- 顶部:当前论文短标题、模型名、设置入口
|
||||
- 中部:消息列表(User / Assistant)
|
||||
- 底部:输入框、附加选区按钮、发送、停止、快捷动作(总结)
|
||||
2. **偏好面板 — ChatPapers**
|
||||
- Provider、凭据、模型、生成参数、Prompt 模板、隐私说明
|
||||
3. **(可选)独立对话窗口**:侧边栏空间不足时弹出(P2)
|
||||
|
||||
### 6.2 关键流程(MVP 主路径)
|
||||
|
||||
```text
|
||||
安装插件 → 配置 API → 打开 PDF
|
||||
→ 打开 ChatPapers 面板
|
||||
→(可选)选中文本「添加到上下文」
|
||||
→ 输入问题 / 点击「总结」
|
||||
→ 流式显示回答
|
||||
→「保存为笔记」→ 条目下新增 Note
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 数据与隐私
|
||||
|
||||
### 7.1 本地数据
|
||||
|
||||
| 数据 | 存储位置 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| Provider 预设、API Key、模型等 | Zotero Preferences | 前缀如 `extensions.chatpapers.*` |
|
||||
| 会话历史 | 插件本地存储(prefs JSON / SQLite / 文件,待技术选型) | 按条目隔离 |
|
||||
| 笔记内容 | Zotero 数据库(用户主动保存时) | 标准 Note 条目 |
|
||||
|
||||
### 7.2 外发数据
|
||||
|
||||
仅在用户点击发送 / 总结时,向**用户当前所选** API 端点发送:
|
||||
|
||||
- System Prompt(含模板与元数据,按设置)
|
||||
- 组装后的 PDF 文本片段 / 选区
|
||||
- 对话历史(按窗口策略)
|
||||
|
||||
行为约定:
|
||||
|
||||
- 选择 **Ollama / LM Studio** 时,请求发往本机,不经过第三方云(除非用户改成远程 Base URL)
|
||||
- 选择 **OpenRouter / OpenAI 等云端** 时,内容发往对应服务商,设置页需显著提示
|
||||
- **不默认发送**:整个 Zotero 库、未打开条目、其他附件
|
||||
|
||||
---
|
||||
|
||||
## 8. 里程碑
|
||||
|
||||
| 里程碑 | 交付物 | 验收要点 |
|
||||
| --- | --- | --- |
|
||||
| M0 | 需求/开发文档定稿 | 本文档与开发文档评审通过 |
|
||||
| M1 | 插件骨架可安装 | Zotero 9 加载、侧边栏占位、偏好页 |
|
||||
| M2 | PDF 文本 + 单轮问答 | 能对当前 PDF 提问并显示回复 |
|
||||
| M3 | 流式 + 总结 + 存笔记 | MVP 主路径闭环 |
|
||||
| M4 | 会话持久化 + i18n + 打包发布 | 可分发 `.xpi` 与更新清单 |
|
||||
| M5+ | Post-MVP 能力 | 按优先级排期 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 风险与依赖
|
||||
|
||||
| 风险 | 影响 | 缓解 |
|
||||
| --- | --- | --- |
|
||||
| Zotero 9 Reader / PDF API 变动 | 文本提取或侧边栏注入失败 | 跟进官方 changelog;抽象 Reader Adapter |
|
||||
| 超长论文超出模型上下文 | 回答质量下降 | 分块摘要、RAG、截断提示 |
|
||||
| 扫描版 PDF 无文本 | 核心功能不可用 | 明确提示;后续可选 OCR |
|
||||
| API 费用与密钥泄露 | 用户损失 | 本地存储、日志脱敏、用量提示 |
|
||||
| 竞品功能重叠(PapersGPT 等) | 差异化不足 | 聚焦「轻量、可自托管、笔记回流」 |
|
||||
|
||||
---
|
||||
|
||||
## 10. 待决策事项(需产品确认)
|
||||
|
||||
请在开工前确认以下选项:
|
||||
|
||||
1. **开源协议**:AGPL-3.0 vs MIT?
|
||||
2. **是否兼容 Zotero 8**:仅 9,还是 `8.*`–`9.*`?
|
||||
3. **MVP 是否必须流式输出**:可先非流式降低复杂度?
|
||||
4. **长文策略**:仅截断 / 先分块摘要再问答 / 直接上简单 RAG?
|
||||
5. **默认 Provider 与默认模型**:建议默认 `openrouter` 或 `ollama`?各预设的默认 model 字符串?(当前草案:无强制默认云,首次打开引导选择)
|
||||
6. **品牌名是否确定为 ChatPapers**(插件 ID、命名空间将据此固定)?
|
||||
7. **对话历史是否需要跨设备同步**(当前默认:不同步)?
|
||||
8. ~~Ollama / LM Studio / OpenRouter 是否进 MVP~~ → **已确认进 MVP(P0)**
|
||||
|
||||
---
|
||||
|
||||
## 附录 A. 偏好项清单(草案)
|
||||
|
||||
| Preference Key | 类型 | 默认 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `extensions.chatpapers.provider` | string | `""`(首次引导) | 预设 ID:`ollama` / `lmstudio` / `openrouter` / … / `custom` |
|
||||
| `extensions.chatpapers.apiBaseUrl` | string | 随预设 | API 根路径(可覆写) |
|
||||
| `extensions.chatpapers.apiKey` | string | `""` | API Key;本地预设可空 |
|
||||
| `extensions.chatpapers.model` | string | 随预设 | 模型名 |
|
||||
| `extensions.chatpapers.openrouterReferer` | string | `https://github.com/chatpapers` | OpenRouter 可选 Referer |
|
||||
| `extensions.chatpapers.openrouterTitle` | string | `ChatPapers` | OpenRouter 可选 X-Title |
|
||||
| `extensions.chatpapers.temperature` | number | `0.3` | 温度 |
|
||||
| `extensions.chatpapers.maxTokens` | number | `2048` | 最大生成 Token |
|
||||
| `extensions.chatpapers.timeoutMs` | number | `120000` | 超时(本地大模型可调大) |
|
||||
| `extensions.chatpapers.maxContextChars` | number | `80000` | 上下文上限 |
|
||||
| `extensions.chatpapers.answerLanguage` | string | `zh-CN` | 回答语言偏好 |
|
||||
| `extensions.chatpapers.systemPrompt` | string | (内置模板) | 可覆盖 |
|
||||
| `extensions.chatpapers.summaryPrompt` | string | (内置模板) | 总结模板 |
|
||||
| `extensions.chatpapers.sendMetadata` | bool | `true` | 是否附带条目元数据 |
|
||||
| `extensions.chatpapers.verboseLog` | bool | `false` | 调试日志 |
|
||||
|
||||
---
|
||||
|
||||
## 附录 B. 竞品参考(仅作范围对照,非抄袭目标)
|
||||
|
||||
- PapersGPT、Zotero-easyGPT、llm-for-zotero:侧边栏对话 / 多模型
|
||||
- Zotero MCP 类插件:对外暴露库能力给 Cursor/Claude
|
||||
|
||||
ChatPapers MVP:单 PDF 对话 + 总结 + 笔记回流 + **多 Provider 预设(Ollama / LM Studio / OpenRouter 等)**。
|
||||
Reference in New Issue
Block a user