ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Hindsight 观测去重工具(obs_dedup)实战指南:基于余弦相似度的 Observation 重复检测

Hindsight 观测去重工具(obs_dedup)实战指南:基于余弦相似度的 Observation 重复检测 Hindsight 观测去重工具obs_dedup实战指南基于余弦相似度的 Observation 重复检测【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight导读本文介绍 Hindsight 开发工具包中的观测去重模块hindsight-dev/hindsight_dev/obs_dedup。该工具解决了一个真实痛点Hindsight 的记忆库bank中同一事件经过多次重新整合re-consolidation后会产生大量语义上几乎相同的 observation观测记忆单元形成冗余。由于 Hindsight API 既没有批量导出接口也不直接暴露 embedding 向量本工具通过分页读取记忆列表、本地重新向量化文本、分块余弦相似度扫描与传递闭包聚类的三步流水线找出近似重复的观测并输出可审查的聚类报告。读完本文你将掌握find-duplicate-observations命令的完整用法、阈值调优策略、底层算法原理与源码级实现细节。一、工具定位与设计动机1.1 为什么需要观测去重在 Hindsight 中observation 是记忆的核心载体之一。记忆维护maintenance与重新整合流程可能反复处理同一事件导致语义相近的观测在库中堆积。这些冗余观测会稀释召回质量、浪费 token 预算也让下游 Agent 检索时难以判断哪一条是权威记录。obs_dedup 模块位于 hindsight-dev/hindsight_dev/obs_dedup/正是为发现这类近似重复而设计。它聚焦于 observation 类型不处理 fact、mental model 等其他记忆单元。1.2 三个硬约束决定了工具形态工具作者在 client.py 与 dedup.py 的文档字符串中明确说明了设计前提Hindsight API 没有批量导出接口——必须通过分页遍历GET /v1/{tenant}/banks/{bank}/memories/list?typeobservation逐个读取API 不暴露 embedding 向量——必须用本地模型重新对文本做向量化余弦相似度是廉价的初筛——真实语义是否重复可交由后续的 agentic 校验器verifier对候选聚类做二次确认流水线被刻意拆分为可独立测试、可替换的阶段。二、快速上手运行去重扫描2.1 前置条件一个正在运行的 Hindsight API 服务默认地址http://localhost:8888hindsight-dev开发工具包环境使用uv管理Python 3.11依赖见 hindsight-dev/pyproject.toml首次运行时去重工具会下载默认 embedding 模型BAAI/bge-small-en-v1.5并本地加载。2.2 基本用法# 对 bank hermes 执行默认阈值扫描 uv run find-duplicate-observations --bank-id hermes --threshold 0.92 # 收紧阈值聚焦近乎逐字重复的观测并输出 JSON 报告 uv run find-duplicate-observations --bank-id hermes --threshold 0.97 \ --json-out report.jsonfind-duplicate-observations是由 hindsight-dev/pyproject.toml 中[project.scripts]定义的命令行入口实际指向hindsight_dev.obs_dedup.cli:main见 cli.py。2.3 完整参数表参数默认值说明--bank-id必填要扫描的 bank 名称如hermes--api-urlhttp://localhost:8888取环境变量HINDSIGHT_API_URLHindsight API 基地址--api-key环境变量HINDSIGHT_API_KEY可选 API Key以Bearer令牌形式发送--tenantdefaultAPI 路径中的租户段--threshold0.92两观测结链的最小余弦相似度取值范围(0, 1]--min-cluster-size2报告的聚类最小成员数--page-size200分页抓取每页条数--embedding-modelBAAI/bge-small-en-v1.5同 Hindsight 默认本地模型本地向量化模型--force-cpu关闭即使有 GPU 也强制 CPU 推理--max-text160终端报告中观测文本的截断长度--json-out无将完整报告写入指定 JSON 文件参数解析逻辑见 cli.py。其中--threshold在 cli.py 中被显式校验超出(0, 1]范围会直接报错并返回退出码 2。2.4 运行流程与退出码主流程cli.py依次执行创建ObservationClient并调用check_health()探测 API 健康分页拉取 bank 内全部 observation终端实时显示fetched/total进度本地向量化全部观测文本执行相似对扫描与聚类终端渲染汇总表格与聚类明细可选写 JSON 报告。退出码0正常完成观测数 2 时也会提示并返回 0退出码1API 不可达、HTTP 状态错误或请求失败退出码2--threshold非法。2.5 健康检查与分页抓取ObservationClientclient.py封装了全部 HTTP 交互启动时先请求GET {api_url}/health失败即中止避免对不可用服务做无谓的长时间分页随后循环请求GET {api_url}/v1/{tenant}/banks/{bank_id}/memories/list携带typeobservation、limit、offset参数每个观测被映射为 models.py 中冻结的Observation数据类保留id、text、entities、tags、mentioned_at以空页或已抓满 total作为终止条件天然兼容服务端返回的total字段。三、算法原理从向量到传递聚类整个核心算法位于 dedup.py被刻意拆成三个可独立替换的阶段3.1 阶段一本地向量化与 L2 归一化embed_observationsembeddings LocalSTEmbeddings(model_namemodel_name, force_cpuforce_cpu) asyncio.run(embeddings.initialize()) vectors embeddings.encode_documents([obs.text for obs in observations]) matrix np.asarray(vectors, dtypenp.float32) norms np.linalg.norm(matrix, axis1, keepdimsTrue) norms[norms 0.0] 1.0 return matrix / norms关键设计点复用 Hindsight 的默认本地模型默认值直接取自hindsight_api.config.DEFAULT_EMBEDDINGS_LOCAL_MODEL定义为BAAI/bge-small-en-v1.5见 hindsight-api-slim/hindsight_api/config.py保证与 Hindsight 存储时的向量空间一致使用encode_documents而非查询前缀代码注释明确说明这与 Hindsight 存储事实的嵌入方式一致不加 query prefix从而保证相似度可比预先归一化把余弦相似度化简为点积使得下一步的分块扫描退化为一次矩阵乘法matmul大幅提升扫描吞吐。3.2 阶段二分块余弦扫描find_similar_pairsfor start in range(0, n, block_size): end min(start block_size, n) sims matrix[start:end] matrix.T # shape: (end - start, n)采用block_size默认 512的分块策略峰值内存从完整n × n矩阵降为block_size × n个 float使数万条观测的 bank 也能在单机上扫描只保留j i的上三角部分天然避免自匹配与重复计数仅保留相似度 threshold的(i, j, similarity)三元组。3.3 阶段三并查集传递聚类cluster_pairs使用带路径压缩的 union-find 把相似对合并为传递闭包A≈B 且 B≈C则 A、B、C 归入同一聚类每个聚类计算max_similarity与min_similarity前者反映组内最相似的一对后者揭示传递链端点的真实相似度组内并非任意两两都过阈值过滤掉成员数 min_cluster_size的组按聚类大小, 最大相似度降序排列让最大、最可疑的重复组排在最前。find_duplicate_clusters将三个阶段串联为端到端入口未来可在阶段二与阶段三之间插入 agentic 校验器对候选对做语义确认。四、阈值选择0.92 与 0.97 的语义差别README 给出了两条实用经验直接影响扫描结果的查准/查全平衡阈值区间语义含义典型用途~0.97近乎逐字重复——例如同一事件被重新整合re-consolidated产生的副本精确定位真重复可直接决策合并/删除~0.92较宽松允许主题相关但表述不同的观测互相结链发现冗余热点区域redundancy hot-spots用于排查但作为真重复判决则噪音较大需要特别留意传递聚类的链式放大效应在 0.92 阈值下A≈B、B≈C 会把彼此并不直接相似可能低于阈值的 A 与 C 拉进同一聚类聚类可能迅速膨胀为覆盖一大片主题相近的观测。这正是DuplicateCluster.min_similarity存在的意义——它如实暴露聚类内最低的一对相似度帮助判断聚类是否已经发散。五、报告输出与解读5.1 终端报告rich 渲染每次运行都会输出汇总与聚类明细汇总行Total observations、Similarity threshold、Duplicate clusters、Redundant observations每个聚类Cluster N (size 个观测, similarity min–max)下方表格逐条列出成员观测的id与截断后的text默认截断 160 字符空白折叠若无重复打印No near-duplicate observations found.渲染逻辑见 report.py。5.2 JSON 报告--json-out{ bank_id: hermes, total_observations: 5000, threshold: 0.97, duplicate_clusters: 12, redundant_observations: 45, clusters: [ { size: 5, max_similarity: 0.99, min_similarity: 0.97, observations: [ { id: obs-xxxx, text: ..., entities: ..., tags: [], mentioned_at: 2026-01-01T00:00:00Z } ] } ] }redundant_observations表示若每个聚类坍缩为一条可移除的观测总数sum(size - 1)是衡量清理收益的关键指标similarity保留 4 位小数便于机器后续按阈值二次筛选序列化实现在 report.py 的DedupReport.to_dict()。5.3 与 Agent 工作流的衔接报告可作为 agentic 校验器的输入对每个候选聚类用 LLM 判断成员是否确实是同一事件的不同表述确认后才建议合并。README 与init.py 均明确将余弦扫描定位为廉价初筛语义确认留给上层代理。六、源码级验证测试如何锁定算法行为核心算法有完整的单元测试覆盖hindsight-dev/tests/test_obs_dedup.py不依赖网络与真实模型用构造的单位向量矩阵验证行为test_find_similar_pairs_thresholds完全相同的一对相似度为 1.0 被召回正交向量不触发——验证阈值过滤与自匹配排除test_find_similar_pairs_respects_block_sizeblock_size小于样本数时仍能发现全部无序对——锁定分块扫描的正确性test_cluster_pairs_is_transitive三个依次相近的向量被并查集合并为一个 3 成员聚类redundant_count 2并验证min_similarity max_similarity——锁定传递闭包语义test_cluster_pairs_min_size_filters_singletons默认min_cluster_size2丢弃孤立观测调高阈值后聚类为空——锁定最小聚类尺寸过滤test_report_to_dict_counts验证duplicate_clusters、redundant_observations与 JSON 载荷中观测数量的计算。这些测试同时充当了可执行的行为规格任何对阈值比较方向、分块边界或并查集实现的修改都必须保持上述语义不变。七、局限性、扩展方向与周边资源7.1 已知边界仅覆盖 observation 类型/memories/list请求固定携带typeobservation不处理 fact 等其他记忆单元余弦相似度是近似匹配语义表述差异大但含义相同的观测可能低于阈值而漏报本地向量化有资源成本数万条观测的 embedding 推理需要 CPU/GPU 时间--force-cpu可在无 GPU 环境显式约束不直接执行清理工具只报告候选聚类不调用任何删除/合并 API清理动作需要人工或上层 Agent 依据报告决策。7.2 设计上的扩展点流水线的三段式拆分向量化 → 相似对 → 聚类为后续演进预留了清晰的注入点可在find_similar_pairs与cluster_pairs之间插入 LLM 校验器或对聚类结果整体做二次确认DedupReport的 JSON 序列化格式也让外部编排如批量巡检多个 bank变得简单。7.3 相关资源模块入口与包说明hindsight-dev/hindsight_dev/obs_dedup/init.py命令行实现hindsight-dev/hindsight_dev/obs_dedup/cli.py端到端算法hindsight-dev/hindsight_dev/obs_dedup/dedup.pyAPI 分页客户端hindsight-dev/hindsight_dev/obs_dedup/client.py数据模型与报告hindsight-dev/hindsight_dev/obs_dedup/models.py、hindsight-dev/hindsight_dev/obs_dedup/report.py单元测试hindsight-dev/tests/test_obs_dedup.py默认 embedding 模型常量hindsight-api-slim/hindsight_api/config.py 与本地嵌入实现 hindsight-api-slim/hindsight_api/engine/embeddings.py通过本文介绍的流程你可以定期对 Hindsight 记忆库执行观测去重巡检先用--threshold 0.97找出可安全处理的逐字副本再用--threshold 0.92排查冗余热点结合 JSON 报告交由 LLM 校验后决定是否合并从而持续保持记忆库的精炼与可检索性。【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表