拓冰建站拓冰建站
首页 / 资讯中心 / 正文

OpenHuman TokenJuice 适配器:宿主侧接入独立加载型上下文压缩模块的完整解析

OpenHuman TokenJuice 适配器宿主侧接入独立加载型上下文压缩模块的完整解析【免费下载链接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.项目地址: https://gitcode.com/GitHub_Trending/op/openhuman本文围绕 OpenHuman 仓库中 src/openhuman/inference/tokenjuice/README.md 展开解析 TokenJuice 作为 TinyBus 宿主适配器与共享 wire 契约层的定位压缩引擎本身作为独立发布的tinyjuiceTinyBus 模块运行不进入 OpenHuman 的依赖图。读完本篇你将理解引擎-适配器分离的模块边界如何落地掌握[tokenjuice]配置块全部参数与默认值、JSON-RPC 诊断控制面、tokenjuice_retrieve取回工具的调用方式以及节省统计savings的归因与持久化机制。一、架构定位引擎独立发布宿主只做适配README 开篇即明确了这条架构红线The reusable compression engine ships as the separately releasedtinyjuiceTinyBus module. It is not linked into OpenHumans dependency graph. This directory is the host adapter and shared wire-contract layer.也就是说src/openhuman/inference/tokenjuice/目录不包含任何压缩算法实现它只做四件事通过 TinyBus 消息总线调用远端的tinyjuice模块INSTALL/COMPACT/COMPRESS/DETECT/RETRIEVE/CACHE_STATS等方法名来自tinyjuice_bus::names::methods把宿主的[tokenjuice]配置块安装进模块在任何失败路径上提供直通回退pass-through fallback——压缩失败绝不破坏 agent 主流程维护宿主侧才关心的周边能力JSON-RPC 控制面、agent 取回工具、模型计价归因、可选的 ML 压缩回调。README 同时给出了两侧文件的职责分界表这是理解本目录的最佳索引OpenHuman 拥有的文件本仓库内路径职责mod.rsTinyBus 调用、配置安装、直通回退、节省统计接线types.rs稳定 JSON wire 契约无依赖副本schemas.rsJSON-RPC 控制器 schema 与 handlerconfig_patch.rs[tokenjuice]配置块的部分更新patch形状tools.rstokenjuice_retrieveagent 工具实现ml/TinyJuice 可选 ML 回调到runtime_python_serverKompress 的桥接savings.rs模型计价归因与持久化的仪表盘统计TinyJuice 拥有的引擎件位于独立的 TinyJuice 仓库TinyJuice 仓库路径职责src/compress.rs内容路由器content router入口src/compressors/JSON、代码、日志、搜索结果、diff、HTML、ML 槽位与通用压缩器src/cache/CCR 存储、取回标记、磁盘层、范围取回辅助src/rules/规则加载/编译器与内嵌规则表src/vendor/rules/*.json打包的vendored上游规则 JSONsrc/detect/、text/、tokens.rs、types.rs内容检测、文本辅助、token 估算、公共类型README 最后一条规则值得强调不要把tinyjuicecrate 加回 OpenHuman——运行时服务、配置持久化、JSON-RPC、工具、计价与 ML 回调留在宿主侧引擎行为留在可加载模块边界之后。二、模块代理proxy()与配置安装的指纹去重从 mod.rs 的源码看宿主与模块之间只有一条通道tinybus::Proxy。#[cfg(feature modules)] pub(super) async fn proxy(config: crate::openhuman::config::Config) - Resulttinybus::Proxy, String { // ... crate::openhuman::modules::ensure_loaded(config, tinyjuice).await?; let record crate::openhuman::modules::registry::find(tinyjuice) .ok_or_else(|| unknown module tinyjuice.to_string())?; crate::openhuman::modules::host::runtime() .await? .proxy(record.bus_name, record.object_path) .map_err(|e| e.to_string()) }关键点有三个特性门控proxy有两个编译版本。feature modules时走真实加载路径ensure_loaded保证模块已加载再从modules::registry查表拿到bus_name与object_path建立代理非 modules 构建直接返回native modules are not compiled into this build错误由上层转为直通回退。测试注入点TINYJUICE_TEST_MODULE环境变量可以注入一个显式的模块 fixture 路径并强制modules.enabled true。源码注释解释了原因显式 fixture 是对模块执行的 opt-in即使宿主测试工作区里持久化了modules disabled类似地mod.rs 中#[cfg(test)]分支会改用Config::default()避免回归测试继承运维人员持久化的压缩阈值或关闭的路由器开关。配置安装去重install_from_config 把[tokenjuice]配置转成 wire 上的InstallRequestlet request InstallRequest { options: types::CompressOptions { router_enabled: tj.router_enabled, ccr_enabled: tj.ccr_enabled, search_enabled: tj.search_enabled, code_enabled: tj.code_enabled, html_enabled: tj.html_enabled, ml_text_enabled: tj.ml_compression_enabled, min_bytes_to_compress: tj.min_bytes_to_compress, ccr_min_tokens: tj.ccr_min_tokens, ..types::CompressOptions::default() }, max_cache_entries: tj.max_cache_entries, max_cache_bytes: tj.max_cache_bytes, ccr_ttl_secs: tj.ccr_ttl_secs, disk_tier_root: tj.ccr_disk_enabled .then(|| config.workspace_dir.join(.tokenjuice).join(ccr)) .map(|path| path.to_string_lossy().into_owned()), };两个实现细节值得注意其一请求体被序列化为字节序列作为指纹存入进程级OnceLockMutexOptionVecu8指纹相同则跳过重复INSTALL调用配置不同才重装其二disk_tier_root是条件字段——只有ccr_disk_enabled true时才指向workspace/.tokenjuice/ccr对应 CCR 磁盘持久层的位置。三、[tokenjuice]配置块全参数与默认值配置结构体定义在 src/openhuman/config/schema/tokenjuice.rsserde(default) 逐项default函数保证缺省字段全部走内置默认。完整参数表如下参数类型默认值作用router_enabledbooltrue内容路由器总开关false时工具输出不做压缩、直通ccr_enabledbooltrue有损压缩是否把原文卸载进 CCRCompress-Cache-Retrieve存储并发出⟦tj:hash⟧取回脚注关闭后压缩变成单向不可逆ccr_disk_enabledboolfalse是否把 CCR 原文持久化到workspace/.tokenjuice/ccr使取回在内存淘汰后仍可用仅核心写入max_cache_entriesusize256内存 CCR 存储保留的原文条数上限max_cache_bytesusize64 MiB内存 CCR 存储保留的总字节上限ccr_ttl_secsOptionu64NoneCCR 条目 TTL秒None表示永不过期min_bytes_to_compressusize2048尝试压缩前的最小输出字节数ccr_min_tokensusize500工具结果估算 token 数 ≥ 该值才触发 CCR卸载原文 有损压缩更小的结果直通search_enabledbooltrue启用搜索结果grep相关性压缩器code_enabledbooltrue启用 AST/启发式代码压缩器html_enabledbooltrue启用 HTML→文本抽取器ml_compression_enabledboolfalse启用 Python/ML 纯文本压缩器Kompress需要runtime_python.enabled不可用时优雅降级ml_model_idStringanswerdotai/ModernBERT-baseML 压缩器使用的 HuggingFace 模型 idml_target_ratiof640.5ML 压缩器的目标压缩比0–1提示ml_sidecar_idle_timeout_secsu64900ML sidecar 进程空闲多少秒后被回收以释放内存ml_max_input_charsusize200000ML 压缩器接受的最大输入字符数超限回退到原生压缩器ml_deviceStringcpu推理设备cpu或auto部分更新 patch只改一个开关不用重发全部config_patch.rs 中的TokenjuiceSettingsPatch是全Option字段结构体服务于tokenjuice.settings_updateRPC字段名与[tokenjuice]配置键一一对应snake_case使 UI 读写同一形状。apply()只写入存在的字段并带几个防御性约束可以直接从源码确认max_cache_entries/max_cache_bytes取v.max(1)拒绝把缓存压到 0ccr_ttl_secs传0语义化为清除 TTL永不过期缺省则保持原值ml_target_ratio只有落在0.0..1.0区间才被接受ml_model_id/ml_device空白字符串被忽略避免误清空。四、JSON-RPC 诊断控制面8 个控制器函数schemas.rs 为 CLI/调试界面提供只读诊断控制面文件头注释明确这些都不在每次工具输出的热路径上共 8 个函数命名空间统一为tokenjuice函数输入输出用途detectcontent必需、tool_name、extensionkind探测内容类型json/code/log/search/diff/html/plain_textcompresscontent必需、tool_name、mime、extension、query、explicitresultJSON对 blob 做 dry-run 路由压缩返回 applied 标志、类型、压缩器、字节数、CCR token 与压缩后文本cache_stats无{ entries, bytes }CCR 缓存占用retrievetoken来自⟦tj:…⟧标记的哈希{ found, content }从 CCR 缓存取回被卸载的原文settings_get无settingsJSON读取当前[tokenjuice]配置块settings_updatepatch部分字段对象settings更新后全量打补丁、持久化并实时生效savings_stats无{ attributionModel, total, byModel, byCompressor, cache }路由累计的 token 与成本节省savings_reset无ok清空全部节省统计其中compress的 hint 组装最值得细看。compress_hint_from_params 会把tool_name、mime、extension、query、explicit五个字段全部传进ContentHint——源码注释说明在 #6088 之前只读了source_tool导致调试控制器无法复现内容路由器的真实行为尤其是无法用explicit强制指定类型该字段会完全跳过检测。并且无法识别的explicit会被显式拒绝而不是静默忽略let explicit match str_param(params, explicit) { Some(raw) Some(raw.parse::ContentKind().map_err(|()| { format!(invalid explicit: {raw:?} — expected one of: \ json, code, log, search, diff, html, plain_text) })?), None None, };settings_update的 handlerschemas.rs接受{patch: {...}}或裸字段对象两种形式打补丁并config.save()之后会立即调用install_from_config重新安装使路由标志、CCR 限制与阈值不重启即生效。五、tokenjuice_retrieve让有损压缩可逆的 agent 工具tools.rs 实现了 agent 工具tinyjuice_retrieve这是 CCR 机制的取回半边。内容路由器可能把一条大型工具结果替换为压缩视图加一个⟦tj:hash⟧标记原文暂存在 CCR 存储中该工具按需取回原文——全量或按字节/行范围——使即使有损压缩也保持可逆。工具头注释声明它是只读的、无副作用、无路径/网络访问的。其参数 schematools.rs{ type: object, properties: { token: { type: string, description: The hash from a ⟦tj:…⟧ marker (or legacy retrieve footer). }, range: { type: object, description: Optional slice of the original to return., properties: { start: { type: integer, minimum: 0 }, end: { type: integer, minimum: 0 }, unit: { type: string, enum: [bytes, lines] } }, required: [start, end] } }, required: [token] }执行逻辑上有三个兼容与健壮性细节参数名兼容接受规范的token参数也接受旧名hashargs.get(token).or_else(|| args.get(hash))范围缺省语义start缺省为 0end缺省为u64::MAX即整段unit只有显式bytes才按字节否则一律按行缓存未命中的提示token 未找到时返回no cached original for token {token} (it may have been evicted; re-run the tool to regenerate it)——明确告诉 agent 原文可能已被逐出重跑原工具即可再生。mod.rs 还维护了一组恢复工具名表RECOVERY_TOOL_NAMES [tinyjuice_retrieve, tokenjuice_retrieve, retrieve_tool_output]与is_recovery_tool()判定用于识别 agent 会话中属于 CCR 恢复动作的工具调用新旧两个命名都收录兼容旧版。六、直通回退任何失败都不阻断 agentcompact_output_with_policy 是热路径入口其控制流体现了压缩是增强而非依赖的原则失败点逐级降级并打log::debug!enabled false或 profile 为Off→ 原样返回配置加载失败 → 直通install_from_config失败 → 直通proxy()失败模块未编译/未加载→ 直通模块COMPACT调用失败 → 直通。成功路径上则调用record_savings把original_tokens/compacted_tokens连同内容类型与压缩器类型交给 savings.rs 记账。另一条非策略入口compressmod.rs则用(bytes as u64).div_ceil(4)做字节到 token 的粗估——即每 4 字节约 1 token与业界常见的英文 token 密度经验值一致可从源码结构看这是刻意保守的估算。七、wire 契约tinyjuice_bus重导出与演进背景types.rs 只有约 30 行却是全目录最讲故事的文件。它的模块文档完整记录了契约的演进史曾经这里内联声明了 259 行与模块共享的类型但共享只是约定——模块侧副本私有、库侧副本私有没有任何机制保证三方一致一侧加一个字段另一侧就是解码失败。现在的做法是把契约固化为tinyjuice_bus这个普通 crate本模块只做重导出保持约 40 个调用点的路径不变pub use tinyjuice_bus::types::{ AgentTokenjuiceCompression, CompressOptions, CompressedOutput, CompressorKind, ContentHint, ContentKind, }; pub use tinyjuice_bus::wire::{ CacheStats, CompactResponse, InstallRequest, RangeUnit, RetrieveRange, };文档注释还说明了一个契约内部分层RangeUnit、RetrieveRange、CacheStats来自契约的wire模块而非types模块——分界线是tinyjuice 库自身使用的值与只存在于总线上的信封而宿主侧无需关心区别。八、ML 压缩桥KompressRwLock 配置快照实现热更新ml/mod.rs 是 TinyJuice 可选 ML 回调到宿主runtime_python_serverKompress 后端的薄桥。其设计要点全部写在源码注释里为什么需要 ML纯文本没有可利用的结构骨架高质量压缩需要学习模型ModernBERT 的 token/句子显著性为什么默认关、且没有编译期 feature 门torch 在运行时通过 pip 供应从不参与链接所以门控在运行时config.tokenjuice.ml_compression_enabled默认false配置为何用RwLock而非OnceLockconfigure(config)在启动和每次tokenjuice.settings_update时都会被调用RwLock使从设置界面打开 ML 压缩无需重启即可被运行时看到。compress()的降级矩阵非常清晰ml/mod.rs情形返回配置未安装Err(tokenjuice ml not configured)ml_compression_enabled falseOk(None)输入超过ml_max_input_charsOk(None)交给原生压缩器后端不可用Err调用方降级到原生压缩器压缩输出为空或不比原文短Ok(None)没有收益就不算收益正常Ok(Some(compacted))实现上先在读锁内快照一份Config副本再释放锁、然后await避免跨 await 持有锁。九、savingstoken 与成本的双维度归因savings.rs 回答路由器到底省了多少。每次压缩都会记录压缩前后估算的 token 数并按被丢弃 token 作为输入送给目标 LLM 的成本计价——工具结果进入下一轮上下文时是输入 token所以取的是按模型输入单价input_per_mtok_usd价格表来自 src/openhuman/agent 的cost::lookup_pricingfn cost_saved_usd(model: str, tokens_saved: u64) - f64 { let pricing crate::openhuman::agent::cost::lookup_pricing(model); (tokens_saved as f64) / 1_000_000.0 * pricing.input_per_mtok_usd }聚合结构SavingsAggregate维护三个维度total全量累计、by_model按归因模型、by_compressor按压缩器每个SavingsBucket记录events、original_tokens、compacted_tokens、tokens_saved、cost_saved_usd。两个值得注意的工程决策每轮模型归因TURN_MODEL是一个tokio::task_local!agent 循环在run_turn_via_tinyagents_shared周围用with_turn_model作用域化当前轮实际运行的模型record()优先取该 task-local未作用域非 harness 调用方、测试则回退到配置默认模型。源码注释标注这是 issue #4122 的修复且是严格增量的改动——不破坏未作用域路径快照防陈旧覆盖configure()只在快照路径变化时加载历史快照workspace_dir/state/tokenjuice_savings.json而不是每次工具结果都重读——源码注释解释了并发场景下的竞态若两个并发调用一个刚写完新聚合、另一个随后用稍早读到的陈旧文件覆盖回去统计会倒退。savings_reset()会清空聚合并持久化清空content_kind参数目前显式标记为reserved for a future by-kind breakdown——按内容类型的细分是预留能力。十、验证与可运行前提围绕适配器本体的测试文件与实现一一配对可直接运行确认上述行为mod_tests.rs安装去重与回退路径schemas_tests.rs8 个控制器函数与explicit拒绝逻辑tools_tests.rstokenjuice_retrieve的参数兼容与范围取回config_patch_tests.rs / savings_tests.rs / types_tests.rspatch 约束、聚合纯函数record_saving特意设计为不触碰进程全局态以便单测、wire 契约。需要说明的适用前提模块通路的真实压缩能力依赖feature modules构建且tinyjuice可加载模块在注册表中modules::registry::find(tinyjuice)非 modules 构建下所有模块调用都会走直通回退此时本目录的控制器、工具与配置面依然存在但压缩不生效。配置面settings_get/settings_update、节省统计savings_stats以及诊断函数在两种构建下均可通过 JSON-RPC 访问只是涉及模块的调用会返回错误而非压缩结果。总结TokenJuice 适配器是 OpenHuman 中引擎独立、宿主适配模式的典型样本压缩引擎作为独立发布的 TinyBus 模块运行在模块边界之后本目录承担配置安装指纹去重、条件磁盘层、wire 契约tinyjuice_bus重导出、诊断控制面8 个 JSON-RPC 函数、可逆取回工具tokenjuice_retrieve 范围取回、ML 热更新桥Kompress与成本归因savings 三维聚合 持久化快照六类宿主专属职责并以任何失败直通原文为不变式保证 agent 主流程不受压缩子系统影响。若要进一步深入建议按 README 的职责表逐文件对照源码阅读并留意src/openhuman/modules/tokenjuice_host.rs中的宿主侧模块接线。【免费下载链接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.项目地址: https://gitcode.com/GitHub_Trending/op/openhuman创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门