内容
<div align="center">
# 🗜️ 保存上下文
**适用于大型语言模型的上下文窗口的 Git LFS。**
将大型文档保留在模型外部 - 而是为其提供一个可搜索的句柄。
模型读取一个廉价的摘要来找到所需内容,然后提取**确切的原始词句**进行引用,仅使用一小部分令牌。
适用于 Claude Code、Claude Desktop 和任何模型上下文协议客户端的 **MCP 服务器** - 还有一个独立的 CLI。
[](https://github.com/AlexanderBoger/SaveContext/blob/master/LICENSE)
[](https://www.python.org)
[](https://modelcontextprotocol.io)
[](#reference)
[](#reference)
</div>
---
```
摄入 150k-token 合同 ─▶ ctx://acme@v1
├─ ~700-token 语义摘要
├─ 块映射 (b0000 … b0042)
├─ 保护原子 (money · dates · obligations …)
└─ 原始来源以压缩形式存储,永不自动发送
提问 6 个问题 ─▶ 查找 (...) ─▶ 一次调用 · 顶部块 · 确切原子
· 原文引用 · 置信度标志
```
## 安装
使用 [uv](https://docs.astral.sh/uv/),一键将 SaveContext 添加到 Claude Code 中 - 无需克隆、无需 `pip`、无需虚拟环境:
```bash
claude mcp add savecontext -- uvx savecontext
```
然后打开 Claude Code,运行 `/mcp` 确认工具已加载,并**将模型指向一个大文档并提问** - 它会自动摄入、查找并引用。要固定数据库的位置,请在 `--` 之前添加 `-e SAVECONTEXT_DB=/abs/path.db`。
使用其他 MCP 客户端(例如 Claude Desktop)? 将其服务器配置指向相同的命令:`uvx savecontext`。如果不需要 MCP,可以使用独立的 [CLI](#reference)。
## 为什么它与众不同
大多数上下文工具都是有损汇总器 - 有帮助,但会模糊确切的数字,无法告诉你何时在猜测。SaveContext 做了它们不能做的两件事:
- **🎯 精确,有凭证。** 事实以**原始字符**的形式返回,附带来源位置,从不改述 - 每个跨度都逐字节重建。摘要用于**查找**;引用用于**信任**。
- **🙅 表示“未找到”而不是捏造。** 当答案不在文档中时,检索被标记为弱,代理会放弃 - 而不是编造一个看似合理的答案。
- **📉 平衡成本。** 回答问题的负载保持在 ~7,300 个令牌,无论文档大小如何。粘贴会线性扩展;这不会。
- **🔁 一次调用,多条查询。** `lookup` 在一次往返中回答一批查询,而不是每个问题一次检索。
## 数据
<div align="center">
<table border="0">
<tr>
<td align="center" width="180"><h2>20.5×</h2>减少上下文<br>在 150k令牌</td>
<td align="center" width="180"><h2>~7.3k</h2>平衡令牌成本,<br>任意文档大小</td>
<td align="center" width="180"><h2>54/54</h2>实时答案正确,<br>包括<i>未找到</i></td>
<td align="center" width="180"><h2>100%</h2>逐字节引用,<br>0 次幻觉</td>
</tr>
</table>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/AlexanderBoger/SaveContext/master/assets/benchmark-dark.svg">
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/AlexanderBoger/SaveContext/master/assets/benchmark-light.svg">
<img alt="Bar chart: context tokens to answer six questions. Pasting the whole document scales with size (15,135 to 150,135 tokens) while SaveContext stays flat near 7,300 — 20.5x less at 150k." src="https://raw.githubusercontent.com/AlexanderBoger/SaveContext/master/assets/benchmark-light.svg" width="720">
</picture>
</div>
使用真实代理在合同集上测量,加上**保留**文档(RFC 和合成事件日志,检索器从未调整过),回答植入干扰值的事实问题,针对真实结果进行评分。
交叉点 ≈ 5k 令牌 - 低于此,直接粘贴;高于此,差距随大小增加。
> 诚实备注:实时运行是单个样本 - 将小差异视为噪音。**可持续的发现**是平衡成本曲线、逐字节检索和在缺失事实时零幻觉。密集的技术散文是当前的检索前沿。自己重现:[`examples/benchmark_suite/`](https://github.com/AlexanderBoger/SaveContext/blob/master/examples/benchmark_suite)。
---
## 参考
<details>
<summary><b>11 种工具</b></summary>
<br>
所有工具都返回干净的 JSON。句柄稳定且可读:`ctx://label@vN` 用于上下文,`out://label@vN` 用于输出。
| 工具 | 用途 |
|------|---------|
| `ingest` | 存储长文本;返回句柄、简要介绍、块映射、保护原子摘要、安全备注。**不返回原始来源。** 可选 `agent_brief` 让模型提供自己的摘要。 |
| `lookup` | **批量检索** - 在一次调用中回答多个查询。每个查询:顶部块、确切原子、逐字最佳匹配句子和 `confidence` 标志(`strong`/`weak`),以便代理可以放弃而不是猜测。 |
| `brief` | 任务特定简介:给定任务的相关块和原子,附有不确定性说明。 |
| `expand` | 延迟展开块 / 原子 / 部分 / 搜索匹配,精度为 `summary` | `facts` | `quotes` | `full`。 |
| `quote` | 逐字引用(按原子 ID 或搜索查询)并附上来源引用。 |
| `map` | 完整的(或分页的)块映射 + 原子摘要,延迟获取。 |
| `set_brief` | 用作者撰写的简介替换上下文简介。原始来源和原子保持不变。 |
| `diff` | 存储的上下文与新来源之间的差异;报告添加/删除/更改的**原子**和含义影响。创建新版本。 |
| `zip_output` | 存储大型生成的**输出**;返回章节映射 + 预览。 |
| `expand_output` | 在 `preview` | `section` | `full` 精度下展开存储的输出的一部分。 |
| `audit` | 压缩率、原子计数、按类别的保留估计、`safe_for` / `unsafe_for`、警告。 |
**`expand` 精确度级别:** `summary`(提取性引导句子,最便宜)· `facts`(摘要 **加** 确切原子,`[money] $500,000`)· `quotes`(您可以引用的逐字跨度)· `full`(原始块文本 - 唯一返回源代码的路径)。
</details>
<details>
<summary><b>一个回合的样子</b></summary>
<br>
```text
1. 用户粘贴 150,000-token 合同。
2. Claude → ingest(source_text=…, label="acme")
← ctx://acme@v1, ~700-token 简介, 块映射, 原子。
3. 用户:“责任上限?通知期?管辖法律?”
4. Claude → lookup(ctx://acme@v1, ["liability cap", "termination notice", "governing law"])
← 每个查询:控制块,其原子,逐字句子,置信度。
5. Claude → quote(ctx://acme@v1, search_query="shall not exceed") # 验证确切措辞
← “…total liability shall not exceed $750,000…” + 来源偏移。
6. Claude 使用仅相关、逐字引用、来源的上下文回答。
```
可运行版本位于 [`examples/demo.py`](https://github.com/AlexanderBoger/SaveContext/blob/master/examples/demo.py) (`python examples/demo.py`).
</details>
<details>
<summary><b>命令行(<code>savectx</code>)</b></summary>
<br>
该软件包附带一个 CLI,共享与 MCP 服务器相同的存储 - 在一个上摄入,另一个上查询:
```bash
savectx ingest report.md --label q4 --type auto # 摄入文件
savectx ingest - --label pasted # 或读取 stdin
savectx list # 存储中有什么
savectx lookup ctx://q4@v1 --query "liability cap" --query "fees" # 批量
savectx brief ctx://q4@v1 --task "liability risks"
savectx expand ctx://q4@v1 --selector liability --fidelity facts
savectx quote ctx://q4@v1 --search "shall not exceed"
savectx audit ctx://q4@v1
savectx diff ctx://q4@v1 report_v2.md # 版本 + 更改报告
savectx serve # 运行 MCP 服务器
```
裸 `savecontext`(和 `python -m savecontext`)运行 MCP 服务器,因此 MCP 配置保持不变。
</details>
<details>
<summary><b>配置</b></summary>
<br>
通过环境(或 MCP `env` 块)设置:
| 变量 | 默认值 | 用途 |
|---|---|---|
| `SAVECONTEXT_DB` | `~/.savecontext/savecontext.db` | 存储位置。`:memory:` 用于临时存储。CLI 和服务器共享。 |
| `SAVECONTEXT_TRANSPORT` | `stdio` | `stdio` \| `http` \| `sse` |
| `SAVECONTEXT_HOST` / `SAVECONTEXT_PORT` | FastMCP 默认值 | 用于 `http`/`sse` 传输 |
| `SAVECONTEXT_EMBEDDINGS` | 关闭 | `1` 启用本地句子转换器检索后端(默认无依赖 BM25) |
| `SAVECONTEXT_LLM_SUMMARY` | 关闭 | `1` 具有本地 Ollama 模型,撰写摄入时的抽象简介(失败时转为提取) |
`ctx://` 句柄方案是稳定的。`SAVECONTEXT_*` 变量优先;`CONTEXTSAVER_*` / `CONTEXTVAULT_*` 名称仍作为回退被继承。
</details>
<details>
<summary><b>工作原理</b>(架构 + 无损保证)</summary>
<br>
| 层 | 模块 | 行为 |
|-------|--------|-----------|
| 分词器 | `tokenizer.py` | tiktoken `cl100k_base`,否则 `chars/4` |
| 分块 | `chunking.py` | 确定性:标题 + 段落打包到令牌预算,精确偏移 |
| 提取 | `extraction.py` | 正则原子:日期,货币,%,数字,网址,电子邮件,实体,否定,义务,代码 ID,文件路径 |
| 检索 | `retrieval.py` | **BM25** + 概念组扩展 + 答案类型意图 + 饱和度评分;可选嵌入后端 |
| 摘要 | `summarize.py` | 提取:排名块 + 引导句子 + 高价值原子行;可选本地 LLM |
| 差分 | `diffing.py` | 原子集差 + 粗糙块文本差 + 风险影响 |
| 存储 | `storage.py` | SQLite 元数据 + **zstd 压缩**原始来源;块/原子作为偏移 |
| 服务/服务器 | `service.py`, `server.py` | 十一种工具;FastMCP 通过 stdio / HTTP / SSE |
**无损保证。** 块和原子存储为**原始来源的偏移**,因此任何跨度都逐字节重建。简介明确标记为有损;确切的措辞始终来自 `quote()` 或 `expand(fidelity="quotes")`。完整原始来源仅通过 `expand(fidelity="full")` 返回。
</details>
<details>
<summary><b>谁编写简介?</b></summary>
<br>
三种摘要选项,最佳优先 - 所有保护原子精确;只有散文简介不同:
1. **调用代理(推荐)。** Claude 已经在 `ingest` 时在上下文中拥有文档,因此它可以免费编写一个忠实、密集的简介 - 内联通过 `ingest(agent_brief=…)` 或之后通过 `set_brief`。(`brief_mode='agent'`)
2. **本地 LLM(可选)。** `SAVECONTEXT_LLM_SUMMARY=1` → 本地 Ollama 模型编写抽象简介;失败时转为提取。(`brief_mode='abstractive(local-llm)'`)
3. **提取(默认)。** 基于规则的源代码真实句子 - 免费,离线,确定性,始终可用。(`brief_mode='extractive'`)
</details>
<details>
<summary><b>开发和测试</b></summary>
<br>
```bash
git clone https://github.com/AlexanderBoger/SaveContext && cd SaveContext
python -m pip install -e ".[tokenizer,dev]"
python -m pytest # 80 个测试
```
涵盖分词器/句柄/分块/提取/BM25 检索单元、所有十一工具的端到端测试(偏移准确性、逐字引用、版本控制、货币变更差异、审计保留桶、错误处理)、批量 `lookup` 检索 + 置信度逻辑以及 CLI 工作流。
</details>
<details>
<summary><b>路线图</b></summary>
<br>
- ✅ BM25 + 混合语义排名(概念组、答案类型意图)- 无需模型
- ✅ 批量 `lookup` 及每个查询的置信度/放弃
- ✅ `audit` 中的逐字完整性 + 提取召回报告
- ✅ PDF / DOCX / HTML 加载器和递归文件夹摄入
- ✅ 除 stdio 之外的 HTTP / SSE 传输
- ⬜ 嵌入式后端基准测试,使用保留的套件(密集散文检索)
- ⬜ 嵌入式存储持久化,以便嵌入式存储不需重新计算
- ⬜ LLM 辅助原子提取,用于模糊/多跨度事实
</details>
## 许可证
[Apache License 2.0](https://github.com/AlexanderBoger/SaveContext/blob/master/LICENSE) - 另见 [NOTICE](https://github.com/AlexanderBoger/SaveContext/blob/master/NOTICE)。如果您重新分发 SaveContext 或在其基础上构建,请保留版权和 `NOTICE` 文件,按照许可证要求(这是要求)。