Hindsight 0.8.1 版本深度解读:可选文档原文存储、VectorChord 探针修复与 public schema 维护例程
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
Hindsight 0.8.1 是构建在 0.8.0 之上的补丁版本,核心内容为三项:为数据最小化与隐私敏感部署新增“跳过持久化文档原文”的开关HINDSIGHT_API_STORE_DOCUMENT_TEXT,以及两个面向自管 PostgreSQL 部署的运维修复——VectorChord 索引探针调度的正确性与publicschema 下后台维护例程的可靠安装。读完本文,你将掌握该开关的配置方式与行为边界、理解 0.8.0 中两个自管 PostgreSQL 场景故障的根因与源码级修复路径,并据此判断自己的部署是否需要升级。
版本定位:谁应该升级到 0.8.1
0.8.1 发布于 2026-06-09,是一个以运维健壮性为主的补丁版本(版本日志见 hindsight-docs/blog/2026-06-09-version-0-8-1.md,前序版本 0.8.0 的说明见 hindsight-docs/blog/2026-06-08-version-0-8-0.md 对应文档)。官方给出的升级建议非常明确:任何在外部 PostgreSQL 上使用 VectorChord、或运行单 schema(默认public)部署的用户都应该升级。版本变更可归纳为四点:
| 变更 | 影响面 | 性质 |
|---|---|---|
可选文档原文存储(HINDSIGHT_API_STORE_DOCUMENT_TEXT) | 所有部署(默认行为不变) | 新功能 |
VectorChordvchordrq.probes探针修复 | 外部 PostgreSQL + VectorChord 用户 | 缺陷修复 |
publicschema 维护例程安装修复 | 默认单 schema 部署 | 缺陷修复 |
tokenizers版本上限、Control Plane URL 清理 | 本地 ML 额外依赖安装、控制台 URL 展示 | 杂项 |
可选文档原文存储:HINDSIGHT_API_STORE_DOCUMENT_TEXT
功能背景与默认行为
默认情况下,Hindsight 会保留你 retain 的每个文档的原始源文本,以便后续回读文档或对文档执行 append(追加)操作。出于数据最小化(data minimization)、隐私或合规原因,部分部署希望根本不持久化这份原始文本。0.8.1 引入了HINDSIGHT_API_STORE_DOCUMENT_TEXT环境变量(默认true)来控制这一行为。
配置方式只需在 API 进程环境中设置:
export HINDSIGHT_API_STORE_DOCUMENT_TEXT=false设为false后,Hindsight 不再持久化原始源文本,但抽取出的记忆(memory units)、实体与链接照常存储且完全可检索。
禁用原文存储后的三项行为约定
关闭存储后,系统有明确的行为约定,避免客户端出现静默故障:
- 读取仍然工作。获取文档时返回其元数据,
original_text字段为空(null),而不是报错——现有客户端保持兼容。这一点在 GET 文档端点测试 中有专门验证:响应模型将original_text声明为可选字段,若声明为非可选str,NULL 文本会触发ResponseValidationError导致 HTTP 500。 - Append 被明确拒绝。追加文档需要读回已有正文才能拼接,原文不存在时 append 只会静默丢失既有内容。因此 append 请求返回清晰的客户端错误(HTTP 400,detail 中包含 "append" 字样),而不是产出残缺结果。引擎层的检查逻辑位于 memory_engine.py:在解析后的 bank 配置中读取
store_document_text,为false时对update_mode='append'直接抛出ValueError。 - Control Plane 给出提示。控制台文档视图会显示“文本存储已关闭”的提示,空文本不会被误认为数据丢失。UI 的判断依据来自
/version端点暴露的features.store_document_text特性标志(见 features-context.tsx 与 documents-view.tsx)。
这是一个服务器级设置:已经 retain 的记忆保持其当初存储时的文本状态,开关只影响新写入。
源码级实现:从环境变量到写入路径
从源码结构看,该开关的完整链路如下:
配置解析。config.py 中定义环境名常量
ENV_STORE_DOCUMENT_TEXT = "HINDSIGHT_API_STORE_DOCUMENT_TEXT"(第 791 行)与默认值DEFAULT_STORE_DOCUMENT_TEXT = True(第 1563 行,注释说明其持久化位置为documents.original_text/chunks.chunk_text),并在配置构建处解析:store_document_text=os.getenv(ENV_STORE_DOCUMENT_TEXT, str(DEFAULT_STORE_DOCUMENT_TEXT)).lower() == "true"注意解析方式是大写后与
"true"精确比较,因此只有字面量true(不区分大小写)视为开启,其余取值一律视为关闭。写入路径。关闭后,
documents.original_text存NULL、chunks.chunk_text存空字符串(字段仍保留,用于文档/分块图结构)。召回不受影响。recall 读取的是
memory_units而非original_text,因此禁用原文存储后检索照常返回事实。测试 test_text_storage_disabled_nulls_text_but_keeps_memories 完整验证了这一闭环:retain 产生 memory unit → 文档original_text为NULL但memory_unit_count > 0→ 分块chunk_text全为空 →recall_async("Where does Alice work?")仍返回结果。bank 级覆盖。从测试
test_store_document_text_is_bank_configurable与test_store_document_text_per_bank_override可以看到,store_document_text位于HindsightConfig.get_configurable_fields()的可配置字段集中,可通过配置解析器按 bank 覆盖(全局 → tenant → bank 的层级结构)。也就是说,虽然文档将其描述为服务器级开关,实际上同一服务器内可以“一个 bank 丢弃原文、另一个 bank 保留原文”,这是仓库测试明确验证过的行为。Reflect 工具集联动。当原文存储关闭时,reflect 阶段的
expand工具(用于回读分片/文档源文本)会从工具集中剔除,其余工具(如recall、done)不受影响,见 tools_schema 的include_expand分支及其测试。
运维修复一:VectorChord 探针调度的正确性
问题:会话级vchordrq.probes并非万能旋钮
VectorChord 通过会话 GUCvchordrq.probes暴露 ANN 搜索时的探针数调优。但该值必须与索引的build.internal.lists层级结构匹配。VectorChord 1.1 才为索引引入按索引的 fallback 参数来解决这一问题,而在这之前:
- 一个会话 GUC 会覆盖所有vchordrq 索引;
- 单一取值对无列表(listless)布局或混合布局的索引可能是无效的。
Hindsight 内置的 vchord 索引创建子句(USING vchordrq (embedding vector_cosine_ops),见 _vector_index.py)并不设置lists参数,因此对这类索引在会话层面强制vchordrq.probes会导致向量搜索在部分 VectorChord 索引类型上直接失败,而不是降级工作。
修复:按后端分派的 GUC 表
_vector_index.py 中的注释完整记录了这一决策:0.8.1 起,搜索时调优 GUC 改由_ANN_TUNING_LOW_LATENCY/_ANN_TUNING_HIGH_RECALL两张按后端分派的表驱动,vchordrq.probes不再出现在任何一张表中——分派器ann_search_tuning_settings()对 vchord 返回空元组,即默认不做任何会话级探针覆盖。源码注释同时给出了部署侧建议:需要调优探针数的 VectorChord 部署,应将 probes 附加到索引的存储参数上,而不是依赖会话 GUC。
测试 test_link_utils.py 对此做了直接断言:retain 链路探针执行产生的 SQL 中不得出现任何vchordrq.probes语句,确保修复在回归层面被锁定。
运维修复二:publicschema 下维护例程的安装
0.8.0 引入的两个后台例程
0.8.0 新增了两个 PL/pgSQL 只读(STABLE)发现例程,安装于publicschema,用于驱动后台维护(定义见迁移 e5f6a7b8c9d0):
public.banks_needing_consolidation():返回存在“可合并但未排程”事实(consolidated_at IS NULL AND consolidation_failed_at IS NULL、bank 级未显式关闭自动合并、且无 consolidation 操作在途)的(schema_name, bank_id)行,驱动周期性 consolidation 对账(reconcile),使终端失败后滞留的事实能够被重新排程;public.schemas_with_expired_rows(p_table, p_ts_col, p_days):返回在指定表中存在超过p_days天行的 schema 名,驱动跨租户的audit_log与llm_requests保留期清理——例程本身只读,实际的 DELETE 由调用方仅对返回的 schema 执行。
两者都通过遍历pg_class中真正持有目标表的 schema 来工作,一次函数调用即可覆盖所有租户,替代客户端侧在数千租户下的逐库查询风暴。
Bug 根因:单 schema 部署上例程从未被创建
0.8.1 修复的缺陷是:原始迁移只在“没有任何target_schema的基础运行”中创建这两个函数。但单租户运行时总是迁移一个显式 schema(默认即public),于是在所有默认 PostgreSQL 部署上,迁移被标记为已应用、函数却从未创建。后台维护随之记录:
Retention sweep failed for llm_requests: function public.schemas_with_expired_rows(...) does not exist Consolidation reconcile discovery failed: function public.banks_needing_consolidation() does not exist修复迁移b2d4f6a8c1e3的设计
由于e5f6a7b8c9d0在受影响的 0.8.0 数据库上已被打上已应用戳,直接改它不会重新执行。因此 0.8.1 引入了前向迁移 b2d4f6a8c1e3_repair_maintenance_routines_public.py,以幂等的CREATE OR REPLACE方式在“基础运行(无target_schema)或显式target_schema=public的运行”上重装例程,既自愈已升级的 0.8.0 部署,也覆盖从更早版本直接升级的部署。迁移文档字符串同时解释了为什么其他租户 schema 的运行仍然跳过:并发地对同一pg_proc目录行执行CREATE OR REPLACE会以tuple concurrently updated中止,而针对public的运行受每 schema 迁移咨询锁串行化,只有一个会赢得创建。
其他值得注意的变更
- 本地 ML 额外依赖的
tokenizers版本上限。pyproject.toml 将tokenizers钉在>=0.22.0,<=0.23.0(见 issue #2055):transformers在运行时强制tokenizers<=0.23.0,但其发布的元数据声明了更宽的范围;不加此上限时,就地升级可能拉到tokenizers 0.23.1,导致本地 embeddings/reranker 启动失败。加上了这一上限后,全新安装可以干净地解析依赖。 - 更干净的 Control Plane URL。控制台 URL 不再追加 locale 前缀。
小结
0.8.1 的三个主题分别对应三类读者:对数据最小化有要求的合规部署(用HINDSIGHT_API_STORE_DOCUMENT_TEXT=false在不牺牲记忆检索能力的前提下停止持久化原文)、自建 PostgreSQL + VectorChord 的运维者(避免探针 GUC 在不兼容索引上的搜索失败)、以及默认单 schema 部署(让 0.8.0 引入的 consolidation 对账与保留期清理真正跑起来)。如果你的部署命中后两类中的任一项,升级到 0.8.1 应当是优先事项;升级后相关行为分别由 test_store_document_text.py、test_link_utils.py 与修复迁移 b2d4f6a8c1e3 所对应的测试与迁移链锁定在回归测试层面。
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考