Files
HomeAgent/docs/zh/vector-provider-decision.md
JianFeeeee cf14b840ef docs: 补齐文档状态分类 + 校正两轮代码改动后的失真
## 背景

上一次文档校订(b9b5ac0)之后又有两次代码提交(5194a96 / 8293282),
把 future-plan §1.1 整节变成了错的 —— 它还写着「档位没有生效点」
和「在 prepareInputTask 里加一次 activateSecurityProfile 调用」,
而后者正是被后来的收敛**否定掉的方案**。

## 新增 docs/zh/README.md(文档索引)

32 篇文档此前混着三种时态(当时实测 / 历史推演 / 设计规划),外观相同。
索引给出**状态分类与可信度规则**:

| 状态 | 能不能当事实用 |
|---|---|
| 已实现并部署 | ✅ 直接信 |
| 部分实现 | ⚠️ 只信标了"生效"的部分 |
| 设计 / 未实现 | ❌ 只能当设计意图 |
| 归档说明 | ❌ 不要改、也不要信 |

并写死**判据名可信度规则**:文档里的 `TestXxx` 不保证还存在。
给了核对命令,以及当前基线(27 条缺失的分布 —— 18 条属"设计未实现"类
文档的规划名、7 条是 §2.7.3 有意保留的历史对照表左栏、2 条属视频能力
未纳入契约)。判定标准:**在"已实现"类文档正文里找不到才是缺陷**。

## 重写 future-plan §1.1(已结案)

原节写的是错的方案。改成记录**真正的缺陷分三层**:

```
第 3 层(表面):activateSecurityProfile 零调用方
第 2 层:agent/core 在替 security 做策略决策
         (自己抠 security_profile / 自己选判定链 /
           自己写 Kind:"resident" 声明主体类别 —— 提权口子)
第 1 层(根因):security 缺少「输入接入点」
```

并补上「每 agent 一个实例」的最终形态(共享注册表 + per-agent 执行视图,
sessionProfile / longtimeProfile 两层,优先级 session > longtime 本身是安全语义)。

§〇「机制 ≠ 接线」表格里档位那一条从 🔴 改为 ✅。

## 各文档状态行

此前 14 篇缺状态行(runbook / 实测报告 / 计划类)。逐篇补上**符合实际内容**
的声明,而不是统一套一句。特别地:

- `commondev-design.md` 标题本就写「设计 · 未实现」→ 归到"设计"类
- `live-run-evidence-2026-10-04.md` → 明确标注"历史证据快照,不要用它的
  结论覆盖现在的实现判断"
- `legacy-issues.md` → 写明它与 future-plan 的分工(前者收已知问题,
  后者收能力缺失与零调用方)

## 正文里两处判据名漂移

- `TestBootCtxCloseAllIsReverseOrder` → 实际是
  `TestKernelStateCloseAllIsReverseOrder`(`BootCtx` 改名时判据跟着改的)
- `TestNilTypedBusSafety` → 标注为"规划名,仓库中不存在"

## 新增 §2.7.5 模块产物的实例化粒度

依赖图保证"设施已就绪",但没说该有几个实例 —— 这是独立决策。
记下 security 的两个答案:全局基线共享(否则插件声明对部分 agent 不生效)、
轮次状态 per-agent。并给出给未来新模块的两条判断标准。

## 安全文档

状态头补「架构形态」段(防火墙定位、per-agent 视图、两层档位);
接线状态表里 `ActivateProfile` 从 🔴 改为 ✅(2026-10-31 接通)。

## README

文档列表加索引与 future-plan 入口 —— 此前从 README 找不到 docs/zh 的任何指引。

## 核对

- docs/zh 32 篇全部有状态行
- 索引里列的文档全部存在,无遗漏
- 分类与各文档自述一致(逐篇抽查)
- go build 仍通过(纯文档改动)
2026-10-31 07:50:58 +08:00

218 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 向量 provider 决策:Qwen3-VL vs chineseclip
> **状态:决策记录(已定)。** 记录了 provider 选型过程与结论,属决策归档性质。
> 结论先行(2026-10-03 实测,真库 260 个块,两套 ONNX 均已导出校验通过)
>
> **不切换 provider。** 各用其位:
> - 块级检索:**保留 chineseclip + 中心化校正**(分离度 7.3 倍,端到端 5/7 → 6/7)
> - 维度名别名:**用词法**(判别力 0.4500,是 Qwen3-VL 的 5.6 倍)
> - Qwen3-VL 保留给**多模态**场景(图像/视频),那是它不可替代的地方
## 一、导出校验(两套都通过)
Qwen3-VL-Embedding-2B,12.49 GiB,7 项校验 cos≈1.0:
| 用例 | cos |
|---|---|
| text | 0.999999940 |
| image | 0.999999940 |
| generation | 1.000000000 |
| video_g2 | 1.000000119 |
| video_g3 | 1.000000119 |
| video_g4 | 1.000000000 |
## 二、三个用途分别实测
### ① 块级检索:同属性不同值的区分度
| provider | 现象 | 判定 |
|---|---|---|
| chineseclip | `4324` vs `4379`:0.9284 / 0.9298 | 差 0.0014,**不可分** |
| Qwen3-VL | `9条` vs `15条`:**0.9882**;`4324` vs `4379`:0.9130 | 分离度 **−0.1843**(负) |
**Qwen3-VL 在这一项上更差。** 原因:last_token 池化只取序列**最后一个
token** 的表示,而"值"通常在句中——`第113批 告警规则9条` 的最后一个
token 是「条」,两条记录的末 token 完全相同。
### ② 粗筛有效性(阈值是否还有意义)
| provider | 平均 | P50 | P90 | >0.9 占比 |
|---|---|---|---|---|
| Qwen3-VL | 0.7160 | 0.6950 | 0.8956 | **9.7%** |
| chineseclip | 0.8783 | 0.8949 | 0.9891 | **44.0%** |
**★ 这一项 Qwen3-VL 明显更好** —— chineseclip 的 44% 意味着
0.9 阈值等于没有阈值。
但那个"44%"是**各向异性**造成的,不是模型能力:实测均值向量范数
0.9374,即 93.7% 的能量在同一个方向上。中心化校正后分离度
0.0095 → 0.0689(**7.3 倍**),端到端 5/7 → 6/7。
⇒ **两种解释都成立,但对策不同**:
chineseclip 需要中心化才能用;Qwen3-VL 天然不需要。
而中心化是**通用手段**(任何 provider 都能加),换 provider 不是。
### ③ 短文本(维度名)判别名
| 用途 | provider | 判别力 |
|---|---|---|
| 别名发现 | **词法** | **0.4500** |
| 别名发现 | Qwen3-VL | 0.0798 |
逐条(Qwen / 词法):
| 对 | 类型 | Qwen | 词法 | 谁对 |
|---|---|---|---|---|
| 批次号 / 批次 | 别名 | 0.8296 | 0.9500 | 词法 |
| 等待队列告警阈值 / 等待队列长度告警阈值 | 别名 | 0.9747 | 0.9000 | Qwen |
| 版本 / 版本号 | 别名 | 0.9293 | 0.9500 | 词法 |
| 灰度比例 / 观察比例 | 别名 | 0.6838 | 0.2000 | **Qwen**(词法漏检) |
| 值班分机号 / 旧分机号 | **非**别名 | 0.8520 | 0.9000 | **词法**(Qwen 排错) |
| 端口 / 端点 | 非别名 | 0.8530 | 0.0000 | 词法 |
| 停机时长 / 发布窗口 | 非别名 | 0.6187 | 0.0000 | 词法 |
**Qwen3-VL 给非别名对也打高分(0.85)** —— 它不区分"这几个字像"
与"这几个字是一回事"。而别名判别的要点恰恰是后者。
## 三、为什么最终不切
1. **各向异性是主因,不是模型能力。** chineseclip 的 44% 高相似里,
大部分是共同方向贡献的假象。中心化是通用手段,换 provider 不是。
2. **Qwen3-VL 在 overwrite 维度上反而更差**(分离度负值),
而那是本项目当前最痛的维度。
3. **短文本上词法判别力是它的 5.6 倍**,别名发现的主要工作恰恰在短文本上。
4. **切换成本高**:provider 换了,库里 448 个块的向量全部失效
(fingerprint 不匹配会被跳过,实测 `RecallBlocks` 的指纹校验会
把它们全丢掉),需要全量回填。而回填在 CPU 上是分钟级/百条。
## 四、Qwen3-VL 该用在哪
它的 **last_token 池化 + 视觉塔** 在图像/视频上是 chineseclip 不可替代的:
导出校验里 image/video_g2~g4 全部 cos≈1.0,而 chineseclip 是
CLIP 架构(图像侧能用但文本侧弱)。
所以:**多模态块走 Qwen3-VL,纯文本块走 chineseclip + 中心化** ——
而这正是 `pkg/embedding` 注册表 + `fingerprint` 字段存在的意义
(RecallBlocks 的指纹校验保证两个空间互不干扰)。
## 五、被这个实验推翻的一个判断
我在 `feat(memory): 向量中心化` 那步写过:
> 「CLIP 架构是为图文对齐训的,纯文本的细粒度区分度天然低」
**那是把症状当成了原因。** chineseclip 的文本塔是 RoBERTa-wwm-base,
与 CLIP 无关;真正的现象是 RoBERTa CLS 向量各向异性(均值范数 0.9374)。
修正后才有中心化这个 7.3 倍的解法 —— 而换 provider 解决不了它。
## 补充(2026-10-04):决策漏了一类 —— 同义改写
### 原决策测的是什么
```
维度名别名 词法胜(0.4500 vs Qwen3-VL 0.0803)
值分离度 Qwen3-VL 负(−0.1843),chineseclip 胜
结论 纯文本保留 chineseclip,Qwen3-VL 留多模态
```
**两项都是「形近」的任务**——问的是「这两个词像不像」「这两个值差多远」。
### 但生产失败的那两类都不属于这两项
生产探针(1391 块)的失败:
```
[casual] agentmail 公网访问地址是什么 ✘
[casual] agentmail 公网访问地址查询 ✘
```
目标块内容:
```
http://101.201.37.155:8083/ ← 裸 URL,无任何描述词
```
查询与块**零词法重叠**——这是**同义改写**,原决策完全没测这一项。
### 实测:chineseclip 在这类上的能力接近于零
```
查询 目标块排名 top1 分数
agentmail 公网访问地址是什么 452 0.8041
公网地址 389 0.5070
对外的服务地址 297 0.7362
101.201.37.155 是哪台机器 58 0.5471
```
★ 排名随「查询的可词法化程度」剧烈变化(452 → 58)。
查询里带上 IP 后排名降到 58 —— 说明起作用的主要还是词法信号,
语义贡献极小。
⇒ **这解释了生产探针 4/9 的上限**:不是算法不够好,
而是**块里根本没有可供语义匹配的文本**。
### 决策缺口与两条出路
| 出路 | 说明 |
|---|---|
| A 用 Qwen3-VL 做同义改写 | last_token 池化在长文本上可能更强,**但未测** |
| B **给块补描述** | 让 `http://101.201.37.155:8083/` 带上「agentmail 公网地址」这类上下文 |
★ **B 更有希望**:裸 URL 的语义信息**不在文本里**,任何 embedding 模型
都无法凭空生成它。这不是模型选型问题,是**数据形态**问题。
⇒ 原决策的结论(纯文本用 chineseclip)在**现有数据形态**下仍成立,
但那个前提没有被写出来:**块文本必须自带语义描述**。
数据形态变了,决策要重估。
## 否定实验(2026-10-04):给块补描述**不管用**
上面说「裸 URL 的语义信息不在文本里,给块补描述更有希望」——
**这个假设被实验否定了。**
### 实验设计:三档位,分离「有上下文」与「有正确上下文」
在同一个库副本(2686 块,230 个裸值型块)上依次测:
```
A 基线 原文本(裸值无描述)
B 中性描述 追加不含查询关键词的中性描述
C 作弊对照 追加含查询关键词的描述(量上限,不应计入)
```
### 结果(裸值块最佳排名,越小越好)
```
A基线 B中性 C作弊
agentmail 公网访问地址 26 96 57
公网地址 37 15 3
对外的服务地址 30 11 21
```
★ **B 让第一个查询从 26 掉到 96** —— 给裸 URL 追加无意义文字
**反而更差**(噪声文本稀释了原值信号)。
★ C 也没稳定变好(26 → 57,也是变差)。只有「公网地址」这一条
因为查询短、匹配到 generic 描述而变好,**不构成方法**。
### 结论
**「给块补描述」这条路不成立**,至少不能用「统一追加中性文本」的方式做。
剩下的可能性:
| 方向 | 状态 |
|---|---|
| 给每个 URL 配**真实**的上文(哪条命令/哪次排障产生的) | 未测,需知道来源链 |
| 换更擅长同义改写的向量模型(Qwen3-VL) | 未测,12.5 GiB |
| **接受现状**:URL 类事实靠符号路(输入 URL 就精确命中) | 已可用 |
★ 而第 3 条其实已经覆盖了大部分场景:
用户问「公网地址是什么」时不带 URL,
这是**召回的困难形态**;真要用时用户通常会带 IP/域名,
那是词法/符号路的强项(实测排名 58,vs 不带时的 452)。
⇒ **生产召回的实际可用性可能比我给的 4/9 更高**,
因为探针问的正是最难的那种形态。