ITADN
PlayForm/Aphrodite
README.md
以下内容由 AI 翻译,如有问题请点此提交 issue 反馈

Aphrodite


Aphrodite 💋 (aphrodite)

你的 LLM 将 90% 的上下文消耗在它从未读取的输出上。我们解决了这个问题。

面向 Hermes Agent 的 CCR 压缩代理 + 吸收式预览管道。 在标准语料库上最高可达 610×(整体 132×),端到端约 10 ms, 26 类型分类器,由 TOML 驱动。 单一二进制文件。零依赖。节省数百万个 token。

release crates.io plugin rust license


安装 ⚡

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.ps1download.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.tomlplugin.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 往返时间):

  1. Classify - 26 种类型的正则分类器识别内容(40-123 ns)
  2. Preview - 默认在代理和钩子路径上生成丰富的、类型感知的预览(git/test/grep/log/build/diff/ code/ls 等)
  3. Store - BLAKE3 → SQLite/内存 → <<<CCR:hash|type|size>>> 标记
  4. 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:9797In-memory>8 KB速度,临时会话
Token:9798SQLite>1 KB持久性,工具中继

所有压缩逻辑都位于 Rust dylib 中。Python 是一个轻量级的 FFI 加载器。 热重载:重新构建 dylib → 检测到 mtime 变化 → 下一次调用自动加载新 代码。这两个 Aphrodite crate 包含单元测试(外加完整的 vendored Headroom 测试套件)- 运行 cargo test --workspace 以查看当前 数量并确认它们通过。


你节省了什么 💰

内容类型无 Aphrodite有 Aphrodite节省
Git diff (42L)~350 tok~15 tok23×
Build output (142L)~1,400 tok~10 tok140×
Traceback~45 tok~12 tok3.8×
Terminal output~200 tok~10 tok20×
Table (50 rows)~650 tok~8 tok81×
JSON blob (30 keys)~400 tok~10 tok40×
Web search (10 results)~800 tok~15 tok53×
Browser snapshot (342 el)~5,000 tok~12 tok416×

中位数:工具输出的 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.jsonprepare 脚本自动设置,该脚本还会执行初始的子模块 同步 - 见下文)启用了 .githooks/post-checkout.githooks/post-merge。 两者都会运行 .githooks/lib/sync-submodules.sh,该命令在每次 checkout/merge/pull 之后,将三个 已引入的子模块(plugins/aphroditevendor/headroomvendor/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/rtkorigin 恰好是上游 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 工具在对话中途进行替换。 随附的集合包括 focusforesightccr-handlingcleanupexplorelazy(延迟至需要时执行)。使用 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 指令处于激活状态:

PromptOFF (tokens)ON (tokens)SavedAPI calls OFF/ON
Read + summarize444,236178,63660%13 → 7
Cargo build output28,91328,9030%2 → 2
Search codebase68,71930,50056%4 → 2
Read two docs34,07534,0490%2 → 2
Total575,943272,08853%21 → 13

成本:$0.18(OFF)→ $0.15(ON)——便宜 18%,API 调用减少 38%。


与 Headroom 的关系

Aphrodite 嵌入了 Headroom - 我们自定义的 fork,作为 git 子模块在 vendor/headroom/ 处进行跟踪。Headroom 提供 内容转换(分类器、智能压缩器、分词器);Aphrodite 增加了 预览管道、CCR 存储、Hermes 集成以及双代理架构。

完整对比:Aphrodite 与 Headroom


贡献指南 🤝

想要…从这里开始
报告一个 bug提交一个 issue
建议一个功能发起一个讨论
提交一个 PRFork 并打开一个 PR
提问Discussions Q&A

没有太小的贡献。首次贡献者?尤其欢迎。


由 PlayForm 用 ❤️ 构建。