59 lines
5.7 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.

---
name: embed-knowledge
description: 使用固定 Qwen3 嵌入模型将知识草稿或实体批量写入 pgvector,并按内容哈希幂等处理 owner 与版本。知识行需要建立或刷新检索向量时使用;不嵌入参考书全文。
disable-model-invocation: true
---
# 嵌入知识内容
对应 muse API 面:AI 网关(嵌入)。通道事实见 [`连接信息.md`](../../../../authority/db/连接信息.md):BASE `http://100.64.0.8:3000`、模型 `Qwen/Qwen3-Embedding-8B`、请求体 `"dimensions":1024`(实测生效)、**禁系统代理**(`trust_env=False`)。
库实现装为共享包 `muse-embed`(`-e ./muse/platform/embed`):拆书与检索侧 `from muse_embed import embed_texts, build_embed_text`,`scripts/embed_drafts.py` 只是本 Skill 的 CLI。
## 用法
```bash
# 批量补嵌 pending 草稿(无活向量,或活向量的当前 payload+model hash 已过期)
.venv/bin/python muse/lifecycle/context/skills/embed-knowledge/scripts/embed_drafts.py
# 指定 work(默认兼容参考书拆书批次,按 source_id)或限量
.venv/bin/python muse/lifecycle/context/skills/embed-knowledge/scripts/embed_drafts.py --work-id 3 --limit 100
# 章后抽卡按作品的 draft.work_id 筛选(source_id 是章节 id)
.venv/bin/python muse/lifecycle/context/skills/embed-knowledge/scripts/embed_drafts.py --work-id 12 --source-type chapter_extract
# 自由文本试嵌(调试/B3 查询端复用同实现)
.venv/bin/python muse/lifecycle/context/skills/embed-knowledge/scripts/embed_drafts.py --probe "机甲近战的节奏控制"
```
## 合同
- **嵌入文本构造**:`【型】名称:一句话摘要\n字段正文摘选`(draft_payload 的 `embed_text` 字段优先;无则兼容中文键 `型/名称/一句话摘要/字段` 与作品抽卡英文键 `type/name/brief/fields`),与检索端 query 语义对齐。
- **幂等与 owner**:sha256(嵌入文本+模型) 为 `content_hash`(uk: tenant+hash+model)。只有唯一行 `deleted=FALSE`、绑定同一 `draft_id`,且 owner draft 同租户并 `deleted=FALSE` 时才幂等跳过;`entity_id` 非空或其他 active draft owner 明确冲突并失败,绝不迁移 owner。旧 owner draft 已软删时,允许在写前活性重验后把唯一行条件迁到当前 draft。
- **批量**:读取每个 pending draft 的全部活向量,在 Python 中复用统一文本与 hash 规则筛选“无活向量”或“活向量 hash/model 与当前目标不一致”的候选;对完整候选集完成状态、同批 hash 与目标 owner 只读预检并提交后,`limit` 才限制实际 HTTP/写入行,每个实际 chunk 在 HTTP 前再次预查 owner 以封住竞态。每请求 ≤16 条文本;响应 `index` 必须是范围内唯一整数并完整覆盖请求槽位,缺项、重复或越界进入既有整批重试和逐条降级。失败整批重试 2 次(指数退避),仍失败逐条降级重试,坏行记错并继续(不断批)。网络异常、返回 `bad`、向量缺项或 `None` 均只记失败,不改旧向量,下一轮仍可重试;owner 冲突、多条活向量、同批目标 hash 冲突属于确定性异常,明确报告后令整条命令失败退出,不降级成失败计数。
- **落库与 reset/confirm/parse 并发**:HTTP 期间不持数据库事务。每个 draft 写入使用独立事务,先 `SELECT ... FOR UPDATE` 锁定 draft 并重验租户、`deleted=FALSE`、`status='pending'`;同时读取当前 `draft_payload`,重构文本与 hash,和 HTTP 前快照任一不一致即跳过。随后 `SELECT ... FOR UPDATE` 锁定该 draft 全部活向量:多条活向量是异常状态并失败关闭,任一 `entity_id` 非空则冲突失败,同 hash 且同 model 的当前活向量才幂等跳过,其他 hash 或 model 的无 entity 旧活向量在 UPSERT 前统一软删,保证每 draft 仅一个活向量。最后锁同 hash 唯一行,执行带 owner 条件的 UPSERT 并用 `RETURNING draft_id` 校验。同批多个 draft 的目标 hash 相同时整组失败,不按执行顺序抢 owner。该 draft 行锁与 reset 的 11 表 `SHARE ROW EXCLUSIVE`(4 个输入源表 + 7 个产出表)配合:embed 先锁时 reset 等待且随后能发现快照漂移;reset 先完成时 embed 等待后看到软删并跳过。confirm/parse 先完成时 embed 在锁后看到状态或 payload/hash 漂移并跳过。以上跳过或失败路径均零向量写入。
- **落库字段**:`example_knowledge_embedding(draft_id, content_hash, embed_text, model, dimensions=1024, embedding)`;draft 确认落 entity 后由 confirm 流程把 owner 迁到 `entity_id` 并清空 `draft_id`,关系草稿确认后关闭无 canonical owner 的临时向量。
- 汇报:新嵌 N、跳过 M、失败 K;幂等、失活和冲突原因均输出可追踪明细。
## 红线
- 调用必须 `trust_env=False`(系统代理会假 502);普通令牌只从 `MUSE_EMBED_TOKEN` 读取,可回退 `MUSE_LLM_TOKEN`,不得使用管理令牌或写入仓库。
- 只嵌知识行内容,不嵌参考书原文全文(原文私有库不进向量面——脱敏边界在 B2 拆书层保证)。
## 输出
- 面向当前任务的可执行判断、检查清单或改写建议(Markdown 结构化段落)。
- 不直接落库、不代替 `write-next-chapter` / `decide-candidate` 写 Canonical。
## 数据边界
- 读写范围限于本 Skill 合同声明的表/文件;失败整体回滚,不留半写入状态。
- 模型调用走统一网关;raw 证据由 `record-run-evidence` 归档。
## 复利合同
- 嵌入批次完成后经 `propose_lesson_dedup` 登记 `example_lesson`(绑 work_id / source_type / limit)。
- 升格仍走人工评审,不自动把嵌入参数调优升为公共规则。
## 输入