5.7 KiB
Raw Blame History

name, description, disable-model-invocation
name description disable-model-invocation
生成知识向量 使用固定 Qwen3 嵌入模型将知识草稿或实体批量写入 pgvector,并按内容哈希幂等处理 owner 与版本。知识行需要建立或刷新检索向量时使用;不嵌入参考书全文。 true

嵌入知识内容

对应 muse API 面:AI 网关(嵌入)。通道事实见 连接信息.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。

用法

# 批量补嵌 pending 草稿(无活向量,或活向量的当前 payload+model hash 已过期)
.venv/bin/python muse/lifecycle/context/skills/生成知识向量/scripts/embed_drafts.py

# 指定 work(默认兼容参考书拆书批次,按 source_id)或限量
.venv/bin/python muse/lifecycle/context/skills/生成知识向量/scripts/embed_drafts.py --work-id 3 --limit 100

# 章后抽卡按作品的 draft.work_id 筛选(source_id 是章节 id)
.venv/bin/python muse/lifecycle/context/skills/生成知识向量/scripts/embed_drafts.py --work-id 12 --source-type chapter_extract

# 自由文本试嵌(调试/B3 查询端复用同实现)
.venv/bin/python muse/lifecycle/context/skills/生成知识向量/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 结构化段落)。
  • 不直接落库、不代替 写下一章 / 决定正文候选去留 写 Canonical。

数据边界

  • 读写范围限于本 Skill 合同声明的表/文件;失败整体回滚,不留半写入状态。
  • 模型调用走统一网关;raw 证据由 记录运行证据 归档。

复利合同

  • 嵌入批次完成后经 propose_lesson_dedup 登记 example_lesson(绑 work_id / source_type / limit)。
  • 升格仍走人工评审,不自动把嵌入参数调优升为公共规则。

输入