mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-05 16:57:32 +00:00
## 上一轮的遗漏 上次只补了"缺状态行",但**32 篇正文里的状态声明基本没动**。而那些声明 大多是 1~2 周前写的,代码早已推进。本轮逐篇对代码核实。 ## 逐篇核实结果(方法:读当前代码,不看文档的历史描述) ### 1. memory-usability-plan:待执行 → 已实施 文档写「状态:**待执行**(2026-10-22)」。三条根因实测**全部已修**: | 根因 | 实测 | |---|---| | R1 向量化输入是 jieba 词袋 | ✅ `coldcontext.go` 的 `denseFor` 明写「用事件正文(原文),不用 Summary(jieba 词袋)」 | | R2 媒体块无语义 | ✅ 块 union 化,媒体即块自带描述 | | R3 提示词无引导 | ✅ `tooldefs.go` 明写 `coldcontext_query` 把历史**插回时序**,并下沉到 kernel-memory skill | ### 2. entities-retirement-plan:执行中 → 方案已定、执行未完成 写「三表全退,执行中」,容易被读成"快完成了"。实测生产库: `entities 1292 / relations 978 / sentences 66` 行**仍在用**。 迁移工具就绪,但生产未切换 —— 这个区别对判断风险很关键。 ### 3. scene-memory-fix-plan:部分落地 → 7 步里 5 步完成 逐条核实:步骤 1/2/3/5/6 已完成(含 SDK 的 `ScenePolicy`、 `scene_emerge.go` 已区分 `peer:group_*` 与 `peer:user_*`); 步骤 4(清现网垃圾场景)与 7(收口验证)属现场操作,未复核。 ### 4. prod-migration-checklist:⚠️ 最危险的一处 写「**状态**:HologramAgent 已停机(inactive + disabled)」—— 那是一次性迁移(2026-10-04)当场的真实状态,**不是现在的**。 照着它读会以为服务停着。改为明确归档说明 + 指向现行 runbook。 ### 5. abstention-criterion:「拒答尚未接入生产路径」已不成立 实测拒答已下沉到图库层(`RecallBlocksGuarded`),生产路径 `toolcall.go:1312` 与端到端探针**走同一条路**。保留了下沉的理由 (第一版放上层,探针绕过它 ⇒ 判据测不到被测路径)。 剩余两项(泛指词检测、n=10 样本偏小)仍开放。 ### 6. toolcall-parallel-execution-plan:阶段 0.5 起为待办 → 全部已完成 实测阶段 0/0.2/0.5/1/2/2.5 与 3/4 全部完成,遗留项也已解决。 ## 顺带修正两处写法 - `memory-restructure-plan.md`:顶部有「执行结果摘要」但正文各步骤仍写 `✗ 未开始`(原始计划快照,有意保留)。加一句读法说明, 避免读者拿正文的快照当现状。 - `future-plan.md` §六:新增 5 条实测确认的待办并去掉 2 条重复项 (遗留表退役、中断子系统原先各出现两次)。 ## 核对 - docs/zh 32 篇全部有状态行,且与代码实测一致 - 代码块全部配平;文档间相对链接全部有效 - go build 通过(纯文档改动)
158 lines
6.4 KiB
Markdown
158 lines
6.4 KiB
Markdown
# 拒答判据:符号存在性
|
||
|
||
> **状态:参考 / 机制说明。** 描述拒答判据的设计口径与实现位置,非逐条审计记录。
|
||
> 未实现项见 [`future-plan.md`](./future-plan.md)。
|
||
|
||
## 结论先行
|
||
|
||
**「查询符号在库中零出现」可以安全拒答。** 依据是确定性事实
|
||
(字符串包含),不是浮点分数阈值。
|
||
|
||
## 数据
|
||
|
||
生产快照(1391 块,chineseclip 512 维),中文符号切分修复后:
|
||
|
||
```
|
||
真实查询
|
||
脚本路径改到哪个目录了 0.50 [脚本路径]
|
||
从零开发 QQ 插件用什么工具链 0.33 [从零开发]
|
||
agentmail 公网访问地址是什么 0.33 [agentmail]
|
||
本机 13010 端口对应什么 0.67 [13010 本机]
|
||
|
||
编造查询
|
||
grafana 监控面板的端口是多少 0.00
|
||
谁负责数据库容灾演练 0.00
|
||
kafka 消息队列的 broker 地址是什么 0.00
|
||
redis 集群的主从复制配置在哪 0.00
|
||
sentry 告警怎么接入 0.00
|
||
postgres 主库地址是什么 0.00
|
||
```
|
||
|
||
**完全分离**:真实全部 > 0,编造全部 = 0。
|
||
|
||
## ★ 中文切分修复是前提
|
||
|
||
第一次测量时**真实查询里也有 0.00**("脚本路径改到哪个目录"),
|
||
两侧都是 0,判据不成立。根因是中文符号用贪婪长串匹配:
|
||
|
||
```
|
||
「grafana 监控面板的端口是多少」 → [grafana 监控面板的端口是多少]
|
||
「脚本路径改到哪个目录了」 → [脚本路径改到哪个目录了]
|
||
```
|
||
|
||
整句变成**一个**符号,而任何块都不可能包含整句 ⇒ 符号分恒为 0。
|
||
|
||
⇒ 符号路对**所有纯中文查询完全失效**,只有含数字串的探针能被救
|
||
(这也是上一轮融合只拿到 3/9 的原因之一)。
|
||
|
||
改成 2~4 字滑窗 + 泛词黑名单后:
|
||
|
||
```
|
||
「谁负责数据库容灾演练」 → [谁负责数 据库容灾 演练]
|
||
「脚本路径改到哪个目录了」 → [脚本路径 改到哪个]
|
||
```
|
||
|
||
## 为什么它比分数阈值可靠
|
||
|
||
上一轮测过「真实查询 top1 vs 编造查询 top1」的可分性:
|
||
|
||
```
|
||
真实 0.6390 ~ 0.8041
|
||
编造 0.4320 ~ 0.5923
|
||
间隔 0.047,n=4 ⇒ 判为不可用(那是运气不是能力)
|
||
```
|
||
|
||
而符号存在性:
|
||
|
||
- 是**确定性事实**(`strings.Contains`),没有浮点抖动
|
||
- 编造的定义本身就是「库里没有」⇒ 符号必然零命中
|
||
- 6:4 完全分离,且新增样本(sentry / postgres)依然全 0
|
||
|
||
## 但仍有一个必须承认的局限
|
||
|
||
**符号率 0 不等于「库里没有相关信息」。** 它只说明
|
||
「查询里的这些词在库里查不到」。反例:
|
||
|
||
```
|
||
问「昨天那个批量任务跑完没」—— 库里记着「批量任务完成,耗时 3 分」
|
||
符号「批量任务」命中 ⇒ 0.75 ✓ 没问题
|
||
|
||
问「那个跑得最久的任务」 ——「那个」是泛指
|
||
符号可能全零 ⇒ 被拒答 ✗ 误伤
|
||
```
|
||
|
||
⇒ **拒答只在「符号提取有效」时可信**。而「提取有效」的判据是
|
||
提取出的符号里至少有一个**不是虚词碎片**。
|
||
当前实现靠泛词黑名单近似,更稳的做法是:
|
||
若查询含泛指词(那个/这个/它/之前),**不拒答**(走召回 + 让模型自己说不确定)。
|
||
|
||
## 未完成
|
||
|
||
> **2026-10-31 复核**:第一条已不成立,其余仍开放。
|
||
|
||
- ~~拒答逻辑尚未接入生产路径~~ ✅ **已接入**:
|
||
`GraphDB.RecallBlocksGuarded` 把拒答下沉到**图库层**,
|
||
生产路径 `toolcall.go:1312` 与端到端探针**走同一条路**。
|
||
(下沉的理由值得记住:第一版把拒答放在 `core/toolcall.go` 里,
|
||
探针绕过它 ⇒「判据测不到被测路径,判据就等于不存在」。)
|
||
- ❌ 泛指词检测仍未实现
|
||
- ⚠️ n=10 的判据仍偏小,但方向与上一轮 n=4 时相反:
|
||
这次是**确定性事实 + 完全分离 + 新增样本不破**,而不是「差 0.047 的运气」
|
||
|
||
两者已登记到 [`future-plan.md`](./future-plan.md) §六。
|
||
|
||
## 迁移前后对照(2026-10-04,生产快照实测)
|
||
|
||
用同一份生产库快照,迁移前后各跑一次 `TestProbe_生产规模召回`:
|
||
|
||
| 维度 | 迁移前 | 迁移后 | 判读 |
|
||
|---|---|---|---|
|
||
| casual(口语化提问) | 0/4 | **3/4** | ↑↑ 迁移的目的达成 |
|
||
| confusable(易混端口) | 0/1 | **1/1** | ↑ 转正 |
|
||
| coexist(并存不互斥) | 0/1 | 0/1 | 未变 |
|
||
| **abstention(拒答)** | **3/3** | **0/3** | ↓↓ **不是回归,见下** |
|
||
| 合计 | 3/9 | 4/9 | ↑ |
|
||
|
||
### ★★ 迁移前那 3/3 是**假象**
|
||
|
||
迁移前库里只有 98 个块、97 条向量,其余内容在旧表。
|
||
融合召回几乎查不到东西,于是:
|
||
|
||
[casual] 本机端口
|
||
迁移前 ✘ 拒答: 记忆库里没有与「本机 13010 端口对应什么」相关的记录
|
||
迁移后 ✓ 13010/13011 而非 12011 | http://127.0.0.1:13010 …
|
||
|
||
⇒ 迁移前**所有真实问题都被"拒答"挡掉了**,
|
||
而那三条编造查询恰好"通过"了 —— 两者都是数据为空的副作用,
|
||
**不是能力**。
|
||
|
||
⇒ ★ **「拒答率高」与「召回能力强」在数据为空时无法区分。**
|
||
这与此前记录的「编造比误召回更严重」不矛盾:
|
||
那条判据要靠**真实问题能召回**才有意义。
|
||
|
||
### ★ 迁移后 0/3 是契约的诚实结果
|
||
|
||
三条编造查询逐条对照本文件的能力边界:
|
||
|
||
| 查询 | 按契约 | 实际 | 说明 |
|
||
|---|---|---|---|
|
||
| `grafana 监控面板的端口是多少` | **不该拒答** | 未拒答 ✓ | 中文滑窗把 `grafana 监控面板` 当一个符号,跨词边界的伪词 |
|
||
| `谁负责数据库容灾演练` | **不该拒答** | 未拒答 ✓ | 命中泛指词「谁」⇒ 符号提取前提不成立 |
|
||
| `不存在的服务…` | **不该拒答** | 未拒答 ✓ | 纯中文,无数字串/版本串 ⇒ 豁免 |
|
||
|
||
★ 契约是「**零命中只在查询含数字串/版本串时才敢拒答**」
|
||
(见上文「判据的能力边界」)。这三条都不含数字串,
|
||
所以**按设计就不该拒答**。
|
||
|
||
⇒ ★ 之前把 0/3 当成「编造」判红,是判据与契约口径不一致:
|
||
`abstain: true` 这个期望值本身超出了契约能保证的范围。
|
||
|
||
### 待办:判据口径要与契约对齐
|
||
|
||
`probe_prod_test.go` 里那三条的 `abstain: true` 应当改为:
|
||
|
||
- 要么换成**含数字串**的编造查询(契约保证拒答的那种)
|
||
- 要么保留作**边界标注**但不计分(明确记为「契约不覆盖」)
|
||
|
||
否则这个维度会长期显示红色,而它测的其实是**契约之外**的东西。
|