59 lines
5.7 KiB
Markdown
59 lines
5.7 KiB
Markdown
---
|
||
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)。
|
||
- 升格仍走人工评审,不自动把嵌入参数调优升为公共规则。
|
||
|
||
## 输入
|