yttrium400/reducethemtokens
GitHub: yttrium400/reducethemtokens
reducethemtokens 压缩代码库为结构骨架以减少LLM token使用,解决AI在不熟悉代码库上导航效率低的问题。
Stars: 6 | Forks: 6
# rtt - 优化token使用
[](https://pypi.org/project/reducethemtokens/)
[](https://pypi.org/project/reducethemtokens/)
[](LICENSE)
在单次、低成本的读取中,为任何LLM提供您代码库的完整地图。

`rtt` 提取每个文件的导入、函数签名、类层次结构和方法
列表,并将其压缩成紧凑的纯文本骨架 - 通常比原始源代码小90% -
并将其连接到您代理的配置中,以便该地图从每个会话的第一条消息起就可用。
## 它解决的问题
现代编码代理(Cursor、Claude Code、Copilot)擅长为
*具体的、有针对性的查询*检索上下文。询问一个bug、一个函数、一个文件——它们能找到。
但它们在**方向性问题**上存在困难:在不熟悉的代码库上开始一个会话,或者提出跨越整个结构的问题。在代理能够检索到正确的上下文之前,它需要理解存在什么以及在哪里。没有这个地图,它
要么投机性地扫描文件(消耗token),要么对结构做出错误的假设。
`rtt` 通过预先、一次性、低成本地提供该地图来解决这个问题。代理在会话开始时读取骨架,了解完整的API表面,然后只打开它实际需要的特定文件。
**rtt 不是代理检索的替代品。** 检索更适合有针对性的、实现级别的任务。rtt是方向层,它在代理开始搜索之前为其提供正确的心理模型,从而使检索更准确。
## 代理在哪里节省token
每个代码更改任务都遵循相同的四个步骤:
```
1. Task arrives 2. Navigate 3. Read 4. Write
"add a rate-limit → find the right → open that file → make the edit
endpoint" file to edit in full
↑
tokens wasted here
without a map
```
**步骤2是代理不必要地消耗token的地方。** 没有结构地图时,代理会进行投机性扫描 - 打开那些最终被证明是错误的文件,然后才找到正确的文件。使用rtt后,步骤2变成了单次骨架查找:代理预先看到每个文件的导出、导入和签名,直接识别目标,并跳过探索性读取。
步骤3总是会发生的——代理需要函数体才能编写正确的编辑。rtt 并不能取代这一点。
### 在真实的私有代码库上测量
我们在一个包含**246个文件的TypeScript/Next.js**仓库上运行了相同的5个代码更改导航任务两次——一次没有预先上下文,一次预先添加了rtt骨架(18,149 tokens):
| | 无骨架 | 有骨架 |
|---|---|---|
| 文件读取次数 | 16 | **7** |
| 总工具调用次数 | 22 | **14** |
**文件读取减少56%。总工具调用减少36%。** 几个导航任务完全从骨架中得到了解答——根本没有打开任何文件——而其余的读取则直接指向正确的文件。
### 为什么更大的仓库节省更多
在一个只有50个文件的小仓库上,代理通常仅从文件名就能猜到正确的文件。在一个500个文件的仓库上则不行——探索性开销随着表面面积增长。骨架开销随文件数量线性增长,但被阻止的投机性读取次数增长得更快。一个粗略模型:
| 仓库规模 | 骨架开销 | 每个会话预估节省的读取次数 | 盈亏平衡点 |
|---|---|---|---|
| 50 个文件 | ~2k tokens | 1–2 次读取 | 立即 |
| 250 个文件 | ~18k tokens | 5–10 次读取 | 第一个会话 |
| 1,000+ 个文件 | ~60k tokens | 20+ 次读取 | 第一个会话 |
每次被阻止的文件读取都避免了在会话的剩余时间内将该文件的完整源代码加载到上下文中。对于平均200–500行的TypeScript/Python文件,这相当于每次读取消耗1,000–4,000 tokens。一旦骨架阻止了4–6次探索性读取——在任何超过200个文件的仓库上,这通常会在单个任务中发生——它就能收回成本。
## 何时使用它
**在以下情况使用 rtt:**
- 代理在它从未见过的代码库上开始一个会话
- 任务涉及跨多个文件的交叉更改(重构、重命名、添加影响多层的功能)
- 您正在使用没有内置检索功能的聊天界面(ChatGPT、Claude.ai、直接API)——每个会话都从零开始
- 您正在构建CI流水线、代码审查机器人或任何可重现的、确定性的上下文很重要的自动化工作流
- 您想为LLM提供仓库上下文而无需设置向量存储或任何额外的基础设施
**rtt 在以下情况不太有用:**
- 您询问的是某个特定文件或函数——直接打开它即可
- 您的代理已经具有完整的检索功能,并且您正在处理有针对性的、范围明确的任务
## 安装
```
pip install reducethemtokens
```
需要Python 3.10+。
## 快速开始
```
cd your-repo
rtt install .
```
这会写入 `.rtt/context.txt`(骨架),并将一段简短的指令添加到每个支持的代理配置文件中 - `CLAUDE.md`、`AGENTS.md`、`.cursor/rules/` 等。
该指令告诉代理在会话开始时读取骨架以了解方向,然后正常工作。
提交这两个文件。每个协作者和每个未来的会话都会自动获得该地图。
```
# 代码更改后 - 重新生成 skeleton
rtt update .
# 查看 skeleton 节省了多少 tokens 对比原始源代码
rtt compare .
```
**单个文件的示例骨架输出:**
```
# rtt/bench.py [python]
imports: os, random, re, dataclasses.dataclass, dataclasses.field, pathlib.Path, typing.Optional, rtt.RepoIndex, rtt.Symbol
class BenchQuestion
class QuestionResult
class BenchReport
def heuristic_score(self) -> float
def heuristic_by_kind(self) -> dict[str, tuple[int, int]]
def heuristic_failing(self) -> list[QuestionResult]
def llm_score(self) -> Optional[float]
def generate_questions(repo: RepoIndex) -> list[BenchQuestion]
def score_heuristic(questions: list[BenchQuestion], repo: RepoIndex) -> list[QuestionResult]
def run_bench(path: str, use_llm: bool, llm_sample: int) -> BenchReport
```
## 基准测试 - Django (3,020 个文件)
| 指标 | 值 |
|---|---|
| 原始代码库 | 6,464,961 tokens |
| rtt 骨架 | 585,421 tokens |
| 减少率 | **90.9%** |
| 启发式基准得分 | **100.0%** (13,665 / 13,670 个问题) |
| 审计覆盖率 (Python) | **99.9%** (34,454 / 34,480 个符号) |
| 审计覆盖率 (JavaScript) | **97.9%** (46 / 47 个符号) |
启发式基准从索引中自动生成事实性问题——参数名称、返回类型、方法列表、导入——并验证每个答案都出现在骨架中。
100% 意味着在压缩过程中没有丢失任何结构信息。
一个单独的受控准确性测试向Claude询问关于代码的结构问题,一次使用完整源代码,一次使用骨架,然后使用Claude作为评判者来验证正确性。骨架在此测试中得分 **90%**——除了涉及在函数体内定义的导入的问题(这是一个结构限制:rtt 设计上只捕获顶级导入)之外,在每个问题上都与完整源代码匹配。
## 命令
### `rtt install`
索引仓库,将骨架写入 `.rtt/context.txt`,并将方向性指令注入每个支持的代理配置文件中。还会安装一个git pre-commit钩子,在每次提交时自动重新生成骨架。
```
rtt install .
rtt install . --platform claude # single agent only
rtt install . --force # overwrite existing rtt sections
rtt install . --no-tests # exclude test/spec/fixture files
rtt install . --max-tokens 100000 # trim to fit a context window budget
rtt install . --include 'src/**' # only index specific directories
rtt install . --exclude 'vendor/**'
```
支持的代理:
| 代理 | 配置文件 |
|---|---|
| Claude Code | `CLAUDE.md` |
| Cursor | `.cursor/rules/rtt.mdc` |
| Windsurf | `.windsurfrules` |
| Codex / OpenAI | `AGENTS.md` |
| GitHub Copilot | `.github/copilot-instructions.md` |
| Kiro | `.kiro/steering/rtt.md` |
| Gemini CLI | `GEMINI.md` |
| Aider | `.aider/prompts/conventions.md` |
| Zed | `.rules` |
| Continue.dev | `.continue/rules/rtt.md` |
添加到每个配置文件的指令告诉代理在会话开始时读取一次 `.rtt/context.txt` 以了解方向,然后正常工作。它不限制代理读取源文件或使用其自身的检索功能。
### `rtt update`
在代码更改后重新生成 `.rtt/context.txt`。不触碰代理配置文件。
`rtt install` 安装的git钩子会在每次提交时自动运行此命令。
```
rtt update .
rtt update . --diff # show what symbols changed
rtt update . --no-tests # same flags as install are accepted
```
### `rtt uninstall`
从所有代理配置文件中移除rtt指令。
```
rtt uninstall .
rtt uninstall . --platform cursor
rtt uninstall . --clean # also delete .rtt/context.txt
```
### `rtt index`
生成骨架并打印到标准输出,或写入文件。可用于管道传递到其他工具或构建自定义工作流。
```
rtt index .
rtt index /path/to/repo --output context.txt
rtt index . --no-tests
rtt index . --include 'src/**' --include 'lib/**'
rtt index . --exclude 'vendor/**' --exclude 'generated/**'
rtt index . --max-tokens 50000
```
### `rtt compare`
显示token减少统计信息,并按文件细分。
```
rtt compare .
rtt compare . --diff HEAD~3..HEAD # token delta for a git range
```
### `rtt bench`
测量骨架保留了多少结构信息。
```
rtt bench . # heuristic only, free, instant
rtt bench . --llm --sample 30 # semantic equivalence via Claude
```
`--llm` 模式需要 `ANTHROPIC_API_KEY` 和 `pip install "reducethemtokens[llm]"`。
### `rtt audit`
验证提取准确性:找到的符号与预期符号的对比,以及签名的正确性。
```
rtt audit .
```
### `rtt vs`
与另一个仓库索引工具(当前支持graphify)比较token占用。
```
pip install graphifyy
rtt vs .
```
### `rtt view`
将骨架渲染为markdown并在分页器中打开。
```
rtt view .
rtt view . --output overview.md
```
## 保持骨架最新
`rtt install` 设置了一个git pre-commit钩子,在每次提交时自动运行 `rtt update`。对于大多数个人工作流来说,这就足够了。
**对于团队**,该钩子仅在安装了rtt的机器上运行。克隆仓库但未安装rtt的新贡献者不会重新生成骨架。两种方法:
添加一个CI步骤,在每次合并到主分支时重新生成并提交骨架:
```
# .github/workflows/rtt.yml
name: Update rtt index
on:
push:
branches: [main]
jobs:
rtt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install reducethemtokens
- run: rtt update .
- uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "chore: update rtt index"
file_pattern: ".rtt/context.txt"
```
或者将其记录在您的贡献指南中:
```
# 拉取更改后
rtt update .
git add .rtt/context.txt
```
`.rtt/context.txt` 的第一行包含生成时间戳和文件数量,因此代理无需读取整个文件即可检测到过时的索引。
**大型仓库和上下文窗口限制**
测试文件通常是骨架大小的最大贡献者。对于大多数项目,最简单的减少方法是使用 `--no-tests`:
```
rtt install . --no-tests # drops test/, spec/, fixture/ files
```
在Django(3,020个文件)上,仅此一项就将骨架从585k tokens减少到193k。
如果骨架仍然太大,可以使用 `--max-tokens` 来裁剪以适应。
rtt会保留符号最多的非测试文件,并丢弃其余文件:
```
rtt install . --max-tokens 100000 # fits in most 128k-window models
rtt install . --max-tokens 50000 # conservative
```
按仓库规模的粗略指南:
| 仓库规模 | 方法 |
|---|---|
| < 500 个文件 | 无需标志 |
| 500–2,000 个文件 | `--no-tests` |
| 2,000+ 个文件 (例如 Django) | `--no-tests` + `--max-tokens 100000` |
或者限制到特定目录:
```
rtt install . --include 'src/**' --include 'lib/**'
rtt install . --exclude 'vendor/**' --exclude 'generated/**'
```
## Python API
```
import rtt
repo = rtt.index("/path/to/repo")
repo = rtt.index("/path/to/repo", no_tests=True)
repo = rtt.index("/path/to/repo", max_tokens=100000)
repo = rtt.index("/path/to/repo", include=["src/**"], exclude=["vendor/**"])
print(repo.token_count) # int
print(repo.text) # full skeleton as a string
for file in repo.files:
print(file.path, file.language)
print(file.imports) # e.g. ["pathlib.Path", "typing.Optional"]
for sym in file.symbols:
print(sym.name, sym.kind, sym.signature)
for child in sym.children:
print(" ", child.signature)
report = rtt.compare("/path/to/repo")
print(f"{report.reduction_pct:.1f}% reduction")
print(f"{report.raw_tokens:,} → {report.compressed_tokens:,} tokens")
```
## 支持的语言
Python, JavaScript, TypeScript, Go, Rust, Java, C, C++, Ruby, Swift, Kotlin, C#, Lua, Dart, Scala.
## 工作原理
`rtt` 使用 [tree-sitter](https://tree-sitter.github.io/tree-sitter/) 解析每个文件,
并遍历AST以收集顶级定义:函数、类、方法和导入。函数体被丢弃。输出是每个符号一行,缩进以显示类成员关系,导入被解析为具体符号
(`from pathlib import Path` → `pathlib.Path`)。
结果按文件内容哈希缓存。在大型仓库上后续运行很快。
## 开发
```
git clone https://github.com/yttrium400/reducethemtokens
cd reducethemtokens
pip install -e ".[dev]"
pytest tests/
```
91个测试。无需网络调用。
## 许可证
MIT
标签:API映射, IPv6支持, LLM优化, SOC Prime, token节省, 代理辅助, 代码分析, 代码压缩, 代码骨架, 会话上下文, 凭证管理, 大语言模型应用, 开发工具, 效率提升, 数据管道, 结构提取, 软件工程, 逆向工具