Aphrodite 💋 (aphrodite)
你的 LLM 将 90% 的上下文消耗在它从未读取的输出上。我们解决了这个问题。
面向 Hermes Agent 的 CCR 压缩代理 + 吸收式预览管道。 在标准语料库上最高可达 610×(整体 132×),端到端约 10 ms, 26 类型分类器,由 TOML 驱动。 单一二进制文件。零依赖。节省数百万个 token。
安装 ⚡
Aphrodite 从两个 crate 中提供两个构建产物:aphrodite 代理
二进制文件(独立的 HTTP 代理,:9797/:9798)以及
libaphrodite_hermes.{dylib,so,dll} dylib(由 Hermes
插件在进程内加载,本身没有 CLI)。对于下面常见的路径,你无需了解这些细节——
一旦需要手动安装,这些细节就开始变得重要。
作为 Hermes 插件(推荐)
# Clone the standalone plugin repo
git clone https://github.com/PlayForm/Aphrodite-Hermes.git
ln -s "$(pwd)/Aphrodite-Hermes" ~/.hermes/plugins/aphrodite
hermes plugins enable aphrodite
hermes
首次启动时,插件会自动从
releases 下载 aphrodite 二进制文件。无需 Rust 工具链。
通过 cargo install
cargo install aphrodite # proxy binary only - see note below
cargo install aphrodite-hermes # helper bin only - see note below
aphrodite setup # plugin structure + config + symlink
cargo install 仅复制 crate 的 [[bin]] 目标到
~/.cargo/bin/ - 它不会(也无法)分发这两个 crate 同时构建的 libaphrodite.dylib
/ libaphrodite_hermes.dylib cdylib 产物。
aphrodite setup 如果无法找到它们,会大声报错("dylib not found"),并且诚实地报告该失败 - 但 dylib 本身
仍需来自某处:要么是完整的源代码检出
(cargo build --release -p aphrodite -p aphrodite-hermes),要么是
上述 "Hermes plugin" 方法已使用的
release-download 流程
(plugins/aphrodite/download.sh)。如果你只需要代理二进制文件本身
(无需 Hermes plugin),仅 cargo install aphrodite 就足够了。
Windows:
plugins/aphrodite/download.ps1是download.sh的原生 PowerShell 等效版本 - 无需 Git Bash/WSL。参见 Windows install 了解快速路径以及完全 手动操作指南。完整的各平台指南(包括 Aphrodite 的两个构建产物中你实际需要的哪一个)位于 docs/install/ 下。
cargo install + 一次性引导
cargo install aphrodite aphrodite-hermes
aphrodite setup --api-key sk-... --api-url https://api.deepseek.com --model deepseek-v4-pro
aphrodite setup 提供 ~/.hermes/aphrodite/ 端到端 - 二进制文件、
dylibs、aphrodite.toml、plugin.yaml 以及 hermes plugins enable aphrodite - 通过一条命令完成。其插件符号链接步骤目前在 Windows 上为空操作
(仅限 Unix 的代码路径);如果遇到该问题,请参阅
docs/install/README.md
从源码(monorepo)
git clone https://github.com/PlayForm/Aphrodite.git
cd Aphrodite
git submodule update --init --recursive # required - vendored deps live in submodules
cargo build --release -p aphrodite -p aphrodite-hermes
# Binary: target/release/aphrodite
# Dylibs: target/release/libaphrodite.dylib, target/release/libaphrodite_hermes.dylib
安装后会发生哪些变化
~/.hermes/
├── plugins/
│ └── aphrodite/ ← symlink to Aphrodite-Hermes
├── aphrodite/
│ ├── aphrodite ← auto-downloaded binary (~12 MB)
│ └── ccr.db ← SQLite CCR store (created on first run)
└── profiles/<name>/
└── plugins/
└── aphrodite → ~/.hermes/plugins/aphrodite
该插件注册了 13 个工具(aphrodite_*)、5 个钩子和一个上下文引擎 -
全部通过 Rust dylib 路由。两个代理在 :9797(缓存)
和 :9798(令牌)上自动启动。
问题
每次你的 agent 读取文件、运行构建、搜索代码或打开浏览器时——原始输出都会淹没其上下文窗口。成千上万个 token 的编译日志。庞大的可访问性树。冗长的 JSON 数据块。你的 agent 将其宝贵的上下文预算用于阅读噪音,而非推理。
Aphrodite 在输出到达 LLM 之前将其拦截,并用紧凑的结构化预览进行替换。 agent 看到的是 15 个 token 的元数据,而不是 500 个 token 的原始文本——并且仅在实际需要时才检索完整内容。
工作原理 ⚙️
ANY OUTPUT ──────► Aphrodite ──────► Agent (preview, not raw)
│
├─ build logs → [build:1E 1W 142L | error[E0432]: ...]
├─ terminal → [terminal:14L exit code: 0]
├─ file read → [code:3fns|2structs fn main() 414L]
├─ grep/ripgrep → [grep:4 hits in 3 files | src/x.rs:12 …]
├─ git status → [git:2M 1A 1D 3?? | src/x.rs +N more]
├─ git log → [gitlog:2 commits | abc123 … → def456 …]
├─ test output → [test:220 pass 0 fail 1 ignored | 0.31s]
├─ dir listing → [ls:3 files 2 dirs | .rs×2 .md×1]
├─ diff → [diff:2F +7/-3 12L | src/main.rs Cargo.toml]
├─ JSON blobs → [json:5items 3L]
└─ plain text → [text:3L 50B | first line hint …]
Agent decides:
• Preview is enough → skip retrieval, keep reasoning
• Needs detail → aphrodite_retrieve(hash) → full content
Context engine (automatic):
• Session hits 45% context → middle turns auto-compressed to CCR
• Agent never hits context window ceiling
四层,全部快速(分类 40-123 ns;整个压缩步骤 亚毫秒级,远小于 HTTP 往返时间):
- Classify - 26 种类型的正则分类器识别内容(40-123 ns)
- Preview - 默认在代理和钩子路径上生成丰富的、类型感知的预览(git/test/grep/log/build/diff/ code/ls 等)
- Store - BLAKE3 → SQLite/内存 →
<<<CCR:hash|type|size>>>标记 - Decide - Agent 读取预览,仅在需要时检索
丰富的预览形状自动发出(无需标志) - 参见 docs/proxy/compression.md 以获取完整的内容类型 → 预览目录。
架构 🏗️
crates/aphrodite/ ← Core compression engine (binary + cdylib)
├── proxy.rs ← HTTP proxy: classify → compress → store → preview
├── hooks.rs ← transform_tool_result, transform_terminal_output
├── resolve.rs ← CCR marker resolution (nested, recursive)
├── stage2.rs ← Semantic reduction (JSON, build, diff, code)
├── struct_extract.rs ← Code structure extraction (Rust, Python, Go, JS/TS)
├── state.rs ← Session state, inline store, LRU
├── catalog.rs, session.rs, marker.rs, prefetch.rs, config_loader.rs
└── lib.rs ← 25 C ABI functions for dylib loading
crates/aphrodite-hermes/ ← Hermes-specific integration (cdylib)
├── tools.rs ← 13 tool dispatch handlers
├── schemas.rs ← JSON Schema definitions
└── skills.rs ← Bundled Hermes skills
plugins/aphrodite/ ← Thin Python loader (421 lines)
└── __init__.py ← loads dylib, registers hooks/tools/engine via C ABI
| 模式 | 端口 | 后端 | 阈值 | 适用场景 |
|---|---|---|---|---|
| Cache | :9797 | In-memory | >8 KB | 速度,临时会话 |
| Token | :9798 | SQLite | >1 KB | 持久性,工具中继 |
所有压缩逻辑都位于 Rust dylib 中。Python 是一个轻量级的 FFI 加载器。
热重载:重新构建 dylib → 检测到 mtime 变化 → 下一次调用自动加载新
代码。这两个 Aphrodite crate 包含单元测试(外加完整的
vendored Headroom 测试套件)- 运行 cargo test --workspace 以查看当前
数量并确认它们通过。
你节省了什么 💰
| 内容类型 | 无 Aphrodite | 有 Aphrodite | 节省 |
|---|---|---|---|
| Git diff (42L) | ~350 tok | ~15 tok | 23× |
| Build output (142L) | ~1,400 tok | ~10 tok | 140× |
| Traceback | ~45 tok | ~12 tok | 3.8× |
| Terminal output | ~200 tok | ~10 tok | 20× |
| Table (50 rows) | ~650 tok | ~8 tok | 81× |
| JSON blob (30 keys) | ~400 tok | ~10 tok | 40× |
| Web search (10 results) | ~800 tok | ~15 tok | 53× |
| Browser snapshot (342 el) | ~5,000 tok | ~12 tok | 416× |
中位数:工具输出的 token 减少 23 倍。 在包含 50 多次工具调用的会话中, 这意味着节省了 15,000-50,000 个 token——足以支撑一个完整的额外推理轮次。
真实示例: 一个 6 轮的开发会话(构建、测试、文档、git)将 216 KB 的原始工具输出压缩为 12 个标记——~54,000 tokens → ~240 tokens (减少 225 倍),使 99.6% 的上下文窗口可用于推理。
工具 🔧
| 工具 | 描述 |
|---|---|
aphrodite_retrieve | 解析 <<<CCR:hash|type>>> 标记 |
aphrodite_compress | 通过 CCR 压缩内容并附带类型提示 |
aphrodite_stats | 代理健康状态、引擎状态、内联存储大小 |
aphrodite_rebuild | 重建二进制文件、终止代理、重启 |
aphrodite_files | 按工具分组的受跟踪文件引用 |
aphrodite_diff | 带有摘要的对话轮次历史 |
aphrodite_search | 按关键词或类型搜索 CCR 存储 |
aphrodite_directive | 列出/交换/添加/移除/重置行为指令 |
aphrodite_test | 冒烟测试套件:快速(1 项检查)、完整(3 项检查) |
aphrodite_catalog | 完整的 CCR 目录,包含哈希值、类型、大小、预览 |
aphrodite_reclassify | 为未分类的 CCR 进行追溯性元数据增强 |
aphrodite_prefetch | 按需读取 + 压缩文件;标记以内联形式返回 |
aphrodite_prefetch_status | 实时预取计划:加载中、就绪、错误 |
内部机制 🧩
./plugins/aphrodite/是一个独立的仓库 - 它位于 PlayForm/Aphrodite-Hermes。 此 monorepo 将其作为 git submodule 进行跟踪。
plugins/aphrodite/ ← Standalone Hermes plugin (git submodule)
__init__.py ← Python loader (ctypes FFI, thin shim)
plugin.yaml ← 13 tools, 5 hooks, context engine
download.sh ← Binary auto-downloader (macOS/Linux/Git Bash/WSL)
download.ps1 ← Binary auto-downloader (native Windows PowerShell)
binaries/ ← Platform-native dylib + proxy binary
README.md ← Standalone install instructions
crates/aphrodite/ ← Core engine (binary + cdylib)
src/
lib.rs ← 25 C ABI functions (session, hooks, catalog, …)
proxy.rs ← HTTP proxy server (:9797/:9798)
hooks.rs ← transform_tool_result, terminal, pre/post LLM
session.rs ← Turn lifecycle, conversation index, git cache
state.rs ← AphroditeState, inline store, LRU, markers
marker.rs ← CCR marker generation + parse (<<<CCR:…>>>)
catalog.rs ← Full/compact/TOC catalog display
resolve.rs ← Recursive CCR marker expansion (5 levels)
stage2.rs ← Semantic reduction for JSON, build, diff, code
struct_extract.rs ← Code structure maps (Rust, Python, Go, JS/TS)
config_loader.rs ← TOML + env var config loading
prefetch.rs ← On-demand file read + compress
crates/aphrodite-hermes/ ← Hermes bridge
src/
lib.rs ← Universal dispatch (5 hooks → Rust functions)
tools.rs ← 13 tool handler implementations
schemas.rs ← JSON Schema for all tools
skills.rs ← Bundled skill registration for Hermes
vendor/headroom/ ← Headroom fork (git submodule)
crates/headroom-core/ ← Content transforms, tokenizer, smart crusher
两个 Aphrodite crate 包含单元测试(内置的 Headroom 分支包含其自身的测试套件)- 运行 cargo test --workspace 以查看当前数量及
通过/失败状态。CC0-1.0 - 公有领域。
开发者工作流 🛠️
# Terminal 1: cargo watch (rebuilds dylib on change)
# Build BOTH packages, not just `aphrodite` - `aphrodite-hermes` (the crate
# that actually produces libaphrodite_hermes.dylib) depends ON `aphrodite`,
# not the other way around, so `cargo build -p aphrodite` alone never
# touches the dylib at all, no matter what changed.
APHRODITE_NO_AUTO_LAUNCH=1 cargo watch -x 'build -p aphrodite -p aphrodite-hermes'
# Terminal 2: Hermes (loads hot-reloaded dylib)
hermes --profile dev-aphrodite
| 变更内容 | 发生的情况 |
|---|---|
任意 .rs 文件 | cargo watch 重新构建 → dylib 的 mtime 发生变化 |
| 下一次 hook 调用 | 插件检测到新的 mtime → 重新加载 dylib |
任意 .py 文件 | /quit + hermes 重启(Hermes 缓存 Python 导入) |
| 代理二进制文件 | aphrodite_rebuild 工具 → 终止 + 复制 + 重启 |
Git hooks
git config core.hooksPath .githooks(由 pnpm install
通过 package.json 的 prepare 脚本自动设置,该脚本还会执行初始的子模块
同步 - 见下文)启用了 .githooks/post-checkout 和 .githooks/post-merge。
两者都会运行 .githooks/lib/sync-submodules.sh,该命令在每次 checkout/merge/pull 之后,将三个
已引入的子模块(plugins/aphrodite、vendor/headroom、vendor/rtk)浮动到
其配置的跟踪分支尖端(.gitmodules 中的 branch = Current),
并自动提交由此产生的 pin 版本更新到
本仓库的索引中(范围仅限于子模块路径 - 绝不会卷入任何
其他已暂存的工作)。净效果是:本地检出永远不会落后于
Current,且新克隆的仓库中普通的 git submodule update --init --recursive (no --remote needed) lands close to Current 的尖端也会同步,
因为 pin 是持续保持同步的,而不是仅通过显式的发布操作来移动。
安全性:包含未提交更改的子模块,或包含尚未推送到其跟踪分支的本地提交的子模块,将被跳过(在 stderr 上报告),而不是强制重置 - 同步操作仅执行等效于快进(fast-forward)的移动。
此仓库中正在进行的 rebase/merge/cherry-pick 也会直接跳过同步。
要从中获取的远程仓库是通过将 .gitmodules 自身配置的 url 与每个子模块的本地远程进行匹配来解析的,而不是假设一个名为 origin 的远程 - vendor/rtk 的 origin 恰好是上游 rtk-ai/rtk 仓库(那里没有 Current 分支);此仓库实际跟踪的 fork 位于一个名为 Source 的远程下。
Maintain/scripts/release/auto-release.sh 自身的 SYNC_SUBMODULES=1 在发布时浮动(float-at-release-time)行为不受此影响,并且仍然可用于作为发布一部分的显式、经过审查的版本固定(pin)提升。
快速入门 🚀
# Build
cargo build --release -p aphrodite
# Run (both proxies start automatically)
aphrodite
# Verify
curl http://127.0.0.1:9798/health
# -> {"status":"healthy","ccr":true,"mode":"token","version":"1.3.8","fill_pct":90.0}
# Dev loop with auto-reload (also rebuilds aphrodite-hermes's dylib, not just
# the proxy binary - see "Developer Workflow" above)
RUST_LOG=aphrodite=info cargo watch -x 'build -p aphrodite -p aphrodite-hermes' -x 'run -p aphrodite'
配置 - 所有配置项集中在一个文件中
# aphrodite.toml - no recompile needed
[compression]
tool_threshold_token = 512 # token proxy threshold (bytes)
tool_threshold_cache = 4096 # cache proxy threshold (bytes)
inline_threshold = 2048 # inline-vs-durable CCR storage cutoff (bytes)
code_multiplier = 3.0 # multiply threshold for code_* content types
这四个 [compression] 字段在 Rust 代理上是实时生效的:每个字段
都可以通过一个 APHRODITE_* 环境变量进行覆盖,并且编辑并保存该文件(或
POST /reload)会立即应用新值,无需重启。其他
[compression]/[previews]/[prompts] 键存在于模式中,但要么
仅影响独立的 Hermes 插件 dylib 会话,要么尚未被
任何组件消费 - 请参阅 docs/config/aphrodite-toml.md
以获取关于哪些部分已连接在何处的完整且准确的分解。
还有两个值得了解的配置项:
- 指令 -
[directives] active = ["focus"]播种简短的行为 指令(directives/*.md),注入到 LLM 的上下文中,每 轮对话都会生效,可通过aphrodite_directive工具在对话中途进行替换。 随附的集合包括focus、foresight、ccr-handling、cleanup、explore和lazy(延迟至需要时执行)。使用aphrodite_directive("load", name)可按需激活其中一个。请参阅docs/plugin/directives.md。 - 管理认证 - 设置
APHRODITE_MGMT_TOKEN以要求 在代理的管理路由上 (/stats、/retrieve、/ccr/*、/reload、...)进行Authorization: Bearer <token>;/health和/metrics保持开放。未设置 = 开放的环回访问(向后兼容),并带有 启动警告。请参阅docs/config/env-vars.md。
性能 ⚡
标准语料库(bench_01,20 个样本,106,256 B,测量日期 2026-07-14)。
比率随输入大小变化,并随熵降低而下降——小尺寸/高熵
输入压缩率较低,大尺寸低熵文本压缩率较高:
| 样本 (大小) | 比率 |
|---|---|
tiny_text (120 B) | 3.00× |
json_tool (675 B) | 16.88× |
rust_code (2,673 B) | 66.83× |
linter_output (4,014 B) | 100.35× |
log_output (4,943 B) | 123.58× |
code_go (5,712 B) | 142.80× |
unicode_cjk (6,720 B) | 168.00× |
build_error (6,949 B) | 173.72× |
code_js (7,212 B) | 180.30× |
search_results (10,080 B) | 252.00× |
large_prose (11,400 B) | 285.00× |
huge_prose (24,400 B) | 610.00× |
| 总体 (106,256 → 800 B) | 132.82× |
范围:3.00× (120 B) 至 610.00× (24 KB 文本);总体 132.82×。 缓存模式和令牌模式测得的比率相同。20/20 压缩成功,20/20 检索往返正常(0 次未命中)。
| 指标 | 值 |
|---|---|
| 端到端延迟 (缓存) | 9-40 ms (HTTP 往返) |
| 端到端延迟 (令牌) | 8-10 ms 典型 |
| 分类延迟 | 40-123 ns |
延迟数据为端到端数据——它们包含 HTTP 往返时间,而不仅仅是 压缩调用。压缩步骤本身在亚毫秒级别;语料库 测试框架并未将其隔离,因此我们引用实测的挂钟时间数值 而非仅压缩的数值。
基准测试(cargo run --release -p aphrodite --example bench_0N_*,参见
crates/aphrodite/examples/)和进程内冒烟测试套件
(aphrodite_test,在 full 模式下有 3 项检查)是可复现的命令——直接
运行它们以复现上述数值。
实际节省(Hermes Agent,deepseek-v4-pro)
通过 .bench/e2e/hermes_z_ab.sh 测量——4 个标准化编码提示,
A/B 测试 aphrodite 开启与关闭,focus 指令处于激活状态:
| Prompt | OFF (tokens) | ON (tokens) | Saved | API calls OFF/ON |
|---|---|---|---|---|
| Read + summarize | 444,236 | 178,636 | 60% | 13 → 7 |
| Cargo build output | 28,913 | 28,903 | 0% | 2 → 2 |
| Search codebase | 68,719 | 30,500 | 56% | 4 → 2 |
| Read two docs | 34,075 | 34,049 | 0% | 2 → 2 |
| Total | 575,943 | 272,088 | 53% | 21 → 13 |
成本:$0.18(OFF)→ $0.15(ON)——便宜 18%,API 调用减少 38%。
与 Headroom 的关系
Aphrodite 嵌入了 Headroom - 我们自定义的 fork,作为 git 子模块在
vendor/headroom/ 处进行跟踪。Headroom 提供
内容转换(分类器、智能压缩器、分词器);Aphrodite 增加了
预览管道、CCR 存储、Hermes 集成以及双代理架构。
贡献指南 🤝
| 想要… | 从这里开始 |
|---|---|
| 报告一个 bug | 提交一个 issue |
| 建议一个功能 | 发起一个讨论 |
| 提交一个 PR | Fork 并打开一个 PR |
| 提问 | Discussions Q&A |
没有太小的贡献。首次贡献者?尤其欢迎。
由 PlayForm 用 ❤️ 构建。