mirror of
https://github.com/lllin000/PaperForge.git
synced 2026-07-22 06:50:53 +00:00
feat: dashboard ui refine — arrow icons, maillard colors, responsive grid, setup bugfix
Dashboard UI: - Replace text expand/collapse with SVG arrow + clickable gradient container - Map agent_platform key to display name (OpenCode, not opencode) - Maillard/Morandi palette for OCR progress bars (pending brown, done deep green) - Shorten 'Needs Attention' to 'Attention' to prevent label wrap - Responsive workflow overview: CSS Grid + container queries (narrow: 2x2, wide: 4x1 with max-width 160px stop) Setup Wizard: - Fix Phase 7 verification crash (undefined agents_src/agents_dst variables) Skill restructure: - Move chart-reading references under references/ directory - Remove old pf-*.md script files (deployed via skill_deploy service) - Add new reference files (deep-reading, paper-qa, paper-resolution, save-session)
This commit is contained in:
parent
f9fbbfb2f0
commit
5c6ccaad34
35 changed files with 1041 additions and 1703 deletions
|
|
@ -1460,11 +1460,20 @@ class PaperForgeStatusView extends ItemView {
|
|||
const truncated = extracted.length > 200 ? extracted.slice(0, 200) + '...' : extracted;
|
||||
excerptEl.setText(truncated);
|
||||
if (extracted.length > 200) {
|
||||
const expandBtn = body.createEl('button', { cls: 'paperforge-paper-overview-expand', text: '展开' });
|
||||
const expandContainer = body.createEl('div', { cls: 'paperforge-expand-container' });
|
||||
const expandBtn = expandContainer.createEl('button', { cls: 'paperforge-expand-icon', title: '展开/收起' });
|
||||
|
||||
// Insert arrow SVG
|
||||
expandBtn.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
|
||||
|
||||
let expanded = false;
|
||||
expandBtn.addEventListener('click', () => {
|
||||
|
||||
// Make the whole container clickable
|
||||
expandContainer.addEventListener('click', () => {
|
||||
excerptEl.setText(expanded ? truncated : extracted);
|
||||
expandBtn.setText(expanded ? '展开' : '收起');
|
||||
expandBtn.innerHTML = expanded
|
||||
? '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>'
|
||||
: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"></polyline></svg>';
|
||||
expanded = !expanded;
|
||||
});
|
||||
}
|
||||
|
|
@ -1556,14 +1565,23 @@ class PaperForgeStatusView extends ItemView {
|
|||
: (qa.answer || '');
|
||||
aEl.createEl('span', { cls: 'paperforge-discussion-a-text', text: '解答:' + shortAnswer });
|
||||
if (qa.answer && qa.answer.length > 150) {
|
||||
const expandLink = aEl.createEl('button', { cls: 'paperforge-discussion-expand', text: '展开' });
|
||||
const expandContainer = aEl.createEl('div', { cls: 'paperforge-expand-container' });
|
||||
const expandBtn = expandContainer.createEl('button', { cls: 'paperforge-expand-icon', title: '展开/收起' });
|
||||
|
||||
// Insert arrow SVG
|
||||
expandBtn.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
|
||||
|
||||
let expanded = false;
|
||||
expandLink.addEventListener('click', () => {
|
||||
|
||||
// Make the whole container clickable
|
||||
expandContainer.addEventListener('click', () => {
|
||||
const textSpan = aEl.querySelector('.paperforge-discussion-a-text');
|
||||
if (textSpan) {
|
||||
textSpan.setText(expanded ? ('解答:' + shortAnswer) : ('解答:' + qa.answer));
|
||||
}
|
||||
expandLink.setText(expanded ? '展开' : '收起');
|
||||
expandBtn.innerHTML = expanded
|
||||
? '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>'
|
||||
: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"></polyline></svg>';
|
||||
expanded = !expanded;
|
||||
});
|
||||
}
|
||||
|
|
@ -1692,9 +1710,19 @@ class PaperForgeStatusView extends ItemView {
|
|||
});
|
||||
|
||||
// Show "Run in [agent_platform]" label below the button (DASH-02)
|
||||
const platform = this.app.plugins.plugins['paperforge']?.settings?.agent_platform || 'opencode';
|
||||
const platformKey = this.app.plugins.plugins['paperforge']?.settings?.agent_platform || 'opencode';
|
||||
const AGENTS = {
|
||||
'opencode': 'OpenCode',
|
||||
'claude': 'Claude Code',
|
||||
'cursor': 'Cursor',
|
||||
'github_copilot': 'GitHub Copilot',
|
||||
'windsurf': 'Windsurf',
|
||||
'codex': 'Codex',
|
||||
'cline': 'Cline'
|
||||
};
|
||||
const platformName = AGENTS[platformKey] || platformKey;
|
||||
const labelEl = card.createEl('div', { cls: 'paperforge-agent-platform-label' });
|
||||
labelEl.setText(t('run_in_agent').replace('{0}', platform));
|
||||
labelEl.setText(t('run_in_agent').replace('{0}', platformName));
|
||||
} else if (nextStep === 'ready') {
|
||||
const trigger = card.createEl('button', { cls: 'paperforge-next-step-trigger' });
|
||||
trigger.createEl('span', { text: '✓ ' + info.label });
|
||||
|
|
@ -1806,7 +1834,7 @@ class PaperForgeStatusView extends ItemView {
|
|||
{ cls: 'pending', value: ocrPending, label: 'Pending' },
|
||||
{ cls: 'active', value: ocrProcessing, label: 'Processing' },
|
||||
{ cls: 'done', value: ocrDone, label: 'Done' },
|
||||
{ cls: 'failed', value: ocrFailed, label: 'Needs Attention' },
|
||||
{ cls: 'failed', value: ocrFailed, label: 'Attention' },
|
||||
];
|
||||
for (const l of ocrLabels) {
|
||||
const cnt = ocrCounts.createEl('div', { cls: 'paperforge-ocr-count' });
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1012,7 +1012,7 @@ def headless_setup(
|
|||
"OCR dir": (pf_path / "ocr").exists(),
|
||||
"paperforge.json": pf_json.exists(),
|
||||
"Obsidian plugin": (vault / ".obsidian" / "plugins" / "paperforge" / "main.js").exists(),
|
||||
"AGENTS.md": True if not agents_src.exists() else agents_dst.exists(),
|
||||
"AGENTS.md": (vault / "AGENTS.md").exists(),
|
||||
}
|
||||
failed = [k for k, v in checks.items() if not v]
|
||||
if failed:
|
||||
|
|
|
|||
80
paperforge/skills/literature-qa/SKILL.md
Normal file
80
paperforge/skills/literature-qa/SKILL.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
---
|
||||
name: literature-qa
|
||||
description: >
|
||||
学术文献精读与问答。MUST trigger when user types /pf-deep, /pf-paper, /pf-end,
|
||||
or says "精读", "深度阅读", "读一下", "查一下这篇论文", "帮我看看这篇文章",
|
||||
"这篇文章讲了什么", "保存讨论", "结束讨论", "做这篇文献的问答",
|
||||
or any phrase about reading/analyzing papers in their Zotero library.
|
||||
支持 Zotero key, DOI, 标题, 作者/年份, 自然语言描述定位论文.
|
||||
license: Apache-2.0
|
||||
compatibility: opencode
|
||||
---
|
||||
|
||||
# Literature QA — 学术文献精读与问答
|
||||
|
||||
## 路由表
|
||||
|
||||
Agent 读到本文件后,首先根据用户意图路由到对应的 reference 文件:
|
||||
|
||||
| 用户意图 | 典型输入 | 加载文件 |
|
||||
|---------|---------|---------|
|
||||
| 三阶段精读(指定论文) | `/pf-deep <query>`, `pf-deep <query>`, "精读 XXX", "深度阅读 XXX" | [references/deep-reading.md](references/deep-reading.md) |
|
||||
| 三阶段精读(查看队列) | `/pf-deep`(无参数), "精读队列", "有哪些该读了" | [references/deep-reading.md](references/deep-reading.md) |
|
||||
| 论文问答 | `/pf-paper <query>`, `pf-paper <query>`, "做这篇的问答", "帮我看看 XXX" | [references/paper-qa.md](references/paper-qa.md) |
|
||||
| 保存讨论记录 | `/pf-end`, `pf-end`, "保存", "结束讨论", "完成讨论" | [references/save-session.md](references/save-session.md) |
|
||||
|
||||
> **重要:** 加载 reference 文件后,严格按照该文件的流程执行。不要跳过任何步骤。
|
||||
|
||||
## 论文定位(所有路由共用,先执行)
|
||||
|
||||
详见 [references/paper-resolution.md](references/paper-resolution.md)。
|
||||
|
||||
**核心原则:二路定位。Python 干确定的活,Agent 干理解的活。路径全在环境变量里,零硬编码。**
|
||||
|
||||
### 第零步:加载环境变量(每条路由启动时跑一次)
|
||||
|
||||
```pwsh
|
||||
python -m paperforge.worker.paper_resolver env --vault . --shell pwsh | Invoke-Expression
|
||||
```
|
||||
|
||||
此后所有路径用环境变量引用,不再拼接:
|
||||
|
||||
| 变量 | 含义 |
|
||||
| ------------------ | --------------------------- |
|
||||
| `$env:PF_VAULT` | vault 根目录 |
|
||||
| `$env:PF_INDEX_PATH` | formal-library.json 路径 |
|
||||
| `$env:PF_LITERATURE_DIR` | formal notes 目录 |
|
||||
| `$env:PF_OCR_DIR` | OCR 结果目录 |
|
||||
|
||||
### 第一步:判断输入类型,选择路径
|
||||
|
||||
| 输入特征 | 执行命令 |
|
||||
|---------|---------|
|
||||
| 8位 key | `python -m paperforge.worker.paper_resolver resolve-key <KEY> --vault "$env:PF_VAULT"` |
|
||||
| DOI | `python -m paperforge.worker.paper_resolver resolve-doi "<DOI>" --vault "$env:PF_VAULT"` |
|
||||
| 标题片段 | `python -m paperforge.worker.paper_resolver search --title "..." --vault "$env:PF_VAULT"` |
|
||||
| 作者+年份 | `python -m paperforge.worker.paper_resolver search --author "Smith" --year 2024 --vault "$env:PF_VAULT"` |
|
||||
| 自然语言 | Agent 读 `$env:PF_INDEX_PATH` 指向的 formal-library.json |
|
||||
|
||||
### 第二步:处理结果
|
||||
|
||||
- **Python 返回匹配:** 直接使用返回的 workspace(`formal_note_path` 等由 config 动态计算)
|
||||
- **Python 搜不到:** Agent grep fallback:`rg -l "zotero_key:.*ABC" "$env:PF_LITERATURE_DIR/"`
|
||||
- **自然语言搜不到:** 告知用户 "未找到,请确认或先运行 `paperforge sync`"
|
||||
- **命中多篇:** 列出候选清单让用户选
|
||||
|
||||
## 文件结构
|
||||
|
||||
```
|
||||
literature-qa/
|
||||
├── SKILL.md ← 本文件(路由入口)
|
||||
├── references/
|
||||
│ ├── deep-reading.md ← 精读工作流
|
||||
│ ├── paper-qa.md ← 问答工作流
|
||||
│ ├── save-session.md ← 保存记录工作流
|
||||
│ ├── paper-resolution.md ← 论文定位详细协议
|
||||
│ ├── deep-subagent.md ← 子代理提示词模板
|
||||
│ └── chart-reading/ ← 19 个图表类型阅读指南
|
||||
└── scripts/
|
||||
└── ld_deep.py ← 精读引擎(Python)
|
||||
```
|
||||
171
paperforge/skills/literature-qa/references/deep-reading.md
Normal file
171
paperforge/skills/literature-qa/references/deep-reading.md
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
# 三阶段精读
|
||||
|
||||
Keshav 三阶段组会式精读。触发后执行以下工作流。
|
||||
|
||||
> **路径说明:** 本文件中的 `scripts/ld_deep.py` 相对于本 skill 目录。Agent 运行时 skill 目录由平台注入(通常为 `<installation_path>/paperforge/skills/literature-qa/`)。如不确定,AI 应从 SKILL.md 所在目录推断。
|
||||
|
||||
---
|
||||
|
||||
## 前置条件检查
|
||||
|
||||
执行前确认:
|
||||
- [ ] 已完成论文定位(参考 [paper-resolution.md](paper-resolution.md)),拿到 zotero_key 和 workspace
|
||||
- [ ] `analyze: true`(在 formal note frontmatter 中,resolver 返回的 workspace 里可查到)
|
||||
- [ ] `ocr_status: done`(在 resolver 返回的 workspace 里可查到)
|
||||
|
||||
如果前置条件不满足,告知用户并停止。
|
||||
|
||||
---
|
||||
|
||||
## 执行流程
|
||||
|
||||
### Step 1: Prepare(机械操作,跑脚本)
|
||||
|
||||
```bash
|
||||
python scripts/ld_deep.py prepare --vault . --key <ZOTERO_KEY>
|
||||
```
|
||||
|
||||
返回 JSON 解析:
|
||||
- `status: "ok"` → 继续
|
||||
- `status: "error"` → 报告 `message` 给用户,停止
|
||||
|
||||
Prepare 做的事情(Agent 不需要关心细节):
|
||||
- 检查 analyze 和 ocr_status
|
||||
- 生成 figure-map.json 和 chart-type-map.json
|
||||
- 在 formal note 中插入 `## 🔍 精读` 骨架
|
||||
|
||||
读 formal note 确认骨架已插入。
|
||||
|
||||
---
|
||||
|
||||
### Step 2: Pass 1 — 概览
|
||||
|
||||
只填 `### Pass 1: 概览` 区域。不碰 Pass 2/3。
|
||||
|
||||
**填写内容:**
|
||||
|
||||
- **一句话总览**:论文类型 + 核心发现,一句话。
|
||||
- **5 Cs 快速评估**:
|
||||
- **Category**(类型):RCT / 队列研究 / 病例对照 / 综述 / 基础研究 / ...
|
||||
- **Context**(上下文):该领域当前共识,本文要解决什么问题
|
||||
- **Correctness**(合理性初判):初步直觉,逻辑是否有明显漏洞
|
||||
- **Contributions**(贡献):1-3 条
|
||||
- **Clarity**(清晰度):写作质量,图表可读性
|
||||
- **Figure 导读**(基于 fulltext.md 浏览各图 caption):
|
||||
- 关键主图:列出并一句话概括每个主图要证明什么
|
||||
- 证据转折点:哪个 figure 是叙事的关键转折
|
||||
- 需要重点展开的 supplementary:如果有
|
||||
- 关键表格:列出
|
||||
|
||||
填完立即保存 formal note。
|
||||
|
||||
---
|
||||
|
||||
### Step 3: Pass 2 — 精读还原
|
||||
|
||||
填 `### Pass 2: 精读还原` 区域。**按 figure 顺序逐个处理。**
|
||||
|
||||
#### 图表类型定位(两步)
|
||||
|
||||
**Step A: Python 给建议(快速初筛)**
|
||||
```bash
|
||||
python scripts/ld_deep.py chart-type-scan --vault . --key <ZOTERO_KEY>
|
||||
```
|
||||
输出每个 figure 的关键词命中结果。这只是建议,Agent 不要盲信。
|
||||
|
||||
**Step B: Agent 读 caption 做最终判断**
|
||||
|
||||
对每个 figure:
|
||||
1. 读该 figure 的 caption(来自 fulltext.md 或 figure-map.json)
|
||||
2. 根据 caption 内容,对照 [chart-reading/INDEX.md](chart-reading/INDEX.md) 判断图表类型
|
||||
3. 如果 Python 建议和 Agent 判断不一致 → 以 Agent 判断为准
|
||||
4. 如果无法确定类型 → 跳过 chart guide,按通用 figure 结构分析
|
||||
5. 确定类型后,读对应的 chart-reading 指南(如 `chart-reading/条形图与误差棒.md`),按指南中的检查清单分析
|
||||
|
||||
#### 每张 Figure 的子标题(固定,不可少)
|
||||
|
||||
按以下格式填入 formal note 中该 figure 的 callout block:
|
||||
|
||||
```
|
||||
**图像定位与核心问题**:页码 + 要回答什么问题
|
||||
**方法与结果**:实验设计/数据来源/技术手段。核心数据、趋势、对比。
|
||||
**图表质量审查**:按 chart-reading 指南检查坐标轴、单位、误差棒、统计标注等。
|
||||
**作者解释**:作者在正文中对该图的解读
|
||||
**我的理解**:自己的理解(区分于作者解释)
|
||||
**疑点/局限**:读图时发现的疑问,用 `> [!warning]` 突出
|
||||
```
|
||||
|
||||
#### 每张 Table 的子标题
|
||||
|
||||
```
|
||||
回答什么问题、关键字段/分组、主要结果、我的理解、疑点/局限
|
||||
```
|
||||
|
||||
#### 每张 figure 填完立即保存,再处理下一张。
|
||||
|
||||
#### 所有 figure/table 处理完后,填:
|
||||
|
||||
**关键方法补课**:简要解释不熟悉的实验技术(1-2 项即可)
|
||||
|
||||
**主要发现与新意**:
|
||||
- 发现 1:...(来源:Figure X)
|
||||
- 发现 2:...(来源:Figure Y / Table Z)
|
||||
|
||||
保存。
|
||||
|
||||
---
|
||||
|
||||
### Step 4: Postprocess(跑校验脚本,修正问题)
|
||||
|
||||
```bash
|
||||
python scripts/ld_deep.py postprocess-pass2 <formal_note_path> --figures <N> --format text
|
||||
```
|
||||
|
||||
- 输出 `OK` → 继续
|
||||
- 输出错误 → 按错误提示修正(包含行号),修正后重新跑
|
||||
- 最多 3 轮修正。3 轮后仍失败 → 报告剩余错误给用户
|
||||
|
||||
---
|
||||
|
||||
### Step 5: Pass 3 — 深度理解
|
||||
|
||||
填 `### Pass 3: 深度理解` 区域。基于 Pass 1/2 已写的内容。
|
||||
|
||||
**填写内容:**
|
||||
|
||||
- **假设挑战与隐藏缺陷**:隐含假设;如果放宽某个假设结论还成立吗;缺少哪些关键引用;实验/分析技术潜在问题
|
||||
- **哪些结论扎实,哪些仍存疑**:
|
||||
- **较扎实**:...
|
||||
- **仍存疑**:...(用 `> [!warning]`)
|
||||
- **Discussion 与 Conclusion 怎么读**:作者真正完成了什么;哪些地方有拔高;哪些是推测
|
||||
- **对我的启发**:研究设计上;figure 组织上;方法组合上;未来工作想法
|
||||
- **遗留问题**:...(用 `> [!question]`)
|
||||
|
||||
保存。
|
||||
|
||||
---
|
||||
|
||||
### Step 6: Final Validation
|
||||
|
||||
```bash
|
||||
python scripts/ld_deep.py validate-note <formal_note_path> --fulltext <fulltext_path>
|
||||
```
|
||||
|
||||
- 输出 `OK` → 告知用户精读完成
|
||||
- 输出错误 → 修正缺失项,不报告成功直到通过
|
||||
|
||||
---
|
||||
|
||||
## Callout 格式规则
|
||||
|
||||
- `> [!important]`:每个 main finding
|
||||
- `> [!warning]`:疑问、局限、证据边界、仍存疑条目
|
||||
- `> [!question]`:遗留问题
|
||||
- **间距:** 相邻 callout block 之间必须有空行,否则 Obsidian 会合并
|
||||
- 正确:`> [!important] A\n\n> [!important] B`
|
||||
- 错误:`> [!important] A\n> [!important] B`
|
||||
|
||||
## Supplementary 规则
|
||||
|
||||
- 默认不逐张展开 supplementary figure/table
|
||||
- 仅在以下情况纳入:对主结论形成关键支撑、补足方法可信度、限制主文结论解释范围、作者在正文中明显依赖该补充材料
|
||||
61
paperforge/skills/literature-qa/references/paper-qa.md
Normal file
61
paperforge/skills/literature-qa/references/paper-qa.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# 论文问答
|
||||
|
||||
交互式论文 Q&A 工作台。不强制要求 OCR,但 OCR 完成后回答更准确。
|
||||
|
||||
---
|
||||
|
||||
## 前置条件
|
||||
|
||||
- [ ] 已完成论文定位(参考 [paper-resolution.md](paper-resolution.md)),拿到 zotero_key 和 workspace
|
||||
- [ ] OCR 完成(推荐但非强制)
|
||||
|
||||
---
|
||||
|
||||
## 执行流程
|
||||
|
||||
### Step 1: 加载论文
|
||||
|
||||
1. 确认 workspace 路径
|
||||
2. 读 `fulltext.md`(如果存在)作为主要回答依据
|
||||
3. 读 formal note frontmatter 获取元数据(标题、作者、期刊、年份)
|
||||
4. 如果 fulltext.md 不存在,告知用户 "OCR 文本不可用,回答将基于元数据和公开信息"
|
||||
|
||||
### Step 2: 显示论文信息
|
||||
|
||||
```
|
||||
已加载论文: [title] ([year], [journal])
|
||||
作者: [authors]
|
||||
Zotero Key: [key]
|
||||
领域: [domain]
|
||||
OCR 状态: [done / 不可用]
|
||||
结束对话时说 "保存" 即可保存讨论。
|
||||
请问有什么问题?
|
||||
```
|
||||
|
||||
### Step 3: 进入 Q&A 模式
|
||||
|
||||
- 等待用户提问
|
||||
- 每次回答后等待下一个问题
|
||||
- 持续到用户说 "保存"、"结束"、"完成" 等关键词
|
||||
|
||||
---
|
||||
|
||||
## 回答原则
|
||||
|
||||
- **严格基于** fulltext.md 中的文本内容回答
|
||||
- 引用原文时标注来源页码/章节(如 "第 3 页,Methods 部分")
|
||||
- 用中文(简体中文)回答
|
||||
- 论文中未提及的内容,明确说明 "论文中未提及该内容"
|
||||
- 需要结合论文以外知识的问题,说明 "该问题需要结合论文以外的知识"
|
||||
|
||||
---
|
||||
|
||||
## 切换模式
|
||||
|
||||
用户在当前对话中可以说 "精读这篇文章" 切换到 deep-reading 模式。此时加载 [deep-reading.md](deep-reading.md) 执行精读流程。
|
||||
|
||||
---
|
||||
|
||||
## 保存记录
|
||||
|
||||
用户说 "保存"、"结束"、"完成"、"保存讨论" 时,加载 [save-session.md](save-session.md) 执行保存。不要自动保存。
|
||||
173
paperforge/skills/literature-qa/references/paper-resolution.md
Normal file
173
paperforge/skills/literature-qa/references/paper-resolution.md
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
# 论文定位协议
|
||||
|
||||
本文件定义如何将用户输入(key / DOI / 标题 / 作者年份 / 自然语言)解析为论文 workspace。所有子流程(deep-reading, paper-qa, save-session)共用此协议。
|
||||
|
||||
## 核心原则
|
||||
|
||||
1. **确定性输入走 Python。** key、DOI、标题片段、作者+年份 —— 这些是机器能精确处理的。
|
||||
2. **自然语言走 Agent。** "关于骨再生的那篇"、"去年那篇Nature" —— 需要 AI 理解语义。
|
||||
3. **Python 搜不到时 Agent 兜底。** 不是报错,是换个方式再试一次。
|
||||
4. **所有路径从环境变量获取。** 每条路由启动时先跑 `python -m paperforge.worker.paper_resolver env --vault . --shell pwsh | Invoke-Expression`。此后 `$env:PF_VAULT`、`$env:PF_LITERATURE_DIR`、`$env:PF_OCR_DIR`、`$env:PF_INDEX_PATH` 全程可用。不写死任何目录名。
|
||||
|
||||
---
|
||||
|
||||
## 前置:获取 vault 路径配置(每个路由启动时跑一次)
|
||||
|
||||
```bash
|
||||
python -m paperforge.worker.paper_resolver paths --vault .
|
||||
```
|
||||
|
||||
返回示例(所有路径均由 `paperforge.json` 动态计算):
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"data": {
|
||||
"vault_root": "/path/to/vault",
|
||||
"index_path": "<system_dir>/PaperForge/indexes/formal-library.json",
|
||||
"literature_dir": "<resources_dir>/<literature_dir>",
|
||||
"ocr_dir": "<system_dir>/PaperForge/ocr"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**后续所有路径操作使用此输出中的值,不要自己拼接。**
|
||||
|
||||
---
|
||||
|
||||
## 输入类型判断
|
||||
|
||||
### 类型 1: Zotero Key(8位字符)
|
||||
|
||||
**识别规则:** 8位字母数字组合,如 `XGT9Z257`、`ABC12345`
|
||||
|
||||
**执行命令:**
|
||||
```bash
|
||||
python -m paperforge.worker.paper_resolver resolve-key <KEY> --vault .
|
||||
```
|
||||
|
||||
**返回示例(路径由 paperforge.json 配置决定,不固定):**
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"data": {
|
||||
"match": {
|
||||
"key": "ABC12345",
|
||||
"title": "TGF-beta in Bone Regeneration",
|
||||
"domain": "骨科",
|
||||
"formal_note_path": "...",
|
||||
"ocr_path": "...",
|
||||
"fulltext_path": "...",
|
||||
"ocr_status": "done"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**返回 `"match": null` 时:** Agent fallback — 用 `paths` 命令获取的 `literature_dir` 路径 grep frontmatter:
|
||||
```bash
|
||||
rg -l "zotero_key:.*ABC12345" <literature_dir>/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 类型 2: DOI
|
||||
|
||||
**识别规则:** 以 `10.` 开头的标准 DOI 格式,可能带 URL 前缀
|
||||
|
||||
**执行命令:**
|
||||
```bash
|
||||
python -m paperforge.worker.paper_resolver resolve-doi "10.1016/j.jse.2018.01.001" --vault .
|
||||
```
|
||||
|
||||
**返回格式同类型1。** 返回的路径直接使用,不自己拼接。
|
||||
|
||||
---
|
||||
|
||||
### 类型 3: 标题片段
|
||||
|
||||
**识别规则:** 看起来像论文标题的文本(含学术关键词,非自然语言问句)
|
||||
|
||||
**执行命令:**
|
||||
```bash
|
||||
python -m paperforge.worker.paper_resolver search --title "Predictive findings on MRI" --vault .
|
||||
```
|
||||
|
||||
**返回示例:**
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"data": {
|
||||
"matches": [{ "key": "...", "title": "...", "formal_note_path": "...", ... }],
|
||||
"count": 3
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 类型 4: 作者 + 年份
|
||||
|
||||
**识别规则:** 包含作者名(英文姓)和年份
|
||||
|
||||
**执行命令:**
|
||||
```bash
|
||||
python -m paperforge.worker.paper_resolver search --author "Smith" --year 2024 --vault .
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 类型 5: 自然语言
|
||||
|
||||
**识别规则:** 中文自然语言描述,如 "关于骨再生的那篇"、"去年Nature上那篇讲TGF的"
|
||||
|
||||
**Agent 操作:**
|
||||
1. 用 `paths` 命令获取的 `index_path` 读 `formal-library.json`
|
||||
2. 理解用户意图中的关键信息:主题词、年份、期刊、领域
|
||||
3. 在 JSON 的 `title`、`domain`、`journal`、`abstract` 字段中搜索匹配
|
||||
4. 如果 formal-library.json 无结果,用 `paths` 命令获取的 `literature_dir` grep formal notes:
|
||||
```bash
|
||||
rg -i -l "骨再生|bone regeneration" <literature_dir>/ --include "*.md" -g "!*.canvas"
|
||||
```
|
||||
5. 读匹配的 frontmatter 确认是目标论文
|
||||
|
||||
---
|
||||
|
||||
## 多篇匹配处理
|
||||
|
||||
当搜索返回多个匹配时,Agent 必须列出候选清单,让用户选择:
|
||||
|
||||
```
|
||||
找到 3 篇匹配的论文:
|
||||
|
||||
[1] ABC12345 — TGF-beta in Bone Regeneration (2024, 骨科, OCR: done)
|
||||
[2] DEF67890 — Bone Healing After Fracture (2023, 骨科, OCR: pending)
|
||||
[3] GHI11111 — Scaffold Design for Bone Repair (2024, 骨科, OCR: done)
|
||||
|
||||
请输入编号选择,或 refine 搜索词。
|
||||
```
|
||||
|
||||
**格式要求:**
|
||||
- 编号 + key + title + (year, domain, ocr_status)
|
||||
- 不要只列标题或只列 key
|
||||
|
||||
---
|
||||
|
||||
## Fallback 顺序
|
||||
|
||||
```
|
||||
输入
|
||||
│
|
||||
├── 看起来像 key/DOI/标题/作者年份?
|
||||
│ └── YES → Python paper_resolver
|
||||
│ ├── 有结果 → 使用
|
||||
│ └── 无结果 → Agent grep fallback
|
||||
│ ├── 有结果 → 使用
|
||||
│ └── 无结果 → 告知用户
|
||||
│
|
||||
└── 看起来像自然语言?
|
||||
└── Agent 读 formal-library.json
|
||||
├── 有结果 → 列出/使用
|
||||
└── 无结果 → Agent grep fallback
|
||||
├── 有结果 → 使用
|
||||
└── 无结果 → 告知用户
|
||||
```
|
||||
55
paperforge/skills/literature-qa/references/save-session.md
Normal file
55
paperforge/skills/literature-qa/references/save-session.md
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# 保存讨论记录
|
||||
|
||||
将 paper-qa 会话中的 Q&A 记录持久化到论文工作区。
|
||||
|
||||
---
|
||||
|
||||
## 触发条件
|
||||
|
||||
- 用户显式说 "保存"、"保存记录"、"结束"、"完成讨论"、"save"
|
||||
- 或显式输入 `/pf-end`
|
||||
- 不要自动触发
|
||||
|
||||
---
|
||||
|
||||
## 执行
|
||||
|
||||
### Step 1: 收集 Q&A 对
|
||||
|
||||
汇总本次 paper-qa 会话中所有 Q&A,序列化为 JSON 数组:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"question": "用户的问题",
|
||||
"answer": "Agent 的回答",
|
||||
"source": "user_question",
|
||||
"timestamp": "2026-05-10T12:00:00+08:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
`source` 为 `"user_question"`(用户提问)或 `"agent_analysis"`(Agent 主动分析)。
|
||||
|
||||
### Step 2: 调用 discussion 模块
|
||||
|
||||
```bash
|
||||
python -m paperforge.worker.discussion record <ZOTERO_KEY> \
|
||||
--vault . \
|
||||
--agent pf-paper \
|
||||
--model "<CURRENT_MODEL>" \
|
||||
--qa-pairs '<JSON_ARRAY>'
|
||||
```
|
||||
|
||||
### Step 3: 确认结果
|
||||
|
||||
CLI 返回 `{"status": "ok", ...}` → 告知用户记录已保存。
|
||||
|
||||
返回 `{"status": "error"}` → 记录错误,重试一次。仍失败则告知用户。
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 仅 paper-qa 会话需要记录。deep-reading 的内容直接写入 formal note,不需要通过本文件。
|
||||
- 如果无法从 formal-library.json 找到论文 domain/title,记录失败不应影响用户使用。
|
||||
|
|
@ -1,237 +0,0 @@
|
|||
---
|
||||
name: pf-deep
|
||||
description: Complete three-pass deep reading of an academic paper (Keshav method). Requires OCR fulltext. Searches by Zotero key, title, DOI, or PMID.
|
||||
allowed-tools: [Read, Bash, Edit]
|
||||
---
|
||||
|
||||
# <prefix>pf-deep
|
||||
|
||||
## Purpose
|
||||
|
||||
基于单篇论文的组会式精读入口。
|
||||
|
||||
1. 解析 `<prefix>pf-deep <query>` 中的查询词
|
||||
2. 支持 Zotero key、标题片段、DOI、PMID、关键词
|
||||
3. 优先搜索本地 Zotero 并锁定单篇论文
|
||||
4. 绑定该论文对应的:
|
||||
- `<system_dir>/PaperForge/ocr/<KEY>/fulltext.md`
|
||||
- `<system_dir>/PaperForge/ocr/<KEY>/meta.json`
|
||||
- `<resources_dir>/<literature_dir>/.../KEY - Title.md`
|
||||
5. 在正式文献卡片中检查或创建 `## 精读`
|
||||
6. 以"研究思路 + figure-by-figure"方式一次性完成精读写回
|
||||
|
||||
## CLI Equivalent
|
||||
|
||||
```bash
|
||||
# 准备阶段(间接)
|
||||
python .opencode/skills/pf-deep/scripts/ld_deep.py prepare --vault "<VAULT_PATH>" --key <ZOTERO_KEY>
|
||||
# 返回 JSON:{status, formal_note, fulltext_md, figures, tables}
|
||||
```
|
||||
|
||||
> `<prefix>pf-deep` 是 **Agent 层命令**,通过 Python 代码自动检测论文状态,无需先行 CLI 准备。
|
||||
|
||||
## Detection(自动检测,无需手动 sync)
|
||||
|
||||
启动时,Agent 执行以下 Python 检测命令,代码会自动判断是否需要精读:
|
||||
|
||||
```bash
|
||||
python .opencode/skills/pf-deep/scripts/ld_deep.py prepare --vault "<VAULT_PATH>" --key <ZOTERO_KEY>
|
||||
```
|
||||
|
||||
返回 JSON:
|
||||
- `status: "ok"` → 就绪,可以开始精读
|
||||
- `status: "error"` → 被阻塞(`message` 说明原因:analyze=false / OCR 未完成 / 未找到论文)
|
||||
|
||||
Agent 根据返回的 `status` 决定是否进入精读流程,不自行读取 frontmatter。
|
||||
|
||||
**队列模式**(无参数时自动检测):Agent 运行:
|
||||
```bash
|
||||
python .opencode/skills/pf-deep/scripts/ld_deep.py queue --vault "<VAULT_PATH>"
|
||||
```
|
||||
代码自动扫描 canonical index 中 `analyze=true` 且 `deep_reading_status=pending` 的论文,按 OCR 状态分组。
|
||||
|
||||
## Arguments
|
||||
|
||||
| 参数 | 必需 | 说明 |
|
||||
|------|------|------|
|
||||
| `<query>` | 是(queue 模式除外) | Zotero key、标题片段、DOI、PMID 或关键词 |
|
||||
| `queue` | 否 | 启动批量精读队列模式 |
|
||||
|
||||
### 参数说明
|
||||
|
||||
1. 如果输入看起来像 8 位 Zotero key,则直接按 key 解析。
|
||||
2. 否则先在本地 Zotero 中搜索标题/摘要。
|
||||
3. 若命中唯一结果或明显最佳结果,则直接载入。
|
||||
4. 若存在多个合理候选,则先列候选清单再让用户选。
|
||||
5. 不要强迫用户先知道 Zotero key。
|
||||
|
||||
## Example
|
||||
|
||||
### 单篇精读(已知 key)
|
||||
|
||||
```bash
|
||||
<prefix>pf-deep XGT9Z257
|
||||
<prefix>pf-deep Predictive findings on magnetic resonance imaging
|
||||
<prefix>pf-deep 10.1016/j.jse.2018.01.001
|
||||
```
|
||||
|
||||
### 无参数:自动检测队列
|
||||
|
||||
```bash
|
||||
<prefix>pf-deep
|
||||
```
|
||||
|
||||
当不提供具体 key/标题时,agent 自动检测精读队列:
|
||||
|
||||
1. 运行 `python .opencode/skills/pf-deep/scripts/ld_deep.py queue --vault "<VAULT_PATH>"` 扫描队列
|
||||
2. 解析输出的 JSON,按 OCR 状态分组展示
|
||||
3. 由用户选择篇目
|
||||
|
||||
无需先跑 `paperforge sync`。
|
||||
|
||||
## Output
|
||||
|
||||
Agent 在正式笔记中创建或更新 `## 精读` 区域,包含:
|
||||
|
||||
- **Pass 1: 概览** — 一句话总览、5 Cs 快速评估、Figure 导读
|
||||
- **Pass 2: 精读还原** — Figure-by-Figure 解析、Table-by-Table 解析、关键方法补课、主要发现与新意
|
||||
- **Pass 3: 深度理解** — 假设挑战与隐藏缺陷、结论扎实性评估、Discussion 解读、个人启发、遗留问题
|
||||
|
||||
## Error Handling
|
||||
|
||||
### OCR 未完成
|
||||
- **表现**:Agent 提示 `ocr_status` 不是 `done`
|
||||
- **解决**:先运行 `paperforge ocr`,确认 `meta.json` 中 `ocr_status` 变为 `done`
|
||||
|
||||
### 内容已存在(覆盖确认)
|
||||
- **表现**:正式笔记中已存在 `## 精读` 区域且包含非占位符的实质内容
|
||||
- **处理**:Agent **必须**询问用户:追加 / 覆盖 / 跳过
|
||||
|
||||
### 未找到论文
|
||||
- **表现**:Zotero key 无效或搜索无结果
|
||||
- **解决**:确认 key 正确,或尝试用标题片段搜索
|
||||
|
||||
## 精读结构参考
|
||||
|
||||
### 执行原则
|
||||
|
||||
- `<prefix>pf-deep` 对用户来说是一次触发直接完成。
|
||||
- 内部逻辑分两步:
|
||||
1. 先生成 `## 精读` 骨架和 figure 标题位
|
||||
2. 再补全所有空段
|
||||
- 后续再次运行时(用户选择追加):
|
||||
- 只补空段,不覆盖已有内容
|
||||
|
||||
### 精读定位
|
||||
|
||||
这不是综述提取,也不是信息摘录。目标是模拟高水平博士/博士后组会讲解单篇论文的学习型精读。
|
||||
|
||||
主线必须是:
|
||||
|
||||
1. 文章整体研究思路
|
||||
2. 主文 figure 逐张解析
|
||||
3. 关键方法补课
|
||||
4. 主要发现、新意、疑点与启发
|
||||
|
||||
### Supplementary 规则
|
||||
|
||||
- 默认不逐张展开 supplementary figure/table。
|
||||
- 仅在以下情况下纳入:
|
||||
- 对主结论形成关键支撑
|
||||
- 补足方法可信度
|
||||
- 限制主文结论的解释范围
|
||||
- 作者在正文中明显依赖该补充材料
|
||||
|
||||
### 标准骨架
|
||||
|
||||
```md
|
||||
## 精读
|
||||
|
||||
**证据边界**:区分三层信息:`论文结果`、`作者解释`、`我的理解/推断`。
|
||||
|
||||
### Pass 1: 概览
|
||||
|
||||
**一句话总览**
|
||||
(待补充)
|
||||
|
||||
**5 Cs 快速评估**
|
||||
- **Category**(类型):
|
||||
- **Context**(上下文):
|
||||
- **Correctness**(合理性初判):
|
||||
- **Contributions**(贡献):
|
||||
- **Clarity**(清晰度):
|
||||
|
||||
**Figure 导读**
|
||||
- 关键主图:
|
||||
- 证据转折点:
|
||||
- 需要重点展开的 supplementary:
|
||||
- 关键表格:
|
||||
|
||||
### Pass 2: 精读还原
|
||||
|
||||
#### Figure-by-Figure 解析
|
||||
(每张 figure 下方按以下顺序填写)
|
||||
- **图像定位与核心问题**:页码 + 要回答什么问题
|
||||
- **方法与结果**:方法 + 结果
|
||||
- **作者解释**:作者对该图的解读
|
||||
- **我的理解**:自己的理解(区分于作者解释)
|
||||
- **在全文中的作用**:该图在整体故事线中的位置
|
||||
- **疑点 / 局限**:读图时发现的疑问
|
||||
|
||||
#### Table-by-Table 解析
|
||||
(如有重要表格,按同样结构展开)
|
||||
|
||||
#### 关键方法补课
|
||||
- 方法 1:
|
||||
- 方法 2:
|
||||
|
||||
#### 主要发现与新意
|
||||
**主要发现**
|
||||
- 发现 1:
|
||||
- 发现 2:
|
||||
|
||||
### Pass 3: 深度理解
|
||||
|
||||
#### 假设挑战与隐藏缺陷
|
||||
- 隐含假设:
|
||||
- 如果放宽某个假设,结论还成立吗?
|
||||
- 缺少哪些关键引用?
|
||||
- 实验/分析技术的潜在问题:
|
||||
|
||||
#### 哪些结论扎实,哪些仍存疑
|
||||
**较扎实**
|
||||
-
|
||||
|
||||
**仍存疑**
|
||||
-
|
||||
|
||||
#### Discussion 与 Conclusion 怎么读
|
||||
- 作者真正完成了什么:
|
||||
- 哪些地方有拔高:
|
||||
- 哪些地方是推测:
|
||||
|
||||
#### 对我的启发
|
||||
- 研究设计上:
|
||||
- figure 组织上:
|
||||
- 方法组合上:
|
||||
- 未来工作想法:
|
||||
|
||||
#### 遗留问题
|
||||
**遗留问题**
|
||||
-
|
||||
```
|
||||
|
||||
### Figure 节要求
|
||||
|
||||
每个 figure 小节按以下顺序填写:
|
||||
|
||||
- **图像定位与核心问题**:页码 + 要回答什么问题
|
||||
- **方法与结果**:方法 + 结果
|
||||
- **作者解释**:作者对该图的解读
|
||||
- **我的理解**:自己的理解(区分于作者解释)
|
||||
- **在全文中的作用**:该图在整体故事线中的位置
|
||||
- **疑点 / 局限**:读图时发现的疑问(可酌情用 `> [!warning]` 突出)
|
||||
|
||||
## See Also
|
||||
|
||||
- [pf-paper](pf-paper.md) — 快速摘要与问答
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
---
|
||||
name: pf-end
|
||||
description: Save the paper Q&A discussion record. Triggered when user says "保存" "结束" "save" or types $pf-end. Summarizes all Q&A pairs and writes them to the paper's ai/discussion directory via the discussion module.
|
||||
allowed-tools: [Read, Bash]
|
||||
---
|
||||
|
||||
# <prefix>pf-end
|
||||
|
||||
## Purpose
|
||||
|
||||
结束当前论文对话并保存讨论记录。需要用户**显式要求**时才执行,不自动触发。
|
||||
|
||||
1. 汇总本次对话中所有 Q&A 对
|
||||
2. 通过 `discussion.record_session()` 写入论文工作区的 `ai/` 目录
|
||||
3. 告知用户记录已保存
|
||||
|
||||
## Trigger
|
||||
|
||||
用户说以下任一关键词时执行(全平台通用):
|
||||
- `保存` / `记录` / `保存记录`
|
||||
- `结束` / `完成`
|
||||
- `save discussion` / `save` / `done`
|
||||
|
||||
也可以显式指定 key:
|
||||
- `{prefix}pf-end <zotero_key>`(OpenCode)
|
||||
- `保存 <zotero_key>`(全平台)
|
||||
|
||||
如果未指定 key,则使用当前已加载的论文 key。
|
||||
|
||||
## Save Format
|
||||
|
||||
将会话期间的所有 Q&A 序列化为 JSON 数组:
|
||||
|
||||
```json
|
||||
{
|
||||
"question": "用户的问题",
|
||||
"answer": "Agent 的回答",
|
||||
"source": "user_question",
|
||||
"timestamp": "2026-05-06T12:00:00+08:00"
|
||||
}
|
||||
```
|
||||
|
||||
`source` 为 `"user_question"`(用户提问)或 `"agent_analysis"`(Agent 主动分析)。
|
||||
|
||||
## Command
|
||||
|
||||
```bash
|
||||
python -m paperforge.worker.discussion record <ZOTERO_KEY> \
|
||||
--vault "<VAULT_PATH>" \
|
||||
--agent pf-paper \
|
||||
--model "<MODEL_NAME>" \
|
||||
--qa-pairs '<JSON_ARRAY>'
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
CLI 返回:
|
||||
```json
|
||||
{"status": "ok", "json_path": "Literature/{domain}/{key} - {title}/ai/discussion.json", "md_path": "..."}
|
||||
```
|
||||
|
||||
如果 `status` 为 `"error"`,记录错误信息并重试,不要跳过。
|
||||
|
||||
## See Also
|
||||
|
||||
- [pf-paper](pf-paper.md) — 论文 Q&A 工作台
|
||||
- [pf-deep](pf-deep.md) — 完整三阶段精读
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
---
|
||||
name: pf-ocr
|
||||
description: Process the PDF OCR queue for formal notes marked do_ocr: true. Uploads PDFs to PaddleOCR API and extracts fulltext with figures.
|
||||
allowed-tools: [Bash]
|
||||
---
|
||||
|
||||
# /pf-ocr
|
||||
|
||||
## Purpose
|
||||
|
||||
处理正式笔记 frontmatter 中 `do_ocr: true` 的 PDF OCR 队列。
|
||||
|
||||
`paperforge ocr` 会自动读取 `paperforge.json` 定位 ocr 目录和 worker 脚本,运行 OCR 并自动诊断结果。
|
||||
|
||||
## CLI Equivalent
|
||||
|
||||
```bash
|
||||
paperforge ocr
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [ ] formal note frontmatter 中 `do_ocr: true` 已设置
|
||||
- [ ] PDF 附件存在(`has_pdf: true`)
|
||||
- [ ] PaddleOCR API Key 已配置(`.env` 中 `PADDLEOCR_API_TOKEN`)
|
||||
- [ ] 网络连接正常(可访问 PaddleOCR 服务)
|
||||
|
||||
## Arguments
|
||||
|
||||
| 参数 | 必需 | 说明 |
|
||||
|------|------|------|
|
||||
| `--diagnose` | 否 | 仅诊断配置,不上传 PDF |
|
||||
| `--key <KEY>` | 否 | 仅处理指定 Zotero key 的文献 |
|
||||
| `--vault <PATH>` | 否 | 指定 Vault 根目录(默认当前目录) |
|
||||
| `--live` | 否 | 与 `--diagnose` 联用,执行实时 PDF 测试 |
|
||||
|
||||
### 诊断等级
|
||||
|
||||
| 等级 | 检查项 | 失败含义 |
|
||||
|------|--------|---------|
|
||||
| L1 | API token 存在性 | `PADDLEOCR_API_TOKEN` 缺失或为空 |
|
||||
| L2 | URL 可达性 | 无法连接 PaddleOCR 服务 |
|
||||
| L3 | API 格式验证 | 服务可达但响应格式异常 |
|
||||
| L4 | 实时 PDF 往返 | 完整提交和结果获取失败 |
|
||||
|
||||
> Exit code `0` = 所有检查通过。Exit code `1` = 至少一项检查失败。
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
# 处理所有标记 do_ocr: true 的文献
|
||||
paperforge ocr
|
||||
|
||||
# 仅处理指定文献
|
||||
paperforge ocr --key ABCDEFG
|
||||
|
||||
# 诊断模式(不实际运行)
|
||||
paperforge ocr --diagnose
|
||||
|
||||
# 完整诊断(含实时测试)
|
||||
paperforge ocr --diagnose --live
|
||||
|
||||
# 指定 Vault 目录
|
||||
paperforge ocr --vault /path/to/vault
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
OCR 完成后,每个文献生成以下文件:
|
||||
|
||||
```
|
||||
<system_dir>/PaperForge/ocr/<key>/
|
||||
├── fulltext.md # 提取的全文(含 <!-- page N --> 分页标记)
|
||||
├── images/ # 自动切割的图表图片
|
||||
├── meta.json # OCR 元数据(含 ocr_status)
|
||||
└── figure-map.json # 图表索引(自动生成)
|
||||
```
|
||||
|
||||
`meta.json` 中的 `ocr_status` 字段:
|
||||
- `pending` — 等待处理
|
||||
- `processing` — 正在处理
|
||||
- `done` — 完成
|
||||
- `failed` — 失败
|
||||
|
||||
## Error Handling
|
||||
|
||||
### API Token 缺失(L1 失败)
|
||||
- `PADDLEOCR_API_TOKEN` 未设置 → 在 `.env` 文件中添加
|
||||
|
||||
### 服务不可达(L2 失败)
|
||||
- 无法连接 PaddleOCR → 检查网络连接
|
||||
|
||||
### PDF 上传失败(L4 失败)
|
||||
- PDF 提交后未返回结果 → 检查 PDF 文件是否损坏
|
||||
|
||||
### OCR 状态卡住
|
||||
- `ocr_status` 长期显示 `processing` → 重新设置 `do_ocr: true` 后再次运行
|
||||
|
||||
## See Also
|
||||
|
||||
- [pf-sync](pf-sync.md) — 文献同步(生成正式笔记)
|
||||
- [pf-deep](pf-deep.md) — 深度精读(依赖 OCR 结果)
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
---
|
||||
name: pf-paper
|
||||
description: Quick paper Q&A workbench. Load a paper by Zotero key, title, DOI, or PMID and answer questions. Does not require OCR.
|
||||
allowed-tools: [Read, Bash]
|
||||
---
|
||||
|
||||
# <prefix>pf-paper
|
||||
|
||||
## Purpose
|
||||
|
||||
基于 Zotero OCR 文本的单篇论文工作台入口。
|
||||
|
||||
1. 解析 `<prefix>pf-paper <query>` 中的查询词
|
||||
2. 支持 Zotero key、标题片段、DOI、PMID、关键词
|
||||
3. 优先搜索本地 Zotero,解析到单篇目标论文
|
||||
4. 根据 Vault 根目录的 `paperforge.json` 加载 `<system_dir>/PaperForge/ocr/<KEY>/fulltext.md` 作为主文本
|
||||
5. 读取 `meta.json` 显示论文标题、作者、期刊、年份
|
||||
6. 进入 Q&A 模式,用中文回答用户关于该论文的问题
|
||||
7. 在当前论文上下文中,用户可再说"精读这篇文章"切换到 deep 层
|
||||
|
||||
## CLI Equivalent
|
||||
|
||||
```bash
|
||||
# 准备阶段(间接)
|
||||
paperforge sync # 生成正式笔记
|
||||
```
|
||||
|
||||
> `<prefix>pf-paper` 是 **Agent 层命令**,无直接 CLI 等效命令。
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [ ] 正式笔记已生成(`paperforge sync` 生成)
|
||||
- [ ] `fulltext.md` 存在(推荐,用于基于原文回答;如不存在则基于元数据回答)
|
||||
- [ ] discussion.py 模块可用(`python -m paperforge.worker.discussion --help` 可执行)
|
||||
|
||||
> **注意**:与 `/pf-deep` 不同,`<prefix>pf-paper` **不强制要求** OCR 完成。没有 OCR 时基于论文元数据和公开信息回答。
|
||||
|
||||
## Arguments
|
||||
|
||||
| 参数 | 必需 | 说明 |
|
||||
|------|------|------|
|
||||
| `<query>` | 是 | Zotero key、标题片段、DOI、PMID 或关键词 |
|
||||
| `<query2> ...` | 否 | 可同时加载多篇论文 |
|
||||
|
||||
### 解析规则
|
||||
|
||||
1. 如果输入看起来像 8 位 Zotero key,则直接按 key 解析。
|
||||
2. 否则先在本地 Zotero 中搜索标题/摘要。
|
||||
3. 若命中唯一结果或明显最佳结果,则直接载入。
|
||||
4. 若存在多个合理候选,则先列候选清单再让用户选。
|
||||
5. 不要强迫用户先知道 Zotero key。
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
<prefix>pf-paper XGT9Z257
|
||||
<prefix>pf-paper Predictive findings on magnetic resonance imaging
|
||||
<prefix>pf-paper 10.1016/j.jse.2018.01.001
|
||||
<prefix>pf-paper XGT9Z257 PQR8KLM
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
加载成功后显示:
|
||||
|
||||
```
|
||||
已加载论文: [title] ([year], [journal])
|
||||
Zotero Key: [key]
|
||||
结束对话时说"保存记录"即可保存讨论。
|
||||
请问有什么问题?
|
||||
```
|
||||
|
||||
### 回答原则
|
||||
|
||||
- **严格基于** `fulltext.md` 中的文本内容回答
|
||||
- 引用原文时标注来源页码/章节
|
||||
- 用中文(简体中文)回答
|
||||
- 论文中未提及的内容,明确说明"论文中未提及该内容"
|
||||
- 需要结合论文以外知识的问题,说明"该问题需要结合论文以外的知识回答"
|
||||
|
||||
## Error Handling
|
||||
|
||||
### 论文未找到
|
||||
- **表现**:Zotero key 无效或搜索无结果
|
||||
- **解决**:确认 key 正确,或尝试用标题片段搜索
|
||||
|
||||
### 多个候选结果
|
||||
- **表现**:搜索返回多个匹配的论文
|
||||
- **处理**:Agent 列出候选清单,让用户选择目标论文
|
||||
|
||||
### OCR 文件缺失
|
||||
- **表现**:`fulltext.md` 不存在
|
||||
- **处理**:Agent 基于元数据和公开信息回答,并告知用户"OCR 文本不可用,回答基于元数据"
|
||||
|
||||
## Saving Discussion Record
|
||||
|
||||
当用户说"保存"、"结束"、"完成"等关键词时(或显式输入 `{prefix}pf-end <key>`),必须执行记录保存。具体步骤见 [pf-end](pf-end.md)。
|
||||
|
||||
### 注意事项
|
||||
|
||||
- 仅 `/pf-paper` Q&A 需要记录。`/pf-deep` 不记录(精读内容已写入正式笔记)。
|
||||
- 如果无法从 formal-library.json 找到论文 domain/title,记录失败不应影响用户使用。
|
||||
|
||||
## See Also
|
||||
|
||||
- [pf-end](pf-end.md) — 结束对话并保存记录
|
||||
- [pf-deep](pf-deep.md) — 完整三阶段精读
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
---
|
||||
name: pf-status
|
||||
description: Check PaperForge installation and runtime status. Verifies configuration, paths, and data integrity.
|
||||
allowed-tools: [Bash]
|
||||
---
|
||||
|
||||
# /pf-status
|
||||
|
||||
## Purpose
|
||||
|
||||
查看 PaperForge 当前安装与运行状态。
|
||||
|
||||
`paperforge status` 会检查:
|
||||
|
||||
- 安装完整性(Python 包、依赖)
|
||||
- 配置文件(`paperforge.json`、`.env`)
|
||||
- 路径连通性(exports、ocr、literature 目录)
|
||||
- Zotero 数据目录链接状态
|
||||
- Better BibTeX 导出文件状态
|
||||
|
||||
## CLI Equivalent
|
||||
|
||||
```bash
|
||||
paperforge status
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
无特殊前置条件。此命令用于诊断安装问题,即使在配置不完整时也会尽量输出可用信息。
|
||||
|
||||
## Arguments
|
||||
|
||||
| 参数 | 必需 | 说明 |
|
||||
|------|------|------|
|
||||
| `--vault <PATH>` | 否 | 指定 Vault 根目录(默认当前目录) |
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
# 检查当前目录的 Vault 状态
|
||||
paperforge status
|
||||
|
||||
# 检查指定 Vault 的状态
|
||||
paperforge status --vault /path/to/vault
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
典型输出示例:
|
||||
|
||||
```
|
||||
PaperForge Lite v1.2
|
||||
====================
|
||||
|
||||
[安装检查]
|
||||
✓ Python 包: paperforge v1.2.0
|
||||
✓ 依赖: requests, pymupdf, pillow
|
||||
|
||||
[配置检查]
|
||||
✓ paperforge.json: 存在且有效
|
||||
✓ .env: 存在
|
||||
✓ PADDLEOCR_API_TOKEN: 已设置
|
||||
|
||||
[路径检查]
|
||||
✓ exports: <system_dir>/PaperForge/exports/
|
||||
✓ ocr: <system_dir>/PaperForge/ocr/
|
||||
✓ literature: <resources_dir>/<literature_dir>/
|
||||
✓ Zotero: <system_dir>/Zotero/
|
||||
|
||||
[数据检查]
|
||||
✓ library.json: 存在,包含 150 条文献
|
||||
✓ 正式笔记: 150 篇
|
||||
|
||||
状态: 一切正常 ✅
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### 配置缺失
|
||||
- `✗ paperforge.json: 未找到` → 运行 `paperforge doctor` 或重新执行安装
|
||||
|
||||
### 路径错误
|
||||
- `✗ Zotero: 目录不存在或不是有效链接` → 创建 junction/symlink 到 Zotero 数据目录
|
||||
|
||||
### 依赖缺失
|
||||
- `✗ 依赖: requests 未安装` → `pip install requests pymupdf pillow`
|
||||
|
||||
### API Key 未设置
|
||||
- `✗ PADDLEOCR_API_TOKEN: 未设置` → 在 `.env` 文件中添加 API token
|
||||
|
||||
## See Also
|
||||
|
||||
- [pf-sync](pf-sync.md) — 文献同步
|
||||
- [pf-ocr](pf-ocr.md) — OCR 提取
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
---
|
||||
name: pf-sync
|
||||
description: Sync Zotero Better BibTeX JSON export and generate/update formal literature notes.
|
||||
allowed-tools: [Bash]
|
||||
---
|
||||
|
||||
# /pf-sync
|
||||
|
||||
## Purpose
|
||||
|
||||
同步 Zotero Better BibTeX JSON 导出并生成/更新正式文献笔记。
|
||||
|
||||
`paperforge sync` 读取 Zotero JSON 中的新条目,直接生成正式文献笔记。
|
||||
|
||||
自动读取 `paperforge.json` 定位 exports 目录和 literature 目录。
|
||||
|
||||
## CLI Equivalent
|
||||
|
||||
```bash
|
||||
paperforge sync
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [ ] Zotero 已安装且 Better BibTeX 插件已启用
|
||||
- [ ] Better BibTeX 已配置自动导出 JSON
|
||||
- [ ] JSON 导出文件存在(`<system_dir>/PaperForge/exports/library.json`)
|
||||
- [ ] `paperforge.json` 配置正确(Vault 根目录下)
|
||||
|
||||
## Arguments
|
||||
|
||||
| 参数 | 必需 | 说明 |
|
||||
|------|------|------|
|
||||
| `--dry-run` | 否 | 预览变更,不实际写入文件 |
|
||||
| `--domain <DOMAIN>` | 否 | 仅同步指定领域(如 `骨科`) |
|
||||
| `--selection` | 否 | (已废弃)仅保留以兼容旧版 |
|
||||
| `--index` | 否 | (已废弃)仅保留以兼容旧版 |
|
||||
| `--vault <PATH>` | 否 | 指定 Vault 根目录(默认当前目录) |
|
||||
|
||||
### 选项
|
||||
|
||||
```bash
|
||||
paperforge sync --dry-run # 预览同步结果
|
||||
paperforge sync --domain 骨科 # 按领域过滤同步
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
# 同步 Zotero 并生成正式笔记
|
||||
paperforge sync
|
||||
|
||||
# 预览模式
|
||||
paperforge sync --dry-run
|
||||
|
||||
# 仅同步特定领域
|
||||
paperforge sync --domain 骨科
|
||||
|
||||
# 指定 Vault 目录
|
||||
paperforge sync --vault /path/to/vault
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
```
|
||||
[INFO] Found 5 new items
|
||||
[INFO] Created 骨科/XXXXXXX.md
|
||||
[INFO] Generated 5 formal notes
|
||||
[INFO] Output: <resources_dir>/<literature_dir>/骨科/XXXXXXX - Title.md
|
||||
```
|
||||
|
||||
生成文件:`<resources_dir>/<literature_dir>/<domain>/<key> - <Title>.md`
|
||||
|
||||
## Error Handling
|
||||
|
||||
### JSON 文件不存在
|
||||
- `[ERROR] library.json not found` → 检查 Better BibTeX 导出路径
|
||||
|
||||
### 空 JSON 导出
|
||||
- `[INFO] Found 0 new items` → 确认 Zotero 中有带 citation key 的文献,Better BibTeX 已启用"Keep updated"
|
||||
|
||||
## See Also
|
||||
|
||||
- [pf-ocr](pf-ocr.md) — OCR 提取(下一步操作)
|
||||
- [pf-status](pf-status.md) — 检查系统状态
|
||||
Loading…
Reference in a new issue