Skip to main content
Glama
README.md
# Study Errorbook · 学习错题 Agent 插件

通过 AI 宿主调用本地 MCP 工具,把 PDF、照片和试卷整理成保留原始证据、可人工复核、可再次练习的错题库。宿主负责理解题意和对话,工具负责导入、TextIn OCR、证据取图、版本记录、受限数学验算与打印导出。

**v0.1.0 开发版,持续更新、完善与迭代中。** 已实现的工具不等于自动判题可靠;OCR、手写擦除、几何理解与真实学习效果仍需原图和人工复核。代码、模拟测试、历史真实 API 调用和当前宿主验收分别记录,见 [发布验证](docs/public-validation.md)。

## 能解决什么

- 保存原卷、作答和批改,不把 OCR 转录直接当成真实题目或学生答案。
- 用证据图形成待复核草稿,区分 Agent 判断与用户确认。
- 检索错题、记录修改历史、生成基础变式、保留实际作答与帮助情况。
- 按用户指定日期安排复习,导出错题本、学生练习册、独立答案册及练习 ZIP。
- 发现识别冲突时回看原图,继续有依据的工作;不自动重传、付费重试或假装确认。

## 环境与兼容性

- Python 3.12+、[uv](https://docs.astral.sh/uv/getting-started/installation/)、Git,以及支持本地 stdio MCP 的 AI 客户端。MCP 是客户端调用本地工具的协议,不是另一个聊天模型。
- macOS 已有本机运行证据;Linux 使用相同 POSIX 文件锁接口,但尚需独立实机验收。
- Windows 原生 Python 暂不支持。可在 WSL2/Linux 内安装并让客户端启动 WSL 中的服务;这一组合尚未实机验收,不提供 Windows 原生安装包。
- 首次安装会下载 Python/依赖,需要网络。API 服务的额度、价格和产品权限由各服务商控制,开源代码不包含免费额度或凭据。

## 安装并接入客户端

```sh
git clone https://github.com/SAKURAfan1023/study-errorbook.git
cd study-errorbook
uv sync --locked --python 3.12
uv run python scripts/configure_local.py
uv run python scripts/setup_private.py
uv run python scripts/smoke_mcp.py
```

`setup_private.py` 只创建专用输入目录与空凭据模板,不覆盖已有配置。`smoke_mcp.py` 使用临时空库验证工具发现和状态,不读取日常错题库、不调用 TextIn;完整合成材料流程由测试和独立安装验证覆盖。把生成的 `.mcp.json` 导入支持本地 stdio 的客户端,或按宿主的本地插件流程注册此仓库;然后调用 `workspace_status` 核对实际版本、数据目录和连接状态。

直接执行 `uv run study-errorbook` 会启动等待 MCP 请求的进程,不会出现独立聊天界面。完整的源码独立安装与升级方式见 [安装说明](docs/distribution.md)。

| 配置 | 含义 | 位置/默认 |
| --- | --- | --- |
| `TEXTIN_APP_ID` / `TEXTIN_SECRET_CODE` | 付费 OCR 与擦除凭据 | 本地 `~/.config/study-errorbook/config.env` 或环境变量 |
| `STUDY_INPUT_ROOT` | 允许导入的专用目录 | 设置脚本创建 `~/Documents/StudyErrorbook/inbox` |
| `STUDY_DATA_DIR` | 数据库、原件与导出 | `~/.local/share/study-errorbook` |
| 解析 mode / 页数上限 | 显式选择免费/付费/VLM 与本次预算 | 每次上传前由用户授权 |

环境变量优先于本地配置。免费接口不代表材料留在本机,也不承诺永久可用。不要将密钥填到公开仓库、截图或对话中。

```mermaid
flowchart LR
  File[授权试卷 / 图片] --> Import[本地导入与原件保存]
  Import -->|明确上传授权| OCR[TextIn 识别]
  Import --> Image[原图与局部证据]
  OCR --> Draft[Agent 整理待复核草稿]
  Image --> Draft
  Draft --> Human[用户复核]
  Human --> Store[版本化错题库]
  Store --> Practice[练习 / 作答 / 日期复习]
  Store --> Export[离线 HTML 与练习包]
```

## 文档入口

- [原图与识别冲突处理](docs/ocr-conflict-user-guide.md)
- [继续已有任务,不重复识别](docs/recover-existing-recognition-2026-09-26.md)
- [复习与作答使用指南](docs/manual-review-guide.md)
- [安装、升级与版本核对](docs/distribution.md)
- [Skill 与工具使用约束](skills/study-errorbook/SKILL.md)

## 开始使用

遇到文字漏识或图形描述与原图冲突时,可按[原图核对指南](docs/ocr-conflict-user-guide.md)继续整理:保留有依据的判断,并明确具体待确认位置。

完成下方安装并在宿主接入后,将授权材料放入 `~/Documents/StudyErrorbook/inbox`。可先说“列出inbox中可选的材料”,Agent通过`list_input_files`查看第一层候选文件名和大小,无需宿主具备终端或文件浏览工具;它不会读取材料内容或自动上传。子目录、隐藏项和链接不在列表中;已知具体子目录文件路径仍可按既有导入规则处理。付费异步解析或手写擦除需在本地配置文件 `~/.config/study-errorbook/config.env` 填写 `TEXTIN_APP_ID`、`TEXTIN_SECRET_CODE`;免费同步解析不需要凭据,但仍会上传材料。密钥仅在本地填写,无需发到对话。其他配置为 `STUDY_INPUT_ROOT`、`STUDY_DATA_DIR`;环境变量优先于配置文件。

凭据在本地填写;公共发行版不包含任何开发者钥匙串启动器或账号授权。

在已连接插件的 AI 会话中可以说:

> 使用学习错题插件,先检查工作区状态,再整理 inbox 中我指定的试卷。保留原答案和批改证据,看不清的集中列出,生成待复核错题草稿。

首次 `parse_document` 会上传材料到 TextIn 并产生 API 用量;必须指定本次允许处理的页数上限。默认 `mode=paid_async`;明确选择免费识别时使用 `mode=free_sync`,单文件最多10MiB、同步请求60秒超时,没有自动回退或重试。`max_paid_pages` 为兼容保留的参数名,在三种模式中都是页数上限。显式 `mode=vlm_sync` 使用付费VLM补充识别,仅支持单张已导入PNG/JPG,本地限10MiB、总等待60秒;原始分块与回执独立留存,不覆盖xParse结果。免费接口的额度和可用性由服务商控制,不承诺与付费接口效果一致。

OCR概览对Image元素提供visual_review提示,引导核对图形位置;图中文字为空或与原题相同不等于学生未答,提示也不是自动发现错误。

导入、证据裁剪、保存、查询、受限代数校验和导出均可本地运行。本地OCR缓存读取仅接受任务材料目录内、不跟随链接且不超过64MiB的普通文件;拒绝时保留任务状态,不自动重提。该上限是本地资源限制,不代表上游限制。擦除上传与原卷证据导出只接受材料目录内、20MiB以内的普通PNG;链接、管道、损坏或超限文件会被拒绝。题目拆分、批改归属、错因解释及出题由宿主 Agent 根据原图和结构数据完成,服务本身不含通用判题模型。

## 当前能力

- 跨任务续接解析:先`list_documents`找材料,再`list_parse_jobs`找原任务ID,直接读取已有结果。列表不需要凭据、不读取源文件或查询TextIn,不会重新上传;保存状态不是远端存活证明。缓存缺失或损坏返回cached_result_unavailable;先核对本地缓存或可信备份,恢复后读取原job_id,不自动重新上传。

- 待导入材料发现:`list_input_files`只读列出专用输入目录第一层候选,按文件名分页;不判断是否已导入,大小合规不代表内容可解析。`list_documents`用于找回已导入材料。

- PDF/JPG/PNG 导入,最多20页、20MiB;保留原件,拒绝材料目录之外的路径。
- 删除影响预览:列出关联副本、历史、作答反馈、复习、文件与混合导出,保留共享验算并报告未能确认的项。可凭当前摘要执行本地级联删除,要求独占工作区;中断可恢复,保留最小回执。不会删除输入原件、备份或服务商数据。
- 上传前区域遮盖:本地生成独立PNG/PDF副本,去掉指定区域像素及原PDF隐藏对象,保留原件;副本预览后用新ID解析。需要明确选区,不自动找全个人信息;PDF转图片后可能影响小字质量。
- TextIn xParse 异步任务、结果缓存及分页读取;提交结果不确定时不自动重新付费。
- `read_study_record` 可按revision读取已保存的题目历史,核对修正前后内容;历史快照不混入当前净题或复习状态。修改Agent判断也会清除旧错因分析和练习,先保存修正,再基于新版本分析;旧版本与历史作答保留。
- `read_document` 提供最多20页的状态摘要(无元素页仍可见)、简短概览和有界复核线索(公式/手写对象计数、最多5项较低置信度字符,不自动判错),`read_element` 可继续读取完整文字、行内公式、字符置信度/候选字、层级、表格和页面信息;不重复调用 OCR。
- 原页/局部证据以真实 MCP 图片内容返回;可按需调用手写擦除,并保留原件。
- `crop_document`本地生成可追溯的单页裁图,记录父页、源哈希和实际像素范围;检查后可显式补识别。裁图与遮盖后代纳入关联删除,不自动拼接OCR或判题。
- `read_element_evidence` 按OCR区域和上游报告方向取证,保存原页区域;旋转显示不保证方向正确。倒置时将返回的document_id与region原样传给read_evidence按原页方向查看;无法可靠映射时先看整页。
- 版本化错题记录、用户复核意见、练习作答;修订题干或证据后清除旧分析与练习。
- 精确有理数验算:默认检查变量 `x` 的多项式恒等;显式 `kind=linear_equation` 检查化简后一元一次方程的唯一解,例如 `2*(x+3)=10` 与答案 `2`。无解、多解、非线性和变量分母标为待复核,检查不证明自然语言题意匹配。
- 原题和变式再次作答,保留当时题面快照与使用提示/解析情况;分页找回历史,题目改版后仍可核对旧作答。提供attempt_key时同次提交重试不会重复计数;不会自动判定掌握。
- 再次作答后的反馈可保存并修订:分别记录Agent判断、具体解释、下一步建议与用户明确意见;仅更新Agent解析会保留已有用户意见;明确撤回有独立标识及来源版本。旧反馈全部保留,版本冲突不会覆盖,原作答和题面不变。反馈状态只表示已记录,不表示已掌握。
- 错题查询:只搜索当前学习内容,可组合精确筛选学科、知识点、材料、复核状态和Agent判断(例如判错或待确认);分页摘要含下一页位置,兼顾条数与摘要字节量;少于limit时仍按next_offset继续,不会把内部字段名当关键词命中。
- 练习题面:单独读取变式题干、原题转录或已复核净题图,不附旧作答和解析;保存作答时检查同一题目版本。
- 日期复习队列:按用户明确日期安排原题或已检查的变式,查询到期/待重新核对项,关联新的匹配作答完成或取消计划;保留全部版本。仅提供可查询队列,不自动通知、计算复习间隔或判定掌握。
- 导出可打印 HTML 错题本、学生练习册和独立答案册。默认只导出用户已纳入的记录,也可明确导出带状态的草稿。错题本分别显示卷面批改和Agent判断;两者不一致时提醒核对,包括卷面正确/部分正确而Agent认为未作答的情形。错题本与manifest保留有界的保存来源链和证据文件哈希,区分裁图页与材料页;不附完整父页,也不代表父文件当前已校验。
- 导出失败恢复:文件全部写成后才生成正式导出目录;普通异常清理本次半成品。强制退出遗留内容在已有构建清单时仍可进入删除预览;不保证断电持久性,也不自动删除无法归属的目录。
- 净题读取:查看、复核、缓存取图和导出均检查对应材料目录中的普通PNG,拒绝链接、异常文件和超过20MiB的单图;练习取图合计仍为12MiB。异常只报告当前不可用,不重新付费擦除。
- 原题重练:按需生成擦除图,关联到记录的clean_evidence_ids;用户对照原图复核后,按来源ID和图片sha256记录确认。有净题时额外导出original-practice.html,按所选顺序展示题图和答题区,不带入原答案/分析。修改记录、图片或再次复核会使旧确认失效;未确认图仅能进入明确标注的草稿。实际擦除效果仍需真实材料验收。

## 本地开发与复现

导入材料须为已保存到本地的普通 PDF/JPG/PNG 文件。误选目录、管道或设备会返回可处理的文件错误,之后仍可继续导入正常材料;插件不会等待管道内容或自动转换不支持的文件。

本地取证、裁图、遮盖生成和解析读取已保存材料时,同样限制为工作区内的普通文件及20MiB以内内容,不跟随源文件链接。裁图和遮盖副本还核对保存的哈希;变化后拒绝复用、取证或解析。渲染及每次解析提交使用已检查的字节快照,提交层不再打开源路径;免费解析仍限制10MiB。解析任务的submitted_source_sha256和submitted_source_bytes描述本次准备提交的内容,不代表服务商已受理,也不等同于规范化前原件的文档哈希。读取期间普通文件被外部原地改写不在一致性保证内。

```bash
uv sync --python 3.12
uv run python scripts/configure_local.py
uv run python scripts/setup_private.py
uv run python scripts/smoke_mcp.py
uv run pytest -q
uv run ruff check src tests scripts
uv run python scripts/demo.py
```

演示使用明确标注的合成卷面和预置分析,**不调用 OCR 或模型 API**。导出目录记录在 `data/demo/latest-export.txt`,打开其中的 `errorbook.html`、`practice.html`、`answers.html` 即可查看。

`uv run python scripts/probe_free_ocr.py` 是另一个显式联网实验:只生成并上传一页合成材料,不读取凭据或现有文件,结果保存到 `data/probes/`,不会自动重试。历史实测摘要不代表当前服务商可用性;真实响应和本地诊断材料不随仓库公开。

开发用 `.mcp.json` 由脚本生成并被 Git 忽略;搬动项目后须重新生成。`.mcp.example.json` 仅用于展示格式。独立安装包使用单独的 wheel 运行环境,不依赖源码目录。可用 `uv run python scripts/build_release.py` 生成 ZIP 安装包,换机器解压后运行安装器,再导入生成的 MCP 配置或注册插件。详见[独立安装说明](docs/distribution.md)。安装会下载固定依赖,不是完整离线包;macOS 已实测,Linux 与其他 Agent 宿主待验证,Windows 暂不支持。

默认真实数据目录为 `~/.local/share/study-errorbook`,与插件缓存分离。同一台机器的多个新版服务进程可以共享错题库;版本冲突会要求先读取最新记录,同一远端任务不会并发重复提交。旧版服务仍在运行时需要先关闭旧连接。不同用户的数据仍应使用独立目录,数据库不能放在网络盘;这不是多用户权限系统。真实材料、配置和数据库均应留在版本控制之外。

解析任务失败或提交结果未知时,可在用户明确同意后调用 `retry_parse_document`。先 `get_job` 读取 `attempt_number`,将其作为 `expected_attempt`,同时提供页数上限、确认标记和用户意见;相同尝试编号不会再次提交。旧尝试与新提交标记在本地同一事务保存,`get_job(include_attempt_history=true)`返回最近10次旧尝试及总数。超时可能已经被上游受理,此功能不能保证上游只处理或计费一次。运行中、部分成功与已完成任务均禁止重提;40306应先联系服务商。若只是运行中任务暂停查询,在用户明确要求后调用 `resume_job_observation(job_id, expected_attempt, expected_observation_revision, user_note)`:复用远端任务ID,不重新上传。两个版本来自get_job;重复决定会被拒绝,再次限流仍停止,3秒查询间隔仍有效。


导出支持离线公式排版:行内 `\(...\)`,独立公式 `\[...\]` 或 `$$...$$`;普通美元金额不会被当作公式。KaTeX 0.18.9及字体随包提供,浏览器不从CDN下载。请保留整个导出目录,包括assets和证据图片。无效/不支持的公式保留原文并提示;使用A4打印样式与答题留白,三册均保留复核状态,未验算的参考答案明确标注。超长题目与复杂公式仍须检查打印预览。

离线打印回归:`uv run python scripts/print_fixture.py` 生成纯合成样例;可选开发脚本 `scripts/verify_print.cjs <导出目录>` 使用本机Node、Playwright与Chrome检查浏览器,并在 `tmp/pdfs/print-qa/` 生成QA用PDF。普通MCP导出仍返回HTML,不自动生成PDF,也不依赖Node/Chrome运行。

错题本导出保留卷面批改、Agent判断、笔迹归属、用户复核意见、知识点和诊断追问。题目、批注、分析引用的证据都会带入导出,通过编号链接跳转;同一证据跨题使用时不会链接到另一题。manifest.json保存记录版本及证据原页坐标,工具返回manifest_path。练习目的放在答案册,学生册不包含答案或这类提示。

已观察到 OCR 漏行、符号误识和涂写串入;接口成功不证明转录完整。原始诊断材料不公开,判断必须回到使用者自己的原图。

学生练习材料可直接使用 `export_errorbook` 返回的 `practice_bundle_path`:ZIP 内保留离线字体和所选净题图,排除答案册、错题本与原卷作答图。完整导出目录仍用于留档;题干和净题图中的提示残留仍须核对。

练习册、答案册和练习包README使用相同资料编号。多次导出后,请同时按资料编号与题号配对;每次导出有独立编号,题目版本仍记录在manifest中。

升级核对可调用workspace_status,比较runtime_version与目标安装目录installation.json中的值。发布wheel包含独立构建时间戳,插件缓存+codex后缀是另一标识。匹配后仍需验证实际工具行为;旧会话缺少此字段时不能声称已加载新版。

复习队列默认使用中性名称,省略可能带答案或错因的自由题目标签与学科。整理题库时可对read_review_queue显式传include_labels=true找回原标签;独立答题前不展示这些标签。

小数验算按原始文本精确读取;超出受限范围时待复核,不经浮点舍入后放行。当前练习状态会本地重算保存的算式,原验算输出仍作为历史保留;升级后的实时结果以exercise_validation中的check_status/check_reason为准。

## 常见问题、升级与项目结构

- **找不到材料**:确认文件位于 `STUDY_INPUT_ROOT`,是受支持的普通文件;先调用 `list_input_files`,不要直接放宽目录限制。
- **重启后记录消失**:先核对 `workspace_status` 中的数据目录;插件缓存、运行环境与数据目录是三个不同位置。
- **OCR 结果缺失或有错**:保留任务 ID 和缓存,按原图核对;`submission_unknown` 可能已经被上游受理,不自动重复提交。
- **宿主仍显示旧能力**:核对服务返回的 `runtime_version`,更新源码或 Skill 不等于旧 MCP 进程已经重载。
- **导出提示待复核**:先核对题干、答案和对应记录版本;不要替用户伪造确认。

源码升级前保存本地改动并备份数据,再执行 `git pull --ff-only`、`uv sync --locked`、重新生成配置并在客户端重载服务。独立发行包安装到新目录后再切换,保留旧版本便于回退。

`src/` 保存实现,`skills/` 保存 Agent 指南,`tests/` 保存回归测试,`scripts/` 保存配置、构建、自检与可选实验,`docs/` 保存公开用户指南。本机历史诊断文档、原卷、数据集、安装记录和 `data/`、`output/` 等不进入公开提交;带实验名称的脚本可能依赖自行准备的材料,并不全部是安装自检。

## 维护、贡献与使用声明

**持续更新、完善与迭代中。禁止恶意转载与滥用。** 转载须保留版权和许可声明,请注明原仓库及修改内容;不得冒充作者或官方、夹带恶意代码、盗取凭据、泄露个人资料或伪造研究/学习证据。

代码按 [MIT License](LICENSE) 开源。上述反滥用声明不额外撤销 MIT 授予的合法使用、修改、转载或商用权利;第三方材料和服务不随代码一并授权。完整说明见 [USE_POLICY.md](USE_POLICY.md)、[第三方声明](THIRD_PARTY_NOTICES.md)。

欢迎通过仓库 Issues 反馈 Bug 或建议。请包含版本、系统、脱敏复现步骤、预期与实际结果;不要上传密钥或真实私密材料。提交代码前阅读 [贡献指南](CONTRIBUTING.md),安全问题见 [SECURITY.md](SECURITY.md)。